<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[John Rom]]></title><description><![CDATA[Thoughts on Web Development and more]]></description><link>http://johnrom.com/</link><generator>Ghost 0.7</generator><lastBuildDate>Wed, 19 Mar 2025 08:01:02 GMT</lastBuildDate><atom:link href="http://johnrom.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[CSS Catch of the Day: Margins don't collapse with min-height]]></title><description><![CDATA[<p>If you have an element with a min-height, and an element that does not achieve that height with a margin at the bottom, the full margin will still be present on the outer element. Chrome doesn't appear to show this margin on the parent element, leading to an "invisible gap.</p>]]></description><link>http://johnrom.com/css-catch-of-the-day-margins-dont-collapse-with-min-height/</link><guid isPermaLink="false">f7f56a5a-9f88-4983-9d5f-466882e62866</guid><dc:creator><![CDATA[John Rom]]></dc:creator><pubDate>Wed, 26 Jul 2017 17:27:43 GMT</pubDate><content:encoded><![CDATA[<p>If you have an element with a min-height, and an element that does not achieve that height with a margin at the bottom, the full margin will still be present on the outer element. Chrome doesn't appear to show this margin on the parent element, leading to an "invisible gap."</p>

<pre><code>|- - - - - - - - - - - - - - -|
| |-------------------------| |
| |-------------------------| |
|  / / / / / / / / / / / / /  | &lt;-- inner margin
|                             | &lt;-- space resulting from min-height
|- - - - - - - - - - - - - - -|
 / / / / / / / / / / / / / / / &lt;-- margin resulting from inner margin
</code></pre>]]></content:encoded></item><item><title><![CDATA[Setting up a WordPress Dev Environment with Docker and Nimble]]></title><description><![CDATA[<p>In my last post, I released the environment I use to set up local WordPress installs on my machine using Docker. In this post, I'm going to show you how to set up a dev environment all your own or for a team with this simple project and get you</p>]]></description><link>http://johnrom.com/a-nimble-docker-wordpress-environment-in-action/</link><guid isPermaLink="false">1b2a0742-cded-4f30-95f0-c9836779d7be</guid><dc:creator><![CDATA[John Rom]]></dc:creator><pubDate>Tue, 02 May 2017 20:21:39 GMT</pubDate><content:encoded><![CDATA[<p>In my last post, I released the environment I use to set up local WordPress installs on my machine using Docker. In this post, I'm going to show you how to set up a dev environment all your own or for a team with this simple project and get you started on customizing it. Once you've set it up once, creating future projects only takes about a minute, so hang in there!</p>

<h3 id="installdocker">Install <em>Docker</em></h3>

<p>The first step is to install Docker. If you're on a Mac, Ubuntu or Windows 10 Professional, follow one of these links:</p>

<ul>
<li><a href="https://docs.docker.com/engine/installation/linux/ubuntu/#install-docker">Install on Ubuntu</a></li>
<li><a href="https://docs.docker.com/docker-for-windows/install/">Install on Windows 10 Professional</a></li>
<li><a href="https://docs.docker.com/docker-for-mac/install/">Install on Mac</a></li>
</ul>

<p>If you're on Windows 10 Home, an earlier version of Windows or an unsupported version of Mac, try <a href="https://www.docker.com/products/docker-toolbox">Docker Toolbox</a> -- though your mileage may vary.</p>

<h3 id="addtbintoyourpath">Add <code>~/bin</code> to your <code>PATH</code></h3>

<h4 id="windows">Windows</h4>

<ol>
<li>Start the System Control Panel applet (Start - Settings - Control Panel - System).  </li>
<li>Select the Advanced tab.  </li>
<li>Click the Environment Variables button.  </li>
<li>Under User Variables, select Path, then click Edit.  </li>
<li>Add <code>%USERPROFILE%\bin</code> as an entry if it doesn't exist.</li>
</ol>

<h4 id="other">Other</h4>

<p>Add to your <code>.bash_profile</code>:</p>

<ol>
<li>Open terminal or bash.  </li>
<li><code>echo "export PATH=$PATH:~/bin" &gt;&gt; ~/.bash_profile</code>  </li>
<li><code>source ~/.bash_profile</code></li>
</ol>

<h3 id="pullthenimbleenvironment">Pull the Nimble Environment</h3>

<p>Go to your preferred location for all of your projects, and pull the Nimble repository. I prefer a spot like <code>~\docker</code> on Mac or <code>~\Documents\docker</code> on Windows, but it's entirely up to you!</p>

<h3 id="createanewproject">Create a new project</h3>

<p>Before creating a new project, open a Bash command line or alternative like <em>Git Bash</em> (Windows), Terminal (Mac), Bash on Ubuntu WSL (Windows) or a regular old command line (Ubuntu). Run the following command to make <code>nimble</code> as easy as can be:</p>

<p><code>./nimble.sh localize</code></p>

<p>Now, you can just type <code>nimble</code> from this location. Please note, all commands must currently be run in this directory. Keeping a command line specifically for this directory helps.</p>

<h3 id="switchthenimbleenvironmenttoyourownrepo">Switch the Nimble Environment to your own repo</h3>

<p>First thing's first, delete the existing Git repository by deleting <code>./.git</code> from the root folder. You can (and should!) keep the <code>.gitignore</code> file. Then create a Git repository either using your GUI of choice, or <code>git init</code>. Once created, you should set up a branch to your own repo if you plan on syncing on the web. Eventually, I'll come up with a way you can update the actual Nimble Environment, but I'd like some community feedback before I delve too far into it.</p>

<p>You can start up the docker containers with no projects via <code>nimble up</code>. For more commands, <a href="https://github.com/johnrom/nimble">check out the Git repo</a></p>

<h4 id="actuallycreateanewproject">Actually create a new project</h4>

<p>Creating a project is easy, and even interactive. Just run the command <code>nimble create myproject</code>, replacing <code>myproject</code> with whatever alphanumeric project name you would like. Nimble will ask you a few questions, notably:</p>

<ul>
<li><p>Do you want this project kept in Git?</p>

<p><em>If so, you can this repo with other users, they can run <code>nimble init myproject</code>, and pull the new project you are creating</em></p></li>
<li><p>Do you want to clone a repo?</p>

<p><em>If this is an existing project, you can pull its repo into the <code>sites/myproject/www</code> folder.</em></p></li>
<li><p>Do you want to add this project to your hosts?</p>

<p><em>No more editing hosts files!</em></p></li>
<li><p>Do you want to generate certificates for this site?</p>

<p><em>Automatic (untrusted) SSL capabilities</em></p></li>
<li><p>Do you want to install WordPress?</p>

<p><em>It will ask you the basic questions for installing WordPress</em></p></li>
</ul>

<p>Once installed, your project will be available at <code>yourproject.local</code>, with PHPMyAdmin at <code>phpmyadmin.yourproject.local</code> and Webgrind at <code>webgrind.yourproject.local</code> (to be used with <code>nimble up profile</code>).</p>

<h3 id="customizingyourprojects">Customizing your projects</h3>

<p>Now that the framework has been laid for a basic project, here's a quick yet complicated briefer on the templates that make this possible. Each WP project is built from a template located at <code>./_templates/docker-wp-template.yml</code>. This template is compiled to a respective <code>docker-compose</code> template responsible for the project's configuration at <code>./_projects/project.yml</code>. Additionally, each project has multiple parts -- database, server, files, phpmyadmin, etc -- which extend services located at <code>./_templates/docker-common-template.yml</code>. </p>

<p>Now, this complicated web of files needs an infographic, which I have not prepared just yet, but the flow is like this:</p>

<p><code>./_templates/docker-wp-template.yml</code> -> creates -> <code>./_projects/myproject.yml</code> -> extends -> <code>./_templates/docker-common-template.yml</code></p>

<p>If you want to make a change across the board, like change the version of MariaDB that is used across all of your WP projects to 10.0.30, you can go to <code>./_templates/docker-common-template.yml</code>, find the <code>wp_db</code> service, and change <code>image:</code> to <code>mariadb:10.0.30</code>.</p>

<p>If you want to make this same change only for <code>myproject</code>, you can go to <code>./_projects/myproject.yml</code>, find service <code>myproject_db</code> and add <code>image: mariadb:10.0.30</code>.</p>

<p>And if you want to make the same change only to new projects that are created, you can go to <code>./_templates/docker-wp-template.yml</code> find <code>PROJECT_db</code> and add <code>image: mariadb:10.0.30</code>.</p>

<p>Now, if you run <code>nimble up</code>, it will whichever of the above containers you just modified and in a matter of moments, you'll be running that version of MariaDB. Of course keep in mind that if the DB data from your version is not compatible with the new version, you could end up with a corrupt database, but you hopefully have a dev database with a single source of truth for your data that you can pull from at any time.</p>

<p>I hope you can see how powerful it is to be able to completely change how your environments are built at any time and share those environments when collaborating. Be sure to leave some notes in the comments if you've tried it out, hated it, experienced bugs, or if it completely changed your life!</p>]]></content:encoded></item><item><title><![CDATA[A Nimble Docker Script to Provision WordPress Installs]]></title><description><![CDATA[<p>There comes a time in every developer's life where they've tired of installing WordPress, editing their hosts file, typing <code>npm install</code>, and various other chores. There comes a point where every team member gets tired of figuring out what the other team member means by "everyone has to install SOAP</p>]]></description><link>http://johnrom.com/a-nimble-script-to-provision-wp-installs/</link><guid isPermaLink="false">210094ec-7b6c-436f-85ee-c90fd8055cf1</guid><dc:creator><![CDATA[John Rom]]></dc:creator><pubDate>Sat, 28 Jan 2017 17:36:27 GMT</pubDate><content:encoded><![CDATA[<p>There comes a time in every developer's life where they've tired of installing WordPress, editing their hosts file, typing <code>npm install</code>, and various other chores. There comes a point where every team member gets tired of figuring out what the other team member means by "everyone has to install SOAP on their systems". Well, a few months ago I had finally reached the point of no return. Docker was recently released, and the system appeared ready to make it possible for you to share your exact environment with your entire team. No worrying about installing <code>soap</code> for everyone on the team. No worrying that your version of <code>php</code> won't translate to the production server. There's just no worrying anymore! Docker is here, and though it is complicated and frustrating to work with sometimes, I've created a script that can (hopefully) tame the beast, give you a place to learn about it, and generally <em>get you to the code faster</em>.</p>

<p>The hardest part of beginning the Docker journey was setting up the first project. There are plenty of tutorials on various websites on "Starting with Docker", that make it seem like a piece of cake. "All you have to do is <code>docker run $image</code>!!" they say. Well, when it comes to provisioning environments that are relatively the same, but sometimes a little different, I found it hard to grasp all the interconnected pieces at times. So in order to spare you the overwhelming feeling of not knowing which of 20 different variables could be the problem, I'm going to provide you with a basic template, biased with WordPress, that will let you see Docker in action, and give you an idea of how it can be used to provision multiple websites for a local server.</p>

<blockquote>
  <p><a href="https://github.com/johnrom/nimble/">https://github.com/johnrom/nimble/</a></p>
</blockquote>

<p>Clone it, give it a try. I recommend cloning it somewhere in your User Directory on Windows or Mac. I've never tested it with Linux, but I assume it would maybe work. This script has some basic dependencies, like <code>basename</code> and other things that are generally installed on all systems. Also, it's a bash script, so your terminal needs to be based off of <code>bash</code>.</p>

<p>Now, if I'm honest, even just using this script could be complex. You will need to make sure Docker is working, that the Docker VM <strong>shares the drive your files are on</strong>, and if you're on Windows, you'll have to use the C:\ drive for Windows files if you'd like the <code>hosts</code> functionality to work. But moving from my work computer to my home computer, it only took about 5 minutes to install Docker and clone this script, so hopefully it works that way for you as well.</p>

<p>If you're able to create your first site with this script, from there you can go backwards. "What if I want to use PHP 7?" Change the image of <code>wp_site</code> under <code>_projects/yourproject.yml</code>. If everything breaks, you'll know that <em>that one change</em> broke everything. Hopefully, you'll never have to experience putting everything together for the first time and not knowing what went wrong, where, and hopefully this can provide a new foundation on which developers can <em>get to the code faster</em>.</p>

<p>As usual, use people's scripts at your own risk, etc. If it doesn't work, create an issue on Github, but this is a personal project so my ability to maintain it depends on my workload.</p>]]></content:encoded></item><item><title><![CDATA[Setting up Ghost on a VirtualBox Shared Folder]]></title><description><![CDATA[<p>A few months ago, when I decided it was time to actually put a blog on my website instead of an "Under Construction" message that had been sitting there for five years, I chose Ghost as my CMS of choice. I'm a WordPress developer by trade, but WordPress has the</p>]]></description><link>http://johnrom.com/setting-up-ghost-on-a-virtualbox-shared-folder/</link><guid isPermaLink="false">135527b0-406c-41ab-b25e-acadd299a8ea</guid><dc:creator><![CDATA[John Rom]]></dc:creator><pubDate>Fri, 22 Jan 2016 19:23:01 GMT</pubDate><content:encoded><![CDATA[<p>A few months ago, when I decided it was time to actually put a blog on my website instead of an "Under Construction" message that had been sitting there for five years, I chose Ghost as my CMS of choice. I'm a WordPress developer by trade, but WordPress has the kind of power I <em>don't need</em> on a blog. I don't need post types, custom fields, user management, or plugins; I just need to write things down for all eternity. Plus, Ghost looks pretty good out-of-the-box, which saves me a whole lot of design time. When it came time to try it out, though, my initial installation didn't go so well.</p>

<p><img src="http://johnrom.com/content/images/2016/01/VirtualBox_Dev-Server_22_01_2016_13_26_02.png" alt="Ghost installation failed"></p>

<p>Okay, that's pretty scary. I might have a pretty edge case. I run a Windows 10 host, with an Ubuntu Guest. However, all of my server files are on my Windows 10 host. So Ubuntu is actually trying to install Ghost on a shared folder mounted on my F: drive.</p>

<pre><code>/srv/host/com/johnrom/test/
</code></pre>

<p>Setting up Ghost on a VirtualBox Shared Folder isn't simple. Basically, installing sqlite3 is impossible on a shared folder, even with symlinks enabled. This has to do with the fact that SQLite3 must be compiled by node (or node-pre-gyp, whatever that is). Then, we have to set up Forever in order to run Ghost on every boot, which also proved a bit troublesome. However, let me walk you through it!</p>

<p>You must have administrative privileges on your device to use this tutorial. I'll be using a Windows 10 Host with an Ubuntu Server 14.04 Guest for this tutorial.</p>

<h6 id="step1enablesymlinksonvirtualboxbrbr">Step 1: enable symlinks on VirtualBox<br><br></h6>

<ul>
<li><p>My Virtualbox is called "Dev Server" (very unique, I know)<br>
I found the exact name by opening Command Prompt and typing "VBoxManage list vms"</p></li>
<li><p>I call my share "projects-com" in the VirtualBox Shared Folders interface.</p></li>
</ul>

<p>Given these tidbits of information, we can now enable Symlinks for this mount point by entering the following into cmd.exe (one line, even if it looks broken)</p>

<pre><code>VBoxManage setextradata "Dev Server" VBoxInternal2/SharedFoldersEnableSymlinksCreate/projects-com 1
</code></pre>

<p>Now that we've done this, be sure to open VirtualBox as an administrator from now on. We'll make this easy by right-clicking the VirtualBox icon in the taskbar (or the shortcut on your desktop), going to properties -> compatibility, and checking "Run this program as an administrator"</p>

<h6 id="step2installnodeandnpmbrbr">Step 2: install Node and NPM <br><br></h6>

<p>Let's get node up and running, as that is a task all on its own.</p>

<p>We're basically following <a href="https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#debian-and-ubuntu-based-linux-distributions">this guide</a> to install Node on Ubuntu 14.04. Use <code>sudo</code> if you aren't running as root.</p>

<pre><code>sudo apt-get install --yes build-essential curl
curl -sL https://deb.nodesource.com/setup_5.x | bash -
sudo apt-get install --yes nodejs
</code></pre>

<p>If you don't use Ubuntu 14.04, check the <a href="http://support.ghost.org/supported-node-versions/">compatibility list</a> and make sure the version of node you are downloading is compatible!</p>

<p>I think I had to update npm to a better-supported version after installing from the repo, so let's do that.</p>

<pre><code>sudo npm install -g npm@latest-2
</code></pre>

<h6 id="step3installghostnotonyourshareddrivebrbr">Step 3: Install Ghost (<em>not on your shared drive!</em> )<br><br></h6>

<p>We're not ready for the shared drive yet! So let's create a temporary directory and get Ghost going.</p>

<pre><code># install unzip
sudo apt-get install unzip

cd /tmp
mkdir ghost
curl -L https://ghost.org/zip/ghost-latest.zip -o ghost.zip
mkdir ghost
unzip -uo ghost.zip -d ghost
cd ghost
npm install --production
</code></pre>

<h6 id="step4copyghosttotheshareddrivebrbr">Step 4: Copy Ghost to the Shared Drive<br><br></h6>

<p>Hopefully you made it this far. Now, we're going to copy Ghost to our Shared Driver, preserving all of the symlinks that exist among the modules Node just installed. Luckily, on Ubuntu these symlinks will be relative, and it does a great job of copying them with the following command:</p>

<pre><code>sudo cp -ad . /path/to/your/document/root
</code></pre>

<p>Let's check and make sure Ghost doesn't crash and burn!</p>

<pre><code>cd /path/to/your/document/root
npm start --production
</code></pre>

<h6 id="step5runningghostonstartupwithforeverbrbr">Step 5: Running Ghost on Startup with Forever<br><br></h6>

<p>If all went well, Ctrl+C out of npm and let's get started running Forever. Forever is a NPM service that will handle starting the server for you and running it forevever. Let's install it:</p>

<pre><code>npm install -g forever
</code></pre>

<p>For this unique case of running Ghost on a VBoxSF shared folder, I find that shares are the happiest when you run them through <code>/etc/rc.local</code>, so I will assume you have read <a href="https://johnrom.com/setting-up-ubuntu-virtualbox-windows-host/">how to set up Ubuntu 14.04 on VirtualBox</a> which covers this topic at the end. </p>

<p><strong>The following technique allows Forever to run Node as the www-data user.</strong></p>

<p>First, we need to make sure www-data has an accessible home directory.</p>

<pre><code>sudo nano /etc/passwd
</code></pre>

<p>Then, we'll find the www-data user, and it should say /var/www or /home/www-data. Whichever one, we will navigate to that directory and set it up for write access for www-data (don't keep anything important in this directory! This doesn't have to be the location of your server files, it is not mine.)</p>

<pre><code>sudo chown www-data:www-data /var/www # (or /home/www-data)
</code></pre>

<p>Now we're going to open up <code>/etc/rc.local</code>, and it should look like similar to the following, having replaced my shared folders with yours. Also replace <code>/srv/host/com/ghost</code> with the location of your ghost installation!</p>

<pre><code># temporarily set logging for this file, to debug any issues
exec 2&gt; /tmp/rc.local.log
exec 1&gt;&amp;2
set -x

sudo mount -t vboxsf -o fmode=666,umask=0002,uid=www-data,gid=www-data projects-com /srv/host/com

# this is the magic
sudo -u www-data NODE_ENV=production /usr/bin/forever --sourceDir /srv/host/com/ghost start index.js
</code></pre>

<p>Restart the server and check /tmp/rc.local.log</p>

<pre><code>sudo shutdown -r now
nano /tmp/rc.local.log
</code></pre>

<p>If it ends with something like the following, we're ready to move on!</p>

<pre><code>info: Forever processing file: index.js
+ exit 0
</code></pre>

<h6 id="step6settingupyourserverbrbr">Step 6: Setting up your Server<br><br></h6>

<p>If you already know the ins and outs of Apache or NGINX, feel free to do this your own way. Just know that Ghost listens on port <code>2368</code> by default.</p>

<p>It is atypical, I know, but I'm going to use Apache for this part because that's how my dev server is built. If you don't have Apache yet, just run</p>

<pre><code>sudo apt-get install apache2
</code></pre>

<p>We need to add some modules to Apache for passing the data through to our NPM server.</p>

<pre><code>sudo a2enmod proxy
sudo a2enmod proxy_http
</code></pre>

<p>Then, we'll create a VirtualHost under /etc/apache2/sites-available/ghost.conf</p>

<pre><code>nano /etc/apache2/sites-available/ghost.conf

&lt;VirtualHost *:80&gt;
    ServerName ghost.dev

    ProxyRequests off
    ProxyPass / http://127.0.0.1:2368/
    ProxyPassReverse / http://127.0.0.1:2368/
&lt;/VirtualHost&gt;
</code></pre>

<p>Restart Apache...</p>

<pre><code>sudo a2ensite ghost
sudo service apache2 restart
</code></pre>

<p>If Node was started correctly, Apache should now be connected to ghost at the domain <code>ghost.dev</code>.</p>

<h6 id="step7edityourhostsfiletopointtoyourserverbrbr">Step 7: Edit your hosts file to point to your server<br><br></h6>

<p>For this part, you will need to set up a VirtualBox Host-Only Adapter for your VM, and know the IP address of your server, which I covered in <a href="https://johnrom.com/setting-up-ubuntu-virtualbox-windows-host/">setting up Ubuntu 14.04 on VirtualBox</a>. Mine is 192.168.56.2, so replace that with your server's IP.</p>

<p>On your host, run Sublime Text or your text editor of choice <strong>as an administrator</strong>. Navigate to /etc/hosts on Mac or Linux, or C:\Windows\System32\drivers\etc\hosts on Windows, and append the following line:</p>

<pre><code>192.168.56.2 ghost.dev
</code></pre>

<h6 id="step8enjoytheelegancethatisghostbrbr">Step 8: Enjoy the elegance that is Ghost<br><br></h6>

<p>Fire up a browser and navigate to <code>ghost.dev</code> for a welcome message! That's all! That was no trouble at all, now, was it?!</p>

<p>If these instructions didn't work for you, feel free to leave a comment with your errors or questions. Up next, I will set up Ghost as a service so that I can quickly restart the Ghost server for development purposes.</p>]]></content:encoded></item><item><title><![CDATA[A History and Brief Comparison of NGINX and Apache]]></title><description><![CDATA[<p>I am by no means a web server expert, but I have quite a bit of experience configuring a local server for web development and experimentation purposes.</p>

<p>When it comes to selecting a Linux-based web server upon which to serve your web assets, it often comes down to a single</p>]]></description><link>http://johnrom.com/a-brief-comparison-of-nginx-and-apache/</link><guid isPermaLink="false">f2b9923f-7e8c-4cae-b844-fef75e80a815</guid><dc:creator><![CDATA[John Rom]]></dc:creator><pubDate>Mon, 21 Dec 2015 20:34:23 GMT</pubDate><content:encoded><![CDATA[<p>I am by no means a web server expert, but I have quite a bit of experience configuring a local server for web development and experimentation purposes.</p>

<p>When it comes to selecting a Linux-based web server upon which to serve your web assets, it often comes down to a single question: <em>"Should I use NGINX or Apache?"</em> Both are excellent web servers, and, with a little configuration, they can both generally do the same job as the other. NGINX will likely always have a slight advantage on a high-volume site with high concurrency, but a properly tuned Apache server can likely get the job done as well.</p>

<p>So the general answer is that it does not matter, especially for local development. If your production website runs on a specific server, I recommend using that one. To get to PHP development as fast as possible, I recommend Apache. If you want to use <code>.htaccess</code> files for per-directory configuration, use Apache. For local development, where requirements might change completely over the years or project to project, I recommend Apache. To have the highest concurrency -- or thousands of people using your site at once -- I recommend NGINX. The good news is, if you want the best of both worlds, you can use both! If you're interested in what each of these servers really stands for, let's go over some history.</p>

<h6 id="apache">Apache</h6>

<p>Apache came before NGINX. It was first written in a world where the web was new, and setting up a server was no trivial task. Its focus was primarily on being a jack-of-all-trades. The impression I've gotten from Apache over the years has always been similar to that of the famous "5-minute install" from WordPress. Installation of a LAMP server (Linux, Apache, MySQL and PHP) is as simple as it gets, and for anyone who wants to get to PHP as fast as possible, I highly recommend this route. </p>

<p>It doesn't come without its drawbacks, though. Continuing our comparison, WordPress, as great as it is, loads a <em>lot</em> of functionality. If you're writing on a simple blog (like this one), that functionality may be overkill, and you may end up with a lesser performance profile than some of the more focused offerings. However, if you require a fair amount of the functionality and flexibility that WordPress provides, you will spend many hours writing a platform for that from scratch, with possibly negligible performance gains. Apache falls in the same boat, with the ability to use .htaccess files and load extra Apache modules at will (including PHP). However, for larger sites and due to the performance limitations of Apache at the time, the way was paved for a new web server.</p>

<h6 id="nginx">NGINX</h6>

<p>NGINX was built after Apache took its place as the server-du-jour for Linux. If you ran a linux server, you probably used Apache, and if you ran a Windows server, you probably used IIS. However, as the web evolved and millions of people began using the internet regularly, concurrency became a huge hurdle for Apache. At the core of Apache's functionality (now the <code>MPM-Prefork</code> module) was the need to spawn a process for every connection. That means every user currently browsing a given website needed a process, and processes are not cheap in terms of CPU. Large sites like social networking and news sites immediately began to feel the struggle -- this is where NGINX comes in. </p>

<p>In order to deal with concurrent connections in the tens of thousands, NGINX was built off of an event-loop. Basically, when many connections came in, one NGINX process would serve one connection after the other -- very quickly. Remember how Apache was a jack-of-all-trades? Each Apache process in this scenario had the capability to parse dynamic content like PHP and serve it. NGINX, on the other hand, simply passes it on to a "PHP Daemon", which is a mini server that is listening only for PHP requests. This means when NGINX responded to a request for an image, <em>PHP was never loaded!</em> The focus, then, for NGINX was to respond to as many requests as quickly as possible.</p>

<h6 id="butwhataboutnow">But what about now?</h6>

<p>Apache has come a long way since then. It now offers different Multi-Processing Modules (MPMs) that change the way these handle requests. These MPMs are not like other Apache Modules -- they must be compiled into the server during installation. Once you've chosen an MPM, you'll have to recompile Apache in order to switch.</p>

<p>These modules are as follows:</p>

<ul>
<li><p><strong>MPM-Prefork</strong><br>
The same as ever. One process spawns for each request. This is the only option for using <code>mod_php</code> built into Apache, and is the default</p></li>
<li><p><strong>MPM-Worker</strong><br>
Each process can spawn child <em>threads</em>, which reduces the overhead for concurrent connections. This isn't compatible with mod_php, but is mostly compatible otherwise. Each thread is left open for a connection, and will be used for loading assets and other files associated with a request.</p></li>
<li><p><strong>MPM-Event</strong><br>
Similar to MPM-Worker, except it will not leave threads waiting for connections. If using SSL or other modules, it will behave like MPM-Worker. This is only stable in Apache 2.4</p></li>
</ul>

<p>As you can see, MPM-Worker and MPM-Event move towards the NGINX way of processing, where each process can process multiple concurrent connections. It is not the same, nor does it necessarily outperform NGINX, but it is useful when you want to use Apache and also handle concurrency.</p>

