As we explained earlier,
git is a good tool for deployment because it keeps track of the changes to your codebase between commits. Once you've set up a remote repository in your production environment, deployment can be as simple as a single
git push command. Git will automatically determine which files need to be updated on the live server.
We can also use the git
post-receive hook to run additional build tasks after the code base is updated, like clearing the cache and recompiling assets.
This guide assumes that you already set up your UserFrosting project as a git repository during installation. If not, go back to the installation guide.
This guide also assumes that you are regularly committing changes to your repository. Git can only push files to the production server if it is tracking them and you have committed your changes. If you are new to git and don't understand what this means, we strongly suggest you check out the free git tutorials from Github or Atlassian before you continue.
Before you can do anything else, you need to first
ssh into the remote machine. In general, I like to keep two terminals open at the same time - one connected to my remote machine, and the other for performing local commands.
First, we'll set up a bare repository on the remote server. The reason we use a bare repository is because it separates the location of the repository (the files managed by git that live in the
.git directory), and the working tree (the files you normally work with and from which you commit to the repository).
If we used a non-bare repository, we wouldn't be able to "push to production" because git does not allow you to push to a checked-out branch. Since the checked-out branch would be the actual set of files that the webserver is running your application on, it would make it impossible to change these files when we do
sudo to run some of these commands.
By default, we'll create a directory
repo in Ubuntu's
var/ directory that will contain all of our bare repositories on this server.
sudo mkdir /var/repo
sudo mkdir /var/repo/<repo name>.git
sudo chown <your username>:<your username> /var/repo/<repo name>.git
cd /var/repo/<repo name>.git
git init --bare
<your username> with the name of the non-root user account you created earlier. You will use this account to push changes from your development environment, so it is important that this account have read and execute permissions on the repo directory.
<repo name> with the name of your project. For example,
If successful, you should see a message like:
Initialized empty Git repository in /var/repo/<repo name>.git
The next thing we'll do is set up the working directory where our files will live and be served from by the webserver. Traditionally on Ubuntu,
/var/www/ is used for web applications. So, we'll make subdirectories in this directory for each application we deploy on this server.
sudo mkdir /var/www/<repo name>
sudo chown <your username>:<your username> /var/www/<repo name>
Again, we take ownership of the directory so that we'll be able to write to it when we push our application remotely.
post-receive hook script
The next step is to set up a
post-receive hook in our repository directory. This hook will tell git to automatically copy the files in the current branch to our working directory every time we deploy.
nano /var/repo/<repo name>.git/hooks/post-receive
This will open up the
nano text editor. Add the following to this file:
# Check the repo out into the working directory for our application
git --work-tree=/var/www/<repo name> --git-dir=/var/repo/<repo name>.git checkout -f
# Clear the UF cache
rm -rf /var/www/<repo name>/app/cache/*
Control-X to exit. When prompted to save, press
Enter to confirm.
Make sure that your user account has ownership of the
post-receive file, and the proper permissions to execute the script. Specifically, give the user owner and group owner "execute" permissions:
sudo chmod u+x,g+x /var/repo/<repo name>.git/hooks/post-receive
Before we can finish configuring our application to run on the live server, we need to push it for the first time. Back on our local (development) environment, we'll set up our Droplet as a remote. In your root project directory:
git remote add live ssh://<your username>@<hostname>/var/repo/<repo name>.git
<your username> should be the user account on your Droplet that you gave permissions earlier to push and execute the
<hostname> can be the IP address of your Droplet, or any domain/subdomain that resolves to this IP address (if you've already configured DNS for your application).
Now, if you type
git remote -v, you should see a list of your current remotes:
$ git remote -v
live ssh://[email protected]/var/repo/owlfancy.git (fetch)
live ssh://[email protected]/var/repo/owlfancy.git (push)
origin https://[email protected]/owlfancy/owlfancy.git (fetch)
origin https://[email protected]/owlfancy/owlfancy.git (push)
upstream https://github.com/userfrosting/UserFrosting.git (fetch)
upstream no-pushing (push)
upstream is the master UserFrosting repository, from which we can pull updates to UF;
origin points to our collaborative development repository on Bitbucket, which gives us free private repos;
live points to our live production server.
To push to production for the first time, we'll use the command:
git push live master
When we do this, two things will happen:
live with an
ssh:// url. This means that git will try to connect to your server as the specified user (
alex) via SSH. If you get an error, double-check your SSH setup.
post-receive script. If there is something wrong with your user's permissions, the script might silently fail to execute, or it might fail to check out the repository to the working directory.
So, let's now check to make sure that
post-receive worked properly. On the remote machine, list the files in the working directory:
ls /var/www/<repo name>
You should see your project files. If the directory is empty, then something went wrong with the
post-receive script - most likely a permissions issue. Fix the issue and try to
pushed to the production server, but the
post-receive script failed to execute properly, git will just say
Everything up-to-date and exit without rerunning your
post-receive script. To force git to run the script, you need to make a commit before you rerun
git push. To make an "empty" commit, use
git commit --allow-empty -m "retry deployment". You may want to create a separate deployment branch to avoid polluting your
master branch with lots of empty commits.
Once you have your
git push working properly, congratulations! Deploying updates to your live application is as simple as running
git push live master again.
The next step is to configure UserFrosting for production.