Run Behind a Reverse Proxy

Nexus Repository Manager is a sophisticated server application with a web-application user interface, answering HTTP requests using the high-performance servlet container Eclipse Jetty. Organizations are sometimes required to run applications like Nexus Repository Manager behind a reverse proxy. Reasons may include:

  • security and auditing concerns
  • network administrator familiarity
  • organizational policy
  • disparate application consolidation
  • virtual hosting
  • exposing applications on restricted ports
  • SSL termination
  • SSO or SAML Integration

This section provides some general guidance on how to configure common reverse proxy servers to work with Nexus Repository Manager. Always consult your reverse proxy administrator to ensure you configuration is secure. The default webapp context path for the repository manager user interface is /. In the instance where the repository manager needs to be proxied at a different base path you must change the default path by editing a property value. In Base URL Creation,  follow the steps to change or update the base URL if you want an alternate server name.

In the following examples, review the sections on changing the HTTP port and context path to properly reverse-proxy the repository manager. Consult your reverse proxy product documentation for details: Apache httpd ( mod_proxy  mod_ssl ),   nginx ( ngx_http_proxy_module  ssl compatibility ).

Example: Reverse Proxy on Restricted Ports

Scenario : You need to expose the repository manager on restricted port 80. The repository manager should not be run with the root user. Instead run your reverse proxy on the restricted port 80 and the repository manager on the default port 8081. End users will access the repository manager using the virtual host URL http://www.example.com/ instead of http://localhost:8081/. Ensure your external hostname (www.example.com) routes to your reverse proxy server. This example uses the default content path (/).

Apache httpd

ProxyRequests Off
ProxyPreserveHost On
  
<VirtualHost *:80>
  ServerName www.example.com
  ServerAdmin admin@example.com

  AllowEncodedSlashes NoDecode

  ProxyPass / http://localhost:8081/ nocanon
  ProxyPassReverse / http://localhost:8081/
  ErrorLog logs/www.example.com/error.log
  CustomLog logs/www.example.com/access.log common
</VirtualHost>

nginx

http {
  
  proxy_send_timeout 120;
  proxy_read_timeout 300;
  proxy_buffering    off;
  keepalive_timeout  5 5;
  tcp_nodelay        on;
  
  server {
    listen   *:80;
    server_name  www.example.com;
  
    # allow large uploads of files
    client_max_body_size 1G;
  
    # optimize downloading files larger than 1G
    #proxy_max_temp_file_size 2G;
  
    location / {
      # Use IPv4 upstream address instead of DNS name to avoid attempts by nginx to use IPv6 DNS lookup
      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;
    }
  }
}

Example: Reverse Proxy Virtual Host at Custom Context Path

Scenario: You need to expose the repository manager using a custom host name repo.example.com on a restricted port at a base path of /nexus. Ensure your external hostname (repo.example.com) routes to your reverse proxy server and edit the webapp path a slash at end (/).

Apache httpd

ProxyRequests Off
ProxyPreserveHost On
  
<VirtualHost *:80>
  ServerName repo.example.com
  ServerAdmin admin@example.com

  AllowEncodedSlashes NoDecode

  ProxyPass /nexus http://localhost:8081/nexus nocanon
  ProxyPassReverse /nexus http://localhost:8081/nexus
  ErrorLog logs/repo.example.com/nexus/error.log
  CustomLog logs/repo.example.com/nexus/access.log common
</VirtualHost>

nginx

http {
  
  proxy_send_timeout 120;
  proxy_read_timeout 300;
  proxy_buffering    off;
  keepalive_timeout  5 5;
  tcp_nodelay        on;
  
  server {
    listen   *:80;
    server_name  repo.example.com;
  
    # allow large uploads of files
    client_max_body_size 1G;
  
    # optimize downloading files larger than 1G
    # proxy_max_temp_file_size 2G;
  
    location /nexus {
      # Use IPv4 upstream address instead of DNS name to avoid attempts by nginx to use IPv6 DNS lookup
      proxy_pass http://127.0.0.1:8081/nexus;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
  }
)

Example: Reverse Proxy SSL Termination at Base Path

Scenario:  Your organization has standardized a reverse proxy to handle SSL certificates and termination. The reverse proxy virtual host will accept HTTPS requests on the standard port 443 and serve content from the repository manager running on the default non-restricted HTTP port 8081 transparently to end users. Ensure your external host name (repo.example.com) routes to your reverse proxy server and edit the webapp path to be slash (/). To test your configuration, review the steps to generate a self-signed SSL certificate for reverse proxy servers.

Apache httpd

The example assumes that Apache httpd has been configured to load  mod_ssl  and  mod_headers modules.

Listen 443
  
ProxyRequests Off
ProxyPreserveHost On
  
<VirtualHost *:443>
  SSLEngine on
  
  SSLCertificateFile "example.pem"
  SSLCertificateKeyFile "example.key"
  
  AllowEncodedSlashes NoDecode

  ServerName repo.example.com
  ServerAdmin admin@example.com
  ProxyPass / http://localhost:8081/ nocanon
  ProxyPassReverse / http://localhost:8081/
  RequestHeader set X-Forwarded-Proto "https"
  
  ErrorLog logs/repo.example.com/nexus/error.log
  CustomLog logs/repo.example.com/nexus/access.log common
</VirtualHost>

nginx

The example assumes that nginx has been compiled using the  --with-http_ssl_module  option.

http {
  
  proxy_send_timeout 120;
  proxy_read_timeout 300;
  proxy_buffering    off;
  keepalive_timeout  5 5;
  tcp_nodelay        on;
  
  server {
    listen   *:443;
    server_name  repo.example.com;
  
    # allow large uploads of files
    client_max_body_size 1G;
  
    # optimize downloading files larger than 1G
    #proxy_max_temp_file_size 2G;
  
    ssl on;
    ssl_certificate      example.pem;
    ssl_certificate_key  example.key;
  
    location / {
      # Use IPv4 upstream address instead of DNS name to avoid attempts by nginx to use IPv6 DNS lookup
      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 "https";
    }
  }
}

Apache httpd with npm Repositories

Npm scoped packages use encoded slash characters ("/") in their URL's.  By default Apache will not allow encoded slashes through.  If you're using npm and have Apache running in front of Nexus add the following to your configuration so that it will allow encoded slashes through:

AllowEncodedSlashes NoDecode

The ProxyPass directive will also need nocanon option:

ProxyPass / http://localhost:8081/ nocanon

Note that the the documentation for "noncanon" says "this keyword may affect the security of your backend". Sonatype server products do not rely on reverse proxies to filter out suspect URLs containing path info with encoded values, so it is OK to use "noncanon" with Nexus Repository Manager.

Apache httpd 2.0.52 to 2.2.8

If you are running Apache httpd 2.0.52 to 2.2.8 and you choose to set:

AllowEncodedSlashes On

Then this will trigger a bug that incorrectly decodes encoded slashes when they should not be:

https://bz.apache.org/bugzilla/show_bug.cgi?id=35256