Deploying Plugins to the Maven Central Repository
this article describes the process of publishing plugins to the Maven central repository. as of March 12, 2024, new deployments to the old legacy OSSRH
will be discontinued. unlike previously published plugins, new plugins must be published to the Maven Central Repository
as described in the documentation.
Maven Central Repository
To register a library in the Maven repository, you need to follow the steps below.
- Authenticate your Maven Central Repository account and namespace
- enter the minimum requirements in pom.xml
- set up signing
- deploy and verify
0. Verify the Maven local repository location
enter the command like below.
local repository location$ mvn help:evaluate -Dexpression=settings.localRepository
...
/Users/____/.m2/repository
____
- login name
0.1. If mingling fails, use the
if the mvn
command fails, you need to install maven.
Maven is a Java application, so there is no installation process, just download the archive and set the path.
windows, Linux, and Mac environments are all similar, so you can find tons of documentation if you Google it. just refer to any of them and finish the installation.
then execute the command below to check if the installation is working properly.
Check version$ mvn --version
if this step fails, you can no longer proceed with the steps below.
0.2. Check the location of settings.xml
once you have the repository path, the settings.xml file is located at the following path
[OK] settings.xml/Users/____/.m2/settings.xml
- settings.xml may not exist.
alternatively, check maven's conf/settings.xml
, downloaded from Section#0.1. only one of them needs to exist.
note that you will need to modify the file later.
1. Authenticate your Sonartype account and namespace
the maven repository as we know it is a place to look up registered plugins, and to register and use your own plugin, you need to sign up for the maven central repository and use it.
you can think of Maven Central Repository
as a brand name.
the account creation and library deployment confirmation is https://central.sonatype.com
, which can be confusing at first.
- for the purposes of this article, we'll refer to it as the
sonartype account
for library publishing purposes.
when you sign up with a github account, the namespace is automatically activated.
if you sign up with a Google account, you'll need to set up your own namespace. this process may require you to verify your own domain.
of course, if you sign up with a Google account, you can use your github account as a namespace if you go through a separate process (I haven't tried)
after signing up, click publish
> namespace
and the namespace will be authorized as io.github.____
.
2. Put the minimum requirements in your pom.xml
the details are well documented in the following link.
to summarize briefly, under the <project>
element, you need to define the following elements according to the rules
XML <groupId></groupId>
<artifactId></artifactId>
<version></version>
<packaging>jar</packaging>
<name>${project.groupId}:${project.artifactId}</name>
<description></description>
<url></url>
<licenses>
...
</licenses>
<developers>
...
</developers>
<scm>
...
</scm>
the following properties can be set arbitrarily by the user.
- artifactId - a descriptive name for the library
- groupId - This can be any name starting with namespace. it can be
io.github.____
, or it can be more specific, such asio.github.____.awesome
. - version - in the form
X.Y.X
. - name - can be anything, but is usually
groupId:artifactId
. - description - a description of the library
the rest of the properties are set according to the repository location and license. you can refer to the official documentation below.
you must also publish your source code and documentation together. this process is also described in the link above.
3. Set up signing
at the end of the build, the following files are created under the target
directory
TXTawesomelib-javadoc.jar
awesomelib-sources.jar
awesomelib.jar
pom.xml
to publish to the central repository, we need to create files that act as fingerprints for each of these files, as follows
Fingerprint values that identify the fileawesomelib.jar
awesomelib.jar.asc
awesomelib.jar.md5
awesomelib.jar.sh1
awesomelib.jar.sh256
awesomelib.jar.sh512
- for every deliverable, you need to create a fingerprint value as above.
- they are collected under the directory
target/central-staging/..
. - the central repository uses these values to validate the deliverables (awesomelib.jar).
it's not trivial to extract them individually.
so we provide a plugin to extract the fingerprint values.
central-publishing-maven-plugin
[config] pom.xml<build>
<plugins>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
<version>0.6.0</version>
<extensions>true</extensions>
<configuration>
<publishingServerId>central</publishingServerId>
</configuration>
</plugin>
</plugins>
</build>
- central
- The value associated with the username/password, usually named __central__. the username/password here is unrelated to the
sonartype account` you signed up for in Section #1, so don't confuse it. Create the username and password in Section #3.2.
the above library doesn't do all the work by itself.
you will need to provide the following tools for the plugin
- install gpg - a tool for generating and managing the
private/public keys
needed to generate and verify fingerprint values. this needs to be installed locally. - install token - you will need to provide username/password information to upload the output to the centralized repository. must be created in the
sonartype account
.
3.1. Install gpg and register a public key
the central-publishing-maven-plugin
runs the gpg
command directly to extract the fingerprint values.
pGP, GPG and similar terms can be confusing, but here's a quick summary.
- PGP : An acronym for Pretty Good Privacy, a commercial software developed for email encryption. it's free for personal use, but commercial use requires a paid version.
- openPGP: A standard (RFC 9580) for vendors to make their encryption programs compatible with each other. It's not a specific piece of software, but rather an interface.
- gPG: Short for Gnu Privacy Guard, which is a publicly available software implementation of the OpenPGP specification. We'll use this implementation here.
it can be found at #### 3.1.1. Installing GPG
each operating system has a slightly different installation method.
you can find more details in the official documentation.
if the installation went well, run gpg --version
like below to verify.
[verify] gpg --version$ gpg --version
gpg (GnuPG/MacGPG2) 2.2.41
libgcrypt 1.8.10
Copyright (C) 2022 g10 Code GmbH
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Home: /Users/____/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
Camellia128, camellia192, camellia256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
3.1.2. Generate a private key public key
there are two main commands to generate a private key
the ```txt:key generation command gpg --full-generate-key gpg --gen-key
TXT
they differ in how much detail you can enter into the settings.
generate a key pair with the following command
```txt:[execute] gpg --full-generate-key
gpg --full-generate-key
- prompt for name, email, etc.
- ask for the length of the key
4096
Recommended. - you can set an expiration period.
asks for a passphrase.
the value entered here must be specified in the subsequent pgp
plugin.
you can skip it if you don't want to, but it's best to do so.
once the key has been generated, you can verify it with the command
[verify] gpg --list-keys (public key)$ gpg --list-keys
pub rsa3072 2024-11-22 [SC] [expires: 2026-11-22]
59______71
uid [ultimate] YourName <your@email>
sub rsa3072 2024-11-22 [E] [expires: 2026-11-22]
[verify] gpg --list-secret-keys (private key)$ gpg --list-secret-keys
sec rsa3072 2024-11-22 [SC] [expires: 2026-11-22]
59______71
uid [ultimate] YourName <your@email>
ssb rsa3072 2024-11-22 [E] [expires: 2026-11-22]
your name, email, etc. can be found in uid
.
the 59______71
is a string representing the public and private key pair. this string is not a key value itself, but is used to retrieve the public key.
the sec
of the private key and pub
of the public key are used to generate and verify the fingerprint value.
- locally, the private key
sec
is used to generate the fingerprint value - the public key
pub
is used to verify the fingerprint value in the centralized storage
no human, plugin does it all.
3.1.2. Public key registration
so how do you provide your public key to the other party (the central repository)?
for this purpose, there exists a place called public keyserver where public keys are collected.
the Maven centralized repository retrieves public keys from the following servers. distributing-your-public-key
- keyserver.ubuntu.com
- keys.openpgp.org
- pgp.mit.edu
now register your public key with keysever with the command below. this will be used by the central repository to verify files.
[execute] Register public key$ gpg --keyserver keyserver.ubuntu.com --send-keys 59______71
uploads the public key corresponding to the string 59______71
to keyserver.ubuntu.com
.
3.2. Configure maven-gpg-plugin
configure maven-gpg-plugin as follows.
[configuration] pom.xml<project
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<keyname>59______71</keyname>
<passphrase>???????</passphrase>
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
- <keyname>59______71</keyname> - Enter the name of the key pair you found in Section#3.1.2.
- <passphrase>???????</passphrase> - Enter the passpharse you entered in Section#3.1.2. if you didn't set a passphrase, enter
<passphrase></passphrase>
.
create an .asc
file with the private key sec.
the configuration path should be project/build/plugins
.
if you set it in project/build/pluginManagement/plugins
, maven-gpg-plugin
may not be executed depending on your maven configuration structure.
3.3. Installing the token
the maven plugin needs a username/password to upload output and fingerprint values.
Click My Account
> View Account
on the Maven Centeral Repository screen where you registered in Section#1 to register a token.
[Screen] New TokenSetup Token-Based Authentication
---- Generate User Token
Generate User Token
---- Revoke User Token
Revoke User Token
click Generate User Token
to generate a token.
you'll see a friendly screen like this
'```xml:[OK] New Token UserName [_____________]
Password [_____________]
Use the following...
you'll only see this screen once now. make a good copy of it.
if you lose it, you'll need to reissue the token and create a username and password.
now you need to enter <server>...</server>
into the settings.xml
maven settings file.
[settings] settings.xml<settings>
<servers>
<server>
<id>central</id>
<username>_____</username>
<password>_______</password>
</server>
</servers>
</settings>
Use the username/password via <publishingServerId/>
in the pom.xml file that you entered in Section#3.
[OK] pom.xml <configuration>
<publishingServerId>central</publishingServerId>
</configuration>
verify that it matches the value entered in the central-publishing-maven-plugin plugin.
4. Deploy
once you have everything set up, you can run the following maven command to build and publish to your repository.
[execute] compile, package, publish$ mvn clean install deploy
- clean - clean the
target
directory - install - compile and package project into a jar, also package source code and documentation into a jar
- deploy - sign jar, generate checksum, and upload to centralized repository
publishing takes about 10 minutes to complete.
you can see which components are currently being deployed by entering the sonartype account
screen.

4.1. Debugging
it is unlikely that the entire process will succeed the first time.
if something goes wrong, you can get the logs to a file as follows.
Generate log$ mvn clean install deploy > debug.log
```txt
it's going to be incredibly complex, but most of the errors will come from these two points.
```txt:[log] maven-gpg-plugin
[INFO] --- maven-gpg-plugin:3.1.0:sign (sign-artifacts) @ _____ ---
[INFO] Signing 4 files with 59______71 secret key.
...
[Log] central-publishing-maven-plugin[INFO] --- central-publishing-maven-plugin:0.6.0:publish (injected-central-publishing) @ _____ ---
[INFO] Using Central baseUrl: https://central.sonatype.com
[INFO] Using credentials from server id central in settings.xml
[INFO] Using Usertoken auth, with namecode: _____
[INFO] Staging 7 files
...
[INFO] Created bundle successfully /____/target/central-staging/central-bundle.zip
[INFO] Going to upload /____/target/central-publishing/central-bundle.zip
this is the final output: central-bundle.zip
.
it takes about 10 minutes for the central repository to unzip, validate the files, and deploy the plugin.
here are some reasons why the deployment might fail
TXTComponent with package url: 'pkg:maven/io.github.___.___/___@1.0.0' already exists
Missing signature for file: ___-1.0.0-javadoc.jar
Missing signature for file: ___-1.0.0-sources.jar
- 1.0.0 is already deployed, but you uploaded the same version (fix
<version/>
in pom.xml) - no source code and no java doc. check the logs to see if
maven-source-plugin
andmaven-javadoc-plugin
are running.