Introduction:

In this tutorial, you will learn how to set up Bitbucket Pipelines for a PHP & Node.js application and deploy them to your Ubuntu 18.04 server.

I’m writing this because I wasn’t able to get a step-by-step guide for how to do it from one source. I had to do some research and use different sources (some of which can be found at the bottom of the article) to achieve what I wanted. Hopefully, this will be of help to someone.

Let’s get to it, shall we?

For starters, let’s define terms:

Continuous Integration(CI) — is a development practice where developers integrate code into a shared repository frequently, preferably several times a day. Each integration can then be verified by an automated build and automated tests.

Continuous Deployment(CD) — is a strategy for software releases wherein any code commit that passes the automated testing phase is automatically released into the production environment, making changes that are visible to the software’s users.

My primary target was deploying an application to my Ubuntu DigitalOcean server (get some credit when you sign up by clicking here. Full disclosure: I get something in return) without having to SSH into it and run the deployment script.

Enable Pipelines in Bitbucket

Go to Your repository Settings -> Under the section of the pipeline, click on Settings -> Click on the Enable Pipelines Switch to enable pipelines.

Pipelines are now enabled.

Next up, we’ll set up SSH keys for our repository.

Set up repository SSH Keys

These are the keys you’ll set up on your production or staging server to enable external logins to your server from bitbucket during the deployment steps which we will discuss later on.

To set these up, got to SSH Keys(still within the Pipelines Section in your repository settings) -> then click on Generate keys. You could use your own keys but there are a couple of sources that have had issues and ended up advise

against it. Generating your own keys is the best alternative.

After that, set up Known Hosts. Enter the IP address of your Ubuntu server as the Host address then click Fetch to generate the host’s fingerprint. After the fingerprint is generated, click on the Add Host button.

Next up, we’ll add the public key from our repository to the authorized_keys file of our Ubuntu server.

Adding public key from Bitbucket Repository to Ubuntu server authorized_keys

Login to your Ubuntu server. It’s important to note that SSH login should be enabled for your server. If you haven’t enabled it, kindly follow the steps outlined here.

# Enter .ssh folder
$ cd ~/.ssh
# Copy key to authorized_keys file
# Open file using your favourite editor e.g. nano
$ sudo nano authorized_keys
# Add the copied public key from bitbucket on a new line then save(there's a 'Copy public key' button on the SSH keys page)

Permanently add private key identity to the authentication agent

To prevent entering the passphrase to your private key while pulling your Bitbucket repositories to your servers, you need to persist your identity using ssh-add. By default, the identity is lost every time you log out hence the need to persist it. This is important if your key has a passphrase set up. If not, you can ignore this part.

Open up your .bashrc using the following command.

$ sudo nano ~/.bashrc

Copy the following contents to the bottom of your .bashrc file.

# SSH Permanent passphrase
SSH_ENV=$HOME/.ssh/environment
# start the ssh-agent
function start_agent {
   echo "Initializing new SSH agent..."
   # spawn ssh-agent
   /usr/bin/ssh-agent | sed 's/^echo/#echo/' > ${SSH_ENV}
 echo succeeded
   chmod 600 ${SSH_ENV}
   . ${SSH_ENV} > /dev/null
   /usr/bin/ssh-add
}
if [ -f "${SSH_ENV}" ]; then
    . ${SSH_ENV} > /dev/null
  ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
       start_agent;
   }
else
   start_agent;
fi

This keeps the ssh-agent running even when you log out of your server and persists your private key identity. To get it going, however, you’ll need to log out and log in to your server. Once you log in, the SSH Agent will be initialized and you’ll be requested to add the passphrase to your private key.

Set up a deployment script on your server

This is the script that we will run to deploy your application. It is basically a list of the commands you use to deploy your application on your server.

Run the following commands to set up an executable deployment script.

# Create script at the root
$ cd
$ touch deployApi.sh
# make executable
$ chmod +x deployApi.sh
# Executing script
$ ./deployApi.sh

A sample PHP application deployment script:

#!/bin/bash
root="/var/www/example.com/public_html"
cd $root
echo -e '\e[1m\e[34mPulling code from remote..\e[0m\n'
git pull origin master
echo -e '\e[1m\e[34m\nInstalling required packages..\e[0m\n'
# Install required packages
composer install
echo -e '\e[1m\e[34m\nAPI deployed\e[0m\n'

A sample Node.js application deployment script:

#!/bin/bash
root="/var/www/example.com/html"
cd $root
echo -e '\e[1m\e[34mPulling code from remote..\e[0m\n'
git pull origin master
echo -e '\e[1m\e[34m\nChecking for new npm version and installing..\e[0m\n'
npm install -g npm
echo -e '\e[1m\e[34m\nInstalling required packages..\e[0m\n'
npm install
echo -e '\e[1m\e[34m\nRestarting service..\e[0m\n'
# Replace 1 with the ID of the service running your application
pm2 restart 1
echo -e '\n\e[1m\e[34mDeployment successful\e[0m'

Setting up this script is important as bitbucket will run it once it’s logged into your server.

Once you are done with that, we can now set up the bitbucket-pipelines.yml.

Setting up bitbucket-pipelines.yml

This is the file that defines your build, test and deployment configurations. It can be configured per branch i.e. what tests to run when some code is pushed to master and where it will be deployed. If you are using a staging server, you can set up the server details separate from the production server details.

Bitbucket has made it easy to set this up by providing templates based on the type of application you are running.

  1. Go to the Pipelines menu item on your left to proceed.
  2. Choose a language template. In this case, PHP or Node.js.
  3. Set up a YML file.
  4. Click on Save. This will commit to your branch and create a new pipeline based on your YML file.

*Note: These are sample yml files. In your script section, you can run the commands necessary for your application.

Setting up bitbucket-pipelines.yml file for our PHP application

This script showcases how you can deploy changes based on different branches.

# This is a sample build configuration for PHP.
# Check our guides at https://confluence.atlassian.com/x/e8YWN for more examples.
# Only use spaces to indent your .yml configuration.
# -----
# You can specify a custom docker image from Docker Hub as your build environment.
image: php:7.1.29
pipelines:
  # default - contains the steps that will run on every push.
  # default:
  branches:
   # You can include your custom branches and the steps you'd like to undertake e.g. testing
   #staging:
   master:
    - step:
        caches:
          - composer
        script:
          - apt-get update && apt-get install -y unzip
          - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
          - composer install
    - step:
       name: Deploy to production
       deployment: production
       script:
         - pipe: atlassian/ssh-run:0.2.2
           variables:
             SSH_USER: 'your-server-username'
             SERVER: 'your-server-ip-address'
             COMMAND: './your-deployment-script.sh'

Setting up bitbucket-pipelines.yml file for your Node.js application

# This is a sample build configuration for JavaScript.
# Check our guides at https://confluence.atlassian.com/x/14UWN for more examples.
# Only use spaces to indent your .yml configuration.
# -----
# You can specify a custom docker image from Docker Hub as your build environment.
image: node:10.15.3
pipelines:
  default:
    - step:
        caches:
          - node
        script: # Modify the commands below to build your repository.
          - npm install 
          - npm test
    - step:
        name: Deploy to production
        deployment: production
        # trigger: manual  # Uncomment to make this a manual deployment.
        script:
          - echo "Deploying to production environment"
          - pipe: atlassian/ssh-run:0.2.2
            variables:
              SSH_USER: 'your-server-username'
              SERVER: 'your-server-ip-address'
              COMMAND: './your-deployment-script.sh'

Conclusion

By following this tutorial, you will be able to deploy your applications to your Ubuntu server.

Bitbucket allocates 50 free build minutes per account so keep that in mind as you write your YML files. The builds won’t run if you are past your allocated minutes. Keep the YML files short and sweet.

Thank you for reading.

If you find any errors, have any issues or questions don’t hesitate to reach out via the comment section.

Sources:

READ: Setting Expectations For Software Engineering Teams

featured_image
About the Author

Nicholas Kimuli

Software Engineer at Andela

Thanks for subscribing!

 

More Insights

January 22, 2020

Continuous Deployment(CD) Using Bitbucket Pipelines and Ubuntu Server

Nicholas Kimuli

Introduction:

In this tutorial, you will learn how to set up Bitbucket Pipelines for a PHP & Node.js application and deploy them to your Ubuntu 18.04 server.

I’m writing this because I wasn’t able to get a step-by-step guide for how to do it from one source. I had to do some research and use different sources (some of which can be found at the bottom of the article) to achieve what I wanted. Hopefully, this will be of help to someone.

Let’s get to it, shall we?

For starters, let’s define terms:

Continuous Integration(CI) — is a development practice where developers integrate code into a shared repository frequently, preferably several times a day. Each integration can then be verified by an automated build and automated tests.

Continuous Deployment(CD) — is a strategy for software releases wherein any code commit that passes the automated testing phase is automatically released into the production environment, making changes that are visible to the software’s users.

My primary target was deploying an application to my Ubuntu DigitalOcean server (get some credit when you sign up by clicking here. Full disclosure: I get something in return) without having to SSH into it and run the deployment script.

Enable Pipelines in Bitbucket

Go to Your repository Settings -> Under the section of the pipeline, click on Settings -> Click on the Enable Pipelines Switch to enable pipelines.

Pipelines are now enabled.

Next up, we’ll set up SSH keys for our repository.

Set up repository SSH Keys

These are the keys you’ll set up on your production or staging server to enable external logins to your server from bitbucket during the deployment steps which we will discuss later on.

To set these up, got to SSH Keys(still within the Pipelines Section in your repository settings) -> then click on Generate keys. You could use your own keys but there are a couple of sources that have had issues and ended up advise

against it. Generating your own keys is the best alternative.

After that, set up Known Hosts. Enter the IP address of your Ubuntu server as the Host address then click Fetch to generate the host’s fingerprint. After the fingerprint is generated, click on the Add Host button.

Next up, we’ll add the public key from our repository to the authorized_keys file of our Ubuntu server.

Adding public key from Bitbucket Repository to Ubuntu server authorized_keys

Login to your Ubuntu server. It’s important to note that SSH login should be enabled for your server. If you haven’t enabled it, kindly follow the steps outlined here.

# Enter .ssh folder
$ cd ~/.ssh
# Copy key to authorized_keys file
# Open file using your favourite editor e.g. nano
$ sudo nano authorized_keys
# Add the copied public key from bitbucket on a new line then save(there's a 'Copy public key' button on the SSH keys page)

Permanently add private key identity to the authentication agent

To prevent entering the passphrase to your private key while pulling your Bitbucket repositories to your servers, you need to persist your identity using ssh-add. By default, the identity is lost every time you log out hence the need to persist it. This is important if your key has a passphrase set up. If not, you can ignore this part.

Open up your .bashrc using the following command.

$ sudo nano ~/.bashrc

Copy the following contents to the bottom of your .bashrc file.

# SSH Permanent passphrase
SSH_ENV=$HOME/.ssh/environment
# start the ssh-agent
function start_agent {
   echo "Initializing new SSH agent..."
   # spawn ssh-agent
   /usr/bin/ssh-agent | sed 's/^echo/#echo/' > ${SSH_ENV}
 echo succeeded
   chmod 600 ${SSH_ENV}
   . ${SSH_ENV} > /dev/null
   /usr/bin/ssh-add
}
if [ -f "${SSH_ENV}" ]; then
    . ${SSH_ENV} > /dev/null
  ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
       start_agent;
   }
else
   start_agent;
fi

This keeps the ssh-agent running even when you log out of your server and persists your private key identity. To get it going, however, you’ll need to log out and log in to your server. Once you log in, the SSH Agent will be initialized and you’ll be requested to add the passphrase to your private key.

Set up a deployment script on your server

This is the script that we will run to deploy your application. It is basically a list of the commands you use to deploy your application on your server.

Run the following commands to set up an executable deployment script.

# Create script at the root
$ cd
$ touch deployApi.sh
# make executable
$ chmod +x deployApi.sh
# Executing script
$ ./deployApi.sh

A sample PHP application deployment script:

#!/bin/bash
root="/var/www/example.com/public_html"
cd $root
echo -e '\e[1m\e[34mPulling code from remote..\e[0m\n'
git pull origin master
echo -e '\e[1m\e[34m\nInstalling required packages..\e[0m\n'
# Install required packages
composer install
echo -e '\e[1m\e[34m\nAPI deployed\e[0m\n'

A sample Node.js application deployment script:

#!/bin/bash
root="/var/www/example.com/html"
cd $root
echo -e '\e[1m\e[34mPulling code from remote..\e[0m\n'
git pull origin master
echo -e '\e[1m\e[34m\nChecking for new npm version and installing..\e[0m\n'
npm install -g npm
echo -e '\e[1m\e[34m\nInstalling required packages..\e[0m\n'
npm install
echo -e '\e[1m\e[34m\nRestarting service..\e[0m\n'
# Replace 1 with the ID of the service running your application
pm2 restart 1
echo -e '\n\e[1m\e[34mDeployment successful\e[0m'

Setting up this script is important as bitbucket will run it once it’s logged into your server.

Once you are done with that, we can now set up the bitbucket-pipelines.yml.

Setting up bitbucket-pipelines.yml

This is the file that defines your build, test and deployment configurations. It can be configured per branch i.e. what tests to run when some code is pushed to master and where it will be deployed. If you are using a staging server, you can set up the server details separate from the production server details.

Bitbucket has made it easy to set this up by providing templates based on the type of application you are running.

  1. Go to the Pipelines menu item on your left to proceed.
  2. Choose a language template. In this case, PHP or Node.js.
  3. Set up a YML file.
  4. Click on Save. This will commit to your branch and create a new pipeline based on your YML file.

*Note: These are sample yml files. In your script section, you can run the commands necessary for your application.

Setting up bitbucket-pipelines.yml file for our PHP application

This script showcases how you can deploy changes based on different branches.

# This is a sample build configuration for PHP.
# Check our guides at https://confluence.atlassian.com/x/e8YWN for more examples.
# Only use spaces to indent your .yml configuration.
# -----
# You can specify a custom docker image from Docker Hub as your build environment.
image: php:7.1.29
pipelines:
  # default - contains the steps that will run on every push.
  # default:
  branches:
   # You can include your custom branches and the steps you'd like to undertake e.g. testing
   #staging:
   master:
    - step:
        caches:
          - composer
        script:
          - apt-get update && apt-get install -y unzip
          - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
          - composer install
    - step:
       name: Deploy to production
       deployment: production
       script:
         - pipe: atlassian/ssh-run:0.2.2
           variables:
             SSH_USER: 'your-server-username'
             SERVER: 'your-server-ip-address'
             COMMAND: './your-deployment-script.sh'

Setting up bitbucket-pipelines.yml file for your Node.js application

# This is a sample build configuration for JavaScript.
# Check our guides at https://confluence.atlassian.com/x/14UWN for more examples.
# Only use spaces to indent your .yml configuration.
# -----
# You can specify a custom docker image from Docker Hub as your build environment.
image: node:10.15.3
pipelines:
  default:
    - step:
        caches:
          - node
        script: # Modify the commands below to build your repository.
          - npm install 
          - npm test
    - step:
        name: Deploy to production
        deployment: production
        # trigger: manual  # Uncomment to make this a manual deployment.
        script:
          - echo "Deploying to production environment"
          - pipe: atlassian/ssh-run:0.2.2
            variables:
              SSH_USER: 'your-server-username'
              SERVER: 'your-server-ip-address'
              COMMAND: './your-deployment-script.sh'

Conclusion

By following this tutorial, you will be able to deploy your applications to your Ubuntu server.

Bitbucket allocates 50 free build minutes per account so keep that in mind as you write your YML files. The builds won’t run if you are past your allocated minutes. Keep the YML files short and sweet.

Thank you for reading.

If you find any errors, have any issues or questions don’t hesitate to reach out via the comment section.

Sources:

READ: Setting Expectations For Software Engineering Teams

featured_image
About the Author

Nicholas Kimuli

Software Engineer at Andela

Thanks for subscribing!

 

More Insights

Talks At Andela: Building Engineering Teams at Scale

What does “building engineering teams at scale” mean to you (as an engineer or team lead) and yo...

19_February_2020

How to Build a CRUD App in Vanilla PHP

Introduction During a recent technical assessment, I was tasked to develop a simple CRUD events man...

17_February_2020

How To Stay Productive When Dealing With Anxiety Disorder

Disclaimer: This isn't really a hack. There are no eight steps to beat any kind of disorder. If you'...

8_January_2020

Setting Expectations for Software Engineering Teams

Introduction When I started at Andela as CTO I had an opportunity to introduce myself and set expec...

19_December_2019

Battle-tested hacks to grow exponentially as a software engineer

So, you just switched careers and now you are into tech, a software engineer or you have been doing ...

9_December_2019

Remote Heroes Kampala: Event Recap

The Remote Heroes event in Kampala was held on 21st November 2019 at Innovation Village in Ntinda. G...

29_November_2019

Partners

Tap into a global talent pool and hire the “right” developers in days, not months.

Developers

Accelerate your career by working with high-performing engineering teams around the world.

BECOME A DEVELOPER

Hire Developers

We take great pride in matching our developers with the best partners. Tell us about your team below!

preloader_image

Thank you for your interest

A member of our team will reach out to you soon.