Installing Linux + (Nginx + Apache) + PostgreSQL + PHP Server on VirtualBox (Ubuntu Server 16.04.3 LTS)

On the Internet, I did not find a single recipe for installing and configuring such a rather non-standard server. I decided to write my recipe.

The principle of operation is as follows:

Nginx gives static data (files), and Apache does the dynamics.
Let's get started.

We need:

Ubuntu Server 16.04.3 LTS (LTS - Long Time Support)

Install VirtualBox

  1. Run the VirtualBox installer.

    Install VirtualBox.  Step 1
  2. Leave the default settings.

    Install VirtualBox.  Step 2

    Install VirtualBox.  Step 3
  3. The installer will temporarily disconnect us from the network. Click "Yes."

    Install VirtualBox.  Step 4
  4. We begin the installation.
    Install VirtualBox.  Step 5
  5. Finish.

    Install VirtualBox.  Step 6

Prepare VirtualBox for Ubuntu Server 16.04.3 LTS Installation

  1. Download the ubuntu-16.04.3-server-amd64.iso image
  2. Create a virtual machine.

  3. Name: default_server
    Type: Linux
    Version: Ubuntu (64-bit)
    RAM: 2048 MB
    Important: I have 8 GB of RAM, and in my case, two gigabytes will be enough. Yours may be different ...

    Hard disk size: 15 GB
    Other parameters will be left by default.

    Click "Create."
  4. Immediately configure the network.

    Change the connection type from NAT to Network Bridge.

    In the future, we will not deal with port forwarding.
  5. We start our car.


Install Ubuntu Server 16.04.3 LTS

  1. Select the boot disk with the Ubuntu Server 16.04.3 LTS image.

  2. We choose a convenient language, I have Russian.

    Install Ubuntu Server 16.04.3 LTS (Step 1)
    Click "Enter."
  3. Select "Install Ubuntu Server."

    Install Ubuntu Server 16.04.3 LTS (Step 2)
  4. Choose a country.

    Install Ubuntu Server 16.04.3 LTS (Step 3)
    Important: Read the prompt at the bottom of the screen.
  5. I will not determine the keyboard layout, I do not need this.

    Install Ubuntu Server 16.04.3 LTS (Step 4)
  6. We select the country for which the keyboard is intended.

    Install Ubuntu Server 16.04.3 LTS (Step 5)
  7. Choose the layout region.

    Installing Ubuntu Server 16.04.3 LTS (Step 6)
  8. Select a key combination to switch the language. I am comfortable using CTRL +

    Install Ubuntu Server 16.04.3 LTS (Step 7)
  9. Enter the name of the computer by which it will be known on the network.

    Installing Ubuntu Server 16.04.3 LTS (Step 8)
  10. Enter the name of the admin.

    Installing Ubuntu Server 16.04.3 LTS (Step 9)
  11. Enter the name of the administrator account (It will be used as a login to enter the system).

    Installing Ubuntu Server 16.04.3 LTS (Step 10)
  12. Enter the password for the admin account.

    Installing Ubuntu Server 16.04.3 LTS (Step 11)
  13. We repeat the password.

    Install Ubuntu Server 16.04.3 LTS (Step 12)
  14. Why not..?

    Installing Ubuntu Server 16.04.3 LTS (Step 13)
  15. Choose a time zone.

    Install Ubuntu Server 16.04.3 LTS (Step 14)
  16. Let the system automatically use the entire disk.

    Install Ubuntu Server 16.04.3 LTS (Step 15)
  17. Partition disk, select by default.

    Install Ubuntu Server 16.04.3 LTS (Step 16)
  18. We write the changes to disk.

    Install Ubuntu Server 16.04.3 LTS (Step 17)
  19. We do not have a proxy, leave the field empty and continue.

    Install Ubuntu Server 16.04.3 LTS (Step 18)
  20. Let the system itself install security updates.

    Install Ubuntu Server 16.04.3 LTS (Step 19)
  21. We select the set of programs that will be installed with the system.
    The standard set and OpenSSH Server will be enough for us.

    Install Ubuntu Server 16.04.3 LTS (Step 20)
  22. Set GRUB as the main one.

    Install Ubuntu Server 16.04.3 LTS (Step 21)
  23. Great, almost done.

    Install Ubuntu Server 16.04.3 LTS (Step 22)
    We need to remove the disk from the drive.
    Devices -> Optical Discs -> Remove Disk from Drive

    Now click on Continue.
  24. Great, Ubuntu Server is installed.

    Ubuntu Server 16.04.3 LTS
    We enter the login, followed by the password, we get into the system, everything is OK.
    Turn off our car:
  25. Specifically, we will leave this machine alone, and will only use it for cloning.
    Clone our car:
    Enter a name.

    We continue.
    We choose full cloning.

    Click to clone. My cloning lasted two minutes.

Install PuTTY to access via SSH

  1. Run the installation file.

    Install PuTTY (Step 1)
  2. Leave the default settings.

    Установка PuTTY (Шаг 2)

    Установка PuTTY (Шаг 3)
    Click "Install."
  3. Finish.

    Установка PuTTY (Шаг 4)

Connection via SSH to the server

  1. Run a clone of our machine to find out its ip address.
    Let's write the command:

    In the screenshot, I marked the place where your ip address will be written. I have it: (it can change while writing an article, it has changed to for me).
    Now you can log out of your account by writing:
  2. Переходим в PuTTY, вводим ip адрес, и имя для сохраняемой сессии.

    Жмем «Save».
  3. Теперь, при двойном клике по имени сохраненной сессии.

    Мы должны наблюдать следующее:

    Вводим логин, после пароль.
    SSH соединение успешно настроено, теперь можно приступать к настройке (Nginx + Apache) + PostgreSQL + PHP.

Установка и настройка (Nginx + Apache) + PostgreSQL + PHP

Let's go into superuser mode.
sudo su
Let's go to the root directory.
cd /
Add a PostgreSQL repository.
wget -q -O - | sudo apt-key add -

sh -c 'echo "deb `lsb_release -cs`-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
Add a PHP repository.
add-apt-repository ppa:ondrej/php
Make an update.
apt-get update
Make an upgrade
apt-get upgrade
. I upgrade took five minutes.
We will
apt-get install python
install python, we will need it later. Let's proceed with the installation of Apache, PHP and PostgreSQL.
apt-get install apache2 php7.2 php7.2-cli php7.2-curl php7.2-fpm php7.2-pgsql postgresql postgresql-contrib postgresql-server-dev-10 libapache2-mod-rpaf build-essential apache2-dev
By default, PostgreSQL does not have single-byte and unsigned numbers, so we will install them.
There is an extension for PostgreSQL, pguint -
git clone /pguint
Let's go to the created directory
cd /pguint
Now we need to compile this extension (here we will need the python that we installed earlier).

make install
Now, to the PostgreSQL server, in the desired database, where we want to use unsigned and single-byte numbers, we will send:

Let's go back to the root directory.
cd /
Install Nginx, but before that we stop Apache so that it does not occupy port 80, otherwise Nginx will not install.
service apache2 stop
Installing Nginx
apt-get install nginx
Great, now stop Nginx as well
service nginx stop
Configuring Apache Change the Apache port Replace
a2dismod mpm_event

a2enmod mpm_worker

a2enmod proxy_fcgi

a2enconf php7.2-fpm

nano /etc/apache2/ports.conf

Listen 80

on the
Listen - means that Apache can be accessed only at the local address.
8080 - you can put any free port.
Let's go to the folder with available sites.
cd /etc/apache2/sites-available
Create a configuration file for our sideboard
nano domain-name.local.conf
and bring it to this form:

	ServerName domain-name.local
	ServerAlias www.domain-name.local
	ServerAdmin admin@domain-name.local
	DocumentRoot /var/www/domain-name.local
	ErrorLog ${APACHE_LOG_DIR}/domain-name.local_error.log
	CustomLog ${APACHE_LOG_DIR}/domain-name.local_access.log vhost_combined

Let's see what we have in / var / www The html folder, we no longer need it, delete it together with the contents Let's create our own folder, with our website Let's go to the folder with our website Let's create the index.pnp document We will write to it:
cd /var/www/

ls -F

rm -R html

mkdir domain-name.local/

cd domain-name.local/

nano index.php

We are done with this for now.
Let's go back to the root directory
cd /
. Apache has rpaf 0.6 and it does not transmit / receive a port from nginx and does not work correctly, as it should. Therefore, it must be updated. Now we will compile. We leave in the root directory Well, we will continue the Apache setup. Replace
wget -O rpaf_v0.8.4.tar.gz

gunzip rpaf_v0.8.4.tar.gz

tar xvf rpaf_v0.8.4.tar

cd mod_rpaf-0.8.4/


make install

cd /

nano /etc/apache2/apache2.conf

LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined

on the
LogFormat "%v:%p %{X-Forwarded-For}i %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined

Put in order rpaf.conf
nano /etc/apache2/mods-available/rpaf.conf
Let's bring it to this form:

	RPAF_Enable			On
	RPAF_ProxyIPs ::1
	RPAF_SetHostName		On
	RPAF_SetPort			On
	RPAF_ForbidIfNotProxy	Off
	RPAF_Header			X-Forwarded-For

We will enable our site in Apache.
a2ensite domain-name.local.conf
And run our Apache.
service apache2 start
C Apache finished.
Configure Nginx
nano /etc/nginx/sites-available/domain-name.local
Bring it to this view:
server {
	listen 80;
	listen [::]:80;
	root /var/www/domain-name.local;
	index index.php index.html index.htm;
	server_name domain-name.local www.domain-name.local;
	location / {
		proxy_redirect        off;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_pass_header Set-Cookie;
	location ~ /\.ht {
		deny all;
	location ~* \.(ico|docx|doc|xls|xlsx|rar|zip|jpg|jpeg|txt|xml|pdf|gif|png|css|js|html)$ {
		root   /var/www/domain-name.local;
	add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
	add_header Content-Security-Policy "block-all-mixed-content";
	add_header X-Frame-Options "SAMEORIGIN";
	add_header X-XSS-Protection "1; mode=block";
	add_header X-Content-Type-Options "nosniff";

Now create a symbolic link to this file.
ln -s /etc/nginx/sites-available/domain-name.local /etc/nginx/sites-enabled/domain-name.local
Edit / etc / nginx / sites-available / default.
nano /etc/nginx/sites-available/default
Remove the default_server.
And insert the redirection from www. and ip
server {
	listen 80;
	listen [::]:80;
	server_name www.domain-name.local;
	return 301 http://domain-name.local$request_uri;
server {
	listen 80;
	listen [::]:80;
	return 301 http://domain-name.local$request_uri;

We start Nginx.
service nginx start
Great, we can check how it works.
But before that, edit the host file C: \ Windows \ System32 \ drivers \ etc
Open the hosts file through a text editor, and insert at the very bottom: Replace ip and domain with your own. In the browser, we ’ll go to domain-name.local , and if you did everything according to this recipe, we should see a page with phpinfo. Well, the matter is left to the small. Set up PostgreSQL. Create a new PostgreSQL user. Log in to the DBMS and change the password for the new user. Now the new user needs to change the connection type, for this we need to find the pg_hba.conf file. We write domain-name.local www.domain-name.local

sudo -u postgres createuser --superuser test-user

sudo -u postgres psql

\password test-user

SHOW hba_file;

We leave the DBMS
and start editing /etc/postgresql/10/main/pg_hba.conf
nano /etc/postgresql/10/main/pg_hba.conf
We are looking for
# Database administrative login by Unix domain socket
Find the following: We will look like this: Restart PostgreSQL Now we will enter the DBMS through a new user Enter the password and go to the DBMS. Create a test database
# Database administrative login by Unix domain socket
local all postgres peer

# Database administrative login by Unix domain socket
local all postgres peer
local all test-user md5

service postgresql restart

psql test-user -h -d postgres


And immediately go into it.
\c test_db
Connect the pguint extension

And create a test pattern
	id uint4 PRIMARY KEY,
	title TEXT

Fill the table with test data
INSERT INTO test_tb(id, title) VALUES (1, 'Бла бла бла 1'), (2, 'Бла бла бла 2'), (3, 'Бла бла бла 3'), (4, 'Бла бла бла 4'), (5, 'Бла бла бла 5'), (6, 'Бла бла бла 6'), (7, 'Бла бла бла 7'), (8, 'Бла бла бла 8'), (9, 'Бла бла бла 9'), (10, 'Бла бла бла 10'), (2147483642, 'Бла бла бла 2147483642'), (2147483643, 'Бла бла бла 2147483643'), (2147483644, 'Бла бла бла 2147483644'), (2147483645, 'Бла бла бла 2147483645'), (2147483646, 'Бла бла бла 2147483646'), (2147483647, 'Бла бла бла 2147483647'), (2147483648, 'Бла бла бла 2147483648'), (2147483649, 'Бла бла бла 2147483649'), (2147483650, 'Бла бла бла 2147483650'), (2147483651, 'Бла бла бла 2147483651'), (2147483652, 'Бла бла бла 2147483652'), (4294967286, 'Бла бла бла 4294967286'), (4294967287, 'Бла бла бла 4294967287'), (4294967288, 'Бла бла бла 4294967288'), (4294967289, 'Бла бла бла 4294967289'), (4294967290, 'Бла бла бла 4294967290'), (4294967291, 'Бла бла бла 4294967291'), (4294967292, 'Бла бла бла 4294967292'), (4294967293, 'Бла бла бла 4294967293'), (4294967294, 'Бла бла бла 4294967294'), (4294967295, 'Бла бла бла 4294967295') RETURNING id, title;

Let's see the contents of the test_tb table
SELECT * FROM test_tb;

Now let's try to get this data out of php.
Close the connection to the DBMS
Open /var/www/domain-name.local/index.php
nano /var/www/domain-name.local/index.php
And bring it to the following form:
prepare('SELECT * FROM test_tb;');
	echo "
	echo "
"; ?>

Now let's check and make sure that it works.

Great, we have configured (Nginx + Apache) + PostgreSQL + PHP and it works properly.

Configure FTP access to the site

Install the FTP server.
apt-get install vsftpd
Stop vsftpd before configuration.
service vsftpd stop
Open etc / vsftpd.conf.
nano etc/vsftpd.conf
Install / replace / switch the following parameters:
  1. listen = YES
  2. listen_ipv6 = NO
  3. local_enable = YES
  4. write_enable = YES
  5. chroot_local_user = YES
  6. pam_service_name = ftp

Создадим нового пользователя для доступа через FTP
useradd -d /home/domain-name -s /sbin/nologin domain-name
Установим для него пароль
passwd domain-name
Создадим домашнюю директорию пользователя
mkdir -p /home/domain-name
Установим для нее права
chmod a-w /home/domain-name
Создадим группу для пользователя
groupadd ftps
Добавим пользователя в группу
usermod -G ftps domain-name
Поменяем владельца каталога
chown -R domain-name:ftps /home/domain-name
Создадим папку нашего сайта
mkdir /home/domain-name/domain-name.local
Сменим у нее владельца
chown -R domain-name:ftps /home/domain-name/domain-name.local
Смонтируем наши каталоги, откроем файл /etc/fstab
nano /etc/fstab
В самый низ вставим
/var/www/domain-name.local /home/domain-name/domain-name.local none bind 0 0
Добавим владельца /var/www/domain-name.local
chown www-data:domain-name /var/www/domain-name.local/ -R
Назначим права
find /var/www/domain-name.local -type d -exec chmod 775 {} \;
find /var/www/domain-name.local -type f -exec chmod 664 {} \;

И запустим vsftpd
service vsftpd start
Проверим, я буду использовать FileZilla.

Все хорошо, попробуем создать каталог.

Настроим защищенное FTP соединение.
Остановим vsftpd
service vsftpd stop
Сгенерируем сертификат
openssl req -x509 -nodes -days 720 -newkey rsa:2048 -keyout /etc/ssl/private/vsftpd.key -out /etc/ssl/private/vsftpd.pem
Here we introduce everything that your soul wants
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg server FQDN or YOUR name) []:
Email Address []:

Open etc / vsftpd.conf
nano etc/vsftpd.conf
Install / add the following parameters:
  1. ssl_enable = YES
  2. ssl_tlsv1 = YES
  3. ssl_sslv2 = NO
  4. ssl_sslv3 = NO
  5. rsa_cert_file = / etc / ssl / private / vsftpd.pem
  6. rsa_private_key_file = / etc / ssl / private / vsftpd.key
  7. allow_anon_ssl = NO
  8. force_local_data_ssl = YES
  9. force_local_logins_ssl = YES
  10. ssl_ciphers = HIGH

Save and run vsftpd
service vsftpd start
Let's try

ur, everything works, you can start developing a web application.

PS This recipe does not claim to be the only correct and ideal. If you missed something or you have suggestions for supplementing this recipe, welcome to comments, I will accept any criticism. As my skills grow, this recipe will be supplemented and modified.

Also popular now: