Jenkins Production Setup Guide (Ubuntu 24.04)
This guide configures Jenkins securely behind Apache2 with HTTPS, firewall, and hardened settings.
1. System Preparation
Update System
sudo apt update && sudo apt upgrade -y
Install Required Packages
Not to use
sudo apt install -y fontconfig openjdk-21-jre apache2 ufw fail2ban curl wget
sudo apt install -y fontconfig openjdk-21-jre apache2 ufw fail2ban curl wget
Verify Java:
java -version
2. Install Jenkins (LTS)
sudo wget -O /etc/apt/keyrings/jenkins-keyring.asc https://pkg.jenkins.io/debian-stable/jenkins.io-2026.key
echo "deb [signed-by=/etc/apt/keyrings/jenkins-keyring.asc]" https://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt update
sudo apt install jenkins
Enable & start:
sudo systemctl enable jenkins
sudo systemctl start jenkins
3. Restrict Jenkins to Localhost Only
Edit:
sudo nano /etc/default/jenkins
Ensure:
JENKINS_ARGS="--httpPort=8080 --httpListenAddress=127.0.0.1"
Restart:
sudo systemctl restart jenkins
Verify:
ss -lntp | grep 8080
Should bind only to 127.0.0.1.
4. Configure Firewall (UFW)
sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
sudo ufw status
DO NOT expose 8080 publicly.
5. Enable Apache Required Modules
sudo a2enmod proxy proxy_http proxy_wstunnel headers rewrite ssl
sudo systemctl restart apache2
6. Apache Production VHost (HTTPS + Redirect)
Create:
sudo nano /etc/apache2/sites-available/jenkins.conf
Paste:
<VirtualHost *:80>
ServerName jenkins.digi.saroj.name.np
ProxyPreserveHost On
AllowEncodedSlashes NoDecode
# --- Forwarded headers for Jenkins ---
RequestHeader set X-Forwarded-Host "%{HTTP_HOST}s"
RequestHeader set X-Forwarded-Port "80"
RequestHeader set X-Forwarded-Proto "http"
# Reverse proxy
ProxyPass / http://127.0.0.1:8080/ nocanon
ProxyPassReverse / http://127.0.0.1:8080/
# WebSocket support
ProxyPass /ws/ ws://127.0.0.1:8080/ws/ nocanon
ProxyPassReverse /ws/ ws://127.0.0.1:8080/ws/
ErrorLog ${APACHE_LOG_DIR}/jenkins_error.log
CustomLog ${APACHE_LOG_DIR}/jenkins_access.log combined
</VirtualHost>
<VirtualHost *:80>
ServerName jenkins.digi.saroj.name.np
RewriteEngine On
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<VirtualHost *:443>
ServerName jenkins.digi.saroj.name.np
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/jenkins.digi.saroj.name.np/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/jenkins.digi.saroj.name.np/privkey.pem
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
ProxyPreserveHost On
AllowEncodedSlashes NoDecode
RequestHeader set X-Forwarded-Host "%{Host}i"
RequestHeader set X-Forwarded-Port "443"
RequestHeader set X-Forwarded-Proto "https"
ProxyPass / http://127.0.0.1:8080/ nocanon
ProxyPassReverse / http://127.0.0.1:8080/
ProxyPass /ws/ ws://127.0.0.1:8080/ws/ nocanon
ProxyPassReverse /ws/ ws://127.0.0.1:8080/ws/
ErrorLog ${APACHE_LOG_DIR}/jenkins_error.log
CustomLog ${APACHE_LOG_DIR}/jenkins_access.log combined
</VirtualHost>
Enable site:
sudo a2ensite jenkins.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
7. Install SSL (Let's Encrypt)
sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d jenkins.digi.saroj.name.np
Verify certificate:
sudo certbot certificates
curl -I https://jenkins.digi.saroj.name.np
Test auto-renew:
sudo certbot renew --dry-run
8. Jenkins Configuration
Inside Jenkins:
Manage Jenkins → Configure System
Set:
Jenkins URL: https://jenkins.digi.saroj.name.np/
9. Fail2Ban Protection
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Optional custom jail for Apache login protection.
10. Systemd Hardening (Optional)
Create override:
sudo systemctl edit jenkins
Add:
[Service] LimitNOFILE=65536
Reload:
sudo systemctl daemon-reexec
sudo systemctl restart jenkins
11. Monitoring & Logs
Apache logs:
sudo tail -f /var/log/apache2/jenkins_error.log
Jenkins logs:
sudo journalctl -u jenkins -f
Production Checklist
✔ Jenkins bound to localhost
✔ 8080 not publicly exposed
✔ Firewall enabled
✔ HTTPS enforced
✔ HSTS enabled
✔ Fail2Ban active
✔ Auto-renew SSL tested
Jenkins production deployment complete.