Setting Up a Continuous Deployment Workflow With Bitbucket and Linux Server
Configure Bitbucket Pipelines and SSH to continuously deploy an application to a Linux server.
- DevOps
- Infrastructure
Ever seen the acronym CI/CD before? It stands for Continuous Integration and Continuous Deployment.
What does that even mean? I’ll explain with a scenario.
Say you’re a software developer who writes code for an application. Typically, after you make an update, you’ll test your changes to see that nothing is broken. Afterwards, your new build or code changes will be handed over to the server administrator, who will deploy the application to a live server where users can access it.
Here’s the challenge: if you make changes very often—which is common in Agile development—you will have to repeat that process several times. This can be tiring. In a bid to bypass that loop, you may decide to release new changes at the end of the week or later. This defeats the aim of DevOps, where we need to make small, iterative changes accessible to application users. Don’t hinder the process; embrace a continuous workflow!
CI/CD automates that process. You write the code and commit it to version control with Git. Each time you push to a service like GitHub or Bitbucket, automation kicks in. Your code is tested using a predefined system and, if the minimum testing threshold is reached (CI), the changes are deployed to the live server (CD).
Continuous Deployment: Bitbucket and Linux server
Note: This hands-on section sets up a continuous deployment workflow without any form of testing (CI). A fair understanding of Git, Bitbucket, Linux, and the command-line interface is required to get the most from this section.
TL;DR
- Enable Pipelines in your Bitbucket repository and configure it using
bitbucket-pipelines.yml. - Add the server’s remote deploy key to the repository.
- Set up an SSH key pair on the repository.
- Add the repository’s public key to the server’s authorized keys.
- Clone the repository onto the server.
Enable Pipelines and configure the workflow
In the repository settings, enable Pipelines. This provides a file named
bitbucket-pipelines.yml. Here is a sample:
pipelines:
default:
- step:
name: Deploy to production
deployment: production
script:
- echo "Deploying to production environment"
- pipe: atlassian/ssh-run:0.2.2
variables:
SSH_USER: "root"
SERVER: "<ip-address>"
COMMAND: "/home/deploy.sh"
The file gives the repository the information it needs to deploy the application upon a new push.
It logs into the server using SSH with the specified user—in my case, root—and host. Once the
connection succeeds, it runs the deploy.sh script.
Here is a sample deployment script:
echo -e $PWD
echo -e '\e[1m\e[34mEntering into frontend directory...\e[0m\n'
cd /home/my-application
echo -e $PWD
echo -e '\e[1m\e[34mPulling code from remote...\e[0m\n'
git pull origin master
echo -e '\e[1m\e[34mAll done now!\e[0m\n'
echo -e '\e[1m\e[34mThanks to Ileriayo for automating this deployment process!\e[0m\n'
In the deployment script, we change into the app’s directory on the server and pull the latest
code changes. The echo commands are for logging in Bitbucket Pipelines. Your deployment script
can be more complex, but I’d like to keep things simple for this article.
Add the server deploy key to the repository
Under the Access Keys tab in the repository settings (Settings → Access Keys), add the server’s public key—in my case, the key for the server’s root user—and give it a descriptive name.
Set up the repository SSH key pair
We need to create SSH keys for the repository. These provide the secure connection between the repository and remote server. Go to the repository’s settings, then SSH Keys. Add the host address and click fetch to view the host’s fingerprint and add the remote to known hosts.
Add the repository public key to the server
Copy the repository’s public key and paste it into the server’s authorized_keys file. In my
case, it is found at /root/.ssh/authorized_keys.
Clone the repository onto the server
If you have not already cloned the repository onto the server, do that now. Ensure that the app
directory in your deploy.sh script matches the location where you cloned the app.
Going forward, whenever you push a change to the repository, Bitbucket will run the pipeline and deploy the code onto the server.
Debugging
You may encounter some blockers along the way, as I did. Here are some tips:
- User permissions: I used the root user, which is a superuser. For security reasons, you may choose another user.
- Directory and file permissions: Check that the SSH user has appropriate permissions in the
files and directories concerned. For instance, the user should have permission to execute the
deploy.shfile, plus read and write access in the app directory for a successfulgit pull. - Commands: If your SSH user requires you to prepend
sudofor certain commands, you may be required to enter a password during the pipeline. You do not want this to happen. Always strive to run pipeline commands in a non-interactive mode. That’s one reason I used the root user.
Further resources
- Continuous Deployment (CD) Using Bitbucket Pipelines and Ubuntu Server
- An Introduction to Continuous Integration, Delivery, and Deployment
- How to Use the chmod Command on Linux
This post is also available on DEV.