Skip to main content

Jenkins Production Setup Guide (Ubuntu 24.04)

This guide configures Jenkins securely behind Apache2 with HTTPS, firewall, and hardened settings.


1. Install Jenkins (LTS)

Use the main installation guide before following this Apache production setup:

After Jenkins is installed and accessible, continue with the steps below.


2. System Preparation

Update System

sudo apt update && sudo apt upgrade -y

Install Required Packages

Not to use

sudo apt install -y apache2 ufw fail2ban curl wget

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.digi.saroj.name.np.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>

This is final output that we create later.

<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}s"
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

Once ssl installed edit the host file to make some changes,

sudo nano /etc/apache2/sites-available/jenkins.digi.saroj.name.np-le-ssl.conf

make this changes, this is used to forwarded all headers, port = 443, proto = https

    # --- Forwarded headers for Jenkins ---
RequestHeader set X-Forwarded-Host "%{HTTP_HOST}s"
RequestHeader set X-Forwarded-Port "443"
RequestHeader set X-Forwarded-Proto "https"

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.