Downtime & Symlinks

Using Symlinks for a Zero-downtime Deployment

We'll be automating a deployment strategy with Fabric. However, first, let's see what that process is by doing it manually.

Log into the server as user admin, who can use sudo.

Nginx

Let's change the root directory back to what we had a few videos ago.

server {
    # Items skipped for brevity

    root /home/serial/serialapp.com/current/public;

    # Items skipped for brevity
}

We changed the root directory from the repository (/home/serial/serialapp.com/repo/public) to the current/public directory, where our deployed files will live.

Test and reload Nginx after that change:

sudo service nginx configtest
sudo service nginx reload

Log in as the serial user and head to our project directory at ~/serialapp.com.

Github Repo

We'll move the github repo to be one level up, so we end up with:

~/serialapp.com
|-- current
|-- -- public
|-- repo

The steps to do that:

cd ~/serialapp.com
mv current/repo ./

Persist Directory

Next we want to create a directory where files that should persist across deployments should live. These will be environment files, cache file, log files and similar.

cd ~/serialapp.com
mkdir persist

And move our application's .env file there:

cd ~/serialapp.com
mv repo/.env persist/.env

And then we'll take our Laravel application's storage directory, which contains cache and log files that we don't want to lose in deployments:

cd ~/serialapp.com
cp -r repo/storage ./persist/

Releases

We want a place to put the code that we'll use for each release (each deployment). We'll simply name this the releases directory:

cd ~/serialapp.com
mkdir releases

Build Process

We have files in place now, let's see the manual steps to take in order to deploy.

cd ~/serialapp.com/repo

# Get the latest code
git pull origin master

# We'll build a deployment in a new directory which has a timestamp
# as a name. In this case, dir name 1436408501
mkdir ~/serialapp.com/releases/`php -r "echo time();"`

# Build an archive of the site
cd ~/serialapp.com/repo
git archive --worktree-attributes master | tar -x -C ~/serialapp.com/releases/1436408501

# Double check that the files are now in our
# new release directory
ls -lah ~/serialapp.com/releases/1436408501

# Clear our storage, since we want to use our 
# storage from "persist"
rm -rf ~/serialapp.com/releases/1436408501/storage

# Create symlinks to symlink needed files to the latest release
#
## Symlink our .env file
ln -nfs ~/serialapp.com/persist/.env ~/serialapp.com/releases/1436408501/.env
## Symlink our storage directory
ln -nfs ~/serialapp.com/persist/storage ~/serialapp.com/releases/1436408501/storage
## Finally get it up and running in "current" dir
## This is setting us up to use our Nginx web root
ln -nfs ~/serialapp.com/releases/1436408501 ~/serialapp.com/current

## Build our application composer dependencies
cd ~/serialapp.com/releases/1436408501
php composer install

And that's it! On our next release, we would:

  1. Make a new timestamp release directory
  2. Get the latest code in the Git repo
  3. Use git archive to get a copy of the site at that commit to our new release directory
  4. Build composer dependencies in that directory
  5. Symlink the .env, storage and finally current directory to make the latest code live

Moving on, we'll automate this process in Fabric.