Date: July 25, 2025
Certificate: *.axaipay.my (Sectigo)
Server: [email protected]
Target: staging.axaipay.my:9999
Complete step-by-step record of replacing expiring SSL certificate (Aug 8, 2025) with new certificate (valid until Aug 25, 2026).
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$"# 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# 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$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# 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/# Make script executable
chmod +x /tmp/ssl_backup_replace.sh
# Execute script
sudo /tmp/ssl_backup_replace.shBackup 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"# 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/*# Backup current nginx configs
sudo cp -r /etc/nginx/sites-available /etc/nginx/sites-available.backup.$(date +%Y%m%d_%H%M%S)# Replace in specific config file
sudo sed -i 's|/opt/ssl/20242025|/opt/ssl/20252026|g' /etc/nginx/sites-available/your-config-file# 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# 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' {}# 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/*# 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# 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# 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- Visit:
https://staging.axaipay.my:9999 - Check SSL certificate details in browser
- Verify certificate shows "Valid until Aug 25, 2026"
- Ensure no SSL warnings
# 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# Remove temporary files
sudo rm -f /tmp/axaipay_2025_*
sudo rm -f /tmp/ssl_backup_replace.sh- ✅ Record new certificate expiry: August 25, 2026
- ✅ Set calendar reminder for renewal: July 2026
- ✅ Update SSL inventory records
# 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 -# 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# 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- Path:
/opt/ssl/20242025/ - Expires: August 8, 2025
- Status:
⚠️ Expired/Expiring
- 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)
# 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;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:
axaipay_my.p12(8.6KB) - Location:
src/main/resources/keystore/ - Password:
bayar@xai123$ - Alias:
axaipay_my
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$-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
-
/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
-p 18080:8080: Maps host port 18080 to container port 8080-p 50000:50000: Maps agent communication port (for Jenkins slaves)
--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
# 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# 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$# 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- ✅ HTTPS Only: HTTP disabled (
--httpPort=-1) - ✅ Valid SSL Certificate: Uses wildcard
*.axaipay.mycertificate - ✅ Encrypted Communication: All Jenkins traffic encrypted
- ✅ Browser Trust: No SSL warnings with valid certificate
- Internal:
https://localhost:18080 - External:
https://staging.axaipay.my:18080 - Agent Connection: Port 50000 (secured by firewall)
- Keystore Type: JKS (Java KeyStore)
- File:
/var/jenkins_home/ssl/axaipay_my.jks - Password:
bayar@xai123$ - Alias:
axaipay_my - Valid Until: August 25, 2026
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-
Container Won't Start
# Check logs for SSL errors docker logs jenkins # Common fix: Check JKS file permissions sudo ls -la /opt/jenkins/ssl/
-
SSL Certificate Error
# Verify JKS file integrity keytool -list -keystore /opt/jenkins/ssl/axaipay_my.jks -storepass "bayar@xai123$"
-
Port Already in Use
# Check what's using port 18080 sudo netstat -tlnp | grep :18080 # Stop conflicting service or change port
This Jenkins deployment integrates with the SSL certificate infrastructure by:
- Using JKS Format: Converts PKCS#12 to JKS for Java compatibility
- HTTPS Only: Enforces secure connections (
--httpPort=-1) - Certificate Sharing: Uses same wildcard certificate as other services
- Persistent Storage: SSL certificates stored in
/opt/jenkins/ssl/ - 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.
- 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
| Aspect | Before | After |
|---|---|---|
| Certificate Expiry | Aug 8, 2025 | Aug 25, 2026 |
| Status | ✅ Valid for 1+ year | |
| SSL Directory | /opt/ssl/20242025/ |
/opt/ssl/20252026/ |
| Backup | None | Timestamped backup created |
- 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