Skip to content

Instantly share code, notes, and snippets.

@introwit
Last active October 21, 2022 08:48
Show Gist options
  • Save introwit/857d8ddce907713623d678cfb5986f93 to your computer and use it in GitHub Desktop.
Save introwit/857d8ddce907713623d678cfb5986f93 to your computer and use it in GitHub Desktop.
Personally written version of Chris Fidao's video on setting up a Forge like server

Let's Log in!

  • 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.

Alright, let's start installing our stuff boys!

  • 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 up
  • apt-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 running
  • php -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

Let's get NGINX configured to use PHP

  • 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 the sites-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 any
  • sudo service nginx configtest will ONLY tell you if things are ok or not. So the previous one is better
  • sudo service nginx reload
  • Refresh the IP in the browser & now you should see the output of the phpinfo() from our index.php file
  • Done!

Making a Laravel app

  • cd /var/www
  • composer create-project laravel/laravel:dev-develop myapp dev-develop will pull in the latest under development unreleased laravel version
  • sudo 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 & group www-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 user root
  • So the www-data cannot write into the storage directory & the bootstrap/cache directory as they are owned by user & group root which in a laravel app should be writable by the www-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!

Wait Bro!

  • 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!

Solving the above problem (wow what a heading! I know, thanks.)

  • 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 USER forge. 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 & group forge

  • 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!

Allowing user forge to use sudo

  • 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

Here comes the MySQL!

  • 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!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment