Skip to main content

Command Palette

Search for a command to run...

How to Securely Access Jenkins Over HTTPS Using DuckDNS & Nginx

Updated
6 min read
How to Securely Access Jenkins Over HTTPS Using DuckDNS & Nginx

Jenkins is an essential tool for automating software builds, deployments, and CI/CD pipelines. If you're running Jenkins on an AWS EC2 instance, exposing it securely over the internet is crucial. By default, Jenkins runs on port 8080 over HTTP, which isn't ideal for security.

In this guide, we'll walkthrough how to set up DuckDNS with Nginx as a reverse proxy and secure it with Let's Encrypt SSL certificates.

Let's get started!!!

Prerequisites

Before we begin, ensure you have the following:

✅ An AWS EC2 instance running Linux (Amazon Linux, Ubuntu, or CentOS) with Jenkins installed.
Nginx installed as a reverse proxy.
✅ A DuckDNS subdomain (e.g., jenkins-projectlab1.duckdns.org).
✅ A security group that allows inbound traffic on ports 8080 (Jenkins), 80 (HTTP) and 443 (HTTPS).

If you haven’t set up Jenkins yet. You will have to install OpenJDK 17 or newer which is required by Jenkins. For this tutorial I’ll launch an Amazon linux 2023 EC2 instance (t2 medium). You can use any instance you like by make sure you there is enough storage and memory (2 CPU minimum).

First install java:

sudo dnf install -y java-17-amazon-corretto
#verify installation
java -version

Now Proceed with Jenkins Installation

After installing Java, continue with these steps:

a. Add the Jenkins repository:

sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

b. Install Jenkins:

sudo dnf install -y jenkins

c. Enable and start Jenkins:

sudo systemctl enable --now jenkins

#Check if Jenkins is running
sudo systemctl status jenkins

By default, Jenkins runs on http://your-ec2-ip:8080. Let’s make it accessible via https://jenkins-projectlab1.duckdns.org.

Step 1: Set Up DuckDNS for Your Domain

a. Go to DuckDNS and create an account if you don’t have one then sign in using your GitHub or Google account.
b. Under “subdomains” enter a name (e.g., jenkins-projectlab1) and click add domain.
c. Your full domain will be: jenkins-projectlab1.duckdns.org
d. Copy your EC2 Public IP from AWS then go to DuckDNS and update the IP field with your EC2 public IP.

Since EC2 instances often get dynamic IPs, use a script to update DuckDNS automatically, so you don’t have to manually copy the EC2 instance IP and paste in DuckDNS when the IP changes.

To write a script to automatically update DuckDNS with your EC2 instance IP follow the steps below:

a. Connect to your EC2 instance via SSH.

b. Create and cd into the directory**:**

mkdir -p ~/duckdns && cd ~/duckdns

c. Create an executable script to automatically update a new IP in DuckDNS when it changes:

nano duck.sh

d. Login into DuckDNS to get your token and domain name. Add the following lines (replace <YOUR-DUCKDNS-TOKEN> and <YOUR-DOMAIN\>) :

echo url="https://www.duckdns.org/update?domains=<YOUR-DOMAIN>&token=<YOUR-DUCKDNS-TOKEN>&ip=" | curl -k -o ~/duckdns/duck.log -K -

e. Save and exit.

f. Make the duck.sh file executable:

chmod +x duck.sh

g. Test the script:

./duck.sh

#Check duck.log to confirm the update:
cat duck.log

Automate Updates with Cron

Cron is a time-based job scheduler in Unix/Linux systems used to automate tasks at specified intervals. It runs scheduled commands or scripts without manual intervention.

First install Cron on your EC2 Instance:

#For Amazon Linux / Amazon Linux 2
sudo yum install cronie -y

#For Ubuntu/Debian:
sudo apt update && sudo apt install cron -y

#Start and Enable the Cron Service
sudo systemctl start crond
sudo systemctl enable crond

#Verify Cron is Running
systemctl status crond

Next, Open the cron editor:

crontab -e

Add your cron job (e.g., updating DuckDNS every 5 minutes or however you choose):

#This updates your IP every 5 minutes.
*/5 * * * * ~/duckdns/duck.sh >/dev/null 2>&1

Verify Your DuckDNS Domain

Open your browser and go to: http://jenkins-projectlab1.duckdns.org:8080

Note: Ensure your EC2 security group allows traffic on port 8080, 80 & 443 is for Jenkins, HTTP & HTTPS respectively.

Step 2: Install & Configure Nginx as a Reverse Proxy

A reverse proxy is a server that sits between client devices and backend servers, forwarding client requests to the appropriate backend service.

For a better understanding, a reverse proxy is like a middleman between users and a website or app. When you visit a website, instead of connecting directly to the main server, your request first goes through the reverse proxy. The proxy then forwards your request to the correct backend server and sends the response back to you.

Why Use a Reverse Proxy?

Security – Hides the real server, protecting it from attacks. Faster Loading – Stores and delivers frequently used content quickly. Load Balancing – Spreads traffic across multiple servers to prevent overload. HTTPS Support – Handles encryption to secure connections.

To access Jenkins over HTTPS using Nginx as a reserve proxy follow these steps.

First install Nginx:

sudo yum install -y nginx  # For Amazon Linux/CentOS
sudo apt install -y nginx  # For Ubuntu/Debian

#Start and enable Nginx
sudo systemctl enable --now nginx

Configure Nginx for Jenkins

Create a new Nginx configuration file:

sudo nano /etc/nginx/conf.d/jenkins.conf

Add the following content:

server {
    listen 80;
    server_name jenkins-projectlab1.duckdns.org;

    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_set_header X-Forwarded-Proto $scheme;
    }
}

Save and exit (‘:wq’ if using vim editor).

Test and restart Nginx:

sudo nginx -t
sudo systemctl restart nginx

After execution of sudo nginx -t command, you should get “syntax is ok” & “test is successful” confirmation on your terminal.

At this point, your Jenkins should be accessible via http://jenkins-projectlab1.duckdns.org.


Step 3: Secure Jenkins with ‘Let's Encrypt’ SSL

Now, let’s install Certbot to get a free SSL certificate so we can access Jenkins via HTTPS:

First, install Certbot:

#For Amazon Linux/CentOS:
sudo yum install -y certbot python3-certbot-nginx

#For Ubuntu/Debian
sudo apt install -y certbot python3-certbot-nginx

Generate an SSL Certificate

Next step, run the codes below to generate an SSL Certificate for our DuckDNS domain:

sudo certbot --nginx -d jenkins-projectlab1.duckdns.org

Follow the prompts:

  • Enter your email address.

  • Agree to the terms of service.

  • Certbot will configure Nginx for HTTPS automatically.

If it doesn’t, manually update your Nginx config:

sudo nano /etc/nginx/conf.d/jenkins.conf

Replace with:

server {
    listen 80;
    server_name your-subdomain.duckdns.org;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name jenkins-projectlab1.duckdns.org;

    ssl_certificate /etc/letsencrypt/live/jenkins-projectlab1.duckdns.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/jenkins-projectlab1.duckdns.org/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    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_set_header X-Forwarded-Proto $scheme;
    }
}

Save and restart Nginx:

sudo nginx -t
sudo systemctl restart nginx

Note: Certbot will most likely configure Nginx for HTTPS automatically hence you may not need to update manually.

Step 4: Enable Auto-Renewal for SSL

Let's Encrypt certificates expire every 90 days. To renew them automatically, set up a cron job:

sudo crontab -e

Add this line at the bottom:

0 0 * * * certbot renew --quiet && systemctl reload nginx

This will renew the SSL certificate daily at midnight.


Final Test 🎉

Now, open your browser and visit https://jenkins-projectlab1.duckdns.org

Your Jenkins is now running securely over HTTPS! 🚀


Wrapping Up

By following this guide, you:

✅ Configured DuckDNS for dynamic DNS.
✅ Set up Nginx as a reverse proxy for Jenkins.
✅ Secured Jenkins with Let's Encrypt SSL.
✅ Enabled auto-renewal for SSL certificates.

Your Jenkins instance is now secure and accessible over HTTPS from anywhere, and you can use this process to assign a free domain to any IP or resource accessed via HTTPS.

Have questions? Let me know in the comments! 😊

V

Great writeup. This is a practical approach to protect CI/CD pipeline. This writeup proves the need in securing DuckDNS & Nginx

1