Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save jtejido/54e0aac99b211835c112a19b20dd30d7 to your computer and use it in GitHub Desktop.

Select an option

Save jtejido/54e0aac99b211835c112a19b20dd30d7 to your computer and use it in GitHub Desktop.
LEMP (Linux, Nginx, MySQL, PHP), Redis, NodeJS, Laravel Setup

These are the steps that I follow whenever I setup a new dev machine from scratch. This is intended to be for personal use, whenever I stumble upon memory-loss, but I figured I'd share it.

At the time of writing, I've just finished a fresh install of Debian Stretch (9.2.1) on my machine.

This will setup the following on your machine:

Linux/Nginx/MySQL/PHP (LEMP), Composer, Redis, NodeJS, Laravel

Update all pre-installed packages

sudo apt-get update
sudo apt-get upgrade

Install PHP and dependencies

sudo apt-get install apt-transport-https lsb-release ca-certificates wget
sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
sudo sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" >> /etc/apt/sources.list.d/php.list'
sudo apt-get update
sudo apt-get install -y zip unzip
sudo apt-get install -y php7.1 php7.1-fpm php7.1-mysql php7.1-zip php7.1-gd php7.1-dev
sudo apt-get install mcrypt php7.1-mcrypt
sudo apt-get install -y php7.1-mbstring php7.1-xml --force-yes

Some Optional ones:

sudo apt-get install -y php7.1-curl php7.1-json imagick php-imagick php7.1-bz2 php7.1-soap php7.1-zip php7.1-sqlite3

Turn off PHP path:

sudo nano /etc/php/7.1/fpm/php.ini

And uncomment and fix cgi.fix_pathinfo to

cgi.fix_pathinfo=0

Restart PHP 7.1 FPM

sudo service php7.1-fpm restart

Install Nginx and configure

sudo apt-get install nginx

Run the following in terminal

sudo mkdir -p /var/www/html/dev

Next, we are going to modify the nginx's default configuration file: /etc/nginx/sites-available/default. But before that, just make a backup of the file:

sudo mkdir ~/nginx_backup
sudo cp /etc/nginx/sites-available/default ~/nginx_backup/default

Next modify default from this

server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        root /usr/share/nginx/html;

        server_name localhost;

        location / {
                try_files $uri $uri/ =404;
        }
}

to this:

server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        root /var/www/html/dev/<YOUR LARAVEL APP'S NAME>/public>;
        index index.php index.html index.htm;

        # Make site accessible from http://localhost/
        server_name localhost;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ /index.php?$query_string;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
        }
        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
        }
}

Restart nginx

sudo service nginx restart

Install MariaDB

Configure MariaDB

sudo apt-get install -y mariadb-server mariadb-client
sudo mysql_secure_installation

Create your App's DB:

sudo mysql -u root -p
create database <APP'S DATABASE NAME>;

As a rule of thumb, we would create a user (not root) to be restricted to such DB only.

grant all on <APP'S DATABASE NAME>.* to 'user'@'localhost' identified by 'password';
flush privileges;
exit;
sudo service mysql restart

Install Composer, NodeJS & Bower/Gulp, Redis, and Laravel

Install dependencies

sudo apt-get install -y build-essential curl git
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -

** nodejs version will depend on your app. I've come across apps with libraries not compatible with nodejs >= v7. So feel free to change (at the time of writing, nodejs is v9)

Install Composer

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

Test by composer command to see if it was installed correctly.

Install NodeJS

sudo apt-get install nodejs

Test by node -v or npm -v command to see if it was installed correctly.

Globally Install Bower

sudo npm install -g bower

Globally Install Gulp

sudo npm install -g gulp

Install Redis

cd ~
sudo wget http://download.redis.io/releases/redis-stable.tar.gz
sudo tar xzf redis-stable.tar.gz
cd redis-stable
sudo make && taskset -c 1 sudo make test

If test is fine, proceed...

sudo make install
cd utils && sudo ./install_server.sh

To test, type redis-server -v.

Configure PHP for Redis:

cd ~
sudo git clone https://github.com/phpredis/phpredis.git
cd phpredis
sudo phpize && sudo ./configure && sudo make && sudo make install
echo "extension=redis.so" > /etc/php/7.1/mods-available/redis.ini
ln -sf /etc/php/7.1/mods-available/redis.ini /etc/php/7.1/fpm/conf.d/20-redis.ini
ln -sf /etc/php/7.1/mods-available/redis.ini /etc/php/7.1/cli/conf.d/20-redis.ini
service php7.1-fpm restart

To test, type php --ri redis.

** If etc/php/7.1/mods-available/redis.ini is not found, type touch etc/php/7.1/mods-available/redis.ini

Create your Laravel App:

sudo composer create-project laravel/laravel /var/www/html/dev/<YOUR LARAVEL APP'S NAME>

or Clone your App:

sudo git clone <LARAVEL APP REPO HOST> /var/www/html/dev/<YOUR LARAVEL APP'S NAME>

Setting the proper Permissions for the Laravel folders.

sudo chown -R :www-data /var/www/html/dev/<YOUR LARAVEL APP'S NAME>
sudo chmod -R 775 /var/www/html/dev/<YOUR LARAVEL APP'S NAME>/storage

Setup Everything inside your app (some commands here may never be needed in your own app, nevertheless, they're installed)

cd /var/www/html/dev/<YOUR LARAVEL APP'S NAME>
cp .env.example .env
nano .env <at this point, make the necessary changes in the environment file>
sudo composer install
sudo php artisan key:generate
sudo bower install --allow-root
sudo npm install
sudo gulp watch
sudo php artisan migrate
sudo php artisan db:seed

Finish

Check your site by http://localhost and it should show you either "Laravel" or your own app's homepage.

Optional stuff for a more Optimized setup

Modify /etc/nginx/nginx.conf

Configure nginx workers:

worker_processes auto;
events {
        use epoll;
        worker_connections 1024; # ~ RAM / 2
        multi_accept on;
}

G'zip those stuff

gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types    text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

Modify /etc/nginx/sites-available/default

Deny access to configuration files

client_max_body_size 100M;
client_body_buffer_size 128k;

location ~ \.(neon|ini|log|yml|env|sql)$ {
    deny all;
}

Cache Static Files For As Long As Possible

location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$
{
	access_log off;
	log_not_found off;
	expires max;
}

Turn off access logs for common files

location = /robots.txt  { access_log off; log_not_found off; }
location = /humans.txt  { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }

Security Settings For Better Privacy Deny Hidden Files

location ~ /\. {
	deny all;
	access_log off;
	log_not_found off;
}

Return 403 Forbidden For readme.(txt|html) or license.(txt|html)

if ($request_uri ~* "^.+(readme|license)\.(txt|html)$") {
        return 403;
}

error_page 500 502 503 504 /custom_50x.html;

Modify PHP Pool

Create new pool

sudo nano /etc/php/7.1/fpm/pool.d/new-website.tld.conf

Edit the pool

[new-website]
user = www-data
group = www-data
listen = /run/php/php7.1-fpm-new-website.sock
listen.owner = www-data
listen.group = www-data
php_admin_value[disable_functions] = exec,passthru,shell_exec,system
php_admin_flag[allow_url_fopen] = off
pm = dynamic
pm.max_children = 5 # The hard-limit total number of processes allowed
pm.start_servers = 2 # When nginx starts, have this many processes waiting for requests
pm.min_spare_servers = 1 # Number spare processes nginx will create
pm.max_spare_servers = 3 # Number spare processes attempted to create
pm.max_requests = 500
chdir = /

Configure pm.max_children

  1. Find how much RAM FPM consumes: ps -A -o pid,rss,command | grep php-fpm -> second row in bytes Reference: https://overloaded.io/finding-process-memory-usage-linux
  2. Eg. ~43904 / 1024 -> ~43MB per one process
  3. Calculation: If server has 2GB RAM, let's say PHP can consume 1GB (with some buffer, otherwise we can use 1.5GB): 1024MB / 43MB -> ~30MB -> pm.max_childern = 30

Configuring pm.start_servers, pm.min_spare_servers, pm.max_spare_servers

pm.start_servers == number of CPUs
pm.min_spare_servers = pm.start_servers / 2 
pm.max_spare_servers = pm.start_servers * 3

Restart PHP-FPM AND Nginx

sudo service php7.1-fpm restart
sudo service nginx restart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment