Configure SSL certificates and security hardening for Nexus Repository Manager

Intermediate 45 min Apr 20, 2026 787 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

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 nginx
sudo dnf update -y
sudo dnf install -y openssl certbot nginx

Stop Nexus Repository Manager

Stop Nexus temporarily to modify its configuration files safely without service conflicts.

sudo systemctl stop nexus
sudo systemctl status nexus

Generate 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.crt

Configure 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 nexus

Configure 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=false

Configure 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.crt
Never use chmod 777. It gives every user on the system full access to your files. SSL certificates should be readable only by the Nexus service user for security.

Configure 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 nginx

Configure 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-all

Start 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.log

Security 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.target
sudo systemctl daemon-reload
sudo systemctl enable nexus-backup.timer
sudo systemctl start nexus-backup.timer
sudo systemctl status nexus-backup.timer

Verify 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.log

Authentication 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

Vous ne voulez pas gérer cela vous-même ?

Nous gérons l'infrastructure des entreprises qui dépendent de leur disponibilité. Entièrement infogéré, avec un interlocuteur fixe qui connaît votre environnement.

Vous avez un interlocuteur fixe qui connaît votre installation

À son bureau à Rotterdam 13:53 · joignable par message, sans formulaire de ticket