Cài đặt LEMP Linux Nginx MySQL PHP (LEMP ) trên Ubuntu 20 04
LEMP là một bộ phần mềm được dùng để chạy các trang web động và ứng dụng web được viết bằng PHP. Đây là viết tắt của hệ điều hành L inux, với web server Nginx (phát âm như “ E ngine-X”). Dữ liệu backend được lưu trữ trong database M ySQL và xử lý bởi P HP. Hướng dẫn này sẽ cài đặt LEMP trên server Ubuntu 20.04.Yêu cầu
Để hoàn thành hướng dẫn này, bạn cần server Ubuntu 20.04 với quyền là user sudo
thông thường không phải root và firewall được bật trên server. Nếu chư có bạn có thể làm theo hướng dẫn cài đặt server ban đầu cho Ubuntu 20.04 .
Bước 1 - Cài đặt Web Server Nginx
Để hiển thị các trang web cho khách truy cập trang web , ta sẽ sử dụng Nginx, một web server hiệu suất cao. Ta sẽ sử dụng trình quản lý gói apt
để cài đặt.
Vì đây là lần đầu tiên ta sử dụng apt
cho phiên này, hãy bắt đầu bằng cách cập nhật hệ điều hành của server. Sau đó, bạn có thể sử dụng apt install
để cài đặt Nginx:
- sudo apt update
- sudo apt install nginx
Hãy nhập Y
để xác nhận bạn muốn cài đặt Nginx. Sau khi cài đặt xong, web server Nginx sẽ hoạt động.
Nếu bạn đã bật firewall ufw
, như được khuyến khích trong hướng dẫn cài đặt server ban đầu , bạn cần cho phép kết nối với Nginx. Nginx đăng ký một số cấu hình ứng dụng UFW khác nhau khi cài đặt. Để kiểm tra cấu hình UFW cho phép ứng dụng nào, hãy chạy:
- sudo ufw app list
Available applications: Nginx Full Nginx HTTP Nginx HTTPS OpenSSH
Bạn nên bật cấu hình chặn tối đa mà vẫn cho phép lưu lượng truy cập mà bạn cần. Vì bạn chưa cấu hình SSL cho server trong hướng dẫn này, nên bạn chỉ cần cho phép truy cập HTTP thông thường trên cổng 80
.
Bật tính năng này bằng lệnh:
- sudo ufw allow 'Nginx HTTP'
Bạn có thể xác minh thay đổi bằng lệnh:
- sudo ufw status
Kết quả của lệnh này sẽ cho thấy truy cập HTTP hiện đã được phép:
Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Nginx HTTP ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Nginx HTTP (v6) ALLOW Anywhere (v6)
Với luật firewall mới được thêm vào, bạn có thể kiểm tra xem server có hoạt động hay không bằng cách truy cập vào domain hoặc địa chỉ IP công cộng của server trong trình duyệt web.
Nếu không có domain được trỏ đến server và bạn không biết địa chỉ IP công cộng của server, bạn có thể tìm bằng cách chạy lệnh sau:
- ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'
Thao tác này sẽ in ra một vài địa chỉ IP. Bạn có thể thử lần lượt từng cái trong trình duyệt web.
Môt cách khác, bạn có thể tìm địa chỉ IP của bạn với:
- curl -4 icanhazip.com
Nhập địa chỉ bạn nhận được vào trình duyệt web và địa chỉ đó sẽ đưa bạn đến trang đích mặc định của Nginx:
http://server_domain_or_IP
Nếu bạn thấy trang này, điều đó nghĩa là bạn đã cài đặt thành công Nginx và cho phép truy cập HTTP cho web server.
Bước 2 - Cài đặt MySQL
Đến đây bạn đã có một web server và đang chạy, bạn cần cài đặt hệ thống database để có thể lưu trữ và quản lý dữ liệu cho trang web. MySQL là một hệ quản trị database phổ biến được sử dụng trong môi trường PHP.
Sử dụng apt
để cài đặt phần mềm này:
- sudo apt install mysql-server
Xác nhận cài đặt bằng lệnh Y +
ENTER
.
Khi quá trình cài đặt hoàn tất, bạn nên chạy một tập lệnh bảo mật được cài đặt sẵn với MySQL. Tập lệnh này sẽ xóa một số cài đặt mặc định không an toàn và khóa quyền truy cập vào hệ thống database của bạn. Bắt đầu tập lệnh tương tác bằng lệnh:
- sudo mysql_secure_installation
Điều này sẽ hỏi bạn có muốn cấu hình VALIDATE PASSWORD PLUGIN
.
Lưu ý: Bạn cần cân nhắc áp dụng lệnh trên. Nếu được chạy, password không phù hợp với tiêu chí đã chỉ định sẽ bị MySQL từ chối và báo lỗi. Nếu không áp dụng thì bạn phải nên luôn sử dụng password mạnh đăng nhập database.
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:
Nếu bạn trả lời “yes”, bạn cần chọn mức độ xác thực password. Lưu ý nếu bạn nhập 2
(xem bên dưới) cho cấp độ mạnh nhất, bạn sẽ thấy báo lỗi khi đặt password không chứa số, chữ hoa và chữ thường và các ký tự đặc biệt hoặc dựa trên các từ thông dụng trong từ điển.
There are three levels of password validation policy: LOW Length >= 8 MEDIUM Length >= 8, numeric, mixed case, and special characters STRONG Length >= 8, numeric, mixed case, special characters and dictionary file Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 1
Bất kể bạn đã chọn cài đặt VALIDATE PASSWORD PLUGIN
, server sẽ yêu cầu bạn chọn và xác nhận password cho user root MySQL. (không nhầm với root hệ thống). User root database là admin-user (người-dùng-quản-trị) có đầy đủ các quyền đối với hệ thống database. Mặc dù phương pháp xác thực mặc định cho user root MySQL không cho phép sử dụng password, bạn nên xác định một password mạnh ở đây như một biện pháp an toàn bổ sung. Ta sẽ nói về điều này trong giây lát.
Nếu bạn đã cài đặt xác thực password, bạn sẽ được hiển thị độ mạnh password cho password root mà bạn vừa nhập và server sẽ hỏi bạn có muốn tiếp tục với password đó hay không. Nếu bạn hài lòng với password hiện tại của bạn, hãy nhập Y
cho “yes” tại dấu nhắc:
Estimated strength of the password: 100 Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
Đối với các câu hỏi còn lại, nhấn Y
và nhấn ENTER
tại mỗi dấu nhắc. Thao tác này sẽ xóa một số user ẩn danh và database thử nghiệm, vô hiệu hóa đăng nhập root từ xa và tải các rule (luật) mới này để MySQL áp dụng ngay những thay đổi đã thực hiện.
Khi bạn hoàn tất, hãy kiểm tra xem bạn có thể đăng nhập vào console MySQL hay không bằng lệnh:
- sudo mysql
Thao tác này sẽ kết nối với server MySQL dưới dạng root của user database quản trị. Bạn sẽ thấy kết quả như thế này:
Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 22 Server version: 8.0.19-0ubuntu5 (Ubuntu) Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>
Để thoát khỏi console MySQL, hãy nhập:
- exit
Lưu ý bạn không cần cung cấp password để kết nối với quyền là user root, mặc dù bạn đã xác định password khi chạy tập lệnh mysql_secure_installation
. Đó là bởi vì phương pháp xác thực mặc định cho user MySQL quản trị là unix_socket
thay vì password
. Mặc dù điều này có vẻ giống một nguy cơ bảo mật, nhưng thực ra nó làm cho server database an toàn hơn vì user duy nhất được phép đăng nhập với quyền user MySQL root là user hệ thống có quyền sudo kết nối từ console. Về mặt thực tế, điều đó nghĩa là bạn sẽ không thể sử dụng user root database quản trị để kết nối từ ứng dụng PHP của bạn.
Để tăng cường bảo mật, tốt nhất bạn nên cài đặt các account user riêng với ít quyền hơn cho database, đặc biệt nếu bạn có kế hoạch lưu trữ nhiều database trên server.
Lưu ý: Tại thời điểm viết bài này, thư viện MySQL PHP mysqlnd
không hỗ trợ caching_sha2_authentication
, phương thức xác thực mặc định cho MySQL 8. Vì lý do đó, khi tạo user database cho các ứng dụng PHP trên MySQL 8, bạn cần thực hiện hãy chắc chắn rằng chúng được cấu hình để sử dụng mysql_native_password
thay thế. Ta sẽ trình bày cách thực hiện điều đó trong Bước 6 .
Server MySQL của bạn hiện đã được cài đặt và bảo mật. Tiếp theo, ta sẽ cài đặt PHP, thành phần cuối cùng trong LEMP.
Bước 3 - Cài đặt PHP
Bạn đã cài đặt Nginx để phân phát nội dung của bạn và đã cài đặt MySQL để lưu trữ và quản lý dữ liệu. Đến đây bạn có thể cài đặt PHP để xử lý mã và tạo nội dung động cho web server.
Trong khi Apache nhúng trình thông dịch PHP trong mỗi yêu cầu, thì Nginx yêu cầu một chương trình bên ngoài để xử lý quá trình PHP processor (xử-lý-PHP) như cầu nối. Điều này cho phép hiệu suất tổng thể tốt hơn trong hầu hết các trang web dựa trên PHP, nhưng nó yêu cầu cấu hình bổ sung. Bạn cần cài đặt php-fpm
, viết tắt của “PHP fastCGI process manager” và yêu cầu Nginx chuyển các yêu cầu PHP đến phần mềm này để xử lý. Ngoài ra, bạn cần php-mysql
, một module PHP cho phép PHP giao tiếp với database dựa trên MySQL. Các gói PHP core sẽ tự động được cài đặt dưới dạng các gói phụ thuộc.
Để cài đặt các gói php-fpm
và php-mysql
, hãy chạy:
- sudo apt install php-fpm php-mysql
Khi được yêu cầu, hãy nhập Y
và ENTER
để xác nhận cài đặt.
Đến đây bạn đã cài đặt các thành phần PHP. Tiếp theo, bạn sẽ cấu hình Nginx để sử dụng chúng.
Bước 4 - Cấu hình Nginx để sử dụng PHP processor (xử-lý-PHP)
Khi sử dụng web server Nginx, ta có thể tạo server block (tương tự như VirtualHost trong Apache) để đóng gói chi tiết cấu hình và lưu trữ nhiều hơn một domain trên một server. Trong hướng dẫn này, ta sẽ sử dụng your_domain làm domain mẫu.
Trên Ubuntu 20.04, Nginx có một server block được bật theo mặc định và được cấu hình để cho truy cập tại /var/www/html
. Mặc dù điều này hoạt động tốt cho một trang web nhưng có thể trở nên khó quản lý nếu bạn đang lưu trữ nhiều trang web. Thay vì sửa đổi /var/www/html
, ta sẽ tạo cấu trúc folder trong /var/www
cho trang web your_domain , giữ nguyên /var/www/html
làm folder mặc định đáp ứng các truy cập mặc định (có thể là truy cập vào địa chỉ ip server...).
Tạo folder web root cho your_domain như sau:
- sudo mkdir /var/www/your_domain
Tiếp theo, chỉ định quyền sở hữu folder với biến môi trường $ USER, biến này sẽ tham chiếu đến user hệ thống hiện tại của bạn:
- sudo chown -R $USER:$USER /var/www/your_domain
Sau đó, mở file cấu hình mới trong folder sites-available
của Nginx bằng trình chỉnh sửa dòng lệnh bạn muốn. Ở đây, ta sẽ sử dụng nano
:
- sudo nano /etc/nginx/sites-available/your_domain
Thao tác này sẽ tạo một file trống mới. Paste vào cấu hình cơ bản sau:
server { listen 80; server_name your_domain www.your_domain; root /var/www/your_domain; index index.html index.htm index.php; location / { try_files $uri $uri/ =404; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; } location ~ /\.ht { deny all; } }
Giải thích cú pháp:
listen
- Xác định cổng nào mà Nginx sẽ lắng nghe. Trong trường hợp này, nó sẽ lắng nghe trên cổng80
, cổng mặc định cho HTTP.root
- Xác định root document nơi lưu trữ các file do trang web này cung cấp.index
- Xác định thứ tự mà Nginx sẽ ưu tiên các file index cho trang web này. Một thực tế phổ biến làindex.html
có mức độ ưu tiên cao hơnindex.php
, bạn có thể sửa lại đưa index.php đặt trước index.html, hoặc xóa file index.html đi để luôn phục vụ index.php.server_name
- Xác định domain và / hoặc địa chỉ IP mà server block này sẽ phản hồi. Trỏ chỉ thị này tới domain hoặc địa chỉ IP công cộng của server.location /
- Khối vị trí đầu tiên bao gồm chỉ thịtry_files
, chỉ thị này kiểm tra sự tồn tại của các file hoặc folder trùng với yêu cầu URI. Nếu Nginx không thể tìm thấy tài nguyên thích hợp, nó sẽ trả về lỗi 404.location ~ \.php$
- Khối vị trí này xử lý quá trình PHP thực tế bằng cách trỏ Nginx tới file cấu hìnhfastcgi-php.conf
và filephp7.4-fpm.sock
, file này khai báo socket nào được liên kết vớiphp-fpm
.location ~ /\.ht
- Khối vị trí cuối cùng xử lý các.htaccess
mà Nginx không xử lý. Bằng cách thêm chỉ thịdeny all
, nếu bất kỳ.htaccess
nào tìm thấy đường vào root document, chúng sẽ không được cung cấp cho khách truy cập.
Khi bạn chỉnh sửa xong, hãy lưu file. Nếu bạn đang sử dụng nano
, bạn có thể thực hiện bằng lệnh CTRL+X
rồi đến y
và ENTER
để xác nhận.
Kích hoạt cấu hình của bạn bằng cách liên kết đến file cấu hình từ folder sites-enabled
của Nginx:
- sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/
Điều này sẽ thông báo cho Nginx sử dụng cấu hình trong lần reload (tải-lại) tiếp theo. Bạn có thể kiểm tra cấu hình tìm lỗi cú pháp bằng lệnh:
- sudo nginx -t
Nếu có lỗi, hãy quay lại file cấu hình của bạn để xem lại nội dung của nó trước khi tiếp tục.
Khi đã sẵn sàng, hãy reload (tải-lại) Nginx để áp dụng các thay đổi:
- sudo systemctl reload nginx
Trang web mới của bạn hiện đã hoạt động, nhưng root web /var/www/your_domain
vẫn trống. Tạo index.html
ở vị trí đó để ta có thể kiểm tra xem server block mới của bạn có hoạt động như mong đợi hay không:
- nano /var/www/your_domain/index.html
Bao gồm các nội dung sau trong file này:
<html> <head> <title>your_domain website</title> </head> <body> <h1>Hello World!</h1> <p>This is the landing page of <strong>your_domain</strong>.</p> </body> </html>
Bây giờ, hãy truy cập trình duyệt của bạn và truy cập domain hoặc địa chỉ IP của server, như được liệt kê trong chỉ thị server_name
trong file cấu hình server block của bạn:
http://server_domain_or_IP
Bạn sẽ thấy một trang như thế này:
Nếu bạn thấy trang này, điều đó nghĩa là server block Nginx đang hoạt động như mong đợi.
Bạn có thể để file này ở vị trí như một trang đích tạm thời cho ứng dụng của bạn cho đến khi bạn đặt index.php
để thay thế. Khi bạn làm điều đó, hãy nhớ xóa hoặc đổi tên index.html
khỏi root document của bạn, vì nó sẽ được ưu tiên hơn index.php
theo mặc định.
LEMP của bạn hiện đã được cấu hình đầy đủ. Trong bước tiếp theo, ta sẽ tạo một tập lệnh PHP để kiểm tra xem Nginx trên thực tế có thể xử lý các file .php
trong trang web mới được cấu hình hay không.
Bước 5 – Kiểm tra PHP với Nginx
LEMP của bạn bây giờ sẽ được cài đặt hoàn chỉnh. Bạn có thể kiểm tra nó để xác thực rằng Nginx có thể xử lý chính xác các file .php
cho PHP processor của bạn.
Bạn có thể làm điều này bằng cách tạo một file PHP thử nghiệm trong root document. Mở một file mới có tên là info.php
trong root document trong editor:
- nano /var/www/your_domain/info.php
Edit hoặc paste các dòng sau vào file mới. Đây là mã PHP hợp lệ sẽ trả về thông tin về server:
<?php phpinfo();
Khi bạn hoàn tất, hãy lưu file bằng lệnh CTRL
+ X
rồi đến y
và ENTER
để xác nhận.
Như vậy, bạn có thể truy cập trang này trong trình duyệt web bằng cách truy cập vào domain hoặc địa chỉ IP công cộng mà bạn đã cài đặt trong file cấu hình Nginx của bạn, theo sau là /info.php
:
http://server_domain_or_IP/info.php
Bạn sẽ thấy một trang web chứa thông tin chi tiết về server:
Sau khi kiểm tra thông tin liên quan về server PHP của bạn thông qua trang đó, tốt nhất bạn nên xóa file bạn đã tạo vì nó chứa thông tin nhạy cảm về môi trường PHP và server Ubuntu. Bạn có thể sử dụng rm
để xóa file đó:
- sudo rm /var/www/your_domain/info.php
Bạn luôn có thể tạo lại file này nếu sau này bạn cần.
Bước 6 - Kiểm tra kết nối database từ PHP (Tùy chọn)
Nếu bạn muốn kiểm tra xem PHP có thể kết nối với MySQL và thực thi các truy vấn database hay không, bạn có thể tạo một bảng kiểm tra với dữ liệu và truy vấn nội dung của nó từ một tập lệnh PHP. Trước khi có thể làm điều đó, ta cần tạo một database thử nghiệm và một user MySQL mới được cấu hình đúng cách để truy cập nó.
Tại thời điểm viết bài này, thư viện MySQL PHP mysqlnd
không hỗ trợ caching_sha2_authentication
, phương thức xác thực mặc định cho MySQL 8. Ta cần tạo một user mới với phương thức xác thực mysql_native_password
để có thể kết nối với Database MySQL từ PHP.
Ta sẽ tạo database có tên example_database và user có tên example_user , nhưng bạn có thể thay thế các tên này bằng các giá trị khác nhau.
Đầu tiên, kết nối với console MySQL bằng account root :
- sudo mysql
Để tạo database mới, hãy chạy lệnh sau từ console MySQL của bạn:
- CREATE DATABASE example_database;
Đến đây bạn có thể tạo một user mới và cấp cho họ các quyền đầy đủ trên database tùy chỉnh vừa tạo.
Lệnh sau tạo một user mới có tên example_user
, sử dụng mysql_native_password
làm phương thức xác thực mặc định. Ta đang xác định password của user này là password
, nhưng bạn nên thay thế giá trị này bằng một password an toàn do chính bạn chọn.
- CREATE USER 'example_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
Bây giờ ta cần cấp quyền cho user này trên database example_database
:
- GRANT ALL ON example_database.* TO 'example_user'@'%';
Điều này sẽ cung cấp cho user example_user toàn quyền đối với database example_database , đồng thời ngăn user này tạo hoặc sửa đổi database khác trên server.
Bây giờ thoát khỏi shell MySQL với:
- exit
Bạn có thể kiểm tra xem user mới có quyền thích hợp hay không bằng cách đăng nhập lại vào console MySQL, lần này bằng cách sử dụng thông tin đăng nhập user:
- mysql -u example_user -p
Lưu ý cờ -p
trong lệnh này sẽ nhắc bạn nhập password được sử dụng khi tạo user example_user . Sau khi đăng nhập vào console MySQL, hãy xác nhận bạn có quyền truy cập vào database example_database :
- SHOW DATABASES;
kết quả sau:
+--------------------+ | Database | +--------------------+ | example_database | | information_schema | +--------------------+ 2 rows in set (0.000 sec)
Tiếp theo, ta sẽ tạo một bảng thử nghiệm có tên là todo_list . Từ console MySQL, hãy chạy câu lệnh sau:
- CREATE TABLE example_database.todo_list (
- item_id INT AUTO_INCREMENT,
- content VARCHAR(255),
- PRIMARY KEY(item_id)
- );
Chèn một vài hàng nội dung trong bảng kiểm tra. Bạn có thể cần lặp lại lệnh tiếp theo một vài lần, sử dụng các giá trị khác nhau (ví dụ 4 lần):
- INSERT INTO example_database.todo_list (content) VALUES ("My first important item");
Để xác nhận dữ liệu đã được lưu thành công vào bảng của bạn, hãy chạy:
- SELECT * FROM example_database.todo_list;
Bạn sẽ thấy kết quả sau:
+---------+--------------------------+ | item_id | content | +---------+--------------------------+ | 1 | My first important item | | 2 | My second important item | | 3 | My third important item | | 4 | and this one more thing | +---------+--------------------------+ 4 rows in set (0.000 sec)
Sau khi xác nhận bạn có dữ liệu hợp lệ trong bảng kiểm tra của bạn, bạn có thể thoát khỏi console MySQL:
- exit
Đến đây bạn có thể tạo tập lệnh PHP sẽ kết nối với MySQL và truy vấn nội dung trên. Tạo một file PHP mới trong folder root web tùy chỉnh của bạn bằng trình soạn thảo bạn muốn. Ta sẽ sử dụng nano
cho điều đó:
- nano /var/www/your_domain/todo_list.php
Tập lệnh PHP sau kết nối với database MySQL và truy vấn nội dung của bảng todo_list, hiển thị kết quả trong danh sách. Nếu có vấn đề với kết nối database, nó sẽ đưa ra báo lỗi.
Sao chép nội dung này vào tập lệnh todo_list.php
của bạn:
<?php $user = "example_user"; $password = "password"; $database = "example_database"; $table = "todo_list"; try { $db = new PDO("mysql:host=localhost;dbname=$database", $user, $password); echo "<h2>TODO</h2><ol>"; foreach($db->query("SELECT content FROM $table") as $row) { echo "<li>" . $row['content'] . "</li>"; } echo "</ol>"; } catch (PDOException $e) { print "Error!: " . $e->getMessage() . "<br/>"; die(); }
Lưu file khi bạn chỉnh sửa xong.
Đến đây bạn có thể truy cập trang này trong trình duyệt web bằng cách truy cập vào domain hoặc địa chỉ IP công cộng được cấu hình cho trang web, theo sau là /todo_list.php
:
http://server_domain_or_IP/todo_list.php
Bạn sẽ thấy một trang như thế này, hiển thị nội dung bạn đã chèn vào bảng thử nghiệm của bạn:
Điều đó nghĩa là môi trường PHP của bạn đã sẵn sàng kết nối và tương tác với server MySQL của bạn.
Kết luận
Chúc mừng bạn, trong hướng dẫn này, ta đã xây dựng một nền tảng cơ bản, linh hoạt để cung cấp các trang web và ứng dụng PHP, sử dụng Nginx làm web server và MySQL làm hệ thống database.
Các tin trước
Cài đặt Linux Apache MySQL PHP (LAMP) trên Ubuntu 20 04 2020-04-29
Bảo mật apache với let-s-encrypt trên Ubuntu 20.04 2020-04-29
Cài đặt Apache Web Server trên Ubuntu 20.04 2020-04-27
Cài đặt Nginx trên Ubuntu 20.04 2020-04-24
Khởi tạo bảo mật Server Ubuntu 20.04 2020-04-23
Cài đặt SSH Key trên Ubuntu 20.04 2020-04-23
Cài đặt MySQL trên Ubuntu 18.04 2020-04-21
Cài đặt và bảo mật phpMyAdmin trên Ubuntu 18.04 2020-04-21
Cài đặt Webserver Apache trên CentOS 7 2019-05-29
So sánh SQLite , MySQL , PostgreSQL 2019-03-19