<h6 id="thesearenotexclusive">These are not exclusive</h6>

<p>I think the main reason that Apache continues to flourish is its ability to use .htaccess files to modify your configuration on a per-directory basis. It's sometimes easier to manage a site's <code>.htaccess</code> than it is to go through Apache or NGINX configuration files. WordPress, for example, will automatically generate your .htaccess file if it has write permissions on its own files. This means (both good and bad), that WordPress plugins can modify the rewrite rules in your <code>.htaccess</code>. Talk about customization! NGINX, on the other hand, <a href="https://www.nginx.com/resources/wiki/start/topics/examples/likeapache-htaccess/">is against ever doing this</a> because they love an efficient server (and who doesn't?).</p>

<p>In order to get the best of both worlds, you can listen for traffic with NGINX, check if a static file exists at that location, and if it doesn't -- pass the request to Apache. Apache can then read its .htaccess files, and pass that information to PHP. If a static file exists, Apache and PHP processes are never spawned, and everybody wins.</p>]]></content:encoded></item><item><title><![CDATA[Setting up Ubuntu on VirtualBox (Windows) and Why]]></title><description><![CDATA[<p>I have been collecting valuable tricks and techniques over the years developing for the web. On this blog, I hope to share them with the world (and myself, for future reference), so I figure my first post should be  getting started with Virtual Machines (VMs). Then, I can run the</p>]]></description><link>http://johnrom.com/setting-up-ubuntu-virtualbox-windows-host/</link><guid isPermaLink="false">7048e75f-ca07-4b94-919e-5d121eb843a2</guid><category><![CDATA[ubuntu]]></category><category><![CDATA[virtualbox]]></category><category><![CDATA[windows]]></category><dc:creator><![CDATA[John Rom]]></dc:creator><pubDate>Mon, 14 Dec 2015 06:47:48 GMT</pubDate><content:encoded><![CDATA[<p>I have been collecting valuable tricks and techniques over the years developing for the web. On this blog, I hope to share them with the world (and myself, for future reference), so I figure my first post should be  getting started with Virtual Machines (VMs). Then, I can run the gamut of getting WordPress and Ghost up and running, and eventually maybe I'll give away some code secrets. There are a million posts about setting up VirtualBox, but this one is specifically for the purpose of setting up a development server.</p>

<p>A VM is a little machine within your machine. I use it to run Ubuntu, so that I can get full access to the wonders of the Linux command line. After years of trying to use Windows and WAMP, things became a little bit too complicated using Git and SSH'ing through the Windows command prompt, installing Ruby and Node, SVN -- I can go on. Then, I had to do it all over again on other (Linux flavor) servers. Windows is Windows, and I see it as a GUI-based OS. I use it for gaming, listening to music, emailing, office, and the things the rest of the world uses it for. However, when it came to doing real power-user tasks, I found that most real-world scenarios involve Linux, so instead of learning how to do it on Windows and then learning <em>how to do it again</em> on Linux (because it's kind of my job to know), I decided to use Ubuntu for the techie stuff.</p>

<p>I experimented with dual-booting. It was OK. When I was done watching <em>Mall Cop</em>, I could restart my laptop, boot into Ubuntu Server, and be ready to go. But I want to be able to access my server's PHP and other files from Windows and see the result <em>while watching movies</em>.</p>

<p>I use VirtualBox because it was the first VM manager I tried, and it worked. It didn't come without its complications. For example, I cannot copy and paste to my virtual machine without using SSH because I'm using a barebones server. That's a big issue, but one I haven't quite figured out. If this is too big of an issue, you might want to install the desktop version instead -- just know it will run a bit slower. Prepare to spend an hour or two (with my help!) getting everything set up. Sometimes, this guide might produce errors because of the many dependencies that this setup requires. Let me know, and maybe I'll be able to revise this guide with more information.</p>

<h6 id="enoughbackgroundletsgetstartedbrbr">Enough background, let's get started!<br><br></h6>

<p>For this guide, I am using the following configuration. Some older version of VirtualBox are <strong>not</strong> compatible with Windows 10, but hopefully future versions will be fine. I'm using 64-bit, so hopefully all of this works if you are using a 32-bit device (just be sure to download the 32-bit versions of everything!)</p>

<pre><code>Windows 10 (x64)
VirtualBox 5.0.10 r104061
Ubuntu Server 14.04.3 LTS Trusty Tahr (x64)
</code></pre>

<p>First download <a href="http://www.ubuntu.com/download/">Ubuntu</a>. While it's downloading, Download and install VirtualBox, then download and install the VirtualBox Extension Pack. When your Ubuntu download is complete, open VirtualBox. Go to Preferences -> Network and add a NAT network with the default settings. Under Host-only Networks, edit the settings of your Host-Only Adapter, make sure it is 192.168.56.1, then switch over to "DHCP Server" and uncheck the box to disable it. Click "New" in the top left. Name your server, type: Linux, version: Ubuntu (64-bit). I have 8GB ram, so I usually give it 1024MB (1GB). Create a virtual hard disk (VDI). Since I'm on a solid state drive and for the purposes of this tutorial, I'll be using a fixed size disk. My actual server is dynamically allocated though, because it occasionally needs more space and was created before switching to an SSD.</p>

<p>Once it completes, select your new server and click "Settings". Go to Storage, click "Controller: IDE", and under Attributes click the disc -> "choose optical disk file". Find the Ubuntu ISO you just downloaded. If you're on a solid state drive, click the first Controller: SATA, and under attributes check Solid-State Drive.</p>

<p>Now, go under Network and make sure Adapter 1 has "Enable Network Adapter" checked, attached to NAT. After that, we're ready to get started! Click Start, and the VM should automatically boot from the ISO we added to the first IDE controller. Go through selecting language, etc, and the VM will load the additional components needed to install Ubuntu. I leave all of these options up to you -- I just run the defaults. Eventually, you will come to the Partition disk option. I am not using LVM for this particular instance, but it can come in handy, especially if you chose a Dynamically Allocated Disk at the beginning. Learn more about it <a href="http://askubuntu.com/questions/3596/what-is-lvm-and-what-is-it-used-for">here</a>. I leave everything else default, and don't install any software -- we'll do that next!</p>

<p>Once your server restarts, it'll boot into Ubuntu and we'll be able to...</p>

<h6 id="installvirtualboxguestadditionsbrbr">Install VirtualBox Guest Additions<br><br></h6>

<p>Since we have NAT enabled, we should be able to access the internet from Ubuntu. You'll obviously need an internet connection for this next part. Let's update our repos and install guest additions. If you're on Ubuntu Desktop, open a Terminal now (and never close it!). Using 14.04.3, installing VBox Guest Additions was (thank golly) as simple as:</p>

<pre><code>sudo apt-get update
sudo apt-get install virtualbox-guest-x11
</code></pre>

<p>As of this moment, you should have the capacity to share copy and paste between Ubuntu and Windows if you are on Ubuntu Desktop by clicking "Devices -> Shared Clipboard -> Bidirectional" in the VBox window. However, it doesn't help Ubuntu Server users, because we're using the basic terminal which has no mouse support. I never figured out the copy-paste situation. You can try installing <a href="http://manpages.ubuntu.com/manpages/hardy/man8/gpm.8.html">GPM</a> for a mouse-cursor, install Gnome or use X11... but every time I try it, it bothers me and I remove it. If anybody knows how to get a mouseable, copy-and-pasteable terminal without installing an entire desktop, feel free to let me know and I'll add it to the guide!</p>

<h6 id="configureahostonlynetworkbrbr">Configure a Host-only Network<br><br></h6>

<p>Now, we have to add a Network Adapter to Ubuntu to provide a host-only interface, and connect it with our host's host-only network adapter. This allows us to ping "192.168.56.2" from the host, and reach the guest. Which means, eventually, we will be able to point domains to it in our HOSTS file, and reach our server files.</p>

<p>In VirtualBox, go to Preferences -> Network and add a NAT network with the default settings (if it isn't there already). Under Host-only Networks, edit the settings of your Host-Only Adapter, make sure it is 192.168.56.1, then switch over to "DHCP Server" and uncheck the box to disable it because we'll configure static IP addresses in a minute.</p>

<p>In your VM, we'll edit the network interfaces file.</p>

<pre><code>sudo nano /etc/network/interfaces
</code></pre>

<p>In this file, you should see an eth0 and a loopback adapter. Update this file to look like this:</p>

<pre><code># This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet dhcp

# Host Only Config
auto eth1
iface eth1 inet static
address 192.168.56.2
netmask 255.255.255.0
</code></pre>

<p>When you're done, restart your VM. Now your Windows Host-only adapter will have the IP address 192.168.56.1, your VM will have the IP address 192.168.56.2 and, in Windows, you should be able to <code>ping 192.168.56.2</code> in a Command Prompt. If you receive messages like "Reply from 192.168.56.2", everything is working!</p>

<h6 id="addsharedfoldersbetweenwindowsandubuntubrbr">Add shared folders between Windows and Ubuntu<br><br></h6>

<p>The coolest part of this setup is the ability to fully utilize Ubuntu, while being able to edit server files on Windows. I highly recommending using a <a href="http://www.howtogeek.com/172580/how-to-create-a-separate-data-partition-for-windows/">separate partition</a>, or even better a separate drive, to host your server files, so that Ubuntu has no chance of corrupting your Windows partition. This works for me, since I always use 100GB for Windows and the rest of a drive for a data (F:) partition, where I move my Libraries such as Pictures, Music, etc.</p>

<p>Once you've decided where your server files will live, go to Machine -> Settings -> Shared Folders. Click the Add button to the right, and select the path to your shared folder -- it's okay if there's nothing in there at this point. For the "folder name" option, name it something memorable like "projects". Do not check any of the boxes -- we will handle this manually.</p>

<p>To mount the shared folders, we'll use the <code>rc.local</code> file. This is a file that runs scripts at the end of the boot process, or the beginning of login, one or the other. <code>/etc/fstab</code> is usually used to mount drives, but this is conveniently located <em>before VirtualBox loads its VBoxSF service</em>. I've read articles stating it's not correct to use the <code>rc.local</code> file for this purpose -- this is a dev server. I've never had a problem. We're going to use rc.local to manually mount our vboxsf share with the user and group www-data.</p>

<p>First let's create a directory. I like using /srv/host for my server files located on the host machine.</p>

<pre><code>sudo mkdir /srv/host

sudo nano /etc/rc.local
</code></pre>

<p>We're also going to enable a log file at /tmp/rc.local.log so that we can see immediately if something goes horribly wrong.</p>

<pre><code>#!/bin/sh -e
#
# rc.local
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

exec 2&gt; /tmp/rc.local.log
exec 1&gt;&amp;2
set -x

sudo mount -t vboxsf -o fmode=666,umask=0002,uid=www-data,gid=www-data projects /srv/host

exit 0
</code></pre>

<p>Do a restart, and we'll see how it worked! Create a file in your projects directory in Windows, so you can confirm.</p>

<pre><code>sudo shutdown -r now

ll /srv/host
</code></pre>

<p>If you see your file(s) here, then we are ready to go! You have successfully installed a VirtualBox VM and are ready to plunge deeper. Next steps, we are going to install Apache or NGINX (todo: links), MySQL, PHP, Ruby, Node.JS, whatever you're into! Look for these guides over the next few weeks, or jump ahead now and find those resources online!</p>]]></content:encoded></item></channel></rss>