Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Development Setup on Ubuntu 16.04 Linux

Ubuntu 16.04 LTS for Web Development



  1. Install VirtualBox

    Setting up NatNetwork:

    a. File > Preferences > Network

    b. Under the Nat Networks tab, create a new adapter:

     Name: NatNetwork
     Options: Check support DHCP, uncheck Support IPV6
  2. Download ubuntu-16.04-i386.iso

  3. Make a virtual machine with the following settings:

    • Linux/Ubuntu (32bit)
    • 2048 mb ram
    • 30 gb hdd / vmdk
    • enable 3d acceleration
    • set the video memory to 64 mb
    • enable i/o apic
    • disable uefi
    • set the virtual processor to 2 (dual core)
    • network setup:
      • adapter 1: NAT
        • Setup port-forwarding to allow access from guest to host
        • host:, guest: ip-address of NAT eth:port
      • adapter 2: NAT network
        • to allow virtual machine wide port forwarding features
      • adapter 3: Bridge adapter - Select your WiFi adapter (does not work as of the moment)
        • to allow access from virtual machine guest to LAN
        • select wifi adapter
        • change the mac address to the wifi's mac address to work with bridged wifi adapter
      • adapter 4: Host-only adapter
        • to allow access from virtual machine to host, doesnt need port-forwarding, but generally the same as NAT with port-forwarding, all services allowed
  4. Install Ubuntu

    $ sudo apt-get update
    $ sudo apt-get upgrade
  5. Install dkms before installing Vbox Guest additions

    $ sudo apt-get install dkms
  6. Install VirtualBox Guest Additions

    • Devices > Install Guest Additions > RUN
  7. Change fonts

a. Download fonts from

  - Roboto
  - Roboto-mono
  - Inconsolata

b. System Settings > Appearance > Behavior tab

  - Check In the window's title bar from the Show the menus for a window
  - Check Always displayed from the Menu Visibility

c. Install Unity Tweak Tool from the Ubuntu Software

  - Change fonts to:
  Default font: Roboto regular
  Document font: Roboto regular
  Monospace font: Roboto mono regular
  Window title font: Roboto regular

d. Install mscore fonts

