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
sudo apt-get update
sudo apt-get upgrade
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
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
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 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
Check your site by http://localhost and it should show you either "Laravel" or your own app's homepage.
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;
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;
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
- 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
- Eg. ~43904 / 1024 -> ~43MB per one process
- 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