Chapter 08Lesson 01~130 minutes

Maven Properties, Profiles, settings.xml, Mirrors, Proxies, Servers, and Environment-Specific Builds: Concepts, Architecture, and Mental Model

Separate repository-owned Maven configuration from environment-owned settings: understand property sources, profile activation, global/user settings, mirrors, proxies, server credential indirection, and the effective build state Maven actually uses.

Maven PropertiesProfilessettings.xmlMirrorsTrust Boundary

Learning objectives

  • Separate repository-owned Maven state from machine/user/CI environment state before changing either one.
  • Identify Maven property families and explain why command-line user properties can override project/profile values.
  • Distinguish project, user, and global profiles and explain explicit versus implicit activation.
  • Explain how global/user settings.xml, mirrors, proxies, servers, and repository IDs affect resolution without belonging in the POM.
  • Use read-only Help Plugin goals to reveal active profiles, effective settings, effective POM state, and selected property values.
Current baseline — verified 2026-08-23. Labs use Maven 3.9.16 via Maven Wrapper 3.3.4, JDK 21 to run Maven, Java 17 as the compiler release target, Help Plugin 3.5.2, Dependency Plugin 3.11.0, Compiler Plugin 3.15.0, Resources Plugin 3.5.0, Surefire 3.5.6, and JAR Plugin 3.5.1. Lab resolution uses project-relative isolated local repositories. No normal ~/.m2, global settings, shared CI settings, or real credentials are modified.
Maven 3 versus Maven 4 note. This chapter's production path is Maven 3.9.16. Current Maven profile documentation notes a Maven 4 behavior change: unresolved explicit profile IDs become errors unless marked optional with ?. Do not copy Maven 4-only optional-profile syntax into the Maven 3 lab and assume identical behavior.

1. The practical problem — one POM, many environments

Chapters 04–07 made Maven itself, the POM, dependencies, lifecycle, and plugins visible. A production build still has another source of state: the environment that invokes the project. Developer laptops, CI agents, and controlled release workers may need different proxy routes, mirror endpoints, authentication material, or explicitly selected build modes. If those differences leak into the POM, the project becomes machine-specific. If they remain hidden in uninspected settings, the build becomes difficult to reproduce.

The goal is not “make every machine identical.” The goal is to establish a contract: portable build intent stays with the project; access policy and secrets stay at controlled environment boundaries; every effective difference is observable.

2. The state stores must remain separate

Maven combines several inputs during model building and repository resolution, but combining them at runtime does not make them the same kind of state.

State store Owned by Typical contents Should it be committed?
pom.xml Project Coordinates, dependencies, plugins, portable properties/profiles Yes
.mvn/ Project Wrapper/config/extension state appropriate for the repository Yes, when intentional and secret-free
Global settings.xml Maven installation/platform image Organization or installation defaults Normally managed with the image, not copied into each repo
User settings.xml Developer/CI identity Mirrors, proxies, server credentials, user profiles No secrets in source control
Environment variables / CI secret injection Process/CI Credentials or process-specific selectors No
Local repository Machine/job Resolved artifacts, metadata, installed artifacts No; cache/state, not source of truth
Effective POM/settings Derived evidence Merged/interpolated active model Generated evidence, not hand-edited source

3. Mental model — declared project + environment policy → effective build

Maven first establishes runtime/system/user properties and settings, builds the effective project model with active profiles, and then resolves repositories after mirror/proxy/server policy is applied. This is why a repository URL written in a POM is not necessarily the network endpoint contacted by the build.

Environment-aware Maven model and resolution flow
flowchart TD
  POM[pom.xml + project profiles]
  MVN[.mvn wrapper/config]
  GS[global settings.xml]
  US[user/alternate settings.xml]
  ENV[system + env + CLI user properties]
  EFF[effective POM + active profiles]
  SET[effective settings]
  REPO[declared repository IDs]
  MIR[mirror/proxy/server policy]
  END[actual endpoint]
  POM --> EFF
  MVN --> EFF
  GS --> SET
  US --> SET
  ENV --> EFF
  ENV --> SET
  SET --> EFF
  EFF --> REPO
  SET --> MIR
  REPO --> MIR
  MIR --> END

Every arrow represents a causal relationship you can inspect: settings change the effective environment, active profiles change the effective POM, and mirrors rewrite repository routing before transport begins.

4. Property sources — name the source before arguing about “precedence”

Maven exposes several property families. ${project.version} comes from the project model; ${settings.offline} comes from settings; ${java.home} is a Java system property; ${env.PATH} exposes an environment variable; plain ${academy.channel} may come from POM/profile properties or from a command-line user property such as -Dacademy.channel=cli.

Source Example Operational meaning
Project model ${project.version} A field in the effective POM.
POM <properties> ${academy.channel} Portable default owned by the project.
Active profile property ${academy.channel} Conditional model contribution; source matters.
Settings model ${settings.localRepository} Machine/user settings value.
Java system property ${java.home} Property of the JVM running Maven.
Environment property ${env.ACADEMY_REPO_USER} Process environment exposed through the env. prefix.
CLI user property -Dacademy.channel=cli Invocation-level override; treat as high-precedence deliberate input.
Teaching rule: do not memorize one giant undocumented precedence list. In an incident, capture the active profiles and evaluate the exact property that matters. Maven 3.9 also cleaned up system/user-property handling, so old folklore can be wrong.

5. Profiles are conditional model fragments, not “environments” by themselves

A profile can contribute properties, dependencies, repositories, plugin configuration, and other model elements. Profiles may live in the project POM, user settings, or global settings. Maven resolves profile activation early; profile effects participate in the effective model. A child does not simply inherit the parent's raw profile definition as another switch.

Activation style Example Risk / use
Explicit -Pdev Most auditable when the choice is a conscious build input.
<activeProfiles> in settings User/CI-selected profile ID Useful for controlled environment policy; can be invisible unless inspected.
activeByDefault POM default profile Convenient, but automatically deactivates when another profile in the same POM becomes active.
JDK / OS Automatic runtime match Useful sparingly; can make developer/CI behavior diverge.
System/CLI property Activate when a property exists/matches More explicit when property is supplied deliberately.
File exists/missing Filesystem condition Powerful but easy to make machine-specific.

6. What belongs in settings.xml

Maven merges global and user settings, with user settings dominant where the models overlap. An alternate user settings file may be selected with -s/--settings; an alternate global settings file uses -gs/--global-settings. These are invocation/environment controls, not POM content.

Element Purpose Security/reproducibility note
localRepository Machine-local artifact/install state Use explicit isolated paths in disposable labs/CI diagnostics.
servers Authentication keyed by server/repository ID Credentials stay outside POM.
mirrors Rewrite repository destinations by ID/pattern Mirror breadth is policy; inspect mirrorOf.
proxies Network proxy routing/authentication Environment/infrastructure concern.
profiles User/global conditional properties/repositories Can modify effective build; always inspect activation.
activeProfiles Always activate named profiles for that settings context Hidden default if not captured in CI evidence.
pluginGroups Extra groups searched by short plugin prefixes Executable-code trust boundary from Chapter 07.

7. Mirrors, repository IDs, and server credential indirection

A mirror does not “add another repository.” It substitutes the endpoint Maven uses for repositories matched by mirrorOf. The mirror has its own id. Maven's settings documentation explicitly states that this mirror ID is used to pick corresponding credentials from <servers>. That is why changing only a server ID can turn a working build into a 401 even when username/password values did not change.

<mirrors>
  <mirror>
    <id>corp-mirror</id>
    <url>https://repo.example.invalid/maven-virtual</url>
    <mirrorOf>external:*</mirrorOf>
  </mirror>
