I’ll show you how you can deploy your Symfony demo or production stage application in your VPS system. I’m gonna use Digital Ocean VPS and CentOS 7. This is not tutorial, this is close to my actual project deployment.

Change your timezone

If you didn’t do, you cannot read your logs. For example, you are living in Europe, but server time zone is America, you can see all log times in America times.

You can check this link for your time zone.

timedatectl set-timezone $YOUR_TIMEZONE

Update all system

yum update -y

Change SELinux mode Enforcing to Permissive

You have to change SELINUX=enforcing to permissive

[root@webserver ~]# vi /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

Build the file system

[root@webserver ~]# mkdir -p /home/$USER_NAME/www
[root@webserver ~]# mkdir -p /home/$USER_NAME/log/$PROJECT_NAME
[root@webserver ~]# chown nginx:nginx -R /home/$USER_NAME/www /home/$USER_NAME/log

Install Nginx

Nginx is not available in default CentOS repository. That’s why we have to enable epel-release.

[root@webserver ~]# yum install -y epel-release

Now, we can download it

[root@webserver ~]# yum install -y nginx

If we wanted to reboot the server, Nginx cannot start after the boot. Therefore, we have to run this two lines

[root@webserver ~]# systemctl enable nginx.service

and

[root@webserver ~]# systemctl start nginx.service

Install MySQL (or MariaDB)

Actualy, you can use MySQL either, but in default CentOS’s repository you cannot find it. They have only MariaDB, but I’ll show you how you can install MySQL, too.

First of all, I’ll show you installation MariaDB

[root@webserver ~]# yum install -y mariadb mariadb-server

Than we have to do this again for MariaDB.

[root@webserver ~]# systemctl enable mariadb.service

[root@webserver ~]# systemctl start mariadb.service

RDBMS Security

In default, all first setup MySQL/MariaDB, we run setup script. This script will ask you about your root password or allow anonymous users…

[root@webserver ~]# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure its, we'll need to current
password for the root user. if you've just installed MariaDB, and
you haven't set the root password yet, the password will blank,
you should just press enter here.

Enter current password for root (enter for none):

OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the
MariaDB
Root user without the proper authorization.

Set root password? [Y/n] y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!

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

Remove anonymous users? [Y/n] y
 ... Success!

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? [Y/n] y

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

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

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

Reload privilege tables no? [Y/n] y
 ... Success!

Cleaning up...

All done! If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

Instal PHP 7.1

You must have wget if you want to use this line. If you don’t have, you can download with this line

[root@webserver ~]# yum install -y wget
[root@webserver ~]# wget http://rpms.remirepo.net/enterprise/remi-release-7.rpm
[root@webserver ~]# rpm -Uvh remi-release-7.rpm
[root@webserver ~]# yum install -y yum-utils
[root@webserver ~]# yum-config-manager --enable remi-php71

You will see like this output

[root@webserver ~]# yum-config-manager --enable remi-php71
Loaded plugins: fastestmirror
========================= repo: remi-php71 ==========================
[remi-php71]
async = True
bandwidth = 0
base_persistdir = /var/lib/yum/repos/x86_64/7
baseurl =
cache = 0
cachedir = /var/cache/yum/x86_64/7/remi-php71
check_config_file_age = True
compare_providers_priority = 80
cost = 1000
deltarpm_metadata_percentage = 100
deltarpm_percentage =
enabled = 1
enablegroups = True
exclude =
failovermethod = priority
ftp_disable_epsv = False
gpgcadir = /var/lib/yum/repos/x86_64/7/remi-php71/gpgcadir
gpgcakey =
gpgcheck = True
gpgdir = /var/lib/yum/repos/x86_64/7/remi-php71/gpgdir
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi
hdrdir = /var/cache/yum/x86_64/7/remi-php71/headers
http_caching = all
includepkgs =
ip_resolve =
keepalive = True
keepcache = False
mddownloadpolicy = sqlite
mdpolicy = group:small
mediaid =
metadata_expire = 21600
metadata_expire_filter = read-only:present
metalink =
minrate = 0
mirrorlist = http://rpms.remirepo.net/enterprise/7/php71/mirror
mirrorlist_expire = 86400
name = Remi's PHP 7.1 RPM repository for Enterprise Linux 7 - x86_64
old_base_cache_dir =
password =
persistdir = /var/lib/yum/repos/x86_64/7/remi-php71
pkgdir = /var/cache/yum/x86_64/7/remi-php71/packages
proxy = False
proxy_dict =
proxy_password =
proxy_username =
repo_gpgcheck = False
retries = 10
skip_if_unavailable = False
ssl_check_cert_permissions = True
sslcacert =
sslclientcert =
sslclientkey =
sslverify = True
throttle = 0
timeout = 30.0
ui_id = remi-php71
ui_repoid_vars = releasever,
   basearch
