How to Install and Configure Buildbot on CentOS 7
Buildbot is an open source, Python based, continuous integration tool to automate software building, testing, and deployment. Buildbot consists of one or more Buildbot master and a number of workers. Buildbot master or Buildmaster has central command of the system. It is responsible for managing the build environment, workers and makes all the decisions about sending jobs to workers. Buildmaster detects changes in the code repository and sends the commands or jobs to the workers to execute. Workers execute the jobs and return the result to the Buildmaster. Buildmaster then notifies the developers through multiple supported channels. In this tutorial, we will install Buildbot master and worker on CentOS 7. We will also configure authentication and Nginx as a secured reverse proxy.
Prerequisites
- A Vultr CentOS 7 server instance with at least 1GB RAM.
- A sudo user.
- A registered domain name pointed towards the server.
For this tutorial, we will use 192.168.1.1
as the public IP address and ci.example.com
as the domain name pointed towards the Vultr instance. Please make sure to replace all occurrences of the example domain name and IP address with the actual one.
Update your base system using the guide How to Update CentOS 7. Once your system has been updated, proceed to install PostgreSQL.
Install Python Dependencies
Install Pip, which is a package manager for Python.
sudo yum -y install epel-release
sudo yum -y install python-pip gcc python-devel git
sudo pip install --upgrade pip
Install PostgreSQL
Buildbot supports multiple types of database servers such as MySQL, PostgreSQL, and SQLite. In this tutorial, we will use PostgreSQL to host the Buildbot database server.
PostgreSQL is an object-relational database system, known for its stability and speed. The default yum
repository contains an old version of PostgreSQL, so add the PostgreSQL repository.
sudo yum -y install https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-1.noarch.rpm
Install the PostgreSQL database server.
sudo yum -y install postgresql10-server postgresql10-contrib postgresql10
Initialize the database.
sudo /usr/pgsql-10/bin/postgresql-10-setup initdb
Start the PostgreSQL server and enable it to start automatically at boot time.
sudo systemctl start postgresql-10
sudo systemctl enable postgresql-10
Change the password for the default PostgreSQL user.
sudo passwd postgres
Log in as the PostgreSQL user.
sudo su - postgres
Create a new PostgreSQL user for Buildbot.
createuser bb_user
You can use any username instead of bb_user
, if you prefer. PostgreSQL provides the psql
shell to run queries on the database. Switch to the PostgreSQL shell.
psql
Set a password for the newly created user.
ALTER USER bb_user WITH ENCRYPTED password 'DBPassword';
Replace DBPassword
with a secure password.
Create a new database for the Buildbot installation.
CREATE DATABASE buildbot OWNER bb_user;
Exit from the psql
shell.
\q
Switch to the sudo
user.
exit
Edit the pg_hba.conf
file to enable MD5 based authentication.
sudo nano /var/lib/pgsql/10/data/pg_hba.conf
Find the following lines and change the values peer
and ident
, in the METHOD
column, to trust
and md5
, respectively.
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 ident
# IPv6 local connections:
host all all ::1/128 ident
Once updated, the configuration will look like the following text.
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 127.0.0.1/32 md5
# IPv6 local connections:
host all all ::1/128 md5
Save the file and exit the editor. Install the PostgreSQL database adapter for Python.
sudo pip install psycopg2
Restart PostgreSQL so that the changes can take effect.
sudo systemctl restart postgresql-10
Install Buildbot
Install Buildbot using Pip.
sudo pip install 'buildbot[bundle]' pyopenssl service_identity
The above command will install Buildbot along with buildbot-www
, buildbot-worker
, and several web plugins such as buildbot-waterfall-view
.
To ensure that Buildbot has been successfully installed, you can verify by checking the version of Buildbot.
buildbot --version
The output should resemble the following text.
[user@vultr ~]$ buildbot --version
Buildbot version: 0.9.15.post1
Twisted version: 17.9.0
Modify your firewall rules to allow port 8010
. Buildbot uses this port to listen to the web requests.
sudo firewall-cmd --zone=public --add-port=8010/tcp --permanent
sudo firewall-cmd --reload
Configure Buildbot Master
Create a new unprivileged user to run Buildbot master and worker processes. It is not recommended to run Buildbot master services as the root
user.
sudo adduser buildbot
sudo passwd buildbot
Log in as the newly created buildbot
user.
sudo su - buildbot
Set up the Buildbot master in /home/buildbot/master
directory. This directory will contain the configuration, status and log files of each build.
buildbot create-master --db 'postgresql://bb_user:DBPassword@localhost/buildbot' ~/master
Make sure to replace the credentials of the database user in the above command.
Note: If you wish to use SQLite database instead of PostgreSQL, simply omit the --db 'postgresql://bb_user:DBpassword@localhost/buildbot'
option. The SQLite database will be created in the same directory.
The above command will create the ~/master
directory to store the Buildmaster files. It will also write the data into the PostgreSQL database. You will get the following output.
[buildbot@vultr ~]$ buildbot create-master --db 'postgresql://bb_user:DBPassword@localhost/buildbot' ~/master
mkdir /home/buildbot/master
creating /home/buildbot/master/master.cfg.sample
creating database (postgresql://bb_user:DBPassword@localhost/buildbot)
buildmaster configured in /home/buildbot/master
Copy the sample configuration file to a live configuration file.
cp ~/master/master.cfg.sample ~/master/master.cfg
Edit the configuration file.
nano ~/master/master.cfg
Find the following lines.
c['workers'] = [worker.Worker("example-worker", "pass")]
...
c['builders'].append(
util.BuilderConfig(name="runtests",
workernames=["example-worker"],
factory=factory))
...
c['title'] = "Hello World CI"
c['titleURL'] = "https://buildbot.github.io/hello-world/"
...
c['buildbotURL'] = "http://localhost:8010/"
...
c['db'] = {
'db_url' : "postgresql://bb_user:DBpassword@localhost/buildbot",
}
The above configuration has an entry for a sample worker. We will modify the sample entry for the worker we will be running on localhost
. Change the example-worker
to any suitable name for the localhost
worker and change the pass
to some other password. Make a note of the worker name and password as we will require that later in the tutorial. Change the name of the worker in the list of builders. Change the name of the application and project URL according to your needs.
Change the Buildbot URL from localhost
to your actual domain name or public IP address. Also, verify that the database information in the configuration file matches your actual database credentials.
At the end of the file, add c['buildbotNetUsageData'] = None
. This parameter will disable sending the software version information and plugin usage details to the developers. However, to enable sending the uses information, change the option to Full
.
The configuration should look like the following text.
c['workers'] = [worker.Worker("localhost-worker", "Password123")]
...
c['builders'].append(
util.BuilderConfig(name="runtests",
workernames=["localhost-worker"],
factory=factory))
...
c['title'] = "My Application CI"
c['titleURL'] = "https://example.com/my-app"
...
c['buildbotURL'] = "http://192.168.1.1:8010/"
...
c['db'] = {
'db_url' : "postgresql://bb_user:DBpassword@localhost/buildbot",
}
...
c['buildbotNetUsageData'] = None
Save the file and exit the editor. Check the configuration file for errors.
buildbot checkconfig ~/master
If the configuration file has no errors, you will see following output.
[buildbot@vultr ~]$ buildbot checkconfig ~/master
Config file is good!
Now that everything is configured correctly, you can start the Buildbot master.
buildbot start ~/master
You will see the following output.
[buildbot@vultr ~]$ buildbot start ~/master
Following twistd.log until startup finished..
The buildmaster appears to have (re)started correctly.
Now that the Buildbot master has started correctly, the web user interface is accessible at http://192.168.1.1:8010
. You should see the following Buildbot interface.
Configure Buildbot Worker
Since we have already modified the worker configuration in ~/master/master.cfg
, we can proceed to create a new worker.
buildbot-worker create-worker ~/worker localhost localhost-worker Password123
Make sure that you use the exact same worker name and password as mentioned in ~/master/master.cfg
file. If there's a mismatch in worker name or password, the worker will not be able to connect to the Buildbot master. You will see the following output upon successful execution.
[buildbot@vultr ~]$ buildbot-worker create-worker ~/worker localhost example-worker pass
mkdir /home/buildbot/worker
mkdir /home/buildbot/worker/info
Creating info/admin, you need to edit it appropriately.
Creating info/host, you need to edit it appropriately.
Not creating info/access_uri - add it if you wish
Please edit the files in /home/buildbot/worker/info appropriately.
worker configured in /home/buildbot/worker
Information about the worker is stored in the /info
directory. Edit the administrative information about the developer.
nano ~/worker/info/admin
Replace the example name with your actual name and email.
Your Name <mail@example.com>
Now, open the file containing information about the host.
nano ~/worker/info/host
Replace the example instruction with the actual information about the host system.
Localhost, CentOS 7
The worker admin and host information is only used to tell the users about the system. You can also add additional information about the system such as Buildbot version and Twisted version.
Start the worker.
buildbot-worker start ~/worker
The output will look like the following text.
[buildbot@vultr ~]$ buildbot-worker start ~/worker
Following twistd.log until startup finished..
The buildbot-worker appears to have (re)started correctly.
To check if the worker is registered, head to the web interface of Buildbot and navigate to Builds >> Workers
from the left navigation. You should see that the worker is up and ready to build.
To run a sample build, to check if the Buildbot worker is running successfully, navigate to Builds >> Builders
. Click on the runtests
builder name to open the builder interface and click on the Force
button to force a build. Provide your name and click on the Start Build
button to start the build. Since it is a sample build test to check the Buildbot environment, it will finish in a couple of seconds. You will get a success message and the build result.
Setting up Systemd Service
Although the Buildbot master and worker can be easily started using the commands above, it is recommended to use Systemd units to run and manage the Buildbot services. This will ensure that they are automatically started on system restart and failures.
Note: Switch to the sudo
user again by running either exit
or su <username>
. From now on all the commands need to be executed by the sudo
user.
Stop the running Buildbot worker and master service.
sudo su buildbot -c "buildbot stop /home/buildbot/master"
sudo su buildbot -c "buildbot-worker stop ~/worker"
Create a new Systemd unit file for the Buildbot master.
sudo nano /etc/systemd/system/buildbot.service
Populate the file.
[Unit]
Description=BuildBot master service
After=network.target
[Service]
Type=forking
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/master
ExecStart=/usr/bin/buildbot start
ExecStop=/usr/bin/buildbot stop
ExecReload=/usr/bin/buildbot restart
[Install]
WantedBy=multi-user.target
Start the Buildbot master and enable it to automatically start at boot time.
sudo systemctl start buildbot
sudo systemctl enable buildbot
Create a new Systemd unit file for the Buildbot worker.
sudo nano /etc/systemd/system/buildbot-worker.service
Populate the file.
[Unit]
Description=BuildBot worker service
After=network.target
[Service]
Type=forking
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/worker
ExecStart=/usr/bin/buildbot-worker start
ExecStop=/usr/bin/buildbot-worker stop
ExecReload=/usr/bin/buildbot-worker restart
[Install]
WantedBy=multi-user.target
Start the Buildbot worker and enable it to automatically start at boot time.
sudo systemctl start buildbot-worker
sudo systemctl enable buildbot-worker
You can check the status of the services.
sudo systemctl status buildbot buildbot-worker
If the services are running smoothly, you will see that in the output.
[user@vultr ~]$ sudo systemctl status buildbot buildbot-worker
● buildbot.service - BuildBot master service
...
Active: active (running) since Fri 2018-01-12 16:00:59 UTC; 1min 25s ago
...
Jan 12 16:00:59 vultr.guest systemd[1]: Started BuildBot master service.
● buildbot-worker.service - BuildBot worker service
...
Active: active (running) since Fri 2018-01-12 16:02:00 UTC; 24s ago
...
Jan 12 16:02:00 vultr.guest systemd[1]: Started BuildBot worker service.
Enabling Authentication
By default, authentication is not enabled in the Buildbot web interface. For internet facing sites, it is strongly recommended to setup authentication so that only the authorized users can have the ability to perform administrative tasks. To set up authentication, reopen the Buildbot master configuration file.
sudo su buildbot -c "nano /home/buildbot/master/master.cfg"
Add the following lines to the end of the file.
c['www']['authz'] = util.Authz(
allowRules = [
util.AnyEndpointMatcher(role="admins")
],
roleMatchers = [
util.RolesFromUsername(roles=['admins'], usernames=['admin_user'])
]
)
c['www']['auth'] = util.UserPasswordAuth({'admin_user': 'AdminPassword'})
Replace both occurrences of admin_user
with the actual username you want to use and AdminPassword
with a strong password.
Check for errors in the configuration file.
sudo su buildbot -c "buildbot checkconfig /home/buildbot/master"
Restart Buildbot master service so that the changes can take effect.
sudo systemctl restart buildbot
Browse the web interface again to see that the anonymous users can only view the basic details about the build server. Now, log in using the credentials set in the master.cfg
file and you will see that all other administrative functions are only available to the logged in admin user.
Securing Buildbot with Let's Encrypt SSL
By default, Buildbot listens to the port 8010
on unsecured connections. Securing the web interface with HTTPS
is recommended to ensure that the data is safe during transportation from the browser to the server. In this section of the tutorial, we will install and secure Nginx with Let's Encrypt free SSL certificates. The Nginx web server will work as a reverse proxy to forward the incoming requests to Buildbot's HTTP endpoint.
Install Nginx.
sudo yum -y install nginx
Start Nginx and enable it to automatically start at boot time.
sudo systemctl start nginx
sudo systemctl enable nginx
Install Certbot, which is the client application for Let's Encrypt CA.
sudo yum -y install certbot
Before you can request the certificates, you will need to allow ports 80
and 443
or standard HTTP
and HTTPS
services through the firewall. Also, remove port 8010
, which listens to the unsecured connections.
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --zone=public --remove-port=8010/tcp --permanent
sudo firewall-cmd --reload
Note: To obtain certificates from Let's Encrypt CA, the domain for which the certificates are to be generated must be pointed towards the server. If not, make the necessary changes to the DNS records of the domain and wait for the DNS to propagate before making the certificate request again. Certbot checks the domain authority before providing the certificates.
Generate the SSL certificates.
sudo certbot certonly --webroot -w /usr/share/nginx/html -d ci.example.com
The generated certificates are likely to be stored in the /etc/letsencrypt/live/ci.example.com/
directory. The SSL certificate will be stored as fullchain.pem
and the private key will be stored as privkey.pem
.
Let's Encrypt certificates expire in 90 days, hence it is recommended to set up auto-renewal of the certificates using Cron jobs.
Open the cron job file for the root
user.
sudo crontab -e
Add the following line at the end of the file.
30 5 * * * /usr/bin/certbot renew --quiet
The above cron job will run every day at 5:30 AM. If the certificate is due for expiry, it will automatically renew them.
Now, change the Nginx default configuration file to take out the default_server
line.
sudo sed -i 's/default_server//g' /etc/nginx/nginx.conf
Create a new configuration file for Buildbot web interface.
sudo nano /etc/nginx/conf.d/buildbot.conf
Populate the file.
upstream buildbot {
server 127.0.0.1:8010;
}
server {
listen 80 default_server;
server_name ci.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2 default_server;
server_name ci.example.com;
root html;
index index.html index.htm;
ssl on;
ssl_certificate /etc/letsencrypt/live/ci.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ci.example.com/privkey.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1440m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
access_log /var/log/nginx/buildbot.access.log;
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Host $host;
location / {
proxy_pass http://buildbot;
}
location /sse/ {
proxy_buffering off;
proxy_pass http://buildbot/sse/;
}
location /ws {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://buildbot/ws;
proxy_read_timeout 6000s;
}
}
Check for the errors in the new configuration file.
sudo nginx -t
If you see the following output, the configuration is error free.
[user@vultr ~]$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
If you have received some kind of error, make sure to double check the path to the SSL certificates. Restart the Nginx web server to implement the change in configuration.
sudo systemctl restart nginx
Open the Buildmaster configuration file.
sudo su buildbot -c "nano /home/buildbot/master/master.cfg"
Locate the following line.
c['buildbotURL'] = "http://192.168.1.1:8010/"
Change the URL according to the domain name you are using.
c['buildbotURL'] = "https://ci.example.com/"
Restart the Buildbot master service.
sudo systemctl restart buildbot
Now you can access the Buildbot dashboard at https://ci.example.com
. You will see that the connections to Buildbot are now secured with SSL.
Log in using the administrator credentials and add your first pipeline to start building your application.