Maven settings.xml — The File Everyone Edits Once and Then Forgets
What actually goes in Maven settings.xml, and how to use profiles to manage different environments without hardcoding anything.
settings.xml is one of those files that exists at ~/.m2/settings.xml on every developer’s machine, gets edited once to add a company proxy or repository, and then nobody touches it again for years.
Which is a shame, because it’s actually where a lot of the “why does this only work on my machine” problems get solved.
Where the file lives
Two locations:
~/.m2/settings.xml— your personal settings, not committed to source control$MAVEN_HOME/conf/settings.xml— global settings, applies to all users on the machine
The personal one takes precedence and is the one you’ll touch most often.
Configuring a private repository
Most enterprise environments have a Nexus or Artifactory instance that mirrors public repos and hosts internal artifacts. Without this configured, Maven will hit Maven Central and fail (or succeed but get the wrong artifacts):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<settings>
<mirrors>
<mirror>
<id>company-nexus</id>
<name>Company Nexus</name>
<url>https://nexus.example.com/repository/maven-public/</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
<servers>
<server>
<id>company-nexus</id>
<username>myuser</username>
<password>mypassword</password>
</server>
</servers>
</settings>
<mirrorOf>*</mirrorOf> redirects all repository lookups through Nexus. The server entry provides credentials — the id must match the mirror id.
Never commit credentials to source control. settings.xml lives in
~/.m2/precisely so it stays off the repo. If you’re setting up CI, inject credentials via environment variables or a secrets manager.
Using environment variables for passwords
Maven supports property interpolation in settings.xml:
1
2
3
4
5
<server>
<id>company-nexus</id>
<username>${env.NEXUS_USERNAME}</username>
<password>${env.NEXUS_PASSWORD}</password>
</server>
Set NEXUS_USERNAME and NEXUS_PASSWORD as environment variables on the CI agent, and the credentials never appear in any file.
Profiles for different environments
This is where settings.xml gets genuinely useful. You can define profiles that activate automatically or on demand, and use them to switch between environments without changing the pom:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<profiles>
<profile>
<id>local-dev</id>
<properties>
<db.url>jdbc:oracle:thin:@localhost:1521:DEV</db.url>
<db.username>dev_user</db.username>
<db.password>dev_pass</db.password>
</properties>
</profile>
<profile>
<id>ci</id>
<properties>
<db.url>jdbc:oracle:thin:@ci-db-server:1521:TEST</db.url>
<db.username>${env.DB_USER}</db.username>
<db.password>${env.DB_PASS}</db.password>
</properties>
</profile>
</profiles>
<activeProfiles>
<activeProfile>local-dev</activeProfile>
</activeProfiles>
The activeProfiles section activates local-dev by default on your machine. On the CI server, the CI agent has a different settings.xml (or environment variables) that activates ci instead.
Your pom.xml references the property:
1
2
3
4
5
6
7
8
9
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<configuration>
<url>${db.url}</url>
<user>${db.username}</user>
<password>${db.password}</password>
</configuration>
</plugin>
Same pom, different database, depending on whose machine is running the build.
The proxy configuration
If you’re behind a corporate HTTP proxy:
1
2
3
4
5
6
7
8
9
10
11
12
<proxies>
<proxy>
<id>corporate-proxy</id>
<active>true</active>
<protocol>http</protocol>
<host>proxy.example.com</host>
<port>8080</port>
<username>proxyuser</username>
<password>proxypass</password>
<nonProxyHosts>localhost|*.example.com|nexus.internal</nonProxyHosts>
</proxy>
</proxies>
nonProxyHosts is important — without it, Maven will try to route requests to your internal Nexus through the external proxy, which will fail.
Encrypting passwords in settings.xml
Maven has built-in password encryption, though I’ll admit it’s more of “not plaintext” than real security:
1
2
3
4
5
6
# First, create a master password
$ mvn --encrypt-master-password
# Then encrypt your actual password
$ mvn --encrypt-password mypassword
{6zZPiELYFvJbzQbw/4mxrWhN0FMSqRRLz7n5P5pO0=}
Store the master password in ~/.m2/security-settings.xml and use the encrypted value in settings.xml. Better than plaintext, though for production systems proper secrets management is the right answer.