Generic Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Introduction

In this tutorial, we're going configure Maven to work behind a proxy – a common situation in environments where we don't connect directly to the internet.

In our example, our proxy is running on the machine ‘proxy.baeldung.com' and it listens for proxy requests via HTTP on port '80'. We'll also use some internal sites at internal.baeldung.com where we don't need to go through a proxy.

2. Proxy Configuration

First, let's set up a basic proxy configuration without any credentials.

Let's edit our Maven settings.xml usually found in our ‘<user_home>/.m2′ directory. If there isn't one there yet, then we can copy it from the global settings at ‘<maven_home>/conf' directory.

And now let's create a <proxy> entry inside the <proxies> section:

<proxies>
   <proxy>
        <host>proxy.baeldung.com</host>
        <port>80</port>
    </proxy>
</proxies>

Since we also use a local site that doesn't need to go through the proxy, let's specify it in <nonProxyHosts> using a ‘|' separated list with our localhost:

<nonProxyHosts>internal.baeldung.com|localhost|127.*|[::1]</nonProxyHosts>

3. Adding Credentials

If our proxy wasn't secured, that's all we'd need; however, ours is, so let's add our credentials to the proxy definition:

<username>baeldung</username>
<password>changeme</password>

We don't add username/password entries if we don't need them – even empty ones – as having them present when the proxy doesn't want them can cause our requests to be denied.

Our minimal authenticated configuration should now look like this:

<proxies>
   <proxy>
        <host>proxy.baeldung.com</host>
        <port>80</port>
        <username>baeldung</username>
        <password>changeme</password>
        <nonProxyHosts>internal.baeldung.com|localhost|127.*|[::1]</nonProxyHosts>
    </proxy>
</proxies>

Now, when we run the mvn command we'll go through the proxy to connect to the sites we are after.

3.1. Optional Entries

Let's give it the optional id of ‘BaeldungProxy_Authenticated' to make it easier to reference, in case we ever need to switch proxies:

<id>BaeldungProxy_Authenticated</id>

Now, if we have another proxy we can add another proxy definition, but only one can be active. By default, Maven will use the first active proxy definition it finds.

Proxy definitions are active by default, and get the implicit definition:

<active>true</active>

If we wanted to make another proxy the active one, then we'd de-activate our original entry by setting <active> to false:

<active>false</active>

Maven's default value for the proxy's protocol is HTTP, which is suitable for most cases. If our proxy uses a different protocol, we'd declare it here and replace http with the protocol that our proxy needs:

<protocol>http</protocol>

Note that this is the protocol the proxy uses – the protocol of our requests (ftp://, http://, https://) is independent of this.

And here's what our expanded proxy definition looks like, including the optional elements:

<proxies>
   <proxy>
        <id>BaeldungProxy_Authenticated</id>
        <active>true</active>
        <protocol>http</protocol>
        <host>proxy.baeldung.com</host>
        <port>80</port>
        <username>baeldung</username>
        <password>changeme</password>
        <nonProxyHosts>internal.baeldung.com|localhost|127.*|[::1]</nonProxyHosts>
    </proxy>
</proxies>

So, that's it for our basic proxy entry, but is it secure enough for us?

4. Securing Our Configuration

Now, let's say one of our colleagues wants us to send them our proxy configuration.

We're not too keen on sending our password in plain text, so let's see how easy Maven makes it to encrypt our passwords.

4.1. Creating a Master Password

First, let's choose a master password, say “te!st!ma$ter”.

Now let's encrypt our master password, by entering it at the prompt when we run:

mvn --encrypt-master-password
Master Password:

After we've pressed enter, we see our encrypted password enclosed between curly braces:

{QFMlh/6WjF8H9po9UDo0Nv18e527jqWb6mUgIB798n4=}

4.2. Troubleshooting Password Generation

If we see {} instead of the Master Password: prompt (this can happen when using bash), then we'll need to specify the password on the command line.

Let's wrap the password in quotes to make sure any special characters like ‘!' don't have unwanted effects.

So, let's use single quotes if we're using bash:

mvn --encrypt-master-password 'te!st!ma$ter'

Or use double-quotes if using a Windows command prompt:

mvn --encrypt-master-password "te!st!ma$ter"

Now, sometimes our generated master password contains curly braces, like this example with a closing curly brace, ‘}', after the ‘UD':

{QFMlh/6WjF8H9po9UD}0Nv18e527jqWb6mUgIB798n4=}

In this case, we can either:

  • run the mvn –encrypt-master-password command again to generate another one (hopefully without a curly brace)
  • escape the curly braces in our password by adding a backslash in front of the ‘{‘ or }'

4.3. Creating a settings-security.xml File

Now let's put our encrypted password, with an escaped ‘\}', into a file called settings-security.xml file in our .m2 directory:

<settingsSecurity>
    <master>{QFMlh/6WjF8H9po9UD\}0Nv18e527jqWb6mUgIB798n4=}</master>
</settingsSecurity>

Lastly, Maven lets us add a comment inside the master element.

Let's add some text before the password ‘{‘ delimiter, taking care not to use a { or } in our comment as Maven uses them to find our password:

<master>We escaped the curly brace with '\' {QFMlh/6WjF8H9po9UD\}0Nv18e527jqWb6mUgIB798n4=}</master>

4.4. Using a Removable Drive

Let's say we need to be extra secure and want to store our master password on a separate device.

First, we'll place our settings-security.xml file in a config directory on a removable drive, “R:”:

R:\config\settings-security.xml

And now, we'll update the settings-security.xml file in our .m2 directory to redirect Maven to our real settings-security.xml on our removable drive:

<settingsSecurity>
    <relocation>R:\config\settings-security.xml</relocation>
</settingsSecurity>

Maven will now read our encrypted master password from the file we specified in the relocation element, on our removable drive.

5. Encrypting Proxy Passwords

Now we have a master password encrypted, we can encrypt our proxy password.

Let's run the following command and enter our password, “changeme”, at the prompt:

mvn --encrypt-password
Password:

Our encrypted password is displayed:

{U2iMf+7aJXQHRquuQq6MX+n7GOeh97zB9/4e7kkEQYs=}

Our final step is to edit the proxy section in our settings.xml file, and put in our encrypted password:

<proxies>
   <proxy>
        <id>BaeldungProxy_Encrypted</id>
        <host>proxy.baeldung.com</host>
        <port>80</port>
        <username>baeldung</username>
        <password>{U2iMf+7aJXQHRquuQq6MX+n7GOeh97zB9/4e7kkEQYs=}</password>
    </proxy>
</proxies>

Save this, and Maven should now be able to connect to the internet through our proxy, using our encrypted passwords.

6. Using System Properties

Although configuring Maven via the settings file is the recommended approach, we could declare our proxy configuration via Java System Properties.

If our operating system already has a proxy configured, we could set:

-Djava.net.useSystemProxies=true

Alternatively, so that it is always enabled, if we have admin rights we can set this in our <JRE>/lib/net.properties file.

However, let's note that although Maven itself may respect this setting, not all plugins do, so we may still get failed connections using this method.

Even when enabled, we can override it by setting our HTTP proxy's details on the http.proxyHost system property:

-Dhttp.proxyHost=proxy.baeldung.com

Our proxy is listening on the default port 80, but if it listened on port 8080, we'd configure the http.proxyPort property:

-Dhttp.proxyPort=8080

And for our sites that don't need the proxy:

-Dhttp.nonLocalHosts="internal.baeldung.com|localhost|127.*|[::1]"

So, if our proxy is at 10.10.0.100, we can use:

mvn compile -Dhttp.proxyHost=10.10.0.100 -Dhttp.proxyPort=8080 -Dhttp.nonProxyHosts=localhost|127.0.0.1

Of course, if our proxy requires authentication, we'll also add:

-Dhttp.proxyUser=baeldung
-Dhttp.proxyPassword=changeme

And if we wanted some of these settings to apply to all of our Maven invocations, we can define them in the MAVEN_OPTS environment variable:

set MAVEN_OPTS= -Dhttp.proxyHost=10.10.0.100 -Dhttp.proxyPort=8080

Now, whenever we run ‘mvn‘ these settings will automatically be applied – until we exit.

7. Conclusion

In this article, we configured a Maven proxy both with and without credentials and encrypted our password. We saw how to store our master password on an external drive, and also looked at configuring the proxy by using system properties.

Now we can share our settings.xml file with our colleagues without giving them our passwords in plain text, and show them how to encrypt theirs!

As usual, the examples in this article are available over on GitHub.

Generic bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
Comments are closed on this article!