$ sudo apt-get install ttf-mscorefonts-installer
$ mkdir /usr/share/fonts/windowsfonts
$ cp *.ttf /usr/share/fonts/windowsfonts
$ chmod 755 /usr/share/fonts/windowsfonts/*
$ fc-cache -fv

e. Change Firefox fonts to Times new roman, Arial, Courier New

  1. Install Flash player
    $ sudo add-apt-repository ppa:nilarimogard/webupd8 && sudo apt-get update && sudo apt-get install browser-plugin-freshplayer-pepperflash
    $ sudo add-apt-repository ppa:skunk/pepper-flash && sudo apt-get update && sudo apt-get install pepflashplugin-installer

Development Setup

  1. Git

    $ sudo add-apt-repository ppa:git-core/ppa
    $ sudo apt-get update
    $ sudo apt-get install git
    $ git --version
    git version 2.8.1
  2. Mercurial

    $ sudo apt-get install mercurial
  3. Subversion

    $ sudo apt-get install subversion
  4. ZSH

    $ sudo apt-get install zsh
    $ sh -c "$(curl -fsSL"
    $ cat >> ~/.zshrc << EOF
    export NVM_DIR="/home/gerarldlee/.nvm"
    [ -s "$NVM_DIR/" ] && . "$NVM_DIR/"  # This loads nvm
    source /usr/local/share/chruby/
    source /usr/local/share/chruby/
    source ~/.nvm/
    $ source ~/.zshrc

Programming Languages


To install ruby:

$ wget -O ruby-install-0.6.1.tar.gz 
$ tar -xzvf ruby-install-0.6.1.tar.gz 
$ cd ruby-install-0.6.1/ 
$ sudo make install
$ ruby-install -V
$ ruby-install ruby 2.3


$ wget -O chruby-0.3.9.tar.gz 
$ tar -xzvf chruby-0.3.9.tar.gz
$ cd chruby-0.3.9/
$ sudo make install

Append to ~/.bashrc:

$ cat >> ~/.$(basename $SHELL)rc << EOF
source /usr/local/share/chruby/
source /usr/local/share/chruby/

The will enable switching between different rubies which depends on the file .ruby-version in a particular folder.

To use ruby:

$ chruby ruby
$ ruby --version
ruby 2.3.3p222 (2016-11-21 revision 56859) [i686-linux]
$ cat >> ~/.ruby-version << EOF

Install rails:

$ gem install rails -v 4.2.5 --no-rdoc --no-ri

Ruby database integrations:

$ sudo apt-get install libmysqlclient-dev
$ sudo apt-get install libpq-dev
$ sudo apt-get install libsqlite3-dev


$ sudo apt-get install curl
$ curl | bash

Append to ~/.bashrc:

$ source ~/.nvm/

Find the latest version of nodejs by nvm ls-remote command

$ nvm install v6.9.4
$ nvm alias default v6.9.4

Install essential nodejs modules:

$ npm install -g grunt-cli
$ npm install -g bower
$ npm install -g pm2


$ curl | sh
$ meteor create testproject
$ cd testproject
$ meteor


$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer

$ javac -version
$ sudo apt-get install oracle-java8-set-default

Use oracle-java9-installer and oracle-java9-set-default for Java 9


$ sudo apt-get install php7.0-fpm php7.0-cli php7.0-json php7.0-curl php7.0-mcrypt

$ php -a
Interactive mode enabled

php > var_dump('Hello World!');
string(12) "Hello World!"
php >

PHP database integrations:

$ sudo apt-get install php7.0-mysql
$ sudo apt-get install php7.0-pgsql
$ sudo apt-get install php7.0-sqlite

You can now use the following to test the availability of the PostgreSQL PDO driver.

php -r 'var_dump(PDO::getAvailableDrivers());'
array(3) {
  string(5) "mysql"
  string(5) "pgsql"
  string(6) "sqlite"


Web Development Setup

Option 1: Use nginx Option 2: Use LAMP Option 3: Use XAMPP

Web server: nginx

$ sudo add-apt-repository ppa:nginx/stable
$ sudo apt-get update
$ sudo apt-get install nginx

Open browser to check if nginx is installed

nginx integration

Let us now setup the nginx configuration to route requests via FastCGI to PHP-FPM. Although I will try to demonstrate the common basics here, it is highly recommended that you read and learn about the nginx configuration, specially the pitfalls.

The nginx configuration is divided mostly in two parts. One is the global config which is included by default on installation of nginx at /etc/nginx/nginx.conf. The default configuration file would automatically include sub-config files from the directory /etc/nginx/sites-enabled. So you have to store your config files in the sites-enabled directory only, and they should have the extension .conf.

By convention, each config file in the sites-enabled directory would contain the config for one website. Here is how a simple configuration file looks.

server {
    listen 80 default_server;
    root /usr/share/nginx/html;
    index index.php index.html index.htm;
    server_name localhost;
    location / {
        try_files $uri $uri/ =404;
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

It is not actually difficult to read. Let us take each part, and understand what it does.

listen 80 default_server;

The listen keyword makes nginx listen to the port passed (80, in this case), and it will be the default_server.

root /usr/share/nginx/html;

The root keyword defines where are the scripts for your website placed. So all the files you store in /usr/share/nginx/html could be accessible from outside.

index index.php index.html index.htm;

The index keyword defines the main entry point of your website. So if your website is, any user going to the website directly would be served the first file present in the root directory passed to the index keyword. So if someone goes to, nginx would try to find index.php first. If the file is present, it would be served, else, it would try to match the next one, and so on. This way, your users can type instead of

server_name localhost;

The server_name keyword defines the exact name for the website. localhost is used for development purposes. It is not accessible from other computers. For public websites, replace localhost with your site’s url.

Note that you can’t just define a name here and expect it to work for everyone. You have to register that domain name, and configure the DNS. Your ISP would provide the information required for this.

location / {
    try_files $uri $uri/ =404

The location keyword defines what the user will be served for the given path. In this case, the path is /, which refers to the root directory (yes, it covers sub-directories as well).

The try_files keyword would try to find files in the given order, and serve the one that is found first. The $uri variable is available to the nginx configurations, and holds the URI (and not the URL).

So if the user requests, $uri would contain /foo, and nginx would thus try to find the file foo in the root directory. If it is found, it would be served.

If it is not found, nginx would try to find $uri/ which means /foo/, which means the directory foo present in the root directory. If the directory exists, the request would be served from that directory.

If the directory is not found as well, nginx would return a 404 status code, which means the requested resource was not found.

location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

This might look scary at first, but is not that difficult to understand.

The ~ symbol in after the location keyword means that the path given is in the form of a regex. The regex we gave is .php$, which matches resources which have .php at the end of the resource name.

Since PHP files can’t be directories (obviously), we do not specify the $uri/ word in the try_files directive in this case.

Next, we specify the parameters for the FastCGI interface. fastcgi_pass contains the reference to the listener to which the request must be passed.

fastcgi_index is similar to the index directive which we described earlier, fastcgi_param SCRIPTNAME passes the given parameter under the name SCRIPTNAME to the FastCGI interface.

include fastcgi_params directive will include the file named fastcgi_params already present in the nginx config directory. It contains some conventional parameters like $remote_addr etc. passed to PHP, which are then available to your PHP scripts under the $_SERVER super-global variable.

So go ahead and save this file under /etc/nginx/sites-enabled under the name server.conf, and restart nginx via sudo service nginx restart. Then create a file index.php in /usr/share/nginx/html with the following contents:


Save the file, and navigate to http://localhost (or your site’s name), and you should see the PHP info page!

The only thing which now remains is using Redis with PHP. Using Redis with PHP would require you to use a Redis Client library for PHP. You can use anyone listed at the Redis Clients page under the PHP section. Installation and usage would vary depending upon the client you chose.


  1. Install XAMPP to /opt/lampp

    $ sudo chmod +x
    $ sudo ./
  2. mkdir ~/Projects

  3. $ sudo vi /etc/hosts to add localhost

  4. Edit /opt/lampp/etc/httpd.conf. Look for "Include etc/extra/httpd-vhosts.conf" and remove the #. Save.

  5. Second, edit /opt/lampp/etc/extra/httpd-vhosts.conf so that it contains this configuration:

      DocumentRoot "/home/<user>/path/to/project/" 
    <Directory "/home/<user>/path/to/project/"> 
      Require all granted 
  6. $ sudo /opt/lampp/lampp stop $ sudo /opt/lampp/lampp start

  7. Setup a database from the web browser localhost/phpmyadmin

  8. Type into the web browser to check.

Mail server: EXIM4

Set up mail server to send email to the real world -

$ sudo apt-get install exim4
$ sudo dpkg-reconfigure exim4-config
  • Choose mail sent by smarthost; no local mail
  • System mail name: YOUR_HOSTNAME
  • IP-addresses to listen on for incoming SMTP connections: ; ::1
  • Other destinations for which mail is accepted: blank
  • Visible domain name for local users: blank
  • IP address or host name of the outgoing smarthost:
  • Keep number of DNS-queries minimal (Dial-on-Demand)? No
  • Split configuration into small files? No
  • Root and postmaster mail recipient: blank

Open and edit /etc/exim4/exim4.conf.template

$ cp /etc/exim4/exim4.conf.template /etc/exim4/exim4.conf.template.bak
$ vi /etc/exim4/exim4.conf.template

Find .ifdef DCconfig_smarthost DCconfig_satellite, add these after:

    driver = manualroute
    domains = ! +local_domains
    transport = gmail_smtp
    route_list = *

Remove other smarthost blocks that contains domains = ! +local_domains.

Find begin authenticators, add these after:

    driver = plaintext
    public_name = LOGIN
    client_send = : : YOUR_GMAIL_PASSWORD

Remove other authenticator blocks that contains public_name = LOGIN.

Find transport/30_exim4-config_remote_smtp_smarthost, add these after:

    driver = smtp
    port = 587
    hosts_require_auth = $host_address
    hosts_require_tls = $host_address

Save and close /etc/exim4/exim4.conf.template.

$ sudo nano /etc/exim4/passwd.client

And add the following lines, substituting yourAccountName and y0uRpaSsw0RD as appropriate

Update and restart Exim4:

$ sudo update-exim4.conf
$ sudo /etc/init.d/exim4 restart

To check:

$ host is an alias for has address has address has IPv6 address 2404:6800:4008:c05::6c

$ echo "Test content" | mail -s "Test subject"

$ tail /var/log/exim4/mainlog
2017-01-17 20:54:29 1cTTHI-0005sh-Pd => R=send_via_gmail T=gmail_smtp [] X=TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128 CV=no DN="C=US,ST=California,L=Mountain View,O=Google Inc," A=gmail_login C="250 2.0.0 OK 1484658550 75sm42460596pfp.80 - gsmtp"
2017-01-17 20:54:29 1cTTHI-0005sh-Pd Completed

Check your other email if the message is there. Please note that Gmail sends only up to 100 messages per day.

Database Setup


$ sudo apt-get install sqlite


$ sudo apt-get install postgresql-9.3

Configuring PostgreSQL

Users accustomed to the *AMP stacks and auto-installers might find this part difficult, but it is not.

PostgreSQL will create a user-group on Ubuntu, by the name postgres. Using this user directly in your application is hardly a good idea, because it is a superuser account. We need to create a user, and a database. We also need to ensure that the new user is able to login, has a password, and has privileges to access only this new database.

PostgreSQL has the concept of roles, instead of users and usergroups. A role can be a user, and a usergroup as well. This is actually a very powerful thing, and gives you a lot more flexibility. I recommend reading more about this at the official documentation.

The way PostgreSQL manages users, is that it maps the usernames from your system, straightway to PostgreSQL. What this means is that if your system username is awal, then there needs to be a PostgreSQL user with the same name for the user awal. But as I said before, PostgreSQL comes with the postgres user only…

So we need to login to the default postgres user account that PostgreSQL has created, and create the database and new role from there.

$ sudo -u postgres psql postgres

This would log you into the postgres account. It is recommended to change the password for this account via the following command.

\password postgres

You would be prompted to enter the new password, and then confirm it.

Now you can create a new database, via the traditional SQL commands.

CREATE DATABASE <database-name>;

We will also create a new role with limited privileges, which allows us to operate on the new database.

CREATE ROLE <username> LOGIN PASSWORD '<password-in-quotes>';

This will create a new role under the given username, who can login, via the password you enter. The password MUST be written between single quotes.

Further, your username MUST be the same as your computer’s username. This is because of the way in which PostgreSQL manages users, described previously.

Now we need to provide the new user with the privileges to operate on the new database, and we are good to go!

GRANT ALL PRIVILEGES ON DATABASE <database-name> TO <username>;

And with this, you have successfully configured PostgreSQL, created a database, and a user for your app!

Cache: Redis

$ sudo apt-get install redis-server

$ redis-cli> ping


  1. Install rpl package (cli find/replace in multiple files)-

    $ sudo apt-get install rpl

  2. Install Brackets editor

$ sudo add-apt-repository ppa:webupd8team/brackets && sudo apt-get update && sudo apt-get install brackets
  1. Install Visual Studio Code editor
$ sudo add-apt-repository ppa:ubuntu-desktop/ubuntu-make && sudo apt-get update && sudo apt-get install ubuntu-make
$ umake ide visual-studio-code
  1. Install Sublime Text -

  2. Install Gdebi $ sudo apt-get install gdebi

  3. Install PEAR

    • Synaptic Package Manager php-pear
  4. Install Phing -

  5. Install s3cmd package

    Import S3tools signing key: $ wget -O- -q | sudo apt-key add -

    Add the repo to sources.list: $ sudo wget -O/etc/apt/sources.list.d/s3tools.list

    Refresh package cache and install the newest s3cmd: $ sudo apt-get update && sudo apt-get install s3cmd


  1. Install Samba -

    System --> Administration --> Synaptic Package Manager and install or check these: smbclient, libsmbclient, samba-common, nautilus-share and samba

  2. Change workgroup name -

    $ sudo nano /etc/samba/smb.conf

  3. Set smbpasswd if sharing folder -

    $ sudo smbpasswd -a username

  4. Install Openssh-server -


  1. Edit resolv.conf to set DNS to use Google
$ sudo nano /etc/resolv.conf
  1. Prevent file from being overwritten

    $ sudo chattr +i /etc/resolv.conf

Awesome Apps

  • Chromium (if theres no Chrome on your Linux)
  • $ sudo apt-get install chromium-browser
  • Keepass ( $ sudo apt-get install keepass2
  • Filezila $ sudo aptitude install filezilla
  • Trimage image compressor $ sudo apt-get install trimage
  • Dragondisk Amazon S3 Client -
  • Linkchecker $ sudo apt-get install linkchecker-gui
  • Giggle - graphical frontend for git tracker $ apt-get install giggle
  • Meld diff viewer $ apt-get install meld
  • XVidCap
  • AcidRip
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment