skip to content

How do you lock Maven to trusted sources using <mirrors> and <repositories> in settings.xml, and what does <mirrorOf> control?

level: seniorimportance: must knowfreq 50%

answer

  1. mirror intercepts by repo id, redirects to one url
  2. mirrorOf * vs external:* vs *,!exclude
  3. mirror wins over POM <repositories>
  4. server id must match mirror id
  5. virtual repo on Nexus/Artifactory

basics

~10 s

Add a <mirror> in settings.xml with <mirrorOf>*</mirrorOf> pointing at your trusted virtual repo. That redirects every repository request through it, so builds never hit untrusted public repos directly.

solid answer

~40 s

A <mirror> intercepts requests to repositories whose id matches its <mirrorOf> pattern and redirects them to the mirror URL. Using <mirrorOf>*</mirrorOf> (or external:* to still allow declared internal repos) funnels all resolution through one trusted virtual repository on your Nexus/Artifactory, so even if a POM declares Central, the actual fetch goes to the controlled mirror. The repo manager then decides what the virtual repo aggregates and never proxies your internal coordinate prefixes from upstream. Patterns can be combined: <mirrorOf>external:*,!internal-snapshots</mirrorOf> mirrors everything external except an explicitly excluded id. Because settings.xml lives outside the POM, you can enforce this org-wide and developers can't accidentally bypass it via a rogue <repositories> entry — mirrors win over POM repositories. Pair this with credentials in <servers> and checksum/signature enforcement for defense in depth.

code

xml · 6 lines
xml
<mirror>
  <id>acme-virtual</id>
  <url>https://nexus.acme.internal/repository/maven-virtual/</url>
  <!-- mirror all external repos but let a local file repo through -->
  <mirrorOf>external:*,!my-local-cache</mirrorOf>
</mirror>

go deeper

for a junior

Knows settings.xml has a <mirrors> section that can point builds at a company repo.

for a middle

Can write a <mirror> with <mirrorOf>*</mirrorOf> and attach credentials via <servers>.

for a senior

Understands mirrorOf patterns (external:*, exclusions), mirror-over-POM precedence, and matching server/mirror ids.

for a principal

Mandates a single virtual-repo entry point via managed global settings.xml across all CI agents and prevents POM-level overrides.

## The two mechanisms **`<repositories>`** declares WHERE Maven may look for artifacts. They can appear in a POM or in a `settings.xml` `<profile>`. Each has an `id`, a `url`, and `<releases>`/`<snapshots>` enabled flags. **`<mirrors>`** (only in `settings.xml`) say: "whenever Maven would contact a repository matching this pattern, contact THIS url instead." A mirror **intercepts and redirects** by repository id. ## What `<mirrorOf>` matches The `<mirrorOf>` element is a comma-separated pattern matched against repository **ids**: - `*` — mirror **every** repository (most locked-down). - `external:*` — mirror every repository **except** those on localhost or using `file://` (lets a local/internal repo through while still capturing Central etc.). - `repo1,repo2` — mirror only those ids. - `*,!internal` — mirror everything **except** the id `internal` (the `!` is an exclusion). A repository can be mirrored by at most one mirror; if several match, the first in `settings.xml` wins. **Mirrors take precedence over `<repositories>` declared in a POM**, which is exactly why they're the enforcement point: a developer cannot smuggle in an untrusted repo via the POM because the mirror reroutes it. ## The recommended lock-down Route everything through a single **virtual/group** repository on your repository manager. The repo manager (not the build) controls which upstreams are aggregated and which coordinate prefixes are blocked from upstream proxying. ```xml <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"> <mirrors> <mirror> <id>acme-virtual</id> <name>All resolution via Nexus</name> <url>https://nexus.acme.internal/repository/maven-virtual/</url> <mirrorOf>*</mirrorOf> </mirror> </mirrors> <servers> <server> <id>acme-virtual</id> <username>${env.NEXUS_USER}</username> <password>${env.NEXUS_TOKEN}</password> </server> </servers> </settings> ``` Notes: - The `<server>` `id` must equal the **mirror** id (not the original repo id) so credentials attach to the actual endpoint. - With `<mirrorOf>*</mirrorOf>`, Maven still needs SOMETHING to resolve the super-POM's `central` repo — the mirror supplies it, so this is fine. - For builds that must reach a truly local file repo, prefer `external:*` over `*`. ## Why settings.xml, not the POM The POM is shared with consumers and can be edited by anyone; `settings.xml` is environment/user-level (`~/.m2/settings.xml` or a managed `--global-settings`). Putting the mirror there lets ops/platform teams enforce the trusted source across all builds and CI agents without touching project code.

  • If a POM declares its own <repository> with id 'jitpack', will the mirror still apply?
    Yes if the mirror's <mirrorOf> matches that id (e.g. * or external:*). Mirrors are evaluated before contacting the POM-declared repo, so the request is redirected to the mirror URL.
  • Why must the <server> id match the mirror id, not the original repo id?
    Because the actual HTTP request goes to the mirror endpoint. Credentials are looked up by the id of the endpoint actually contacted, which is the mirror's id.

saying these in an interview costs you the question

  • Putting credentials under the original repo id instead of the mirror id, then wondering why auth fails.
  • Believing a mirror only affects repos you explicitly list (it matches by pattern, including *).
  • Configuring the lock-down in the POM where any contributor can override it.

context