</mirrors>
<servers>
  <server>
    <id>corp-mirror</id>
    <username>${env.REPO_USER}</username>
    <password>${env.REPO_PASSWORD}</password>
  </server>
</servers>

Patterns include exact repository IDs, *, external:*, external:http:*, comma-separated expressions, and ! exclusions. Broader is not automatically safer: * can capture a repository that a test fixture expected to remain local.

8. Proxy state is transport policy, not dependency identity

A proxy controls how Maven reaches an endpoint; it does not change a coordinate such as org.example:lib:1.2.3. Keep this distinction during diagnosis. A 407 proxy-authentication error is not evidence that the dependency version is wrong. Likewise, adding a new repository to “fix networking” changes the supply-chain boundary and is not a harmless network workaround.

9. Read-only inspection before mutation

Use the wrapper and explicit Help Plugin version. Write evidence outside target/ so a later clean does not erase it.

mkdir -p evidence
./mvnw -v | tee evidence/maven-version.txt
./mvnw org.apache.maven.plugins:maven-help-plugin:3.5.2:active-profiles   -Doutput=evidence/active-profiles.txt
./mvnw org.apache.maven.plugins:maven-help-plugin:3.5.2:effective-settings   -Doutput=evidence/effective-settings.xml
./mvnw org.apache.maven.plugins:maven-help-plugin:3.5.2:effective-pom   -Dverbose -Doutput=evidence/effective-pom.xml
./mvnw org.apache.maven.plugins:maven-help-plugin:3.5.2:evaluate   -Dexpression=academy.channel -q -DforceStdout
Secret-safety rule: help:effective-settings hides passwords by default. Do not enable password display for ordinary troubleshooting, and review any debug/effective-model artifact before sharing it outside the trusted build context.

10. DevOps operating contract

A robust CI job records wrapper/Maven/JDK identity, the explicit profile selection, the settings source/policy identifier, and the repository/mirror endpoint IDs without printing secrets. The artifact pipeline should be able to answer: Which profile changed the model? Which settings selected the network path? Which server ID supplied authentication? Which properties were invocation overrides?

11. Common misconceptions

Misconception Correction
“A profile is the deployment environment.” A profile is a model fragment. Deployment runtime configuration often belongs later, outside the build artifact.
“The URL in the POM is the URL Maven contacted.” A matching mirror may replace it before transport.
“Server credentials match the original repository ID after mirroring.” For the selected mirror, credentials are looked up by the mirror ID.
“If my warm local repository works, CI network policy is correct.” Warm cache can mask remote routing/authentication problems.
“settings.xml is safe to commit if it works on my laptop.” It is user/environment state and may contain credentials or machine-specific routes.

Knowledge check

A dependency repository in the POM has ID internal, but settings maps it to mirror ID corp-mirror. Which server ID should hold credentials for the actual mirrored connection?

Why is help:active-profiles evidence more useful than asking “which environment am I on?”

What is the safest first response when a build works from a warm cache but fails on an empty CI worker?

Where should a portable dependency coordinate live: POM or user settings?

Why should a CLI -D override be recorded in CI evidence?

12. Summary and bridge

Chapter 08 starts by making the environment boundary explicit: POM and project wrapper/config are repository-owned build intent; settings, proxy/mirror/server credentials, process environment, and caches are controlled execution context. The effective model is the evidence that joins them. Lesson 2 now builds a safe local fixture so each layer can be observed rather than merely described.

Official references and version notes

Version-sensitive statements in this lesson were checked against Apache Maven primary documentation on 2026-08-23. The mandatory path uses Maven 3.9.16 through Maven Wrapper 3.3.4, JDK 21 to run Maven, Java 17 as the project release target, Help Plugin 3.5.2, Dependency Plugin 3.11.0, Compiler Plugin 3.15.0, Resources Plugin 3.5.0, Surefire 3.5.6, and JAR Plugin 3.5.1. Maven 4-only profile syntax and preview behavior are not required here.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.