Skip to content

Instantly share code, notes, and snippets.

@alifhaikal88
Last active July 27, 2025 07:55
Show Gist options
  • Select an option

  • Save alifhaikal88/92021ae6b3a9d3fb2bc74aed3f62e6ff to your computer and use it in GitHub Desktop.

Select an option

Save alifhaikal88/92021ae6b3a9d3fb2bc74aed3f62e6ff to your computer and use it in GitHub Desktop.
AXP - Complete SSL Certificate Replacement Steps - Nginx, Spring Boot, Jenkins Docker Integration

Complete SSL Certificate Replacement Steps

Date: July 25, 2025
Certificate: *.axaipay.my (Sectigo)
Server: [email protected]
Target: staging.axaipay.my:9999

Overview

Complete step-by-step record of replacing expiring SSL certificate (Aug 8, 2025) with new certificate (valid until Aug 25, 2026).


Phase 1: Certificate Preparation (Local Machine)

Step 1.1: Generate PKCS#12 Certificate

cd "/Users/alifhaikal88/Documents/COMPANY/AXAIPAY/SSL/Axaipay SSL 2026/STAR_axaipay_my"

# Create certificate chain bundle
cat STAR_axaipay_my.crt SectigoPublicServerAuthenticationCADVR36.crt SectigoPublicServerAuthenticationRootR46_USERTrust.crt > certificate_chain.crt

# Generate PKCS#12 file with alias for Spring Boot
openssl pkcs12 -export -out axaipay_my.p12 -inkey 2025ssl.key -in STAR_axaipay_my.crt -certfile certificate_chain.crt -name "axaipay_my" -passout pass:"bayar@xai123$"

Step 1.2: Extract Files for Nginx

# Extract certificate from PKCS#12
openssl pkcs12 -in axaipay_my.p12 -out axaipay_2025.crt -clcerts -nokeys -passin pass:"bayar@xai123$"

# Extract private key from PKCS#12
openssl pkcs12 -in axaipay_my.p12 -out axaipay_2025.key -nocerts -nodes -passin pass:"bayar@xai123$"

# Create certificate bundle for Nginx
cat STAR_axaipay_my.crt SectigoPublicServerAuthenticationCADVR36.crt SectigoPublicServerAuthenticationRootR46_USERTrust.crt > axaipay_2025_bundle.crt

Step 1.3: Convert PKCS#12 to JKS for Jenkins

# Convert PKCS#12 to JKS format for Jenkins (if needed)
keytool -importkeystore \
  -deststorepass bayar@xai123$ \
  -destkeystore axaipay_my.jks \
  -srckeystore axaipay_my.p12 \
  -srcstoretype PKCS12 \
  -srcstorepass bayar@xai123$

Step 1.4: Verify Files Created

ls -la *.p12 *.jks *.crt *.key

# Expected files:
# axaipay_my.p12              (8.6KB) - For Spring Boot
# axaipay_my.jks              (8.5KB) - For Jenkins
# axaipay_2025_bundle.crt     (6.9KB) - For Nginx certificate  
# axaipay_2025.key            (1.9KB) - For Nginx private key

Phase 2: Server Deployment

Step 2.1: Upload Files to Server

# Upload certificate files
scp axaipay_2025_bundle.crt [email protected]:/tmp/
scp axaipay_2025.key [email protected]:/tmp/

# Upload deployment script
scp ssl_backup_replace.sh [email protected]:/tmp/

# Or upload all at once:
scp axaipay_2025_bundle.crt axaipay_2025.key ssl_backup_replace.sh [email protected]:/tmp/

Step 2.2: Connect to Server

Step 2.3: Manual Backup and Replacement

Option A: Using Automated Script

# Make script executable
chmod +x /tmp/ssl_backup_replace.sh

# Execute script
sudo /tmp/ssl_backup_replace.sh

Option B: Manual Step-by-Step

Backup existing certificates:

# Create timestamped backup directory
BACKUP_DIR="/opt/ssl/backup/$(date +%Y%m%d_%H%M%S)"
sudo mkdir -p "$BACKUP_DIR"

