- Create ssh pair for login on a fresh DO droplet.
- ssh into the server
apt-get update
It updates server's knowledgeable packages. Not technically updates any software.
apt-get install -y git tmux vim curl wget zip unzip htop
-y flag to say yes to all prompts- Adding additional repositories so that we can get latest version of the softwares from this respective repositories of them:
- For NGINX:
add-apt-repository -y ppa:nginx/development
(Development branch of nginx repo is actually what they consider stable because its stable + bug-fixes, its not exactly the dev branch) - For PHP:
add-apt-repository -y ppa:ondrej/php
- Now after adding the repos we need to tell the server to suck in & update its cache of available packages:
apt-get update
apt-get install -y nginx
curl localhost
, also we can type in the IP in the browser & confirm the nginx default landing page shows upapt-get install -y php7.1-fpm php7.1-cli php7.1-mcrypt php7.1-gd php7.1-mysql php7.1-pgsql php7.1-imap php7.1-memcached php7.1-mbstring php7.1-xml php7.1-curl php7.1-bcmath php7.1-sqlite3 php7.1-xdebug
ps aux | grep php
To check the php fpm process is runningphp -v
to check we got the latest PHP installed- Install Composer:
php -r "readfile('http://getcomposer.org/installer');" | sudo php -- --install-dir=/usr/bin/ --filename=composer
which composer
to check it was installed in the given directory.composer -v
to check composer is working
cd /var/www/html/
vim index.php
Just dump phpinfo() in that file for time being- Hit IP/index.php in the browser. It will download the file at this moment because PHP isn't working
cd /etc/nginx/
sites-available
has all the configurations.sites-enabled
have the symlinks to the configs in thesites-available
which we want to be enabled.sudo vim sites-enabled/default
- Configure the server block in that default file. To get a basic understanding of the default file watch this part of the video again.
sudo nginx -t
To test the nginx config and show errors if anysudo service nginx configtest
will ONLY tell you if things are ok or not. So the previous one is bettersudo service nginx reload
- Refresh the IP in the browser & now you should see the output of the phpinfo() from our index.php file
- Done!
cd /var/www
composer create-project laravel/laravel:dev-develop myapp
dev-develop will pull in the latest under development unreleased laravel versionsudo vim /etc/nginx/sites-available/default
- Change the root to the new laravel app's public directory path like in this case:
root /var/www/myapp/public;
nginx -t
sudo service nginx reload
- cd into myapp/public directory
- Refresh browser and you will see the permission denied to write into the log file.
- If we do
ps aux | grep php
we see that the "php-fpm" which is running our web requests, which is running our php is owned by user & groupwww-data
. - That means this processes of php are running as user
www-data
- But if you run
ll
you will see that all the files in our app/public directory (in which we currently are) are owned by userroot
- So the
www-data
cannot write into the storage directory & the bootstrap/cache directory as they are owned by user & grouproot
which in a laravel app should be writable by thewww-data
- To solve this do the following:
cd ..
so we are out of the public directory- Then run
sudo chown -R www-data: storage/ bootstrap/
- Solved!
- But now we will probably be pushing our code as some user so the permissions will again override for the storage & bootstrap directory
- What Forge does is it uses PHP as user forge and uploads/pushes the code as user forge as well so the permissions remain at level
- So let's do that!
-
cd ~
-
adduser forge
-
Enter the password for the user forge
-
ll /home/
-
A directory called
forge
have been created in the home directory for the user forge we just created -
cd ~
-
cd /var/www
-
mv myapp/ /home/forge/
We moved this application into the user forge's home directory -
cd /home/forge/
-
ll
-
chown -R forge: myapp/
-
So now our web root is
/home/forge/myapp/public
-
So lets edit the nginx config to replace the above path as the root
-
vim /etc/nginx/sites-available/default
-
Update the root directive
-
WAIT! PHP & NGINX ARE RUNNING AS
www-data
BUT ALL THE FILES & DIRECTORIES IN OUR myapp/ directory ARE OWNED BY USERforge
. So....again the same problem, Laravel could not write to the storage directory and so in the browser we again get the 'permission denied' error. -
So instead to change to files get owned by
www-data
it makes sense to change PHP to change what user PHP would run as. -
cd /etc/php/7.1/fpm/
-
cd pool.d/
-
vim www.conf
This file determines how PHP-fpm runs & how it manages the processes like how many processes it spins up to handle requests. -
In the file there will be: user = www-data group = www-data
-
Change both to forge
-
:wq
-
sudo service php7.1-fpm reload
-
ps aux | grep php
to check the php-fpm is now running as user & groupforge
-
So now the permissions line up as both our code & PHP are running as user & group
forge
. -
Refresh the browser & you will see the laravel landing page.
-
Good Job Chris!
usermod -aG sudo forge
- We can check it worked by running
groups forge
- Now everytime we push our code and since we will be pushing code from the user forge we need to sudo php fpm reload. But that will everytime ask for the user forge's password.
- So we want to make sure that for only that command we do not have to enter the password
visudo -f /etc/sudoers.d/php-fpm
- Add the following in it:
forge ALL=NOPASSWD: /usr/sbin/service php7.1-fpm reload
- This means "user forge from all/any host can run sudo commands with No password but only the following commands" that is the commands after the colon.
- Let's test this!
- Exit to clear the cached password & login back
sudo su forge
- Run
sudo service php7.1-fpm reload
- And voila! It didn't asked for the password. So now we have 1 less barrier in our goal of automated deployment.
We reload php-fpm mainly to clear the opcache so our new code is reflected. Even if we not have opcache it's better to reload php-fpm as some php process might be stuck in the old code might be, not sure! so it's a good practice & doesn't hurts too
sudo apt-get install -y mysql-server
- Enter the password for the new
root
user - You can automate this without prompts. Chris has videos on how to do that on serversforhackers.com
- Check by running
sudo service mysql status
mysql_secure_installation
- Remove anonymous users
- Disallow root logins remotely
- Remove test databases
- Reload privileges
- login to mysql by:
mysql -u root -p
create database myapp charset utf8mb4
create user myuser@localhost identified by 'secret'
grant all privileges on myapp.* to myuser@localhost;
flush privileges;
to burst the privileges cache- exit;
- Update the .env file in the laravel app and we are done!