Laravel Deployment – Setup environment
Setup dependencies
Install NGINX through apt:
$ apt install nginx
Install php dependencies
$ apt install php7.2 php7.2-curl php7.2-common php7.2-cli php7.2-mysql php7.2-mbstring php7.2-fpm php7.2-xml php7.2-zip php7.2-bcmath
Update php.ini properties:
$ nano /etc/php/7.2/fpm/php.ini
#edit according to your setup
memory_limit = 1024M
Setup MariaDB
We need to install mariaDB server, create a dedicated database and user
$ apt install mariadb-server mariadb-client
Secure the setup:
$ 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 it, we'll need the current
password for the root user. If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.
Enter current password for root (enter for none):
Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.
Set root password? [Y/n] Y
[...]
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 the installation
go a bit smoother. You should remove them before moving into a
production environment.
Remove anonymous users? [Y/n] 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? [Y/n] Y
... Success!
By default, MariaDB 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? [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 now? [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!
Use mysql cli to create database schema and user:
$ mysql -p -u root
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 49
Server version: 10.1.41-MariaDB-0ubuntu0.18.04.1 Ubuntu 18.04
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
Create databse:
MariaDB [(none)]> create database <database_name>;
Query OK, 1 row affected (0.00 sec)
Create user and grant access to database:
MariaDB [(none)]> CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password';
Grant privileges:
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'localhost';
MariaDB [(none)]> FLUSH PRIVILEGES;
Setup composer
$ apt install composer
Laravel Deployment
Our Laravel app will be cloned from source control:
$ cd /path-to-app && git clone <app_git_repo>
Then create the .env file: nano .env
APP_NAME=""
APP_ENV=production
APP_KEY=base64:......
APP_DEBUG=true
APP_URL=https://laravel.app.domain
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_name
DB_USERNAME=db_username
DB_PASSWORD=db_password
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=database
SESSION_DRIVER=file
SESSION_LIFETIME=120
REDIS_HOST=
REDIS_PASSWORD=
REDIS_PORT=
MAIL_DRIVER=
MAIL_HOST=
MAIL_PORT=
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=
MAIL_FROM_ADDRESS=
MAIL_FROM_NAME=""
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
Install composer dependencies:
# from official documentation
# Autoloader Optimization
When deploying to production, make sure that you are optimizing Composer's class autoloader map so Composer can quickly find the proper file to load for a given class:
composer install --optimize-autoloader --no-dev
If your run into the following error: SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes, update AppServiceProvider file:
use Illuminate\Support\Facades\Schema;
public function boot()
{
...
Schema::defaultStringLength(191);
}
Setup Queue connections
$ php artisan queue:table
$ php artisan migrate
Setup supervisor:
$ apt install supervisor
Configure supervisor for laravel queue:
$ nano /etc/supervisor/conf.d/queue.conf
[program:queue]
process_name=%(program_name)s_%(process_num)02d
command=php /path-to-app/artisan queue:work --tries=3 --daemon --queue=notifications -vvv
user=www-data
autostart=true
autorestart=true
numprocs=3
redirect_stderr=true
stdout_logfile=/path-to-app/storage/logs/queue.log
Reload supervisor:
$ supervisorctl reread
$ supervisorctl update
$ supervisorctl restart all
Setup directory permissions: follow this tutorial
Setup Nginx
Install Let’s Encrypt Certificate
$ add-apt-repository ppa:certbot/certbot
$ apt-get update
$ apt-get install python-certbot-nginx
Obtain the certificate:
$ certbot --nginx -d example.com -d www.example.com
Force redirect to HTTPS:
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel)
Edit nginx site configuration:
server {
listen 80 ;
listen [::]:80 ;
root /path-to-laravel-app/public;
# Add index.php to the list if you are using PHP
server_name laravel.app.name; # managed by Certbot
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/laravel.app.name/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/laravel.app.name/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}