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 admin who will then 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 the Agile development), you will have to repeat that process several times. This can be tiring and in a bid to bypass that loop, you, the developer, may decide to release new changes at the end of the week or at a later time. This defeats the aim of DevOps where we need to have small, iterative changes accessible to the application users. Don’t hinder the process, embrace a continuous workflow!
CI/CD simply automates that process. You write the codes and commit to version control (git). Each time you push your codes to a service like GitHub or Bitbucket, automation kicks in. Your codes are tested using a predefined metric (testing) system and if the minimum testing threshold is reached (CI), the changes are deployed to the live server (CD).
Continuous Deployment - Bitbucket & Linux Server
Note: This hands-on section is to setup a continuous deployment (CD) workflow excluding any form of testing (CI). A fair understanding of Git, Bitbucket, Linux & the CLI (goes without saying right?) is required to maximize this section.
TL;DR
- Enable Pipelines in your Bitbucket repository and configure it using the bitbucket-pipelines.yml file.
- Add server (remote) deploy key to the repository.
- Setup SSH key pair on the repository.
- Add the repository’s public key to the server’s authorized keys.
- Clone the repository onto the server.
DETAILS
Enable Pipelines in your Bitbucket repository and configure it using the bitbucket-pipelines.yml file
In the repository settings, enable Pipelines. This will provide you with a file named bitbucket-pipelines.yml. Here is a sample file:
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 above simply provides the repository the information it needs to deploy the application upon code any new push. It logs into the server using SSH with the mentioned user (in my case – root) and host (IP address supplied). Once connection is successful, it runs the deploy.sh script.
Here is a sample deploy 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 deploy script, we change directory to the app’s directory on the server and pull the recent code changes. The echo commands are for logging purposes which you’ll see in Bitbucket Pipelines. Off course your deployment script can be more complex than this, I’d just like to keep things simple for the sake of this article.
Add server (remote) deploy key to the repository
Under the Access Keys tab of the repo’s settings (Settings > Access Keys), add the public key of the server (in my case, it’s that of the server’s root user) and give it a descriptive name.
Setup SSH key pair on the repository
Now, we need to create SSH keys for the repository. This will be used for secure connection between the repo and the server (remote). Do that by going to the repo’s settings and then SSH Keys. Afterwards, add the host address and click fetch to see the host’s fingerprint (and add the remote to known hosts.
Add the repository’s public key to the server’s authorized keys
Copy the public key from the repository and paste it in the server’s authorized_keys file. In my case, it is found here: /root/.ssh/authorized_keys.
Clone the repository onto the server
If you have not already cloned the repo onto the server, do that now. Ensure that the app directory in your deploy.sh script matches with wherever you clone the app to.
Going forward, whenever you push a change to the repository, Bitbucket will run the pipeline and deploy the codes onto the server.
Debugging
You may encounter some blockers along the way as I did. Here are some tips to help you.
- User Permissions: Observe that I used the root user, which is a super user. For security concerns, you may have chosen to use another user other than the root user.
- Directory/file Permissions: Check to see that the SSH user has the appropriate permissions in the file/directory of concern. For instance, the SSH user should have a permission to execute (x) the deploy.sh file, and read (r) and write (w) access in the app’s directory for a successful git pull request.
- Commands: If your SSH user requires you to prepend sudo for certain commands in your deploy script, you may then be required you to enter passwords at some point in the pipeline. You do not want this to happen. Always, strive to run pipeline commands in a non-interactive mode (that’s one of the reasons I used the root user).
Further Resources
- Continuous Deployment(CD) Using Bitbucket Pipelines and Ubuntu Server by Nicholas Kimuli
- An Introduction to Continuous Integration, Delivery, and Deployment
- How to Use the chmod Command on Linux
Follow me on Twitter @Ileriayooo for more on Tech and Opportunities.
If you want to be successful in tech, here is a simple framework.
Top comments (3)
hi, The process looks excellent but wont it ask for bitbucket authentication on "git pull origin master" while running deploy.sh? Like it does on our git bash?
Hi, thanks for your kind words.
I'm really sorry for my late response as I had forgotten that comment notifications are not sent to emails.
I do hope however that you have been able to solve this issue.
Nonetheless, here's my response.
At some points when I tried this, I did encounter the authentication issue like you mentioned, hence the debugging tips that I mentioned at the end of the article.
Adding the deploy key and SSH key should take care of authentication. Cloning the repo from the start handles the case of known hosts. Afterwards, things should go on smoothly and the pipeline commands should execute in a non-interactive mode.
Sounds great, thank you Ileriayo.