Secure your Nexus Repository Manager with SSL/TLS certificates, enforce HTTPS connections, and implement comprehensive security hardening including authentication controls, access policies, and audit logging for production environments.
Prerequisites
- Nexus Repository Manager installed
- Root or sudo access
- Domain name configured
- Basic understanding of SSL/TLS
What this solves
This tutorial configures SSL certificates for encrypted HTTPS connections to Nexus Repository Manager and implements security hardening measures to protect your artifact repositories in production. You'll enable TLS encryption, configure security headers, set up proper authentication controls, and establish audit logging for compliance requirements.
Step-by-step configuration
Update system and install SSL tools
Start by updating your system and installing the necessary SSL certificate tools for managing TLS certificates.
sudo apt update && sudo apt upgrade -y
sudo apt install -y openssl certbot nginxsudo dnf update -y
sudo dnf install -y openssl certbot nginxStop Nexus Repository Manager
Stop Nexus temporarily to modify its configuration files safely without service conflicts.
sudo systemctl stop nexus
sudo systemctl status nexusGenerate SSL certificate
Create an SSL certificate using Let's Encrypt for automatic renewal or generate a self-signed certificate for internal use.
# For Let's Encrypt (replace example.com with your domain)
sudo certbot certonly --standalone -d nexus.example.com
# OR for self-signed certificate (internal use)
sudo mkdir -p /opt/sonatype-work/nexus3/etc/ssl
sudo openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
-subj "/C=US/ST=State/L=City/O=Organization/CN=nexus.example.com" \
-keyout /opt/sonatype-work/nexus3/etc/ssl/nexus.key \
-out /opt/sonatype-work/nexus3/etc/ssl/nexus.crtConfigure Java keystore
Convert the SSL certificate to Java keystore format that Nexus can use for HTTPS connections.
# Create PKCS12 keystore from certificate
sudo openssl pkcs12 -export -in /etc/letsencrypt/live/nexus.example.com/fullchain.pem \
-inkey /etc/letsencrypt/live/nexus.example.com/privkey.pem \
-out /opt/sonatype-work/nexus3/etc/ssl/nexus.p12 \
-name nexus -passout pass:nexusssl123
# Convert to Java keystore
sudo keytool -importkeystore \
-deststorepass nexusssl123 \
-destkeypass nexusssl123 \
-destkeystore /opt/sonatype-work/nexus3/etc/ssl/keystore.jks \
-srckeystore /opt/sonatype-work/nexus3/etc/ssl/nexus.p12 \
-srcstoretype PKCS12 \
-srcstorepass nexusssl123 \
-alias nexusConfigure Nexus SSL properties
Update Nexus configuration to enable HTTPS with the SSL certificate and security settings.
# HTTP and HTTPS configuration
nexus.scripts.allowCreation=false
nexus.security.randompassword=false
# SSL/TLS configuration
application-port-ssl=8443
nexus-args=${jetty.etc}/jetty.xml,${jetty.etc}/jetty-https.xml,${jetty.etc}/jetty-requestlog.xml
ssl.etc=${karaf.data}/etc/ssl
# Security hardening
nexus.security.anticsrf.enabled=true
nexus.security.anticsrf.cookieMaxAge=1800
nexus.cleanup.retainDays=30
nexus.scripts.allowCreation=falseConfigure Jetty HTTPS
Create Jetty HTTPS configuration file to define SSL connector settings and security parameters.
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.ServerConnector">
<Arg name="server"><Ref refid="Server" /></Arg>
<Arg name="factories">
<Array type="org.eclipse.jetty.server.ConnectionFactory">
<Item>
<New class="org.eclipse.jetty.server.SslConnectionFactory">
<Arg name="next">http/1.1</Arg>
<Arg name="sslContextFactory">
<New class="org.eclipse.jetty.util.ssl.SslContextFactory$Server">
<Set name="KeyStorePath">/opt/sonatype-work/nexus3/etc/ssl/keystore.jks</Set>
<Set name="KeyStorePassword">nexusssl123</Set>
<Set name="KeyManagerPassword">nexusssl123</Set>
<Set name="TrustStorePath">/opt/sonatype-work/nexus3/etc/ssl/keystore.jks</Set>
<Set name="TrustStorePassword">nexusssl123</Set>
<Set name="ExcludeCipherSuites">
<Array type="String">
<Item>SSL_RSA_WITH_DES_CBC_SHA</Item>
<Item>SSL_DHE_RSA_WITH_DES_CBC_SHA</Item>
<Item>SSL_DHE_DSS_WITH_DES_CBC_SHA</Item>
<Item>SSL_RSA_EXPORT_WITH_RC4_40_MD5</Item>
<Item>SSL_RSA_EXPORT_WITH_DES40_CBC_SHA</Item>
<Item>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</Item>
<Item>SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA</Item>
</Array>
</Set>
<Set name="IncludeProtocols">
<Array type="String">
<Item>TLSv1.2</Item>
<Item>TLSv1.3</Item>
</Array>
</Set>
</New>
</Arg>
</New>
</Item>
<Item>
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
<Arg name="config">
<New class="org.eclipse.jetty.server.HttpConfiguration">
<Set name="secureScheme">https</Set>
<Set name="securePort">8443</Set>
<Call name="addCustomizer">
<Arg>
<New class="org.eclipse.jetty.server.SecureRequestCustomizer"/>
</Arg>
</Call>
</New>
</Arg>
</New>
</Item>
</Array>
</Arg>
<Set name="host">0.0.0.0</Set>
<Set name="port">8443</Set>
<Set name="idleTimeout">30000</Set>
</New>
</Arg>
</Call>
</Configure>Set proper file permissions
Configure correct ownership and permissions for SSL certificates and Nexus configuration files.
# Set ownership for Nexus files
sudo chown -R nexus:nexus /opt/sonatype-work/nexus3/etc/ssl/
sudo chown nexus:nexus /opt/nexus/etc/jetty-https.xml
# Set secure permissions for certificates
sudo chmod 600 /opt/sonatype-work/nexus3/etc/ssl/keystore.jks
sudo chmod 600 /opt/sonatype-work/nexus3/etc/ssl/nexus.key
sudo chmod 644 /opt/sonatype-work/nexus3/etc/ssl/nexus.crtConfigure NGINX reverse proxy
Set up NGINX as a reverse proxy with SSL termination and security headers for enhanced protection.
server {
listen 80;
server_name nexus.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name nexus.example.com;
ssl_certificate /etc/letsencrypt/live/nexus.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nexus.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/nexus.example.com/chain.pem;
# SSL Security
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_stapling_verify on;
# Security Headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Client settings
client_max_body_size 1G;
client_body_timeout 300s;
location / {
proxy_pass http://127.0.0.1:8081;
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;
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
proxy_buffering off;
proxy_request_buffering off;
}
# Docker registry
location /v2/ {
proxy_pass http://127.0.0.1:8081;
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;
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
proxy_buffering off;
proxy_request_buffering off;
}
}Enable NGINX configuration
Enable the Nexus NGINX site configuration and restart the service to apply SSL settings.
sudo ln -s /etc/nginx/sites-available/nexus /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
sudo systemctl enable nginxConfigure firewall rules
Open the necessary ports for HTTPS access while maintaining security with specific port rules.
# UFW firewall
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
sudo ufw status# Firewalld
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-allStart Nexus Repository Manager
Start Nexus with the new SSL configuration and verify it starts successfully with HTTPS enabled.
sudo systemctl start nexus
sudo systemctl enable nexus
sudo systemctl status nexus
# Check Nexus logs for SSL startup
sudo tail -f /opt/sonatype-work/nexus3/log/nexus.logSecurity hardening configuration
Configure authentication policies
Access Nexus web interface at https://nexus.example.com and configure authentication settings through the administration panel.
# Navigate to: Administration > Security > Realms
# Enable: Local Authenticating Realm, Local Authorizing Realm
# Optional: LDAP Realm (if using LDAP integration)
# Password Policy Settings:
# Minimum length: 12 characters
# Require uppercase, lowercase, numbers
# Maximum age: 90 days
</code><h2><code>Account lockout: 5 failed attempts</code></h2></pre></div><div class="step"><h3>Disable anonymous access</h3><p>Remove anonymous access capabilities to ensure all repository access requires authentication.</p><pre class="terminal"><code># In Nexus web UI:
# Administration > Security > Anonymous Access
# Uncheck "Allow anonymous users to access the server"
</code><h2><code>Save configuration</code></h2></pre></div><div class="step"><h3>Configure content trust</h3><p>Enable content trust and signature validation for Docker images and other artifacts.</p><pre class="terminal"><code># For Docker repositories:
# Administration > Repository > Repositories
# Edit Docker repositories
# Enable "Docker Bearer Token Realm"
</code><h2><code>Configure content trust validation</code></h2></pre></div><div class="step"><h3>Set up audit logging</h3><p>Configure comprehensive audit logging to track all repository access and administrative actions.</p><pre class="terminal"><code><configuration>
<appender name="AUDIT_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${karaf.data}/log/audit.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${karaf.data}/log/audit.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date{ISO8601} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.sonatype.nexus.audit" level="INFO" additivity="false">
<appender-ref ref="AUDIT_FILE"/>
</logger>
<root level="INFO">
<appender-ref ref="AUDIT_FILE"/>
</root>
</configuration>Configure backup encryption
Set up encrypted automated backups of Nexus configuration and data with secure storage.
#!/bin/bash
BACKUP_DIR="/backup/nexus"
DATE=$(date +%Y%m%d_%H%M%S)
GPG_RECIPIENT="admin@example.com"
# Create backup directory
mkdir -p $BACKUP_DIR
# Stop Nexus for consistent backup
sudo systemctl stop nexus
# Create compressed backup
sudo tar czf $BACKUP_DIR/nexus-backup-$DATE.tar.gz \
/opt/sonatype-work/nexus3/db \
/opt/sonatype-work/nexus3/etc \
/opt/sonatype-work/nexus3/blobs
# Encrypt backup
gpg --trust-model always --encrypt -r $GPG_RECIPIENT \
$BACKUP_DIR/nexus-backup-$DATE.tar.gz
# Remove unencrypted backup
rm $BACKUP_DIR/nexus-backup-$DATE.tar.gz
# Start Nexus
sudo systemctl start nexus
# Clean old backups (keep 7 days)
find $BACKUP_DIR -name "*.gpg" -mtime +7 -delete
echo "Backup completed: nexus-backup-$DATE.tar.gz.gpg"Set up backup automation
Create a systemd timer for automated daily backups with proper permissions and scheduling.
sudo chmod +x /usr/local/bin/nexus-backup.sh
sudo chown root:root /usr/local/bin/nexus-backup.sh[Unit]
Description=Nexus Repository Backup
After=network.target
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/nexus-backup.sh
StandardOutput=journal
StandardError=journal[Unit]
Description=Daily Nexus Repository Backup
Requires=nexus-backup.service
[Timer]
OnCalendar=daily
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.targetsudo systemctl daemon-reload
sudo systemctl enable nexus-backup.timer
sudo systemctl start nexus-backup.timer
sudo systemctl status nexus-backup.timerVerify your setup
Test SSL configuration, authentication, and security features to ensure proper operation.
# Test SSL certificate
openssl s_client -connect nexus.example.com:443 -servername nexus.example.com
# Test HTTPS redirect
curl -I http://nexus.example.com
# Check SSL rating
curl -s "https://api.ssllabs.com/api/v3/analyze?host=nexus.example.com"
# Verify Nexus service status
sudo systemctl status nexus nginx
# Check listening ports
sudo ss -tlnp | grep -E ':(80|443|8081|8443)'
# Test authentication (should require login)
curl -k https://nexus.example.com/service/rest/v1/repositories
# Check audit logs
sudo tail -f /opt/sonatype-work/nexus3/log/audit.logAuthentication and authorization
Configure LDAP integration
Integrate Nexus with your organization's LDAP directory for centralized user management and authentication.
For detailed LDAP configuration steps, see our Nexus LDAP authentication tutorial.
Set up role-based access control
Create custom roles and privileges for different user groups with principle of least privilege.
# In Nexus web UI:
# Administration > Security > Roles
# Developer Role:
# - nx-repository-view-<em>-</em>-browse
# - nx-repository-view-<em>-</em>-read
# - nx-repository-view-maven2-*-add
# DevOps Role:
# - All Developer permissions
# - nx-repository-admin-<em>-</em>-*
# - nx-repository-view-<em>-</em>-edit
# Read-Only Role:
# - nx-repository-view-<em>-</em>-browse
</code><h2><code>- nx-repository-view-<em>-</em>-read</code></h2></pre></div><div class="step"><h3>Configure API tokens</h3><p>Set up secure API token authentication for automated systems and CI/CD pipelines.</p><pre class="terminal"><code># In Nexus web UI:
# Administration > Security > Users
# Select user > "Tokens" tab
# Generate new token with appropriate permissions
</code><h2><code>Store token securely in CI/CD system</code></h2></pre></div><h2>Monitoring and maintenance</h2><div class="step"><h3>Set up health monitoring</h3><p>Configure monitoring endpoints and health checks for proactive system monitoring.</p><pre class="terminal"><code>#!/bin/bash
NEXUS_URL="https://nexus.example.com"
HEALTH_ENDPOINT="/service/rest/v1/status"
LOG_FILE="/var/log/nexus-health.log"
# Check Nexus health
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$NEXUS_URL$HEALTH_ENDPOINT")
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
if [ "$STATUS" = "200" ]; then
echo "$TIMESTAMP - Nexus health check: OK" >> $LOG_FILE
else
echo "$TIMESTAMP - Nexus health check: FAILED (HTTP $STATUS)" >> $LOG_FILE
# Send alert (configure your alerting sys