<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Scott Robertson</title>
    <description>The latest articles on DEV Community by Scott Robertson (@scottrobertson).</description>
    <link>https://dev.to/scottrobertson</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F166308%2F5e5b3a2a-29f3-4377-84e7-11d17f2782ad.jpeg</url>
      <title>DEV Community: Scott Robertson</title>
      <link>https://dev.to/scottrobertson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/scottrobertson"/>
    <language>en</language>
    <item>
      <title>Easy has_secure_password Rails API Authentication</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Fri, 22 Jan 2021 00:02:59 +0000</pubDate>
      <link>https://dev.to/scottrobertson/easy-hassecurepassword-api-authentication-1oag</link>
      <guid>https://dev.to/scottrobertson/easy-hassecurepassword-api-authentication-1oag</guid>
      <description>&lt;p&gt;I had a very simple API I needed to build, to be consumed by a Nuxt.js application. This sent me down a path of trying to find a simple way to authenticate against an API, using an email/password.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1350422471380529152-367" src="https://platform.twitter.com/embed/Tweet.html?id=1350422471380529152"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1350422471380529152-367');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1350422471380529152&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;However, as I tried more gems and libraries, I quickly found that they were one of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Way over complex&lt;/li&gt;
&lt;li&gt;Broken&lt;/li&gt;
&lt;li&gt;And/or unmaintained&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After speaking with &lt;a class="mentioned-user" href="https://dev.to/marcqualie"&gt;@marcqualie&lt;/a&gt; about this, I discovered that he needed something similar. So we decided to quickly put together a library that we could use in our projects.&lt;/p&gt;

&lt;p&gt;Introducing Tokenable:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/tokenable" rel="noopener noreferrer"&gt;
        tokenable
      &lt;/a&gt; / &lt;a href="https://github.com/tokenable/tokenable-ruby" rel="noopener noreferrer"&gt;
        tokenable-ruby
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Tokenable is a Rails gem that allows API-only applications a way to authenticate users. This can be helpful when building Single Page Applications, or Mobile Applications. Works with Devise, Sorcery, has_secure_password, and any other auth system you may want to use.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Tokenable&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://badge.fury.io/rb/tokenable-ruby" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/020f692092c0b21b2e9044f9a16bd6f7d96f404034a64a17f39377924836cb95/68747470733a2f2f62616467652e667572792e696f2f72622f746f6b656e61626c652d727562792e737667" alt="Gem Version"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/tokenable/tokenable-ruby/workflows/Tests/badge.svg"&gt;&lt;img src="https://github.com/tokenable/tokenable-ruby/workflows/Tests/badge.svg" alt="Tests"&gt;&lt;/a&gt;
&lt;a href="https://codecov.io/gh/tokenable/tokenable-ruby" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/313dc65ca28957875954296a2261eb004975961ea290e7d29acf9ceac6b47ffb/68747470733a2f2f636f6465636f762e696f2f67682f746f6b656e61626c652f746f6b656e61626c652d727562792f6272616e63682f6d61696e2f67726170682f62616467652e7376673f746f6b656e3d55524634353648385249" alt="codecov"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/a93286920599112849c7c2af9d239294be27738b440248e434813b1bd0ffb368/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f6e747269627574696f6e732d77656c636f6d652d627269676874677265656e2e7376673f7374796c653d666c6174"&gt;&lt;img src="https://camo.githubusercontent.com/a93286920599112849c7c2af9d239294be27738b440248e434813b1bd0ffb368/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f6e747269627574696f6e732d77656c636f6d652d627269676874677265656e2e7376673f7374796c653d666c6174" alt="contributions welcome"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/77f283e451439114d3bbb03744b3425d03d4e33e6d2fb1dc049046b5fc626add/68747470733a2f2f7777772e7265706f7374617475732e6f72672f6261646765732f6c61746573742f7769702e737667"&gt;&lt;img src="https://camo.githubusercontent.com/77f283e451439114d3bbb03744b3425d03d4e33e6d2fb1dc049046b5fc626add/68747470733a2f2f7777772e7265706f7374617475732e6f72672f6261646765732f6c61746573742f7769702e737667" alt="Project Status: WIP – Development is in progress"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Tokenable is a Rails gem that allows API-only applications a way to authenticate users. This can be helpful when building Single Page Applications, or Mobile Applications. It's designed to work with the auth system you are already using, such as Devise, Sorcery and &lt;code&gt;has_secure_password&lt;/code&gt;. You can also use it with any custom auth systems.&lt;/p&gt;
&lt;p&gt;Simply send a login request to the authentication endpoint, and Tokenable will return a token. This token can then be used to access your API, and any authenticated endpoints.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Add this line to your application's Gemfile:&lt;/p&gt;
&lt;div class="highlight highlight-source-ruby notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-en"&gt;gem&lt;/span&gt; &lt;span class="pl-s"&gt;'tokenable-ruby'&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;And then execute:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;bundle install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Once you have the gem installed, lets get it setup:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;rails generate tokenable:install User --strategy=devise&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We make it easier for you, by adding out of the box support for some auth libraries. You can pick from the following options for &lt;code&gt;--strategy&lt;/code&gt;, or leave it empty for a &lt;a href="https://github.com/tokenable/tokenable-ruby/wiki/Create-your-own-statergy" rel="noopener noreferrer"&gt;custom&lt;/a&gt;…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/tokenable/tokenable-ruby" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Tokenable is a Rails gem that allows API-only applications a way to authenticate users. This can be helpful when building Single Page Applications, or Mobile Applications.&lt;/p&gt;

&lt;p&gt;Setting it up with your existing auth system is simple, and using it from a JavaScript application, or mobile application is even more simple. &lt;/p&gt;

&lt;p&gt;Once it's set up, all you need to do is send an email/password to the endpoint we provide you, and it will return a JWT token. This token can then be used to authenticate all future API calls.&lt;/p&gt;

&lt;p&gt;Here is an example in Axios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/api/auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;coolpassword123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You then use this token in all future API requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://example.com/api/user/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tokenable also supports Devise and Sorcery out of the box, but it can work with any auth system (or no auth system at all).&lt;/p&gt;

&lt;p&gt;Let us know any feedback you have, and feel free to submit any issues you face.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>authentication</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How long did you live at that address?</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Sun, 19 Mar 2017 01:22:25 +0000</pubDate>
      <link>https://dev.to/scottrobertson/how-long-did-you-live-at-that-address-3nkp</link>
      <guid>https://dev.to/scottrobertson/how-long-did-you-live-at-that-address-3nkp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;How long did you live at that address?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A simple question you answer multiple times a year when applying for anything that requires a credit check. Yet it's a question I literally never know the answer to.&lt;/p&gt;

&lt;p&gt;To solve this issue, I created a little web app to keep track of all my important dates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YlKB6AF5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/03/687474703a2f2f642e70722f692f517137772b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YlKB6AF5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/03/687474703a2f2f642e70722f692f517137772b.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's very simple. It keeps track of the date an event happened, and how long that event lasted for. It also tells you how long ago the event was.&lt;/p&gt;

&lt;p&gt;You can download and deploy the app on &lt;a href="https://github.com/scottrobertson/dates"&gt;Github&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Essential Travel Apps</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Sun, 19 Feb 2017 18:47:26 +0000</pubDate>
      <link>https://dev.to/scottrobertson/essential-travel-apps-54i8</link>
      <guid>https://dev.to/scottrobertson/essential-travel-apps-54i8</guid>
      <description>&lt;p&gt;As some of you may be aware, Libby and I recently spent &lt;a href="https://gingerbreadbuttons.com/my-travel-plans/"&gt;2 months travelling around Europe&lt;/a&gt;. Below are a number of apps that we could not have lived without during that time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Moovit
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p0NCpbsc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screen-Shot-2017-02-19-at-14.08.25-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p0NCpbsc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screen-Shot-2017-02-19-at-14.08.25-1.png" alt="" width="880" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When arriving a strange city for the first time, after hours of travelling, the first thing you want to do is get to your hotel. Navigating around a city can be difficult, especially when Uber is not an option. Moovit fills this gap by providing a comprehensive public transit guide.&lt;/p&gt;

&lt;p&gt;Moovit allows you to select a destination, and it will provide all the information you need. All the transport options (buses, trains, metros etc), along with the timetables (in some cities, it provides real-time information), and most importantly "Get Off Alerts". These alerts will tell you when your stop is coming up, and when to get off. They are especially useful in countries that you do not speak the language, as it's very easy to misread bus stops etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monzo
&lt;/h3&gt;

&lt;p&gt;One of the most expensive aspects of travelling is something that most people don't even know exists, and that is currency exchange rates. You either head to the exchange shop or use your bank card. Both of which may offer "no fee" exchange rates, but what they fail to mention is that they are adjusting the exchange rate so that they make a profit from that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kVfq_3yI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screen-Shot-2017-02-19-at-14.19.03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kVfq_3yI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screen-Shot-2017-02-19-at-14.19.03.png" alt="" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Monzo is a startup, whose goal is to build a better bank. As part of their service, they offer no fee, mid-market exchange rates. This means that you are getting the best possible exchange rate available at that time.&lt;/p&gt;

&lt;p&gt;Using the app, we were able to top up our Monzo accounts as we travelled, and we could use our bank cards as we normally would back home (unless you are in Germany, but that is a rant for another day).&lt;/p&gt;

&lt;p&gt;Having a real time balance is also super useful as you can easily lose track of how much you are spending when a coffee costs 1500 Hungarian Forint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uber
&lt;/h3&gt;

&lt;p&gt;Everyone knows what Uber is, so there is no need for me to explain this one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6jvztY9---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screenshot_20170219-142429--3-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6jvztY9---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screenshot_20170219-142429--3-.png" alt="" width="880" height="817"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One thing I will note though is that Uber charges you in the local currency, so it's very important to pair it with something like Monzo, which will negate any exchange rate charges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kayak Trips
&lt;/h3&gt;

&lt;p&gt;Kayak is known for its website that allows you to buy plane tickets, book hotels, and rent cars. However, they have another product called Kayak Trips.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fw5zPBIY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screen-Shot-2017-02-19-at-14.22.06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fw5zPBIY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screen-Shot-2017-02-19-at-14.22.06.png" alt="" width="880" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trips is essentially a travel assistant. It saves all of your bookings, flights, and activities. Having all of this in 1 place is very useful when you are moving from one city to another every 4 days!&lt;/p&gt;

&lt;p&gt;Not only does it store all of this information, but you also get real-time alerts for events such as flight delays and gate information.&lt;/p&gt;

&lt;p&gt;There are a few alternatives to Kayak Trips out there such as TripIt, which is also very good, but I found Kayak Trips to be perfect for us.&lt;/p&gt;

&lt;h3&gt;
  
  
  Google Translate
&lt;/h3&gt;

&lt;p&gt;To be honest, there were very few times that we actually needed this app, as the vast majority of European countries speak very good English.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bk7NIgNW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screen-Shot-2017-02-19-at-18.18.13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bk7NIgNW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screen-Shot-2017-02-19-at-18.18.13.png" alt="" width="618" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, on the odd occasion that we did use the app, it was normally using the Camera Mode. This allows you to point your phone at some text, and it will instantly translate it. This is especially useful for menus, or directions (when Moovit is not available).&lt;/p&gt;

&lt;h3&gt;
  
  
  Google Photos
&lt;/h3&gt;

&lt;p&gt;This is one of those apps that you are not thankful for until you really need it. While travelling, like me, I am sure you take hundreds of photos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Aj8VTFr7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screen-Shot-2017-02-19-at-14.44.14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Aj8VTFr7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s3-eu-west-2.amazonaws.com/scottrobertson-blog/2017/02/Screen-Shot-2017-02-19-at-14.44.14.png" alt="" width="880" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google Photos allows you to backup all of these photos up, not only allowing you to keep them safe, but it means that you can clean up your phone/camera to allow you to take lots more!&lt;/p&gt;

&lt;p&gt;You can either choose to store photos in their original format, or in Google's compressed format. The latter does not count towards your storage limits, and while I have found that the quality is still very good, I still prefer to store the original, especially when the photos are not from a phone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three (Feel at Home)
&lt;/h3&gt;

&lt;p&gt;Although not an app, I thought I would mention Three's Feel at Home service.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Well, thank you Three &lt;a href="https://t.co/JjIkePXC9Q"&gt;https://t.co/JjIkePXC9Q&lt;/a&gt; &lt;a href="https://t.co/LV5u3QO4TO"&gt;pic.twitter.com/LV5u3QO4TO&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;— Scott Robertson (@scottymeuk) &lt;a href="https://twitter.com/scottymeuk/status/795691316776730626"&gt;7 November 2016&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Feel at Home allows you to use your phone as normal in multiple countries around the world, at no extra cost. Because I have unlimited data, this meant that I did not need to worry about using my phone when I needed it.&lt;/p&gt;

&lt;p&gt;There are a few limitations in this service, but they generally don't get in the way. You are not able to tether, and while you can get 3G, all of the traffic is routed through the UK so it can feel a bit sluggish at points.&lt;/p&gt;

&lt;p&gt;But as you can see, it saved me a lot of money and stress, so it's totally worth it.&lt;/p&gt;

&lt;p&gt;If you have any suggested apps, then &lt;a href="https://twitter.com/scottymeuk"&gt;let me know&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Plex for Chromecast</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Sun, 19 Jan 2014 12:00:00 +0000</pubDate>
      <link>https://dev.to/scottrobertson/plex-for-chromecast-2lce</link>
      <guid>https://dev.to/scottrobertson/plex-for-chromecast-2lce</guid>
      <description>&lt;p&gt;When Plex announced that it would be an official Chromecast partner, I knew that I had to get ahold of one. On Christmas day, I jumped onto Amazon and ordered one for £35.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yY9Taz9N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://scottrobertson.me/img/posts/chromecast.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yY9Taz9N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://scottrobertson.me/img/posts/chromecast.jpg" alt="Chromecast"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had been using Plex for about 4 month before this, however I only had access to a very limited set of features due to using it as a DLNA device. I could browse the media (thumbnail and title) and play, and that was about it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XoSPlevV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://scottrobertson.me/img/posts/plex-for-chromecast.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XoSPlevV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://scottrobertson.me/img/posts/plex-for-chromecast.png" alt="Plex for Chromecast"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Getting the Chromecast has unlocked a lot more features that have made watching TV shows and Movies a whole lot nicer.&lt;/p&gt;

&lt;p&gt;For example, I use &lt;a href="http://trakt.tv/user/Scottymeuk"&gt;trakt.tv&lt;/a&gt; extensively, and with a simple plugin, Plex automatically sends what I am watching to Trakt. This means I can keep track of what I am watching, and even tell Plex to filter only "Unwatched" episodes/movies. This now works with stuff I watch on my TV thanks to their Chromecast support, so I no longer have to worry about marking things as watched manually with &lt;a href="http://seriesgui.de/"&gt;an app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another great advantage is being able to control your TV with basically any device in the house. I can pick my Mac up, choose a TV show and start watching, and then pick my phone up and turn the volume down on the TV. This makes everything seamless and much nicer to use.&lt;/p&gt;

&lt;p&gt;Because it's all going through Plex, it also means that I could stop watching something halfway through, and pick up where I left off on my phone. For example, I could watch QI on the way home on the Metro, and finish watching an episode on my TV using Chromecast when I got in.&lt;/p&gt;

&lt;p&gt;If you use Plex and have not yet got a Chromecast, then I really recommend it. It has made watching media a lot nicer experience overall. And if you do not use Plex, then try it out!&lt;/p&gt;

&lt;p&gt;Let me know how you get on in the comments.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Pushover</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Thu, 10 Oct 2013 12:00:00 +0000</pubDate>
      <link>https://dev.to/scottrobertson/pushover-12kl</link>
      <guid>https://dev.to/scottrobertson/pushover-12kl</guid>
      <description>&lt;p&gt;About 2 month ago, I found a nice service going by the name of pushover.net.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pushover makes it easy to send real-time notifications to your Android and iOS devices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I had a look around for a decent PHP library, but could not find one. Most of them either had way too much code for such a simple task (it's basically a curl call), or where totally untested.&lt;/p&gt;

&lt;p&gt;The library I built is very easy to use, and easy to setup. Below you can see an example of how to send a push notification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;include __DIR__. '/vendor/autoload.php';

$pushover = new \Scottymeuk\Pushover\Client(['token' =&amp;gt; '']);
$pushover-&amp;gt;message = 'testing';

// Push Single
$push = $pushover-&amp;gt;push($token);

// Push Multiple
$push = $pushover-&amp;gt;pushMultiple([
    $token1,
    $token2
]);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only downside to pushover.net is that the &lt;a href="https://pushover.net/clients"&gt;app&lt;/a&gt; costs, but with the amount of things I use it for, its been worth it.&lt;/p&gt;

&lt;p&gt;If you wish to try out the library, then you can view it on &lt;a href="https://github.com/scottrobertson/pushover"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Can't think of a use case? I built a quick CLI tool using the library to make it easy to push things to your mobile from your desktop. You can view that on &lt;a href="https://github.com/scottrobertson/push"&gt;Github&lt;/a&gt; too.&lt;/p&gt;

&lt;p&gt;If you do happen to use any of these, please let me know in the comments below.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Supervisor + PHP + Nginx</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Sun, 25 Aug 2013 12:00:00 +0000</pubDate>
      <link>https://dev.to/scottrobertson/supervisor-php-nginx-5ci1</link>
      <guid>https://dev.to/scottrobertson/supervisor-php-nginx-5ci1</guid>
      <description>&lt;p&gt;While reinstalling my Mac today I realised how easy it was to get PHP and Nginx working with Supervisor. However, if you asked me this the first time I set up my Mac, I probably would have screamed at you for not helping me.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://supervisord.org/"&gt;Supervisor&lt;/a&gt; allows you to manage any process with ease, and through a simple web UI. You can manage anything from PHP itself to long-running scripts. We use it on &lt;a href="http://romhut.com"&gt;romhut.com&lt;/a&gt; to manage the upload workers which are written in PHP, its very powerful to use, once you know.&lt;/p&gt;

&lt;p&gt;I figured I'd write a blog post to explain how simple it is and act as a copy and paste reference for me in the future.&lt;/p&gt;

&lt;p&gt;I am going to assume you have the following installing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://brew.sh/"&gt;Homebrew&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PHP (with "--with-fpm" option)&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, we need to install Supervisord, to do this we need to install "pip". You can do this by running the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;easy_install pip

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will then allow you to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo pip install supervisor

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now create our supervisord.conf file, which will tell Supervisor how and what to run. I created mine in &lt;strong&gt;/usr/local/etc/supervisord.conf&lt;/strong&gt;. Note that you can create it in a few different locations and Supervisord will automatically pick it up, have a look at their docs for this.&lt;/p&gt;

&lt;p&gt;The following is my &lt;strong&gt;supervisord.conf&lt;/strong&gt; file, which includes configs to run the web interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[inet_http_server]
port = 127.0.0.1:9001

; Deamon
[supervisord]
logfile = /var/log/supervisord.log
logfile_maxbytes = 50MB
logfile_backups = 5
loglevel = info
pidfile = /tmp/supervisord.pid
nodaemon = false
minfds = 1024
minprocs = 200
user = root
directory = /tmp
strip_ansi = true

; RPC Interface
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

; CTL
[supervisorctl]
serverurl = http://127.0.0.1:9001

[include]
files = /usr/local/etc/supervisor.d/*.conf

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you notice on the last line, we are including files from &lt;strong&gt;/usr/local/etc/supervisor.d&lt;/strong&gt;. This means we can place config files for PHP, Nginx etc in this folder to keep it cleaner, however, you can place all the configs in the above file if you so with.&lt;/p&gt;

&lt;p&gt;First off, we will create the config file for php-fpm in &lt;strong&gt;/usr/local/etc/supervisor.d/php.conf&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[program:php]
command = /usr/local/sbin/php-fpm
user = root
autostart = true

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above will run PHP on startup as root.&lt;/p&gt;

&lt;p&gt;Next we will add the Nginx config file in its respective file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[program:nginx]
command = /usr/local/bin/nginx
user = root
autostart = true

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will also run nginx on startup as root. You will also want to add the following to your main nginx config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;daemon off;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will stop nginx from daemonizing it's self and is needed for nginx to run smoothly.&lt;/p&gt;

&lt;p&gt;Run the following command to tell Supervisor to look for config file changes. Please note that you will need to run this every time you make a change to the config files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supervisorctl update

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should be it all set up ready for you to get these processes running. Simply type the following to test this out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supervisorctl start php;
supervisorctl start nginx;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHP and Nginx should now be running, to check this simply run. You should see "RUNNING":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supervisorctl status php

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get Supervisord to start when your Mac starts, you will want to use launchctl. Simply put the following inside &lt;strong&gt;/Library/LaunchDaemons/com.agendaless.supervisord.plist&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;
&amp;lt;plist version="1.0"&amp;gt;
&amp;lt;dict&amp;gt;
    &amp;lt;key&amp;gt;KeepAlive&amp;lt;/key&amp;gt;
    &amp;lt;dict&amp;gt;
        &amp;lt;key&amp;gt;SuccessfulExit&amp;lt;/key&amp;gt;
        &amp;lt;false/&amp;gt;
    &amp;lt;/dict&amp;gt;
    &amp;lt;key&amp;gt;Label&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;com.agendaless.supervisord&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;
    &amp;lt;array&amp;gt;
        &amp;lt;string&amp;gt;/usr/local/bin/supervisord&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;-n&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;-c&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;/usr/local/etc/supervisord.conf&amp;lt;/string&amp;gt;
    &amp;lt;/array&amp;gt;
    &amp;lt;key&amp;gt;RunAtLoad&amp;lt;/key&amp;gt;
    &amp;lt;true/&amp;gt;
&amp;lt;/dict&amp;gt;
&amp;lt;/plist&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;launchctl load /Library/LaunchDaemons/com.agendaless.supervisord.plist

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this stage, Supervisord should be running and ready to use, however, I do normally have to restart my Mac for things to work properly. This could have been due to launchctl having not been used before this.&lt;/p&gt;

&lt;p&gt;To check that it is running, simply go to &lt;a href="http://127.0.0.1:9001"&gt;http://127.0.0.1:9001&lt;/a&gt; in your browser, or use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supervisorctl status

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If all works well, you should see the following in your browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i0UvZzn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://scottrobertson.me/img/posts/supervisor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i0UvZzn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://scottrobertson.me/img/posts/supervisor.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any questions or suggestions please let me know in the comments below, or &lt;a href="https://twitter.com/scottymeuk"&gt;tweet me&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Dropbox Server Backups</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Sat, 24 Aug 2013 12:00:00 +0000</pubDate>
      <link>https://dev.to/scottrobertson/dropbox-server-backups-519j</link>
      <guid>https://dev.to/scottrobertson/dropbox-server-backups-519j</guid>
      <description>&lt;p&gt;Over the past few months I have been searching for a backup solution for my VPS's. I wanted a single solution that allowed me to backup multiple sources such as MongoDB, MySQL and the usual files.&lt;/p&gt;

&lt;p&gt;After a while searching, I decided I would build it myself, due to not being able to find the perfect solution.&lt;/p&gt;

&lt;p&gt;Before this, I simply had the Dropbox service running on each machine, and had a cron that copied mysqldump into the Dropbox folder, which was synced. This worked well, but it was quite laborious to setup.&lt;/p&gt;

&lt;p&gt;Because of this, I opted to use the Dropbox API directly to backup from the tool. This allowed me to deploy the script to any server (&lt;a href="https://blog.scottrobertson.me/post/git-deployments"&gt;see here&lt;/a&gt;) and the only dependencies are PHP and Curl.&lt;/p&gt;

&lt;p&gt;When setting it up, all you need to do is run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/console dropbox:auth

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give you an authorisation link for Dropbox, which will return a token which is used to build your config file.&lt;/p&gt;

&lt;p&gt;Once you have set the config file up (see the repo's README.md for details). You will be able to simply setup a cron to run the following for instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/console export:mysql

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will loop over each database you have access to, mysqldump them, gzip them and upload them to Dropbox. My MySQL (and MongoDB) backups, are set to backup once per hour, but the file is stored YMD, which means that the file will be overwritten. This would normally be a bad thing since you could overwrite with a bad backup easily, but because we are using Dropbox, it keeps internal revisions meaning that we have around 23 copied per day, but we keep the storage space to a minimum.&lt;/p&gt;

&lt;p&gt;If you would like to view the source, and maybe use the tool, then please head over to &lt;a href="http://github.com/scottrobertson/backup"&gt;Github&lt;/a&gt;. Let me know if you have any questions, or suggestions.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Git Deployments</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Thu, 22 Aug 2013 12:00:00 +0000</pubDate>
      <link>https://dev.to/scottrobertson/git-deployments-n1</link>
      <guid>https://dev.to/scottrobertson/git-deployments-n1</guid>
      <description>&lt;p&gt;For the past year or so I have been using Rsync to deploy my sites, which has worked perfectly for me until recently.&lt;/p&gt;

&lt;p&gt;I have recently switched to using a simple post-receive hook using a bare repo on the server. I find this works a lot better for me now as it means all I need to do is "push".&lt;/p&gt;

&lt;p&gt;First, you need to set up the repo on your server, I normally set it up in &lt;strong&gt;/var/git/site.com&lt;/strong&gt; for example. This will be a bare git repo, so it will not contain any of your own code. To set this up simply run the following inside your &lt;strong&gt;/var/git/site.com&lt;/strong&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init --bare

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will initialize the repository, allowing you to push your code to it.&lt;/p&gt;

&lt;p&gt;The next step is to tell git where to check your code out too. I usually use &lt;strong&gt;/var/www/site.com&lt;/strong&gt;. For this, I use a very simple post-receive hook that checks the code out to the folder and runs &lt;strong&gt;composer install&lt;/strong&gt;. You would place the following in &lt;strong&gt;/var/git/site.com/hooks/post-receive&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WORKING_DIR=/var/www/site.com;
GIT_WORK_TREE=$WORKING_DIR git checkout -f;
cd $WORKING_DIR &amp;amp;&amp;amp; composer install -o;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing to remember is to make the file executable by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x /var/git/site.com/hooks/post-receive

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that the repo and post-receive hooks are setup, we need to set up your development machine's git remotes. The easiest way to do this is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git remote add production user@site.com:/var/git/site.com

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will mean that you can simply run the following command to deploy your website:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push production master

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can obviously add anything else you wish to the post-receive hook, such as clearing cache, flushing cdn etc. I currently have most of mine set to restart php-fpm after &lt;strong&gt;composer install&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service php5-fpm restart

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have any questions, or I have missed anything, then please let me know below.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Route all .dev URL's to 127.0.0.1</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Thu, 18 Apr 2013 12:00:00 +0000</pubDate>
      <link>https://dev.to/scottrobertson/route-all-dev-url-s-to-127-0-0-1-4ccb</link>
      <guid>https://dev.to/scottrobertson/route-all-dev-url-s-to-127-0-0-1-4ccb</guid>
      <description>&lt;p&gt;If you're like me, you always forget to edit the /etc/hosts file when you want to view a local site.&lt;/p&gt;

&lt;p&gt;To get around this, you can use the following script to route all your .dev urls to 127.0.0.1 (or any other IP). So you could go to "romhut.dev" and that would load from 127.0.0.1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install dnsmasq
mkdir -pv $(brew --prefix)/etc/
echo 'address=/.dev/127.0.0.1' &amp;gt; $(brew --prefix)/etc/dnsmasq.conf
sudo cp -v $(brew --prefix dnsmasq)/homebrew.mxcl.dnsmasq.plist /Library/LaunchDaemons
sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
sudo mkdir -v /etc/resolver
sudo bash -c 'echo "nameserver 127.0.0.1" &amp;gt; /etc/resolver/dev'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you wish to use another IP, only change the first 127.0.0.1, otherwise it will look for a name server on the host.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Select A Character in a String with PHP</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Fri, 01 Feb 2013 12:00:00 +0000</pubDate>
      <link>https://dev.to/scottrobertson/select-a-character-in-a-string-with-php-ehk</link>
      <guid>https://dev.to/scottrobertson/select-a-character-in-a-string-with-php-ehk</guid>
      <description>&lt;p&gt;I love finding little thing in PHP that I did not know before. They are generally not important or advanced but it's still very interesting. Here are a few I found recently:&lt;/p&gt;

&lt;p&gt;Select a character with a string without using substr etc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$string = '1234';
echo $string[1]; // 2

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another one i found was "__halt_compiler", it's one of the ones i have no real use for but interesting nonetheless. It basically stops the PHP compiler so you can just output HTML from then on without any more server resources being used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;__halt_compiler();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I shall no doubt find a lot more of these, and i will have no use for any of them more than likely.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Google's Mod_Pagespeed</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Tue, 23 Oct 2012 12:00:00 +0000</pubDate>
      <link>https://dev.to/scottrobertson/google-s-modpagespeed-2dcn</link>
      <guid>https://dev.to/scottrobertson/google-s-modpagespeed-2dcn</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;mod_pagespeed speeds up your site and reduces page load time. This open-source Apache HTTP server module automatically applies web performance best practices to pages, and associated assets (CSS, JavaScript, images) without requiring that you modify your existing content or workflow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I was in the process of setting up my new VPS, I decided I would try out mod_pagespeed (conveniently it had just come out of beta a few days earlier). It turns out, it's very easy to set up and very easy to use.&lt;/p&gt;

&lt;p&gt;First of all, you need to download the correct package at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://developers.google.com/speed/docs/mod_pagespeed/download

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have downloaded it, its as simple as running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dpkg -i mod-pagespeed-*.deb
apt-get -f install
Or for CentOS you run
yum install at # if you do not already have 'at' installed
rpm -U mod-pagespeed-*.rpm

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default install includes things such as the minification of CSS and js files and also the combining of CSS files (js can be enabled too). Inline images, CSS, and js is also enabled by default, which allows these types of files to be included in the main HTML layout if they are small enough to justify doing so. This will save requests to the server for more files.&lt;/p&gt;

&lt;p&gt;As well as the defaults, i decided to enable a few none default options in the config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/apache2/mods-available/pagespeed.conf
The ones i decided to enable where the following:
ModPagespeedEnableFilters inline_preview_images # Load low quality images before loading high quality ones
ModPagespeedEnableFilters resize_images # Resize the images before serving them (These are then cached in Varnish)
ModPagespeedEnableFilters insert_image_dimensions # If any image does not have width, height set, then insert them
ModPagespeedEnableFilters combine_javascript # Combine javascript files into one file
ModPagespeedEnableFilters collapse_whitespace # Minify the HTML output of the page
ModPagespeedEnableFilters resize_mobile_images # Resize smaller images on mobile
ModPagespeedEnableFilters remove_comments # Remove comments from JS,CSS and HTML files.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some are not 100% ready for production but the risk value of them is quite low.&lt;/p&gt;

&lt;p&gt;From initial tests, it seems to have reduced the page load by about 1/3. Which on a small site may not be a lot, but on a big site with a lot of images etc, this could be a huge saving in bandwidth costs, and also a lot nicer experience for the user.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Copy SSH Keys to Server</title>
      <dc:creator>Scott Robertson</dc:creator>
      <pubDate>Fri, 12 Oct 2012 12:00:00 +0000</pubDate>
      <link>https://dev.to/scottrobertson/copy-ssh-keys-to-server-2164</link>
      <guid>https://dev.to/scottrobertson/copy-ssh-keys-to-server-2164</guid>
      <description>&lt;p&gt;When you wish to log in to a server without having to enter a password, all you need to do is log in with SSH. However I do not know why, but it took me hours to find a simple way to do this a few years ago.&lt;/p&gt;

&lt;p&gt;First of all, you need to generate your SSH keys using the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-keygen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this point, I generally just hit enter and use the defaults. You can set a password, but that can get annoying.&lt;/p&gt;

&lt;p&gt;Now you need to copy the SSH keys to the server you wish to log in to. I have found many ways to do this, but none have been as simple as the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-copy-id username@server.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will then be asked for your password for the last time. Once this has complete, you will be able to login to the server using just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh username@server.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
