While working on my side-projects (UnMarkDocs and Webslides), I had to get data from GitHub Gists. Here are the three ways to do it:
1. The JS way
This is the official way to do it, the one that is mentioned in the GitHub Documentation. It consists on adding .js
and including it in an script tag:
<!-- If we have the following Gist:
https://gist.github.com/m1guelpf/53e1780a5a68fe9281cfbbc9820d381f -->
<script src="https://gist.github.com/m1guelpf/53e1780a5a68fe9281cfbbc9820d381f.js"></script>
2. The JSON way
Adding .json
to the end of the Gist URL returns something like this:
{
"description": "Personally written version of Chris Fidao's video on setting up a Forge like server: https://youtu.be/VQNrsMYCOFg ",
"public": false,
"created_at": "2017-07-13T21:01:10+02:00",
"files": [
"forgeLikeServerSetup.md"
],
"owner": "m1guelpf",
"div": "<div id=\"gist61186747\" class=\"gist\">\n <div class=\"gist-file\">\n <div class=\"gist-data\">\n <div class=\"js-gist-file-update-container js-task-list-container file-box\">\n <div id=\"file-forgelikeserversetup-md\" class=\"file\">\n \n <div id=\"readme\" class=\"readme blob instapaper_body\">\n <article class=\"markdown-body entry-content\" itemprop=\"text\"><h3><a href=\"#lets-log-in\" aria-hidden=\"true\" class=\"anchor\" id=\"user-content-lets-log-in\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Let's Log in!</h3>\n<ul>\n<li>Create ssh pair for login on a fresh DO droplet.</li>\n<li>ssh into the server</li>\n<li><code>apt-get update</code> It updates server's knowledgeable packages. Not technically updates any software.</li>\n</ul>\n<h3><a href=\"#alright-lets-start-installing-our-stuff-boys\" aria-hidden=\"true\" class=\"anchor\" id=\"user-content-alright-lets-start-installing-our-stuff-boys\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Alright, let's start installing our stuff boys!</h3>\n<ul>\n<li><code>apt-get install -y git tmux vim curl wget zip unzip htop</code> -y flag to say yes to all prompts</li>\n<li>Adding additional repositories so that we can get latest version of the softwares from this respective repositories of them:</li>\n<li>For NGINX: <code>add-apt-repository -y ppa:nginx/development</code> (Development branch of nginx repo is actually what they consider stable because its stable + bug-fixes, its not exactly the dev branch)</li>\n<li>For PHP: <code>add-apt-repository -y ppa:ondrej/php</code></li>\n<li>Now after adding the repos we need to tell the server to suck in & update its cache of available packages: <code>apt-get update</code></li>\n<li><code>apt-get install -y nginx</code></li>\n<li><code>curl localhost</code> , also we can type in the IP in the browser & confirm the nginx default landing page shows up</li>\n<li><code>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</code></li>\n<li><code>ps aux | grep php</code> To check the php fpm process is running</li>\n<li><code>php -v</code> to check we got the latest PHP installed</li>\n<li>Install Composer: <code>php -r \"readfile('http://getcomposer.org/installer');\" | sudo php -- --install-dir=/usr/bin/ --filename=composer</code></li>\n<li><code>which composer</code> to check it was installed in the given directory.</li>\n<li><code>composer -v</code> to check composer is working</li>\n</ul>\n<h3><a href=\"#lets-get-nginx-configured-to-use-php\" aria-hidden=\"true\" class=\"anchor\" id=\"user-content-lets-get-nginx-configured-to-use-php\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Let's get NGINX configured to use PHP</h3>\n<ul>\n<li><code>cd /var/www/html/</code></li>\n<li><code>vim index.php</code> Just dump phpinfo() in that file for time being</li>\n<li>Hit IP/index.php in the browser. It will download the file at this moment because PHP isn't working</li>\n<li><code>cd /etc/nginx/</code></li>\n<li><code>sites-available</code> has all the configurations. <code>sites-enabled</code> have the symlinks to the configs in the <code>sites-available</code> which we want to be enabled.</li>\n<li><code>sudo vim sites-enabled/default</code></li>\n<li>Configure the server block in that default file. To get a basic understanding of the default file watch <a href=\"https://youtu.be/VQNrsMYCOFg?t=13m43s\" rel=\"nofollow\">this part of the video</a> again.</li>\n<li><code>sudo nginx -t</code> To test the nginx config and show errors if any</li>\n<li><code>sudo service nginx configtest</code> will ONLY tell you if things are ok or not. So the previous one is better</li>\n<li><code>sudo service nginx reload</code></li>\n<li>Refresh the IP in the browser & now you should see the output of the phpinfo() from our index.php file</li>\n<li>Done!</li>\n</ul>\n<h3><a href=\"#making-a-laravel-app\" aria-hidden=\"true\" class=\"anchor\" id=\"user-content-making-a-laravel-app\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Making a Laravel app</h3>\n<ul>\n<li><code>cd /var/www</code></li>\n<li><code>composer create-project laravel/laravel:dev-develop myapp</code> dev-develop will pull in the latest under development unreleased laravel version</li>\n<li><code>sudo vim /etc/nginx/sites-available/default</code></li>\n<li>Change the root to the new laravel app's public directory path like in this case: <code>root /var/www/myapp/public;</code></li>\n<li><code>nginx -t</code></li>\n<li><code>sudo service nginx reload</code></li>\n<li>cd into myapp/public directory</li>\n<li>Refresh browser and you will see the permission denied to write into the log file.</li>\n<li>If we do <code>ps aux | grep php</code> we see that the \"php-fpm\" which is running our web requests, which is running our php is owned by user & group <code>www-data</code>.</li>\n<li>That means this processes of php are running as user <code>www-data</code></li>\n<li>But if you run <code>ll</code> you will see that all the files in our app/public directory (in which we currently are) are owned by user <code>root</code></li>\n<li>So the <code>www-data</code> cannot write into the storage directory & the bootstrap/cache directory as they are owned by user & group <code>root</code> which in a laravel app should be writable by the <code>www-data</code></li>\n<li>To solve this do the following:</li>\n<li><code>cd ..</code> so we are out of the public directory</li>\n<li>Then run <code>sudo chown -R www-data: storage/ bootstrap/</code></li>\n<li>Solved!</li>\n</ul>\n<h3><a href=\"#wait-bro\" aria-hidden=\"true\" class=\"anchor\" id=\"user-content-wait-bro\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Wait Bro!</h3>\n<ul>\n<li>But now we will probably be pushing our code as some user so the permissions will again override for the storage & bootstrap directory</li>\n<li>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</li>\n<li>So let's do that!</li>\n</ul>\n<h3><a href=\"#solving-the-above-problem-wow-what-a-heading-i-know-thanks\" aria-hidden=\"true\" class=\"anchor\" id=\"user-content-solving-the-above-problem-wow-what-a-heading-i-know-thanks\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Solving the above problem (wow what a heading! I know, thanks.)</h3>\n<ul>\n<li>\n<p><code>cd ~</code></p>\n</li>\n<li>\n<p><code>adduser forge</code></p>\n</li>\n<li>\n<p>Enter the password for the user forge</p>\n</li>\n<li>\n<p><code>ll /home/</code></p>\n</li>\n<li>\n<p>A directory called <code>forge</code> have been created in the home directory for the user forge we just created</p>\n</li>\n<li>\n<p><code>cd ~</code></p>\n</li>\n<li>\n<p><code>cd /var/www</code></p>\n</li>\n<li>\n<p><code>mv myapp/ /home/forge/</code> We moved this application into the user forge's home directory</p>\n</li>\n<li>\n<p><code>cd /home/forge/</code></p>\n</li>\n<li>\n<p><code>ll</code></p>\n</li>\n<li>\n<p><code>chown -R forge: myapp/</code></p>\n</li>\n<li>\n<p>So now our web root is <code>/home/forge/myapp/public</code></p>\n</li>\n<li>\n<p>So lets edit the nginx config to replace the above path as the root</p>\n</li>\n<li>\n<p><code>vim /etc/nginx/sites-available/default</code></p>\n</li>\n<li>\n<p>Update the root directive</p>\n</li>\n<li>\n<p>WAIT! PHP & NGINX ARE RUNNING AS <code>www-data</code> BUT ALL THE FILES & DIRECTORIES IN OUR myapp/ directory ARE OWNED BY USER <code>forge</code>. 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.</p>\n</li>\n<li>\n<p>So instead to change to files get owned by <code>www-data</code> it makes sense to change PHP to change what user PHP would run as.</p>\n</li>\n<li>\n<p><code>cd /etc/php/7.1/fpm/</code></p>\n</li>\n<li>\n<p><code>cd pool.d/</code></p>\n</li>\n<li>\n<p><code>vim www.conf</code> This file determines how PHP-fpm runs & how it manages the processes like how many processes it spins up to handle requests.</p>\n</li>\n<li>\n<p>In the file there will be:\nuser = www-data\ngroup = www-data</p>\n</li>\n<li>\n<p>Change both to forge</p>\n</li>\n<li>\n<p><code>:wq</code></p>\n</li>\n<li>\n<p><code>sudo service php7.1-fpm reload</code></p>\n</li>\n<li>\n<p><code>ps aux | grep php</code> to check the php-fpm is now running as user & group <code>forge</code></p>\n</li>\n<li>\n<p>So now the permissions line up as both our code & PHP are running as user & group <code>forge</code>.</p>\n</li>\n<li>\n<p>Refresh the browser & you will see the laravel landing page.</p>\n</li>\n<li>\n<p>Good Job Chris!</p>\n</li>\n</ul>\n<h3><a href=\"#allowing-user-forge-to-use-sudo\" aria-hidden=\"true\" class=\"anchor\" id=\"user-content-allowing-user-forge-to-use-sudo\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Allowing user forge to use sudo</h3>\n<ul>\n<li><code>usermod -aG sudo forge</code></li>\n<li>We can check it worked by running <code>groups forge</code></li>\n<li>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.</li>\n<li>So we want to make sure that for only that command we do not have to enter the password</li>\n<li><code>visudo -f /etc/sudoers.d/php-fpm</code></li>\n<li>Add the following in it:\n<code>forge ALL=NOPASSWD: /usr/sbin/service php7.1-fpm reload</code></li>\n<li>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.</li>\n<li>Let's test this!</li>\n<li>Exit to clear the cached password & login back</li>\n<li><code>sudo su forge</code></li>\n<li>Run <code>sudo service php7.1-fpm reload</code></li>\n<li>And voila! It didn't asked for the password. So now we have 1 less barrier in our goal of automated deployment.</li>\n</ul>\n<blockquote>\n<p><strong>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</strong></p>\n</blockquote>\n<h3><a href=\"#here-comes-the-mysql\" aria-hidden=\"true\" class=\"anchor\" id=\"user-content-here-comes-the-mysql\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Here comes the MySQL!</h3>\n<ul>\n<li><code>sudo apt-get install -y mysql-server</code></li>\n<li>Enter the password for the new <code>root</code> user</li>\n<li><strong>You can automate this without prompts. Chris has videos on how to do that on serversforhackers.com</strong></li>\n<li>Check by running <code>sudo service mysql status</code></li>\n<li><code>mysql_secure_installation</code></li>\n<li>Remove anonymous users</li>\n<li>Disallow root logins remotely</li>\n<li>Remove test databases</li>\n<li>Reload privileges</li>\n<li>login to mysql by: <code>mysql -u root -p</code></li>\n<li><code>create database myapp charset utf8mb4</code></li>\n<li><code>create user myuser@localhost identified by 'secret'</code></li>\n<li><code>grant all privileges on myapp.* to myuser@localhost;</code></li>\n<li><code>flush privileges;</code> to burst the privileges cache</li>\n<li>exit;</li>\n<li>Update the .env file in the laravel app and we are done!</li>\n</ul>\n</article>\n </div>\n\n </div>\n \n</div>\n\n </div>\n <div class=\"gist-meta\">\n <a href=\"https://gist.github.com/m1guelpf/53e1780a5a68fe9281cfbbc9820d381f/raw/74bcbc312e561ff038f8f43b86004139d9354439/forgeLikeServerSetup.md\" style=\"float:right\">view raw</a>\n <a href=\"https://gist.github.com/m1guelpf/53e1780a5a68fe9281cfbbc9820d381f#file-forgelikeserversetup-md\">forgeLikeServerSetup.md</a>\n hosted with ❤ by <a href=\"https://github.com\">GitHub</a>\n </div>\n </div>\n</div>\n",
"stylesheet": "https://assets-cdn.github.com/assets/gist-embed-3cc724162479db25e452fdf621f2349adef3e742b53552c2a93f82d28156cb96.css"
}
This is very useful when working with Gists server-side
3. GitHub API
Of course, you can use the GitHub API to get this content. According to the API documentation, you have to make a GET
request to https://api.github.com/gists/$GIST_ID
where Gist ID is the part of the URL that appears after your username.
Here's an example response:
{
"url": "https://api.github.com/gists/53e1780a5a68fe9281cfbbc9820d381f",
"forks_url": "https://api.github.com/gists/53e1780a5a68fe9281cfbbc9820d381f/forks",
"commits_url": "https://api.github.com/gists/53e1780a5a68fe9281cfbbc9820d381f/commits",
"id": "53e1780a5a68fe9281cfbbc9820d381f",
"git_pull_url": "https://gist.github.com/53e1780a5a68fe9281cfbbc9820d381f.git",
"git_push_url": "https://gist.github.com/53e1780a5a68fe9281cfbbc9820d381f.git",
"html_url": "https://gist.github.com/53e1780a5a68fe9281cfbbc9820d381f",
"files": {
"forgeLikeServerSetup.md": {
"filename": "forgeLikeServerSetup.md",
"type": "text/plain",
"language": "Markdown",
"raw_url": "https://gist.githubusercontent.com/m1guelpf/53e1780a5a68fe9281cfbbc9820d381f/raw/a74da413bd8ad348523b4535053687533cc10485/forgeLikeServerSetup.md",
"size": 7434,
"truncated": false,
"content": "### Let's Log in!\n- Create ssh pair for login on a fresh DO droplet.\n- ssh into the server\n- `apt-get update` It updates server's knowledgeable packages. Not technically updates any software.\n\n### Alright, let's start installing our stuff boys!\n- `apt-get install -y git tmux vim curl wget zip unzip htop` -y flag to say yes to all prompts\n- Adding additional repositories so that we can get latest version of the softwares from this respective repositories of them:\n- 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)\n- For PHP: `add-apt-repository -y ppa:ondrej/php`\n- Now after adding the repos we need to tell the server to suck in & update its cache of available packages: `apt-get update`\n- `apt-get install -y nginx`\n- `curl localhost` , also we can type in the IP in the browser & confirm the nginx default landing page shows up\n- `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`\n- `ps aux | grep php` To check the php fpm process is running\n- `php -v` to check we got the latest PHP installed\n- Install Composer: `php -r \"readfile('http://getcomposer.org/installer');\" | sudo php -- --install-dir=/usr/bin/ --filename=composer`\n- `which composer` to check it was installed in the given directory.\n- `composer -v` to check composer is working\n\n### Let's get NGINX configured to use PHP\n- `cd /var/www/html/`\n- `vim index.php` Just dump phpinfo() in that file for time being\n- Hit IP/index.php in the browser. It will download the file at this moment because PHP isn't working\n- `cd /etc/nginx/`\n- `sites-available` has all the configurations. `sites-enabled` have the symlinks to the configs in the `sites-available` which we want to be enabled.\n- `sudo vim sites-enabled/default`\n- Configure the server block in that default file. To get a basic understanding of the default file watch [this part of the video](https://youtu.be/VQNrsMYCOFg?t=13m43s) again.\n- `sudo nginx -t` To test the nginx config and show errors if any\n- `sudo service nginx configtest` will ONLY tell you if things are ok or not. So the previous one is better \n- `sudo service nginx reload`\n- Refresh the IP in the browser & now you should see the output of the phpinfo() from our index.php file\n- Done!\n\n### Making a Laravel app\n- `cd /var/www`\n- `composer create-project laravel/laravel:dev-develop myapp` dev-develop will pull in the latest under development unreleased laravel version\n- `sudo vim /etc/nginx/sites-available/default`\n- Change the root to the new laravel app's public directory path like in this case: `root /var/www/myapp/public;`\n- `nginx -t`\n- `sudo service nginx reload`\n- cd into myapp/public directory\n- Refresh browser and you will see the permission denied to write into the log file.\n- 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`.\n- That means this processes of php are running as user `www-data`\n- 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`\n- 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`\n- To solve this do the following:\n- `cd ..` so we are out of the public directory\n- Then run `sudo chown -R www-data: storage/ bootstrap/`\n- Solved!\n\n### Wait Bro!\n- But now we will probably be pushing our code as some user so the permissions will again override for the storage & bootstrap directory\n- 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\n- So let's do that!\n\n### Solving the above problem (wow what a heading! I know, thanks.)\n- `cd ~`\n- `adduser forge`\n- Enter the password for the user forge\n- `ll /home/`\n- A directory called `forge` have been created in the home directory for the user forge we just created\n- `cd ~`\n- `cd /var/www`\n- `mv myapp/ /home/forge/` We moved this application into the user forge's home directory\n- `cd /home/forge/`\n- `ll`\n- `chown -R forge: myapp/`\n- So now our web root is `/home/forge/myapp/public`\n- So lets edit the nginx config to replace the above path as the root\n- `vim /etc/nginx/sites-available/default`\n- Update the root directive\n\n- 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.\n- 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.\n- `cd /etc/php/7.1/fpm/`\n- `cd pool.d/`\n- `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.\n- In the file there will be:\nuser = www-data\ngroup = www-data\n- Change both to forge\n- `:wq`\n- `sudo service php7.1-fpm reload`\n- `ps aux | grep php` to check the php-fpm is now running as user & group `forge`\n- So now the permissions line up as both our code & PHP are running as user & group `forge`.\n- Refresh the browser & you will see the laravel landing page.\n- Good Job Chris!\n\n### Allowing user forge to use sudo\n- `usermod -aG sudo forge`\n- We can check it worked by running `groups forge`\n- 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.\n- So we want to make sure that for only that command we do not have to enter the password\n- `visudo -f /etc/sudoers.d/php-fpm`\n- Add the following in it:\n`forge ALL=NOPASSWD: /usr/sbin/service php7.1-fpm reload`\n- 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.\n- Let's test this!\n- Exit to clear the cached password & login back\n- `sudo su forge`\n- Run `sudo service php7.1-fpm reload`\n- And voila! It didn't asked for the password. So now we have 1 less barrier in our goal of automated deployment.\n\n> **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**\n\n### Here comes the MySQL!\n- `sudo apt-get install -y mysql-server`\n- Enter the password for the new `root` user\n- **You can automate this without prompts. Chris has videos on how to do that on serversforhackers.com**\n- Check by running `sudo service mysql status`\n- `mysql_secure_installation`\n- Remove anonymous users\n- Disallow root logins remotely\n- Remove test databases\n- Reload privileges\n- login to mysql by: `mysql -u root -p`\n- `create database myapp charset utf8mb4`\n- `create user myuser@localhost identified by 'secret'`\n- `grant all privileges on myapp.* to myuser@localhost;`\n- `flush privileges;` to burst the privileges cache\n- exit;\n- Update the .env file in the laravel app and we are done!\n"
}
},
"public": false,
"created_at": "2017-07-13T19:01:10Z",
"updated_at": "2017-07-13T19:01:10Z",
"description": "Personally written version of Chris Fidao's video on setting up a Forge like server: https://youtu.be/VQNrsMYCOFg ",
"comments": 0,
"user": null,
"comments_url": "https://api.github.com/gists/53e1780a5a68fe9281cfbbc9820d381f/comments",
"owner": {
"login": "m1guelpf",
"id": 23558090,
"avatar_url": "https://avatars0.githubusercontent.com/u/23558090?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/m1guelpf",
"html_url": "https://github.com/m1guelpf",
"followers_url": "https://api.github.com/users/m1guelpf/followers",
"following_url": "https://api.github.com/users/m1guelpf/following{/other_user}",
"gists_url": "https://api.github.com/users/m1guelpf/gists{/gist_id}",
"starred_url": "https://api.github.com/users/m1guelpf/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/m1guelpf/subscriptions",
"organizations_url": "https://api.github.com/users/m1guelpf/orgs",
"repos_url": "https://api.github.com/users/m1guelpf/repos",
"events_url": "https://api.github.com/users/m1guelpf/events{/privacy}",
"received_events_url": "https://api.github.com/users/m1guelpf/received_events",
"type": "User",
"site_admin": false
},
"fork_of": null,
"forks": [
],
"truncated": false
}
About the Author
👋 Hi! I'm Miguel Piedrafita, a 15-year-old PHP artisan and open-source lover. How about connecting on Twitter?
Top comments (0)