username =

First PHPs are core PHP packages, you have to download it.

[root@webserver ~]# yum install -y php php-fpm php-common

Than we have to start it, because Nginx can return an error

[root@webserver ~]# systemctl enable php-fpm.service

[root@webserver ~]# systemctl start php-fpm.service

And also you can find your php extensions in this chart

[root@webserver ~]# vi /etc/nginx/conf.d/default.conf

You will see blank conf file, copy this conf to the file

#/etc/nginx/conf.d/default.conf

server {
    # server_name example.com www.example.com;

    # Symfony 3.x default web/app.php path
    root /home/$USER_NAME/www/$PROJECT_NAME/web;

    location / {
        # try to serve file directly, fallback to index.php
        try_files $uri /app.php$is_args$args;
    }

    location ~ ^/app\.php(/|$) {
        fastcgi_pass unix:/var/run/php7-1-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        # When you are using symlinks to link the document root to the
        # current version of your application, you should pass the real
        # application path instead of the path to the symlink to PHP
        # FPM.
        # Otherwise, PHP's OPcache may not properly detect changes to
        # your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
        # for more information).
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        # Prevents URIs that include the front controller. This will 404:
        # http://domain.tld/app.php/some-path
        # Remove the internal directive to allow URIs like this
        internal;
    }

    # return 404 for all other php files not matching the front controller
    # this prevents access to other php files you don't want to be accessible.
    location ~ \.php$ {
        return 404;
    }

    error_log /home/$USER_NAME/log/$PROJECT_NAME/error.log;
    access_log /home/$USER_NAME/log/$PROJECT_NAME/access.log;
}

If you run it run now, you will get an error. Because, we did not create an directory for log, web assets… That’s why don’t run it!

[root@webserver ~]# systemctl restart nginx.service

Now, we have a look php-fpm configuration file.

[root@webserver ~]# vi /etc/php-fpm.d/www.conf

Replace these lines:

user = apache to user = nginx

group = apache to user = nginx

;listen.owner = nobody to liste.owner = nginx

;listen.group = nobody to liste.group = nginx

Important: You have to be careful about semicolons!

Additionally, we won’t use listen = 127.0.0.1:9000, that’s why, we have to edit it.

listen = /var/run/php7-1-fpm.sock

[root@webserver ~]# systemctl restart php-fpm.service

Time is Deploy time - YAY

You can use git or not, but I prefer git.

Use git

I’ll show you can you use git for deploying files, but we have to download git packages [root@webserver ~]# yum install -y git

Than, I’ll clone all repository and do this in tmp folder. Because after the deploy we won’t use it again.

[root@webserver ~]# cd /tmp
[root@webserver tmp]# git clone https://gitsite.example/reponame/project.git
[root@webserver tmp]# mv project/ /home/$USER_NAME/www/$PROJECT_NAME
[root@webserver tmp]# cd
[root@webserver ~]# chown nginx:nginx -R /home/$USER_NAME/www/$PROJECT_NAME
[root@webserver ~]# chmod 755 -R /home/$USER_NAME/www/$PROJECT_NAME/var/cache /home/$USER_NAME/www/$PROJECT_NAME/var/logs
[root@webserver ~]# rm -rf /home/$USER_NAME/www/$PROJECT_NAME/var/cache/* /home/$USER_NAME/www/$PROJECT_NAME/var/logs/*

