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 git push
.
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
Replace <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.
Replace <repo name>
with the name of your project. For example, owlfancy
.
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 scriptThe 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:
#!/bin/sh
# 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/*
Press 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 post-receive
script. <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 push
again.
push
ed 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.