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 restartInstalling 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 -yNext, 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 onBy 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 onEdit 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 withssh-keygen -t rsaand push it to the target withssh-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.
| Resource | Standard VPS | CoolVDS (SSD) |
|---|---|---|
| Disk I/O | 40-80 MB/s | 400+ MB/s |
| IOPS | 100-200 | 10,000+ |
| Build Time | 15 mins | 3 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.