Install all Composer stuffs

15f0a0a40484f0a224034a9ef560fa4e composer.bash

Use this line for downloading main composer.phar file.

Than you can run it.

Wait, you forgot something.

You have to change your $SYMFONY_ENV dev to prod.

It is too important,

If you didn’t do this, you will get an composer error.

[root@webserver ~]# export SYMFONY_ENV=prod
[root@webserver ~]# cd /home/$USER_NAME/www/$PROJECT_NAME
[root@webserver ~]# /usr/local/bin/composer install --no-dev -o --ansi
[root@webserver ~]# chown nginx:nginx -R /home/$USER_NAME/www/$PROJECT_NAME

Download your php extensions right now

I think, this is more efficiently, if you don’t have idea about your php requirements.

For example, I have to install

I ran it

[root@webserver ~]# yum install -y php-pdo php-pdo_mysql php-xml php-zip php-mbstring

Than run this command

[root@webserver ~]# cd /home/$USER_NAME/www/$PROJECT_NAME [root@webserver ~]# php bin/symfony_requirements

Symfony Requirements Checker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

> PHP is using the following php.ini file:
  /etc/php.ini

> Checking Symfony requirements:
  ...........................WWW......


 [OK]                                         
 Your system is ready to run Symfony projects


Optional recommendations to improve your setup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 * posix_isatty() should be available
   > Install and enable the php_posix extension (used to colorize the
   > CLI output).

 * intl extension should be available
   > Install and enable the intl extension (used for validators).

 * a PHP accelerator should be installed
   > Install and/or enable a PHP accelerator (highly recommended).


Note  The command console could use a different php.ini file
~~~~  than the one used with your web server. To be on the
      safe side, please check the requirements from your web
      server using the web/config.php script.

Lastly, I download these extension

[root@webserver ~]# yum install -y php-posix php-intl php-opcache

[root@ln11 housing]# php bin/symfony_requirements

Symfony Requirements Checker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

> PHP is using the following php.ini file:
  /etc/php.ini

> Checking Symfony requirements:
  ...............................W........


 [OK]                                         
 Your system is ready to run Symfony projects


Optional recommendations to improve your setup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 * intl ICU version installed on your system is outdated (50.1.2) and
   does not match the ICU data bundled with Symfony (60.1)
   > To get the latest internationalization data upgrade the ICU
   > system package and the intl PHP extension.


Note  The command console could use a different php.ini file
~~~~  than the one used with your web server. To be on the
      safe side, please check the requirements from your web
      server using the web/config.php script.

ICU 60.1 is not necessarily, but you can find for update in online. Default repository has libicu 50.1.2-15 (12/16/2017)

Database stuffs

In this chapter little bit important because your second system it is…

cd /home/$USER_NAME/www/$PROJECT_NAME
export SYMFONY_ENV=prod
php bin/console doctrine:database:create
php bin/console doctrine:schema:create

Check your ip address / domain in your browser.

If you get an error, let me know. Maybe I can help you.

Errors

Nginx open(), Permission Error

Check your SELinux status with

[root@webserver ~]# getenforce

If return Enforcing you have to run it

[root@webserver ~]# setenforce 0

If you run it again you will get Permisive, and you can run it.

Already geting Nginx default page

If you look /etc/nginx/nginx.conf file you can see server{}, just this block you can comment it. like

[root@webserver ~]# vi /etc/nginx/nginx.conf
...
#server {
#    ...
#}
...

White page

[root@webserver ~]# cat /home/$USER_NAME/log/$PROJECT_NAME/error.log

2017/12/16 13:05:14 [error] 1909#0: *1 FastCGI sent in stderr: "PHP message:
  PHP Fatal error:  Uncaught UnexpectedValueException: The stream or file
  "/home/berkhan/www/housing/var/logs/prod.log" could not be opened: failed
  to open stream: Permission denied in
  /home/berkhan/www/housing/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php:107

Stack trace:
  ...

Solution is:

[root@webserver ~]# chown nginx:nginx -R /home/$USER_NAME/www .

Final

If you have any question, let me know. You can use disqus (I prefer).