Configure SSL certificates and security hardening for Nexus Repository Manager

Intermediate 45 min Apr 20, 2026 31 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

Account lockout: 5 failed attempts

Disable anonymous access

Remove anonymous access capabilities to ensure all repository access requires authentication.

# In Nexus web UI:

Administration > Security > Anonymous Access

Uncheck "Allow anonymous users to access the server"

Save configuration

Configure content trust

Enable content trust and signature validation for Docker images and other artifacts.

# For Docker repositories:

Administration > Repository > Repositories

Edit Docker repositories

Enable "Docker Bearer Token Realm"

Configure content trust validation

Set up audit logging

Configure comprehensive audit logging to track all repository access and administrative actions.

<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---browse

- nx-repository-view---read

- nx-repository-view-maven2-*-add

DevOps Role:

- All Developer permissions

- nx-repository-admin---*

- nx-repository-view---edit

Read-Only Role:

- nx-repository-view---browse

- nx-repository-view---read

Configure API tokens

Set up secure API token authentication for automated systems and CI/CD pipelines.

# In Nexus web UI:

Administration > Security > Users

Select user > "Tokens" tab

Generate new token with appropriate permissions

Store token securely in CI/CD system

Monitoring and maintenance

Set up health monitoring

Configure monitoring endpoints and health checks for proactive system monitoring.

#!/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 system) # systemctl restart nexus fi

Check disk usage

DISK_USAGE=$(df /opt/sonatype-work | awk 'NR==2{print $5}' | sed 's/%//') if [ "$DISK_USAGE" -gt 80 ]; then echo "$TIMESTAMP - Disk usage high: $DISK_USAGE%" >> $LOG_FILE fi

Check certificate expiry

CERT_DAYS=$(openssl x509 -in /etc/letsencrypt/live/nexus.example.com/cert.pem -noout -dates | grep notAfter | cut -d= -f2 | xargs -I{} date -d "{}" +%s) CURRENT_DAYS=$(date +%s) DAYS_LEFT=$(( (CERT_DAYS - CURRENT_DAYS) / 86400 )) if [ "$DAYS_LEFT" -lt 30 ]; then echo "$TIMESTAMP - SSL certificate expires in $DAYS_LEFT days" >> $LOG_FILE fi

Configure log rotation

Set up proper log rotation to prevent disk space issues while maintaining audit trails.

/opt/sonatype-work/nexus3/log/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    copytruncate
    maxage 90
}

Set up certificate renewal

Configure automatic SSL certificate renewal with Let's Encrypt to maintain continuous HTTPS operation.

# Renew SSL certificates and reload nginx
0 3   * root certbot renew --quiet --post-hook "systemctl reload nginx" >> /var/log/certbot-renewal.log 2>&1

Configure performance monitoring

Set up JVM and application performance monitoring for capacity planning and optimization.

For comprehensive monitoring setup, see our guides on Linux system monitoring and Prometheus monitoring.

Common issues

SymptomCauseFix
SSL handshake failuresIncorrect certificate path or keystore passwordVerify keystore location and password in jetty-https.xml
403 Forbidden on repositoriesAnonymous access disabled without proper authenticationConfigure user authentication or enable anonymous for specific repositories
Certificate expired errorsLet's Encrypt certificate not renewedRun sudo certbot renew and restart nginx
High memory usageDefault JVM settings too low for workloadIncrease heap size in /opt/nexus/bin/nexus.vmoptions
Backup failuresInsufficient disk space or permission issuesCheck disk space with df -h and verify backup directory permissions
LDAP authentication not workingIncorrect LDAP configuration or network connectivityTest LDAP connection from Nexus and verify user mapping

Next steps

Running this in production?

Want this handled for you? Setting this up once is straightforward. Keeping it patched, monitored, backed up and performant across environments is the harder part. See how we run infrastructure like this for European teams.

Need help?

Don't want to manage this yourself?

We handle infrastructure security hardening for businesses that depend on uptime. From initial setup to ongoing operations.