Console Login

Stop Dragging Files via FTP: Building a Robust CI Pipeline with Jenkins and Git on CentOS 6

The "It Works on My Machine" Era Ends Today

If I have to hear one more developer say "but it ran fine on localhost" while the production server is spewing 500 errors, I might just pull the plug on the rack. It is 2013. We are done with dragging files via FileZilla. We are done with manual ssh sessions to run git pull on a live server. If you are managing infrastructure for Norwegian clients—who expect uptime stability mirroring our hydroelectric power grid—you need a Continuous Integration (CI) pipeline.

Building software is easy. Building a repeatable, automated assembly line for that software is where the professionals separate themselves from the amateurs. In this guide, we are setting up a Jenkins CI server on a CoolVDS KVM instance running CentOS 6. Why KVM? Because Jenkins is a memory-hungry beast (thanks, Java), and I refuse to let a noisy neighbor on a shared kernel (looking at you, OpenVZ) steal the RAM my build agent needs.

Prerequisites: The Foundation

You need a server that isn't running on spinning rust. Compilation implies heavy disk I/O. If you are compiling Java, C++, or even minifying heavy JavaScript assets, you need IOPS. This is why we use CoolVDS instances backed by pure SSD arrays. Attempting this on a standard SATA VPS will result in iowait spikes that will time out your build scripts.

Start with a fresh CentOS 6.3 or 6.4 install. First, let's secure the perimeter. We aren't using firewalld yet; we stick to the proven iptables.

1. Securing the Box

# Flush existing rules
iptables -F

# Allow SSH, HTTP, and Loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# Drop the rest
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Save rules
service iptables save
service iptables restart

Installing the Engine: Jenkins CI

Jenkins is the undisputed king of open-source CI right now. It is ugly, it is XML-heavy, but it works. It runs on Java, so we need the OpenJDK environment first.

yum install java-1.7.0-openjdk wget -y

Next, we add the Jenkins repository and install the service.

wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
yum install jenkins -y

# Start Jenkins and ensure it runs on boot
service jenkins start
chkconfig jenkins on

By default, Jenkins listens on port 8080. Do not expose port 8080 to the world. It looks unprofessional, and corporate firewalls often block non-standard ports. We will put Nginx in front of it as a reverse proxy.

The Reverse Proxy Strategy

Nginx is lighter and faster than Apache for this specific task. We want Nginx to handle the client connection and pass traffic locally to Jenkins. This also gives us a layer to implement SSL later if needed (and you should).

yum install nginx -y
chkconfig nginx on

Edit your /etc/nginx/conf.d/jenkins.conf. Make sure you tune the client_max_body_size or your developers will scream when they can't upload large WAR files.

server {
    listen       80;
    server_name  ci.yourdomain.no;

    location / {
        proxy_pass         http://127.0.0.1:8080;
        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_max_temp_file_size 0;

        client_max_body_size       10m;
        client_body_buffer_size    128k;

        proxy_connect_timeout      90;
        proxy_send_timeout         90;
        proxy_read_timeout         90;
    }
}

Restart Nginx: service nginx restart. Now you can access your CI server at port 80.

Automating the Deployment: The "War Story"

I once managed a Magento cluster for a retailer in Trondheim. They deployed on Fridays. Manually. One Friday, a developer forgot to upload the app/etc/local.xml file after a migration. The site went down for 4 hours. We lost sales. I lost sleep.

We fixed this by using Jenkins to trigger a shell script upon a successful Git commit. Here is a simplified version of a deployment script you can configure in a Jenkins "Freestyle Project". It uses rsync because it's atomic—files are updated instantly, preventing the "white screen of death" during file transfers.

#!/bin/bash
# Defined in Jenkins environment variables
TARGET_SERVER="user@192.168.10.55"
DEPLOY_DIR="/var/www/html/prod"

echo "Starting deployment to $TARGET_SERVER..."

# Exclude git metadata and config files that shouldn't be overwritten
rsync -avz --delete --exclude '.git' --exclude 'app/etc/local.xml' \
    $WORKSPACE/ $TARGET_SERVER:$DEPLOY_DIR/

# Clear cache remotely (Magento example)
ssh $TARGET_SERVER "rm -rf $DEPLOY_DIR/var/cache/*"

echo "Deployment Complete."
Pro Tip: Always use SSH keys for authentication between your Jenkins server and your production web nodes. Never put passwords in your scripts. On your CoolVDS instance, generate the key with ssh-keygen -t rsa and push it to the target with ssh-copy-id.

The Latency Factor: Why Location Matters

You might ask, "Why not host this in the US where it's cheaper?" Here is why: Latency. If your repository (GitHub/Bitbucket) interacts with your build server, and your build server deploys to your production environment in Oslo, the round-trip time adds up.

Furthermore, we have strict privacy norms here. While the Data Protection Directive governs Europe, the Norwegian Datatilsynet is particularly vigilant. Keeping your infrastructure within Norwegian borders—or at least within the EEA—simplifies your compliance posture significantly. CoolVDS offers low-latency routing via NIX (Norwegian Internet Exchange), ensuring your packets don't take a scenic route through Frankfurt just to reach a server in Bergen.

Optimizing for Performance

A CI server is high-stress. It checks out code, compiles binaries, runs unit tests, and archives artifacts. This is disk-intensive.

ResourceStandard VPSCoolVDS (SSD)
Disk I/O40-80 MB/s400+ MB/s
IOPS100-20010,000+
Build Time15 mins3 mins

When you are running a test suite with 500 database interactions, High I/O wait times on a standard HDD VPS will kill your CPU performance. The CPU sits idle, waiting for the disk to write. On CoolVDS KVM instances, we pass through the SSD speed. This means your builds finish faster, your developers get feedback sooner, and you go home on time.

Final Check

Before you consider your pipeline "production-ready," verify your Java heap settings. In /etc/sysconfig/jenkins, ensure you aren't allocating more RAM than the VPS has, or the OOM Killer will terminate Jenkins in the middle of a build. Set JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Xmx512m" if you are on a 1GB slice.

Stop manually FTPing files. It’s risky, it’s slow, and quite frankly, it’s unprofessional. Spin up a CoolVDS instance, install Jenkins, and automate your workflow. If you value your uptime, you’ll value our SSD architecture.