Ubuntu Development Setup

Install Git

sudo apt-get -y install git

Setup Git

  1. Name and Email
git config --global user.name "Md. Atiqul Islam"
git config --global user.email "[email protected]"
  1. Shortcut
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global credential.https://github.com.username atiq1589

Setup SSH

SOURCE

  1. Generate ssh key
    • go to ~/.ssh
    cd ~/.sshIf you do not have .ssh folder create itmkdir ~/.ssh && cd $\_+ run below command and follow the stepsssh-keygen -t rsa -b 4096 -C "[email protected]"
  2. turn on ssh-agenteval "$(ssh-agent -s)"
  3. Add your SSH key to the ssh-agentssh-add ~/.ssh/your_file_name
  4. Copy .pub content (xclip is not working by the time i write this document)cat ~/.ssh/your_file_name.pub with xclipxclip -sel clip < ~/.ssh/id_rsa.pub
  5. Go to github settings page and add this key
  6. test your ssh connectionssh -T [email protected] ***Hi atiq1589! You’ve successfully authenticated, but GitHub does not provide shell access.***

automatically add ssh key for win bash

SOURCE

  1. Add below command in ~/.bashrc fileif [ -z "$SSH_AUTH_SOCK" ] ; then eval `ssh-agent -s` ssh-add fi
  2. install expectsudo apt-get -y install expect
  3. make a script#!/usr/bin/expect -f spawn ssh-add /home/user/.ssh/id_rsa expect "Enter passphrase for /home/user/.ssh/id_rsa:" send "passphrase\n"; interact For my local pc: ***./mnt/e/work/Resources/bash-command/add-ssh.sh***

Install Docker

SOURCE

echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list

Install Ruby

SOURCE

sudo apt-get install -y ruby

or

sudo apt-get install -y ruby-full

latest ruby

SOURCE

sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev
cd
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL

git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
exec $SHELL

rbenv install 2.3.1
rbenv global 2.3.1
ruby -v

Install LAMP

SOURCE

Install Apache

sudo apt-get install apache2

Install MySQL

sudo apt-get install mysql-server

Install PHP

sudo apt-get install php5 libapache2-mod-php5

Restart Server

sudo /etc/init.d/apache2 restart

or

sudo service apache2 {command [restart, start, stop]}

Check PHP

php -r 'echo "\n\nYour PHP installation is working fine.\n\n\n";'

Install xclip

sudo apt-get -y install xclip

Install NVM (Node Version Manager)

SOURCE

Curl

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash

Wget

wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash

Test

nvm -v 

Use node version per folder

  1. Need to create .nvmrc file in that folder
  2. put version number on that file (.nvmrc)
$ echo "5.9" > .nvmrc

$ echo "lts/*" > .nvmrc # to default to the latest LTS version
  1. then run
nvm use
  1. Automatically load node version.
# place this after nvm initialization!
autoload -U add-zsh-hook
load-nvmrc() {
  local node_version="$(nvm version)"
  local nvmrc_path="$(nvm_find_nvmrc)"

  if [ -n "$nvmrc_path" ]; then
    local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

    if [ "$nvmrc_node_version" = "N/A" ]; then
      nvm install
    elif [ "$nvmrc_node_version" != "$node_version" ]; then
      nvm use
    fi
  elif [ "$node_version" != "$(nvm version default)" ]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc

Install Node

SOURCE

  1. Install NVM
  2. Install Node
nvm install node 

or 
nvm install #version

nvm install 6.9.1

Test

node -v

or 
Check NPM

npm -v

Install Bower

SOURCE

 npm install -g bower

Install python

There is aleardy python2 installed

install pip

sudo apt-get install python-pip

Check pip

pip --version

install Coffee scripts

SOURCE

npm install -g coffee-script

Install Nonemon

SOURCE github

npm install -g nodemon

Install PostgreSQL

  1. Install postgresql
sudo apt-get install postgresql postgresql-contrib
  1. Change password
sudo -i -u postgres
psql
\password postgres

Follow instruction 3. quite

\q
  1. Restart
sudo service postgresql restart

Install Redis

SOURCE

wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make
sudo ln -s path/to/redis-stable/src/redis-server /usr/bin

Install ZSH

sudo apt-get install zsh

Install oh-my-zsh

SOURCE Curl

sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

wget

sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"

Install Theme

SOURCE

Add ZSH_THEME="gnzh" in ~/.zshrc

or

match="robbyrussell"
sed -i -e 's/'$match'/gnzh/g' .zshrc

To Enable ZSH in windows 10 bash add

# Launch Zsh
if [ -t 1 ]; then
exec zsh
fi

in ~/.bashrc file 
It has some problem to start other commands. Need to fix that first


Helpful Supporting package

  1. Dev package
sudo apt-get install libffi-dev
sudo apt-get install libssl-dev
sudo apt-get install python-dev

Helpful custom function

  1. To access drive directly add below command in ~/.bashrc file
drive(){
    cd /mnt/$1;
}

and run

source ~/.bashrc

Install NVM (Node Version Manager) Mac

  1. use brew to install nvm

brew install nvm

  1. make sure you have this line added to your bash_profile file

export NVM_DIR=~/.nvm

source $(brew --prefix nvm)/nvm.sh

  1. install version of node you want

nvm install v4.0.0

  1. use the appropriate node version

nvm use v4.0.0

Express intall empty express application

npm install -g express-generator

This will create a symlink in bin which points to express module in ~/.nvm/versions/v4.0.0/lib/node_modules/ ~/.nvm/bin/express is the symlink created. This is automatically sourced since .nvm/bin is in the path mentioned in .bash_profile or .bashrc dependending on the shell you use

create a empty dir to install express app

mkdir express

install a default express app

express

This will create the folder structure of the app

install express

in the express folder type

npm install

Start a Project

Create empty dir project1

mkdir project1

cd project1

type express –help

express --help

css option stylus

We will use stylus css option so when we create an app using express use

express --css stylus

package.json

package.json has all the dependencies of the project. it is similar to maven

vim package.json

install app using package.json

npm install

npm install will install app using package.json. It will include all depdencies on package.json

launch the application

npm start

localhost 3000

app starts on localhost 3000 do a curl -i (-i is the get response headers). node js and express have an inbuilt server which launches on port 3000 after npm start

curl -i localhost:3000

What does package.json do

package.json has a dependency section

npm install looks at these dependecies and installs them in node_modules. Do not checkin node_modules

stylus files

.styl files are css preprocessors which have code to generate css. node will read these files and generate css files. These files are in the public/stylesheets

routes

routes is a switch board. currently when you start app it will just have the index view

views

views are present in /views folder. It will have a index.jade which extends from layout.jade

app.js

first block is requires. the next instantiates app and next sets config option. app.use is middleware code. Note the app.use(“/”, “routes”) This says routes has the root index, which will render index.js route

JADE

Jade is a templating engine processed on server side. It has syntax built on indentation

STYLUS

stylus is a css language. It can assign variables to to constants

eg link:color = #FFFFFF. a{color: link-color} instead of repeating FFFFF all around code (similar to public static String in java)

check style.styl in project created

BOOTSTRAP

stacked to horizontal(one of the mostly used features)

we can create a row and in the row can have div with classes .col-mid-1 etc. Search stacked to horizontal in bootstrap site

Bootstrap too comes with less and saas version apart from its css version

STATIC FILES

static files are served using the public folder in the project. If I create a file named hello.html in public folder it can be accessed as http://localhost:3000/hello.html. Basically public is root for static files

TEMPLATES OTHER THAN JADE AND STYLUS

moustache

moustace is tamplating engine which uses curly braces {}. One of the main things in moustache is that it can be used with many languager

Handlebars.js

build only for javascript. it is build over moustache and provides server side and client side templating

to use handlebars put express-handlebars in package.json and install it using npm install, then change your views engine in app.js and then make sure you name views with .handlebars extension

Saas

saas is another preprocessor option built with ruby. with epxress you can use it using express --css compass

less

less is another css preprocessor built with javascript

INTRO TO SOME COMMONLY USED JS LIBRARIES

Passport js

  • passport js is used to login user basically to authenticate
  • you can login via facebook, twitter etc
  • we can also use local username and password system

Mongoose js

  • Used to access mongo db

Karma Test Runner

  • Test runner for node js

Mocha js

  • Testing framework for node js*

Chai

  • An assertion library for node*

Sinon js, supertest

  • Sinon js is mocking library, supertest is a helper utility

CREATING APPLICATION

package.json

{
  "name": "project1",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.13.2",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "express": "~4.13.1",
    "jade": "~1.11.0",
    "morgan": "~1.6.1",
    "serve-favicon": "~2.3.0",
    "stylus": "0.42.3",
    "passport": "0.2.*",
    "mongoose": "3.8.*"
  },
  "devDependencies": {
    "chai": "1.10.*",
    "karma": "0.12.*",
    "mocha": "2.0.*",
    "sinon": "1.11.*",
    "supertest": "0.10.*"
  }
}

versioning in node

  • version is specified as “somemodule”: “major:minor:revision”
  • eg “express”: “2.10.3”
  • 2 is major version which signifies incomaptible release change, 10 is minor version which signifies incremental feature release, 3 is revision number which rignifies a bug fix

routes

  • We will not require the users routes so in app js comment out the following
    • var users = require(‘./routes/users’);
    • app.use(‘/users’, users);
    • delete users.js file in routes folder
  • build a contact route
    • create a file contact.js in routes
    • start off with 2 requires to bring in necessary modulesvar express = require('express'); var router = express.Router();
    • now we need to make our contact route and export it since we want to make it public
    router.get('/',function(req,res){ res.send("it worked"); }); module.exports = router
    • note the second arg to get is a anonymous function
    • Even if we write code in routes/{app}.js it dosent work until we make changes in app.js
    app.js changes
    • Where we have the index route import the contact route
    var contacts = require('./routes/contacts')
    • Also include use where we have specified index use
    app.use('/contacts', contacts); supervisor
    • restart the server after changing javascript. To void restarting the server again and again we will use supervisor. supervisor just does a ctrl +c and npm start again after we save a file
    // add supervisor in devdependencies "devDependencies":{ "supervisor": "*" }
    • Then run npm install
    • now supervisor is in your node_modules in bin
    • put this script in the scripts section of package.json
    "scripts": { "start": "node ./node_modules/.bin/supervisor ./bin/www" },
    • then say npm start

create user interface

  • we will use bootstrap to create nice user interfaces for our application
  • in order to use bootstrap we need to import it in style.styl file in public/stylesheets folder
  • put the below 2 lines in “style.styl*
  • also make sure to download the css version of bootstrap and put it in public/stylesheet folder
  • your stylesheet folder should now contain
    • style.styl
    • style.css
    • bootstrap.min.css
    • bootstrap.theme.css
import "bootstrap.min.css"
import "bootstrap.theme.css"

create contacts html for project

  • create a file list.jade in views folder and put in the contact information html
  • contact information html file list.jade (note the pipe character | on line 8. This means continue with the name p tag in jade, if that wasnt there the 2 buttons will be squisshed side by side)

create 3 files in views folder

  • editform.jade
.form-group
  label(for="fullname") Full Name
  input#fullname.form-control(name="fulname", type="text")
.form-group
  label(for="job") Job/position
  input#job.form-control(name="jon", type="text")
.form-group
  label(for="nickname") nickname
  input#nickname.form-control(name="nickname", type="text")
.form-group
  label(for="email") E-mail Address
  input#email.form-control(name="email", type="text")
  • add.jade
extends layout

block content
  .row
    .col-md-6
      h1 Add a contact
      form(role="form", method="post", action="")
        include editform
        button.btn.btn-primary(type="submit") Add user
            
  • edit.jade
extends layout

block content
  .row
    .col-md-6
      h1 Add a contact
      form(role="form", method="post", action="/contacts/1")
        include editform
        button.btn.btn-primary(type="submit") Edit user
    .col-md-6
      h2 Notes
      form(roles="form", method="post", action="/contacts/1")
        dl
          dt Jan 2 2014
          dd Prefers italian food
          dt Jan 19 2014
          dd Just moved into a new office
        .form-group
          label(for="notes")
          textarea#notes.form-control(name="notes")
        button.btn.btn-default(type="submit", value="addnote") Add note
  • note we have followed DRY principle. Do not repeat yourself, by extracting the common in add.jade and edit.jade into editform.jade

** put the new jade templates in contact.js **

  • open contacts.js
  • change res.send to res.render()
  • render takes 2 parameters
    • name of the jade template
    • object that needs to be passed in
  • in short replace the below in contact.js
    • res.send(“it worked”); with res.render(“list”, {});
  • also add a template for add to render the add template

modify contact.js and add the edit and add templates using render

var express = require('express');
var router = express.Router();

router.get('/',function(req,res){
     res.render("list", {});
 });

 router.get('/add', function(req,res){
   res.render('add', {});
 });

 router.route('/contact_id')
  .all(function(req,res,next){
    contact_id = req.params.contact_id;
    next();
  })
  .get(function(req,res){
    res.render('edit', {});
  })
  .post(function(req,res){
    res.send('Post for contact '+ contact_id);
  })
  .put(function(req,res){
    res.send('Put for contact '+ contact_id);
  })



 module.exports = router

add the Contacts button to index.jade

extends layout

block content
  h1= title
  p Welcome to #{title}
  p
    a.btn.btn-default(href="/contacts/") View Contacts

When to use template and when not to (Logic-Less Templates)

  • Logic is code that makes a decision and acts upon it
  • JADE takes dynamic data and converts it into html
  • routes make complicated decisions and chooses what template to show

Dynamic data in jade

  • we dont have a database so we will create in memory database by using javascript objects
  • first install the underscore library . cd into the project directory and execute below
npm install underscore --save

  • You will see that underscore is created in
[email protected] node_modules/underscore
  • –save will install it and automatically add to the package.json as well
  • now in contact.js add the following line
var _ = require('underscore');
  • also include two helper functions
function lookupContact(contact_id){
  return _.find(contacts, function(c){
    return c_id = parseInt(contact_id);
  });
}

function findMaxId() {
  return _.max(contacts, function(contact){
    return contact.id;
  });
}
  • now we want to add a list to show all the contacts
In contact.js
router.get('/',function(req,res){
     res.render("list", {contacts: contacts});
 });
  • method to post a contact should be updated. We will get the last id and then get data from form and post the data
In contact.js
router.post('/', function(req,res){
      var new_contact_id = findMaxId() + 1;
      var new_contact = {
        id: new_contact_id,
        name: req.body.fullname,
        job: req.body.job,
        nickname: req.body.nickname,
        email: req.body.email
      }

      contacts.push(new_contact);

      res.send('New contact created with id: ' + new_contact.id);
      //res.redirect('/contacts/');
 });
  • the get method for contacts is same but in order to be compatible we will add the data section
 router.get('/add', function(req,res){
   res.render('add', {contact:{}});
 });
  • and then we will add lookup_contact method in .all method
  • Every router needs that so we will avoid code duplication and do it only once
router.route('/contact_id')
  .all(function(req,res,next){
    contact_id = req.params.contact_id;
    contact = lookupContact(contact_id);
    next();
  })
  • edit method will have the contact as the data to be passed
 .get(function(req,res){
    res.render('edit', {contact:contact});
  })
  • post method will be to add notes
.post(function(req,res){
  if(!contact.notes){
    contact.notes = [];
  }
  contact.notes.push({
    created: Date(),
    note: req.body.notes
  });
  res.send('Created new note for contact id '+ contact_id);
  //res.redirect('/contact'+contact_id);
})
  • .put method will be used to update the contact
put(function(req,res){
  contact.name = req.body.fullname;
  contact.job = req.body.job;
  contact.nickname = req.body.nickname;
  contact.email = req.body.email

  res.send('Update succeeded for contact id '+ contact_id);
  //res.redirect('/contacts/');
})

changes to JADE file for dynamic content

  • initial jade file
  extend layout

block content
    h1 Your contacts
    p Here is the list of your contacts
    p
      a#delete.btn.btn-default(href="#") Delete
      | 
      a#add.btn.btn-default(href="/contacts/add") Add new
      table.table
        thead
          tr
            th
            th Name
            th Nickname
            th Email
          tbody
            tr
              td
                input(type="checkbox", id="1")
              td
                a(href="/contacts/1") Joe Smith 
                | Plumber
              td Joe
              td
                a(href="mailto:[email protected]") [email protected]
            tr
              td
                input(type="checkbox", id="2")
              td
                a(href="/contacts/2") pratik kale 
                | Carpenter
              td Joe
              td
                a(href="mailto:[email protected]") [email protected]
            tr
              td
                input(type="checkbox", id="3")
              td
                a(href="/contacts/3") litesh sajnani 
                | engineer
              td Joe
              td
                a(href="mailto:[email protected]") [email protected]
                
  • new jade with dynamic content
 extend layout

block content
  h1 Your contacts
  p Here is the list of your contacts
  p
    a#delete.btn.btn-default(href="#") Delete
    | 
    a#add.btn.btn-default(href="/contacts/add") Add new
    table.table
      thead
        tr
          th
          th Name
          th Nickname
          th Email
        tbody
          if !contacts.length
            tr
              td(colspan=4) You should add a contact
          else
            each contact in contacts
              tr
                td
                  input(type="checkbox", id =contact.id)
                td
                  a(href="/contacts/#{contact.id}") #{contact.name}
                  | #{contact.job}
                td #{contact.nickname}
                td
                  a(href="mailto:#{contact.email}") #{contact.email}

Testing

** Full stack testing **

  • Selenium is a popular Full stack testing tool
  • it takes control of the browser and takes control of your application as user would
  • it tests the entire website from css to JS to html to infrastructure to backend to database
  • Its end to end testing from browser to database
  • full stack testing is slow
  • protractor(javascript) and sst(python) can write code to run selenium (we can code tests to invoke selenium)
  • Also selenium will not make it clear where in code the problem lies. eg we might get error on UI but the problem might be network connectivity at backend or just a temp network glitch or a code error ..we dont know
  • Hence we write unit tests

Test tools

  • in package.json check devDependencies we have karma(test runner)mocha(test framework) and chai(assertion library)
  • We also have sinon which is mocking library
  • We have supertest which is a test client to test middleware and routes without starting the node app
  • notice the script section
    • we have a start script.so npm start will just help us to start the app
    • There is no magic it will just execute stuff in ./bin/www and will start the app
  • similarly we need something like test
    • so in script section add the following
    • "test":"./node_modules/.bin/mocha -u tdd"
    • scripts will now look like
    "scripts": {
    "start": "node ./node_modules/.bin/supervisor node ./bin/www",
    "test": "./node_modules/.bin/mocha -u tdd"
    },
  • if we do an npm test now we will get an error since we dont have a folder called test
  • now say npm test you will see a message saying 0 test passing
  • In test folder create a file called demo.js. It dosent matter what its called it should just have a .js extension
  • We will first import chai in demo.js

** First Test **

var chai = require('chai');
var assert = chai.assert;

//test are grouped into suite using describe function
//typically we put suite into a file as same name of module it loads
//so typically we will have 1 describe for a file
//we cannot have a describe inside describe

describe('First test suite', function(){
  x = 0;
  it('Should pass', function() {
    assert.equal(1,x);
  });
});

  • it function takes a label and a function
  • label begins with should keyword to describe what the test should do
  • lets create a beforeEach function in our test suite
  • beforeEach function runs before every test

var chai = require('chai');
var assert = chai.assert;

beforeEach(function(){

x = x+1

})


describe('First test suite', function(){
  x = 0;
  it('Should pass', function() {
    assert.equal(1,x);
  });
});


  • now with above the test should pass
  • lets see another example of beforeEach function
  • The below test should fail since beforeEach is run for every test. so one test passes but other fails
var chai = require('chai');
var assert = chai.assert;

beforeEach(function(){

x = x+1

})


describe('First test suite', function(){
  x = 0;
  it('Should pass', function() {
    assert.equal(1,x);
  });
  
  it('Should also pass', function(){
    assert.equal(1,x);
  });
  
});

  • afterEach function runs after every test
  • lets use after each and fix the above.. we will set x to 0 after each test
var chai = require('chai');
var assert = chai.assert;

beforeEach(function(){

x = x+1

});

afterEach(function(){

x = 0;

});


describe('First test suite', function(){
  x = 0;
  it('Should pass', function() {
    assert.equal(1,x);
  });
  
  it('Should also pass', function(){
    assert.equal(1,x);
  });
  
});

  • Documentation for chai assert library

chaijs assert

  • So this is how it goes
    • We write a module
    • Then we test the module
    • Check if things work as expected

** Testing some real code: test-Jade**

  • This time we will require jade and call a test called jade render
  • We will add a jade template and make the test fail first
    • add a div with word hello
    • check the expected result
var chai = require('chai');
var assert = chai.assert;

var jade = require('jade');

beforeEach(function(){

x = x+1

});

afterEach(function(){

x = 0;

});


describe('First test suite', function(){
  x = 0;
  it('Should pass', function() {
    assert.equal(1,x);
  });

  it('Should also pass', function(){
    assert.equal(1,x);
  });


  it('Jade test', function(){
    var template = "#container hi";
    var expected = '<div id = "container"></div>';
    var result = jade.render(template);
    assert.equal(expected,result);
  });

});

  • In out Project instead of importing jade we will import our module
  • Otherwise the principles are the same

** Testing http requests **

  • We need to require supertest for this
  • We also need to ** require our app ** file
  • We need to use relative path to our module to get the app file ../app

** Test contact and expect 200 ok **


var chai = require('chai');
var assert = chai.assert;

var jade = require('jade');

var request = require('supertest');

var app = require('../app');

beforeEach(function(){

x = x+1

});

afterEach(function(){

x = 0;

});


describe('First test suite', function(){
  x = 0;
  it('Should pass', function() {
    assert.equal(1,x);
  });

  it('Should also pass', function(){
    assert.equal(1,x);
  });


  it('Jade test', function(){
    var template = "#container";
    var expected = '<div id = "container"></div>';
    var result = jade.render(template);
    assert.equal(expected,result);
  });

  it('Supertest test', function(done){
    request(app).get('/contacts')
    .expect(200,done);
  });


});


** note done above us used for asyn testing **

** expect expects a 200 when stuff is done **

Karma client side testing

  • karma loads browser runs test and reports
  • karma is installed in ./node_modules/karma/bin
  • to initialize karma run the below
./node_modules/karma/bin/karma init
  • It will ask me a bunch of questions
  • For which framework to use? press tab till it says Mocha
  • Do you want to use requirejs press no
  • We can capture Chrome automatically
  • next line just press enter since we will only test in chrome..we can also use multiple browsers
  • We need to tell karma where our javascript files are , they are in public/javascripts/**/*.js
  • We will also place some files in
  • so we will also tell karma to include files in browser-tests/**/*.js
  • we currently dont have any files..hit enter on blank line after entering all files
  • Now we have the option to exclude files. You can just press enter to leave this blank
  • Press no -> to run tests automatically if files change
  • to run karma run ./node_modules/karma/bin/karma start –single-run
  • we will make it easy to run karma by adding run configuration in package.json file
  • add karma to the scripts in package.json
"scripts": {
    "start": "node ./node_modules/.bin/supervisor node ./bin/www",
    "test": "./node_modules/.bin/mocha -u tdd"
    "karma": "./node_modules/karma/bin/karma start --single-run"
  },
  

Atom PHP Environment + CodeIgniter 3 & 4

Atom Editor

Install

Download and install Atom Editor:

cd ~/Downloads
wget https://github.com/atom/atom/releases/download/v1.15.0/atom-amd64.deb
sudo dpkg -i atom-amd64.deb

Install required SO packages:

sudo apt install php php-sqlite3 php-mbstring sqlite3 composer npm

Code Formatters

atom-beautify uses JS Beautify by default.

sudo npm -g install js-beautify
apm install atom-beautify

For PHP, atom-beautify follow coding standards from php-codesniffer.

Install php-codesniffer:

sudo apt install php-codesniffer

After, you can see the default Standards with the command phpcs -i. The output will be like:

The installed coding standards are PEAR, Squiz, MySource, PHPCS, Zend, PSR1 and PSR2

CodeIgniter has your own Codeing Standard and the CodeIgniter-for-PHP_CodeSniffer follow this rules.

We can install the CodeIgniter Standard as follow:

mkdir CodeIgniter-for-PHP_CodeSniffer
cd CodeIgniter-for-PHP_CodeSniffer
wget https://github.com/thomas-ernest/CodeIgniter-for-PHP_CodeSniffer/archive/master.zip
unzip master.php

Now, lets put the src folder in the correct path:

sudo cp -r CodeIgniter-for-PHP_CodeSniffer-master/src/ /usr/share/php/PHP/CodeSniffer/Standards/CodeIgniter/

Now, the output of phpcs -i will be:

The installed coding standards are PEAR, Squiz, MySource, PHPCS, Zend, PSR1, PSR2 and CodeIgniter

If do you wnat, you can change the PHPCBF Standard to CodeIgniter.

TODO: Is possible setup PHPCBF Standard by project-manager file?

Linters

sudo npm -g install linter
sudo npm -g install htmlhint
sudo npm -g install csslint
sudo npm -g install jshint

apm install linter
apm install linter-htmlhint
apm install linter-csslint
apm install linter-jshint

The Awesome

PHP Integrator is a powerfull project that provides code analysis and utilities for PHP projects.

PHP Integrator uses composer to install the core and you need install the correct version corresponding to the php-integrator-base version.

composer global require php-integrator/core 2.1.1

PHP Integrator uses the project-manager to activate resources based by project.

Lets install the Atom packages:

apm install project-manager
apm install php-integrator-base
apm install php-integrator-linter
apm install php-integrator-annotations
apm install php-integrator-autocomplete-plus
apm install php-integrator-call-tips
apm install php-integrator-navigation
apm install php-integrator-tooltips
apm install php-integrator-refactoring

CodeIgniter

Atom CodeIgniter

When you works on a CodeIgniter 3 project you can download this file https://raw.githubusercontent.com/natanfelles/codeigniter-phpstorm/master/phpstorm.php inside your project root.

After go to Atom and open the menu Packages > Project Manager > Edit Projects and configure your project like it:

{
  title: "CodeIgniter 3"
  paths: [
    "/home/username/codeigniter3"
  ]
  icon: "icon-flame"
  devMode: false
  php:
    enabled: true
    php_integrator:
      enabled: true
      phpVersion: 5.6
      excludedPaths: [
          "{0}/application/cache/",
          "{0}/application/logs/",
          "{0}/system/core/Controller.php",
          "{0}/system/core/Model.php"
      ]
      fileExtensions: [
        "php"
      ]
}

This tip will do PHP Integrator do not read the Controller.php and Model.php from the system folder, then it will use all the @property from phpstorm.php file.

You can read more about it in Code Completion for CodeIgniter in phpStorm and here Excluding Folders From Indexing.

On CodeIgniter 4 you do not need do this config. PHP Integrator will works natively well.

Extras

Some extra packages that I like:

apm install atom-ternjs
apm install color-picker
apm install pigments
apm install git-plus
apm install docblockr
apm install bootstrap3-snippets
apm install file-icons
apm install editorconfig
apm install todo-show
apm install highlight-selected
apm install emmet
apm install minimap
apm install language-htaccess
apm install language-markdown
apm install linter-write-good
apm install linter-json-lint
apm install api-docs
apm install sync-settings

Ubuntu 18.04 LAMP Setup

Note: Because this is my personal cheat sheet, I’m installing a few PHP modules that you may not need if you’re not running SilverStripe 4.x.x. Otherwise this is a pretty standard and secure LAMP installation.

SECURITY FIRST: Add a sudo user, require public key authentication and disable root login

Log into the remote machine as root: ssh [email protected]

First, add the admin user.

adduser <username>

Add user to sudo’ers:

gpasswd -a <username> sudo

Add your .pub key to authorized_keys and set permissions

mkdir /home/username/.ssh

nano /home/username/.ssh/authorized_keys

Paste your key into the authorized_keys file and save.

chown -R newuser:newuser /home/username/.ssh

chmod 700 /home/username/.ssh

chmod 600 /home/username/.ssh/authorized_keys

Edit the SSH configuration file to enable public key authentication only and disable password login:

nano /etc/ssh/sshd_config

Set this parameter to ‘yes’:

PubkeyAuthentication

Set these parameters to ‘no’:

PermitRootLogin, ChallengeResponseAuthentication, PasswordAuthentication, UsePAM

Save, close and reload the SSH config file:

sudo service ssh reload

Exit the remote machine:

exit

Try to reconnect as the new user. You should not be prompted for a password:

ssh [email protected]

Trying to SSH into the server from another machine you should receive this error: Permission denied (publickey)

Disable root login

As the admin user:

sudo passwd -l root

You will be prompted to enter the sudo user’s password.

SECURITY SECOND: Add a firewall.

sudo apt-get install ufw

Make sure IPv6 is enabled (you are using IPv6, correct?)

sudo nano /etc/default/ufw

IPV6=yes

Save and close and set up rules.

Allow connections:

sudo ufw allow <port>/<optional: protocol>

Examples:

sudo ufw allow 80/tcp or sudo ufw allow 80 or sudo ufw allow www

Deny Connections:

sudo ufw deny <port>/<optional: protocol>

Example:

sudo ufw deny 3306 (Deny default mysql port)

Start by denying all incoming and enabling all outgoing:

sudo ufw default deny incoming

sudo ufw default allow outgoing

Then allow incoming for services you need:

sudo ufw allow ssh

sudo ufw allow http

sudo ufw allow https

Finally, enable the firewall

sudo ufw enable

Common inbound ports to leave open

  • 80 http
  • 443 https
  • 22 ssh

Common inbound ports to close

  • everything else

LAMP installation and setup (mod_php)

Install Apache

sudo apt-get update

sudo apt-get install apache2 -y

Install MariaDB

sudo apt-get install software-properties-common

sudo apt install mariadb-server mariadb-client

You might be prompted to give root a password. Just leave it blank

Run the MySQL secure installation

sudo mysql_secure_installation

Remember to set a root password. By default connections to MariaDB are done through unix_socket. In the next steps you will create a non-root user. For that user you can use password authentication is necessary.

  1. Database creation

Log into MariaDB

sudo mysql -u root

Create a new database

CREATE DATABASE mydb;
  1. User creation
CREATE USER [email protected] IDENTIFIED BY 'newuserpassword';
  1. Grant all privileges to the on a specific database. Only allow access from localhost (this is the most secure and common configuration you will use for a web application)
GRANT ALL privileges ON mydb.* TO [email protected];
  1. Apply changes made

Exit MySQL

exit;

Install PHP

sudo apt-get install libapache2-mod-php php-gd php-curl php7.2-xml php-mysql php-gettext php-mbstring php-xdebug php-intl

Set date.timezone in php.ini

date.timezone = America/Los_Angeles

upload_max_filesize = 20M

post_max_size = 20M

For development:

display_errors = On

Enable Apache mods

sudo a2enmod rewrite headers deflate expires

Optionally install mailutils

sudo apt-get install mailutils

Postfix is now set up with a default configuration. If you need to make changes, edit /etc/postfix/main.cf

After modifying main.cf, be sure to run ‘/etc/init.Distinctlm.com/postfix reload’

Ubuntu 18.04 Apache Web Server Setup

This tutorial shows you how to install a LAMP stack under Ubuntu 18.04 LTS (Bionic Beaver).

Requirements

Install Apache, PHP, MySQL

All required components can be installed from the official package sources. Here you can install other server components besides Apache, MySQL and PHP.

Expert info: During the installation, a password for the database administrator root is always requested. Please choose this password carefully and keep it safe. And please do not confuse the database administrator with the system administrator account root. They are two completely different users, even if the name is identical.

sudo apt-get update
sudo apt-get install vim zip unzip -y
sudo apt-get install apache2 -y
sudo apt-get install mysql-server mysql-client libmysqlclient-dev -y
sudo apt-get install libapache2-mod-php7.2 php7.2 php7.2-mysql php7.2-sqlite -y
sudo apt-get install php7.2-mbstring php7.2-curl php7.2-intl php7.2-gd php7.2-zip php7.2-bz2 -y
sudo apt-get install php7.2-dom php7.2-xml php7.2-soap -y

Test Apache

For a first test with a web browser, visit http://localhost or http://127.0.0.1

The following should be displayed:

It works!

This is the default web page for this server.

The web server software is running but no content has been added, yet.

If this page is not displayed, Apache probably hasn’t started yet. In this case, start the web server with the following command:

sudo service apache2 start 

Create a PHP info page

cd /var/www/html/
sudo echo "<?php phpinfo();" > phpinfo.php

Open: http://localhost/phpinfo.php

Enable apache mod_rewrite

To enable the rewrite modul, run:

sudo a2enmod rewrite
sudo a2enmod actions

If you plan on using mod_rewrite in .htaccess files, you also need to enable the use of .htaccess files by changing AllowOverride None to AllowOverride All.

sudo sed -i '170,174 s/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf

Finally, the configuration of Apache has to be reloaded.

sudo service apache2 restart

Set permissions

Make /var/www/ writable without sudo privileges.

Set owner for /var/www/ to www-data (recursive)

sudo chown -R www-data /var/www/

The next command adds a attribute (recursive) which will keep new files and directories within /var/www/ having the same group permissions.

sudo chmod -R g+s /var/www/

Test the result

ls -l

Note: On a production server it’s recommended to chown www-data to /var/www/another_folder/, not to /var/www/.

Change mysql root password

Start mysql

sudo service mysql start

Change the password:

sudo mysql -u root --password="" -e "update mysql.user set authentication_string=password(''), plugin='mysql_native_password' where user='root';"
sudo mysql -u root --password="" -e "flush privileges;"

Note On a production server you should now run sudo mysql_secure_installation to improve the security of your MySQL installation.

MacOS Mojave: Setup Local Web Server MacOS (Homebrew + Apache + PHP + MariaDB)

This document provides help on getting your macOS development environment up and running with the latest versions of Homebrew, Apache, PHP, etc.

Homebrew Logo

Homebrew Installation

Homebrew is an excellent package manager for macOS, let’s install it.

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Add the Homebrew taps we need.

$ brew tap homebrew/core

Homebrew can self-diagnose and check your system for potential problems. Let’s see if everything is working the the way it should.

$ brew doctor

If successful it should display “Your system is ready to brew.”

Apache Installation

macOS comes with Apache pre-installed. We don’t want Apple in control of our web server so let’s stop it and prevent it from starting on boot.

$ sudo apachectl stop
$ sudo launchctl unload /System/Library/LaunchDaemons/org.apache.httpd.plist 2>/dev/null

Type the following command into your terminal:

$ mkdir ~/Sites

macOS automatically adds the compass icon to your folder.

Now, let’s brew and configure our new Apache version and change it to run on standard ports (80/443).

$ brew install httpd

Check the installation path.

$ which apachectl
/usr/local/bin/apachectl

Set Apache to start now and restart at login

$ sudo brew services start httpd

You can watch the Apache error log in a new Terminal tab/window during a restart to see if anything is invalid or causing a problem:

$ tail -f /usr/local/var/log/httpd/error_log

Remember useful commands.

$ sudo apachectl start
$ sudo apachectl stop
$ sudo apachectl -k restart
$ sudo apachectl configtest

PHP Installation

Install the latest PHP version.

$ brew install php

The php.ini file can be found in: /usr/local/etc/php/7.x/php.ini.

Apache PHP Setup

You have successfully installed PHP, but you need to tell Apache to use it. Edit the httpd.conf file.

vi /usr/local/etc/httpd/httpd.conf 

Find Listen 8080 and change it to port 80:

Listen 80

Uncomment these lines…

LoadModule socache_shmcb_module lib/httpd/modules/mod_socache_shmcb.so
LoadModule ssl_module lib/httpd/modules/mod_ssl.so
LoadModule vhost_alias_module lib/httpd/modules/mod_vhost_alias.so
LoadModule userdir_module lib/httpd/modules/mod_userdir.so
LoadModule rewrite_module lib/httpd/modules/mod_rewrite.so

Add the following entry at the end of the LoadModules section:

LoadModule php7_module /usr/local/opt/php/lib/httpd/modules/libphp7.so

Update user and group…

User username
Group staff

Servername is disabled by default, set it to localhost:

#ServerName www.example.com:8080
ServerName localhost

Modify httpd.conf even more…

Change DocumentRoot, it makes up the basic document tree which will be visible from the web.

DocumentRoot "/Users/username/Sites"
<Directory "/Users/username/Sites">
    AllowOverride All

Check that directive DirectoryIndex includes index.php.

DirectoryIndex index.php index.html

And we need to add the FilesMatch directive so that Apache will now process PHP files.

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

Uncomment to enable User home directories, Virtual hosts and Secure (SSL/TLS) connections…

Include /usr/local/etc/httpd/extra/httpd-userdir.conf
Include /usr/local/etc/httpd/extra/httpd-vhosts.conf
Include /usr/local/etc/httpd/extra/httpd-ssl.conf

Restart apache

$ sudo apachectl -k restart

Run a configuration file syntax test to verify/validate the configuration. It reports Syntax Ok or detailed information about the particular syntax error. This is equivalent to apachectl -t.

$ sudo apachectl configtest

If it says “Syntax OK” open browser using http://127.0.0.1. You should see a message saying “It works!”

php -v should report something like…

PHP 7.3.0 (cli) (built: Dec  7 2018 11:01:10) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.0-dev, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.0, Copyright (c) 1999-2018, by Zend Technologies

SSL/Virtual Hosts

Change default 8443 ports to 443 in the SSL configuration file.

$ vi /usr/local/etc/httpd/extra/httpd-ssl.conf

Replace all lines that say ‘8443’ with ‘443’.

ServerName www.example.com:443

<VirtualHost _default_:443>

Save the file plus generate a key and certificate.

$ cd /usr/local/etc/httpd
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt

Open up /usr/local/etc/httpd/extra/httpd-vhosts.conf and add your own SSL based virtual hosts.

$ vi /usr/local/etc/httpd/extra/httpd-vhosts.conf

Create your virtual host entries…

<VirtualHost *:443>
    DocumentRoot "/Users/username/Sites/yourprojectname"
    ServerName yourprojectdomain.com
    SSLEngine on
    SSLCertificateFile "/usr/local/etc/httpd/server.crt"
    SSLCertificateKeyFile "/usr/local/etc/httpd/server.key"
</VirtualHost>

In Terminal, restart Apache.

$ sudo apachectl restart

MariaDB Installation

Install MariaDB with Homebrew.

$ brew install mariadb

Have MariaDB start on boot.

$ brew services start mariadb

Finally, let’s improve the security of your installation and add a password.

$ mysql_secure_installation

MacOS High Sierra: Setup Local Web Server MacOS (Homebrew + Apache + PHP + MariaDB)

Homebrew Installation

First let’s install Homebrew.

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Homebrew can self-diagnose. Let’s see if everything works the way it should.

$ brew doctor

Add the Homebrew taps we need.

$ brew tap homebrew/core

Apache Installation

macOS comes with Apache pre-installed, stop it and prevent it from starting on boot.

$ sudo apachectl stop
$ sudo launchctl unload /System/Library/LaunchDaemons/org.apache.httpd.plist 2>/dev/null

We don’t want to use the pre-installed Apache. Instead we’ll brew and configure it to run on standard ports (80/443).

$ brew install httpd

Check installation.

$ which apachectl
/usr/local/bin/apachectl

Start Apache, open browser with http://127.0.0.1 and you should see a message saying “It works!”

$ sudo apachectl -k start

Set Apache to launch on startup.

$ sudo brew services start httpd

You can watch the Apache error log in a new Terminal tab/window during a restart to see if anything is invalid or causing a problem:

$ tail -f /usr/local/var/log/httpd/error_log

Remember useful commands.

$ sudo apachectl start
$ sudo apachectl stop
$ sudo apachectl -k restart
$ sudo apachectl configtest

PHP Installation

$ brew install [email protected]
$ brew unlink [email protected]
$ brew install [email protected]

The php.ini file can be found in: /usr/local/etc/php/7.2/php.ini.

Apache PHP Setup

You have successfully installed your PHP versions, but we need to tell Apache to use them. You will again need to edit the /usr/local/etc/httpd/httpd.conf. Modify the paths as follows, comment out all but one entry:

#LoadModule php5_module /usr/local/opt/[email protected]/lib/httpd/modules/libphp5.so
LoadModule php7_module /usr/local/opt/[email protected]/lib/httpd/modules/libphp7.so

Edit /usr/local/etc/httpd/httpd.conf and uncomment these lines…

LoadModule rewrite_module lib/httpd/modules/mod_rewrite.so
LoadModule socache_shmcb_module lib/httpd/modules/mod_socache_shmcb.so
LoadModule ssl_module lib/httpd/modules/mod_ssl.so
LoadModule userdir_module lib/httpd/modules/mod_userdir.so
LoadModule vhost_alias_module lib/httpd/modules/mod_vhost_alias.so

Include /usr/local/etc/httpd/extra/httpd-userdir.conf
Include /usr/local/etc/httpd/extra/httpd-vhosts.conf
Include /usr/local/etc/httpd/extra/httpd-ssl.conf

Modify httpd.conf more…

Check DirectoryIndex includes index.php.

DirectoryIndex index.php index.html

User username
Group staff

DocumentRoot "/Users/username/Sites"
<Directory "/Users/username/Sites">
    AllowOverride All

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

Find Listen 8080 and change it:

Listen 80

Servername is disabled by default, set it to localhost:

#ServerName www.example.com:8080
ServerName localhost

Restart apache

$ sudo apachectl -k restart

PHP Switcher Script

We hard-coded Apache to use PHP 5.6, but we really want to be able to switch between versions. Luckily, some industrious individuals have already done the hard work for us and written a very handy little PHP switcher script.

We will install the sphp script into brew’s standard /usr/local/bin:

$ curl -L https://gist.github.com/w00fz/142b6b19750ea6979137b963df959d11/raw > /usr/local/bin/sphp
$ chmod +x /usr/local/bin/sphp

Testing the PHP Switching

After you have completed these steps, you should be able to switch your PHP version by using the command sphp followed by a two digit value for the PHP version:

$ sphp 72

MariaDB Installation

Install MariaDB with Homebrew.

brew install mariadb

After installation, start the MariaDB server with…

brew services start mariadb

After MariaDB is started, you can connect.

mysql -uroot

$ brew install mariadb
$ brew services start mariadb
$ mysql_secure_installation

SSL/Virtual Hosts

Change default 8443 ports to 443 in the SSL configuration file.

$ vi /usr/local/etc/httpd/extra/httpd-ssl.conf

Replace ‘Listen 8443’ with ‘Listen 443’.

Also update it here:

<VirtualHost _default_:8443>

General setup for the virtual host

DocumentRoot "/usr/local/var/www"
ServerName www.example.com:443

<VirtualHost _default_:443>

Save the file, open up /usr/local/etc/httpd/extra/httpd-vhosts.conf and add your own SSL based virtual hosts.

$ vi /usr/local/etc/httpd/extra/httpd-vhosts.conf

Create your virtual host entries that you want to use SSL with.

<VirtualHost *:443>
    DocumentRoot "/Users/your_user/Sites"
	ServerName yourdomain.com
	SSLEngine on
	SSLCertificateFile "/usr/local/etc/httpd/server.crt"
	SSLCertificateKeyFile "/usr/local/etc/httpd/server.key"
</VirtualHost>

Certificates

Generate a key and certificate.

$ cd /usr/local/etc/httpd
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt

Install iTerm2 + zsh

Download iTerm2

Why we must replace default macOS Terminal to iTerm2 ?

  1. Go to download page https://www.iterm2.com/downloads.html
  2. After downloaded, drag and drop file into our Application folder.

Or if you just type (require homebrew installed)

brew cask install iterm2

Install zsh

  1. Open terminal and paste.
brew install zsh

We need you “oh-my-zsh”

Oh-My-Zsh is an open source, community-driven framework for managing your ZSH configuration. It comes bundled with a ton of helpful functions, helpers, plugins, themes and a few things that make you shout…

“Oh My ZSH!”

Install oh-my-zsh

The oh-my-zsh will be replace default terminal with zsh automatically when you installed.

  1. Open terminal and paste.
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

Decorate Our iTerm2 With Material Design Colours

https://github.com/MartinSeeler/iterm2-material-design/blob/master/img/screen-mock-1.jpg

1. Open terminal and paste.

$ cd Downloads
$ curl -O https://raw.githubusercontent.com/MartinSeeler/iterm2-material-design/master/material-design-colors.itermcolors

2. Open iTerm2 that we already downloaded at the first section

3. Go to iTerm2 > Preferences > Profiles > Colors Tab

4. Click Color Presets… at the bottom right

5. Click Import…

6. Select the material-design-colors.itermcolors file

7. Select the material-design-colors from Load Presets…

iTerm2 with Dracular theme ref: https://draculatheme.com/assets/img/screenshots/iterm.png

Dracula theme is also good click see more.

Manage Plugins

Plugin wiki page: https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins

In this case I want to enable plugin ‘docker’ on my zsh, so I’ll run this command

vi ~/.zshrc

and type “/plugin” (without quotes) press enter, type ‘i’ character and insert the plugin that you want to add.

.
.
.
# Which plugins would you like to load? (plugins can be found in ~/.oh-my-zsh/plugins/*)
# Custom plugins may be added to ~/.oh-my-zsh/custom/plugins/
# Example format: plugins=(rails git textmate ruby lighthouse)
# Add wisely, as too many plugins slow down shell startup.
plugins=(
git
)

In this case, I’ll add docker plugin, just add “docker” to our parentheses.

.
.
.
# Which plugins would you like to load? (plugins can be found in ~/.oh-my-zsh/plugins/*)
# Custom plugins may be added to ~/.oh-my-zsh/custom/plugins/
# Example format: plugins=(rails git textmate ruby lighthouse)
# Add wisely, as too many plugins slow down shell startup.
plugins=(
git
docker
)

After you satisfied, press ‘Esc’ and type ‘:wq’ which means you save a file and exit immediately. And restart iTerm2.

Add An Alias (Permanent Alias)

vi ~/.zshrc
.
.
.
# Example aliases
# alias zshconfig="mate ~/.zshrc"
# alias ohmyzsh="mate ~/.oh-my-zsh"
alias dkps="docker ps"
alias dkst="docker stats"
alias dkpsa="docker ps -a"
alias dkimgs="docker images"
alias dkcpup="docker-compose up -d"
alias dkcpdown="docker-compose down"
alias dkcpstart="docker-compose start"
alias dkcpstop="docker-compose stop"

If I go type ‘dkps’ it will be execute ‘docker ps’

Install Homebrew + Cask Mac (Older)

You probably need to:

  • install XCode CLI Tools (which can be difficult on older versions)
  • update OpenSSL
  • upgrade git

Install XCode CLI Tools

You can use a helper shell script to do this for you. The source comes from this gist. Alternatively, view its source, follow the code, and find your corresponding version of XCode CLI Tools and install accordingly.

Copy + Paste

If you don’t have a new enough version of OpenSSL, you won’t be able to download the script with wget or curl, so just open the link manually in a web browser and save the file with the same name below, on your Desktop.

From a Terminal session:

  • (if able, per note above) curl -O https://gist.github.com/rtrouton/f92f263414aaeb946e54/raw/9ac37d561c38d54ff7fc31dee66e89d10fc3e2b9/gistfile1.sh
  • mv gistfile1.sh xcode-cli-tools-install.sh
  • chmod +x xcode-cli-tools-install.sh
  • sudo sh xcode-cli-tools-install.sh

This script when run, the last line, will download the installer package, perform the install, and remove the dmg once finished.

Updating OpenSSL

1. Install Mac Ports

2. Install OpenSSL from Mac Ports

You can confirm your current version of OpenSSL with the command openssl version.

Install the latest version from Mac Ports with:

sudo port install openssl

Upgrade Git

Download and install the latest version of Git for Mac from git-scm.com.
https://git-scm.com/download/mac

Installing Homebrew + Cask on Mac

Note: If you’re not running a recent version of macOS (formerly known as Mac OS X), you may need to address a few items. Please consult the below NotesForOlderMacs.md.

1. Install Xcode CLI Tools (only)

xcode-select --install

Run from a CLI (command line interface), such as Terminal.app (found in the /Applications/Utilities/ directory). This will perform the install of the command line tools for Xcode, as opposed to a full Xcode install; you may alternately perform the full Xcode install.

2. Install Homebrew

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

This command will use ruby (a language included in the Xcode cli tools) to download a well maintained install script, to perform the install and setup of homebrew (and the brew command). The $(curl ...) portion performs a download of the install script and passes it to the ruby command to execute. Feel uncomfortable executing code you didn’t write? Read the install script for yourself.

Search

brew search wget

Install

brew install wget

Use

Use like normal!

wget --help

3. Setup (Tap) Homebrew Cask

brew tap caskroom/cask

This taps the cask caskroom. This makes all cask content available for search and install.

Search

brew cask search google-chrome

Alternatively, cask availablility will return under a normal brew search command, such as brew search google-chrome.

Install

brew cask install google-chrome

Use

Use like normal! Google Chrome is now an application in your /Applications/ directory, accessible via Finder, Launchpad, etc.

Why?

Homebrew is about the easiest way to install tools for Mac. Homebrew Cask is about the easiest way to install a GUI application, which does perform a native install, it’s just tracked to be more easily upgraded.R