# Backup old certificates
sudo cp -r /opt/ssl/20242025/* "$BACKUP_DIR/"
echo "Backup created: $BACKUP_DIR"

Install new certificates:

# Create new SSL directory
sudo mkdir -p /opt/ssl/20252026

# Copy new certificates
sudo cp /tmp/axaipay_2025_bundle.crt /opt/ssl/20252026/bundle.crt
sudo cp /tmp/axaipay_2025.key /opt/ssl/20252026/axaipay.key

# Set proper permissions
sudo chmod 644 /opt/ssl/20252026/bundle.crt
sudo chmod 600 /opt/ssl/20252026/axaipay.key
sudo chown root:root /opt/ssl/20252026/*

Verify certificate and key match:

# Check hashes match
CERT_HASH=$(sudo openssl x509 -noout -modulus -in /opt/ssl/20252026/bundle.crt | openssl md5)
KEY_HASH=$(sudo openssl rsa -noout -modulus -in /opt/ssl/20252026/axaipay.key | openssl md5)
echo "Certificate hash: $CERT_HASH"
echo "Key hash: $KEY_HASH"

Phase 3: Nginx Configuration Update

Step 3.1: Find Config Files with SSL Paths

# List all config files
ls -la /etc/nginx/sites-available/

# Find files containing old SSL path
grep -l "/opt/ssl/20242025" /etc/nginx/sites-available/*

Step 3.2: Backup Nginx Configuration

# Backup current nginx configs
sudo cp -r /etc/nginx/sites-available /etc/nginx/sites-available.backup.$(date +%Y%m%d_%H%M%S)

Step 3.3: Update SSL Paths in Configuration

Method 1: Replace in specific file (if you know the filename)

# Replace in specific config file
sudo sed -i 's|/opt/ssl/20242025|/opt/ssl/20252026|g' /etc/nginx/sites-available/your-config-file

Method 2: Replace in all files containing old path (recommended)

# Find and replace in all relevant files
for file in $(grep -l "/opt/ssl/20242025" /etc/nginx/sites-available/*); do
    echo "Updating: $file"
    sudo sed -i 's|/opt/ssl/20242025|/opt/ssl/20252026|g' "$file"
done

Method 3: One-liner for all files

# Replace in all files that contain the old path
sudo grep -l "/opt/ssl/20242025" /etc/nginx/sites-available/* | xargs -I {} sudo sed -i 's|/opt/ssl/20242025|/opt/ssl/20252026|g' {}

Step 3.4: Verify Configuration Changes

# Verify old path is gone
grep -r "/opt/ssl/20242025" /etc/nginx/sites-available/

# Verify new path is present
grep -r "/opt/ssl/20252026" /etc/nginx/sites-available/

# Show the updated configuration
grep -A2 -B2 "ssl_certificate" /etc/nginx/sites-available/*

Phase 4: Testing and Deployment

Step 4.1: Test Nginx Configuration

# Test nginx configuration syntax
sudo nginx -t

# Expected output:
# nginx: configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

Step 4.2: Reload Nginx

# Reload nginx with new configuration
sudo systemctl reload nginx

# Check nginx status
sudo systemctl status nginx

# Check if nginx is listening on port 9999
sudo netstat -tlnp | grep :9999

Step 4.3: Verify SSL Certificate

# Check certificate details from server
echo | openssl s_client -connect localhost:9999 -servername staging.axaipay.my 2>/dev/null | openssl x509 -noout -dates

# Expected output:
# notBefore=Jul 24 00:00:00 2025 GMT
# notAfter=Aug 25 07:59:59 2026 GMT

# Test HTTPS connection
curl -I https://staging.axaipay.my:9999

Phase 5: Final Verification

Step 5.1: Browser Testing

  1. Visit: https://staging.axaipay.my:9999
  2. Check SSL certificate details in browser
  3. Verify certificate shows "Valid until Aug 25, 2026"
  4. Ensure no SSL warnings

Step 5.2: Certificate Chain Verification

# Verify full certificate chain
openssl s_client -connect staging.axaipay.my:9999 -servername staging.axaipay.my </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer

# Check certificate fingerprint
echo | openssl s_client -connect staging.axaipay.my:9999 -servername staging.axaipay.my 2>/dev/null | openssl x509 -noout -fingerprint

Phase 6: Cleanup and Documentation

Step 6.1: Clean Temporary Files

# Remove temporary files
sudo rm -f /tmp/axaipay_2025_*
sudo rm -f /tmp/ssl_backup_replace.sh

Step 6.2: Update Documentation

  • ✅ Record new certificate expiry: August 25, 2026
  • ✅ Set calendar reminder for renewal: July 2026
  • ✅ Update SSL inventory records

Step 6.3: Set Up Monitoring

# Add certificate expiry monitoring (optional)
echo "0 0 1 * * /usr/bin/openssl x509 -checkend 2592000 -noout -in /opt/ssl/20252026/bundle.crt || echo 'Certificate expires within 30 days'" | sudo crontab -

Rollback Procedures (If Needed)

Quick Rollback

# Restore old certificates
sudo cp /opt/ssl/backup/*/bundle.crt /opt/ssl/20252026/
sudo cp /opt/ssl/backup/*/axaipay.key /opt/ssl/20252026/

# Test and reload
sudo nginx -t && sudo systemctl reload nginx

Complete Rollback

# Restore nginx configuration
sudo cp -r /etc/nginx/sites-available.backup.* /etc/nginx/sites-available

# Restore old SSL directory
sudo rm -rf /opt/ssl/20252026
sudo mkdir -p /opt/ssl/20242025
sudo cp /opt/ssl/backup/*/* /opt/ssl/20242025/

# Update nginx paths back
sudo sed -i 's|/opt/ssl/20252026|/opt/ssl/20242025|g' /etc/nginx/sites-available/*

# Test and reload
sudo nginx -t && sudo systemctl reload nginx

Certificate Details

Old Certificate (Replaced)

  • Path: /opt/ssl/20242025/
  • Expires: August 8, 2025
  • Status: ⚠️ Expired/Expiring

New Certificate (Active)

  • Path: /opt/ssl/20252026/
  • Domain: *.axaipay.my
  • Expires: August 25, 2026
  • Serial: a37fc45c80f60eb7cb2ad6e9771239e5
  • Issuer: Sectigo Public Server Authentication CA DV R36
  • Algorithm: SHA256withRSA (2048-bit)

Configuration Changes

# Before:
ssl_certificate    /opt/ssl/20242025/bundle.crt;
ssl_certificate_key    /opt/ssl/20242025/axaipay.key;

# After:
ssl_certificate    /opt/ssl/20252026/bundle.crt;
ssl_certificate_key    /opt/ssl/20252026/axaipay.key;

Spring Boot Integration

PKCS#12 Configuration

server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:keystore/axaipay_my.p12
server.ssl.key-store-password=bayar@xai123$
server.ssl.key-alias=axaipay_my

File for Spring Boot

  • File: axaipay_my.p12 (8.6KB)
  • Location: src/main/resources/keystore/
  • Password: bayar@xai123$
  • Alias: axaipay_my

Jenkins Docker SSL Integration

Jenkins Docker Deployment Command

docker run -d -u $UID \
  --name=jenkins \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v $(which docker):/usr/bin/docker \
  -v /opt/jenkins:/var/jenkins_home \
  -p 18080:8080 \
  -p 50000:50000 \
  axaipay/jenkins:1.0 \
  --httpPort=-1 \
  --httpsPort=8080 \
  --httpsKeyStore=/var/jenkins_home/ssl/axaipay_my.jks \
  --httpsKeyStorePassword=bayar@xai123$

What This Command Does

Docker Run Parameters

  • -d: Run container in detached (background) mode
  • -u $UID: Run Jenkins with current user ID (security best practice)
  • --name=jenkins: Assign container name "jenkins" for easy management

Volume Mounts

  • /var/run/docker.sock:/var/run/docker.sock:

    • Mounts Docker socket inside container
    • Enables Jenkins to control Docker on host (Docker-in-Docker)
    • Used for building/deploying Docker images from Jenkins
  • $(which docker):/usr/bin/docker:

    • Mounts Docker binary inside container
    • Provides Docker CLI commands within Jenkins container
  • /opt/jenkins:/var/jenkins_home:

    • Persistent storage for Jenkins data
    • Contains jobs, configurations, plugins, and SSL certificates

Port Mappings

  • -p 18080:8080: Maps host port 18080 to container port 8080
  • -p 50000:50000: Maps agent communication port (for Jenkins slaves)

Jenkins SSL Configuration

  • --httpPort=-1: Disables HTTP (forces HTTPS only)
  • --httpsPort=8080: Enables HTTPS on port 8080
  • --httpsKeyStore=/var/jenkins_home/ssl/axaipay_my.jks: SSL keystore path
  • --httpsKeyStorePassword=bayar@xai123$: Keystore password

SSL Certificate Setup for Jenkins

Step 1: Prepare JKS File for Jenkins

# Upload JKS file to Jenkins SSL directory
scp axaipay_my.jks [email protected]:/tmp/

# SSH to server and setup SSL directory
ssh [email protected]
sudo mkdir -p /opt/jenkins/ssl
sudo cp /tmp/axaipay_my.jks /opt/jenkins/ssl/
sudo chown -R $UID:$UID /opt/jenkins/ssl
sudo chmod 644 /opt/jenkins/ssl/axaipay_my.jks

Step 2: Deploy Jenkins with SSL

# Stop existing Jenkins container (if running)
docker stop jenkins && docker rm jenkins

# Deploy new Jenkins with SSL
docker run -d -u $UID \
  --name=jenkins \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v $(which docker):/usr/bin/docker \
  -v /opt/jenkins:/var/jenkins_home \
  -p 18080:8080 \
  -p 50000:50000 \
  axaipay/jenkins:1.0 \
  --httpPort=-1 \
  --httpsPort=8080 \
  --httpsKeyStore=/var/jenkins_home/ssl/axaipay_my.jks \
  --httpsKeyStorePassword=bayar@xai123$

Step 3: Verify Jenkins SSL

# Check container is running
docker ps | grep jenkins

# Check Jenkins logs
docker logs jenkins

# Test HTTPS connection
curl -k -I https://localhost:18080

# Test from external
curl -k -I https://staging.axaipay.my:18080

Jenkins SSL Features

Security Benefits

  • HTTPS Only: HTTP disabled (--httpPort=-1)
  • Valid SSL Certificate: Uses wildcard *.axaipay.my certificate
  • Encrypted Communication: All Jenkins traffic encrypted
  • Browser Trust: No SSL warnings with valid certificate

Jenkins Access URLs

  • Internal: https://localhost:18080
  • External: https://staging.axaipay.my:18080
  • Agent Connection: Port 50000 (secured by firewall)

Certificate Details for Jenkins

  • Keystore Type: JKS (Java KeyStore)
  • File: /var/jenkins_home/ssl/axaipay_my.jks
  • Password: bayar@xai123$
  • Alias: axaipay_my
  • Valid Until: August 25, 2026

Jenkins Certificate Renewal Process

When SSL certificate expires (Aug 2026), update Jenkins:

# 1. Generate new JKS file (follow Phase 1 steps)
# 2. Upload new JKS to server
scp new_axaipay_my.jks [email protected]:/tmp/

# 3. Replace JKS file
sudo cp /tmp/new_axaipay_my.jks /opt/jenkins/ssl/axaipay_my.jks

# 4. Restart Jenkins container
docker restart jenkins

# 5. Verify new certificate
curl -k -I https://staging.axaipay.my:18080

Troubleshooting Jenkins SSL

Common Issues

  1. Container Won't Start

    # Check logs for SSL errors
    docker logs jenkins
    
    # Common fix: Check JKS file permissions
    sudo ls -la /opt/jenkins/ssl/
  2. SSL Certificate Error

    # Verify JKS file integrity
    keytool -list -keystore /opt/jenkins/ssl/axaipay_my.jks -storepass "bayar@xai123$"
  3. Port Already in Use

    # Check what's using port 18080
    sudo netstat -tlnp | grep :18080
    
    # Stop conflicting service or change port

Integration Summary

This Jenkins deployment integrates with the SSL certificate infrastructure by:

  1. Using JKS Format: Converts PKCS#12 to JKS for Java compatibility
  2. HTTPS Only: Enforces secure connections (--httpPort=-1)
  3. Certificate Sharing: Uses same wildcard certificate as other services
  4. Persistent Storage: SSL certificates stored in /opt/jenkins/ssl/
  5. Docker Integration: Enables CI/CD pipelines with Docker builds

The Jenkins instance will be accessible via HTTPS at https://staging.axaipay.my:18080 with a valid SSL certificate until August 25, 2026.


Summary

✅ What Was Accomplished

  • Generated new PKCS#12 certificate for Spring Boot
  • Extracted separate certificate and key files for Nginx
  • Backed up old SSL certificates with timestamp
  • Installed new certificates with proper permissions
  • Updated Nginx configuration paths
  • Tested and reloaded Nginx service
  • Verified SSL certificate is working
  • Extended certificate validity by 1+ year

📈 Results

Aspect Before After
Certificate Expiry Aug 8, 2025 Aug 25, 2026
Status ⚠️ Expiring in 2 weeks ✅ Valid for 1+ year
SSL Directory /opt/ssl/20242025/ /opt/ssl/20252026/
Backup None Timestamped backup created

🎯 Next Actions

  • Monitor: Certificate valid until August 25, 2026
  • Renew: Schedule renewal for July 2026
  • Test: Periodic SSL connection tests
  • Document: Update SSL certificate inventory

Deployment completed: July 25, 2025
Next renewal due: July 2026
Certificate valid until: August 25, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment