DeepMedia logo
Blog
Picture of a library.

August 13, 2024

How to publish to Maven Central in 2024

A step-by-step guide to understand what Sonatype is, register a Central Portal account and publish libraries to Maven Central, the largest repository in the Java ecosystem.

Picture of Mattia Iavarone

Mattia Iavarone

@natario1

August 13, 2024, 8 minutes read

In this guide, we'll go through the entire process of making your Java, Kotlin, Android or any JVM-based library available to the wider developer community through the Maven Central repository. We'll cover everything from setting up your Sonatype account and getting familiar with the Central Portal to preparing your project and finally syncing it with Maven Central.

Maven Central is the go-to source for dependencies in the JVM ecosystem. By the end of the tutorial, you'll have the knowledge and tools to contribute to the repository and make your code accessible to millions of developers worldwide.

⚠️

The guide focuses on projects using the Gradle build system, but most concepts are generic and will help even if you use a different system.

What is Sonatype?

Founded in 2008, Sonatype has established itself as a prominent player in the JVM software development landscape. While the company provides a suite of tools and services in many areas like supply chain management, quality and security, it is best known for its stewardship of the Maven Central repository.

The Maven Central repository is the primary artifact repository for Java and JVM-based projects. In this context, Sonatype acts as a gatekeeper, filtering, validating and approving new artifacts before they become available to the wider developer community. As such, it plays a fundamental role for the security and health of the whole ecosystem.

What is the Central Portal?

The process of publishing artifacts to Maven Central has historically been a pain point for many developers, especially because of lack of documentation. This lead to a steep learning curve for those attempting to release their projects to the repository.

The initial hurdles involve understanding Maven Central's complex requirements, registering projects to OSSRH (OSS Repository Hosting), setting up the appropriate credentials, signing artifacts with a PGP key and configuring build settings.

The Central Portal is Sonatype's new release process that marks a significant improvement. The revised procedure streamlines the entire publication workflow, making it more intuitive and modern. Notably, the new process is very well documented too.

⚠️

For registrations newer than March 12th, 2024, publishing through the Central Portal is mandatory. Older projects can currently opt-in by emailing Sonatype's support.

How to publish to Maven Central

To publish to Maven Central you can follow the four steps below:

  1. Register a namespace
  2. Generate API tokens
  3. Distribute PGP keys
  4. Configure your Gradle build

While some of these steps may not be trivial, they must only be performed once per publication namespace, which typically spans many projects. For example, io.deepmedia:foo:1.0.0 and io.deepmedia:bar:1.0.0 are both under the io.deepmedia namespace.

For the last step, the presence of Gradle plugins like MavenDeployer makes configuration simpler and reusable across different projects.

Register a namespace

First of all, navigate to the Central Portal website and create a new account. We recommend to use GitHub as a login provider, because in that case you should be automatically granted a namespace that looks like io.github.<your username> which may be useful.

Owning a namespace means that you (and importantly, no-one else) have the right to publish artifacts whose group start with the namespace string. For example, owning the com.example namespace would give you permission to publish artifacts like com.example:project-name:1.0.0 or even com.example.project-name:project-name-api:1.0.0.

To register a namespace:

  1. In the namespaces section, you can add new namespaces in the reverse DNS form. If you own the example.com domain, use com.example.

  2. You'll see a verification code. Add it as a TXT record to your domain's DNS settings and let Sonatype verify it.

You now have publication rights for your domain!

Generate API tokens

The second step is to generate API tokens for API-based publication:

  1. Navigate to the account settings and click on Generate User Token.
  2. Save the generated username and password, as we'll use them later.

How to safely store these credentials? It depends:

  • For CI access (e.g. GitHub actions), you may save them as secret environment variables through your CI provider web interface.
  • Locally, you may put them in a local.properties file, .env file or any other location that can be easily accessed from Gradle and isn't checked in your git repository.
⚠️

Web UI based publications are also allowed, but using APIs through Gradle plugins will save you a lot of time and allow integration in your CI/CD pipeline.

Distribute PGP keys

In order to verify your publication artifacts, Maven Central requires that they are cryptographically signed with a public OpenPGP key. In simple terms, you are required to create a pair of keys:

  1. A secret key, to be used for artifact signing.
  2. A public key, to be distributed in online databases called keyservers.

The public key will be used by the Central Portal to verify that the published artifacts indeed came from you and haven't been tampered with. We recommend following the official guide for key-pair generation and public key distribution.

Then, you'll need to save your passphrase and your secret key in ASCII-armored format. To generate it, use the following command:

shell
gpg --armor --export-secret-keys your-key-id

Both the passphrase and the armored key should be secretly stored, just like you have done with publication tokens. For example, you can use environment variables in CI environments, and a local.properties file for your developer machine.

⚠️

Saving a multiline string in a properties file like local.properties requires replacing newlines with the \n character.

Configure your Gradle build

At this point, you should have everything that you need to publish to Maven Central:

  • An API token username, stored in an environment variable or Gradle property. For the purposes of this guide, let's say the variable or property is named UPLOAD_USERNAME.
  • An API token password, in UPLOAD_PASSWORD.
  • A signing PGP passphrase, in SIGNING_PASSPHRASE.
  • A signing PGP armored private key, in SIGNING_KEY.

The only thing left is to put everything together in your Gradle-based project. For this task, we highly recommend using MavenDeployer or any other plugin that can configure your build to output and upload the right artifacts.

⚠️

At this time, not many Gradle plugins support Central Portal uploads. Check the official list for more information.

First, apply the MavenDeployer plugin:

kotlin logokotlin
// settings.gradle.kts pluginManagement { repositories { gradlePluginPortal() mavenCentral() } } // build.gradle.kts of projects to be published plugins { id("io.deepmedia.tools.deployer") version "0.13.0" }

Then configure projects that need to be published to Maven Central as follows:

kotlin logokotlin
deployer { // 1. Artifact definition. // https://opensource.deepmedia.io/deployer/artifacts content { ... } // 2. Project details. // https://opensource.deepmedia.io/deployer/configuration projectInfo { description = "A sample project to showcase Maven Central publications." url = "https://github.com/sample-company/SampleProject" scm.fromGithub("sample-company", "SampleProject") license(apache2) developer("sampleUser", "sample@sample-company.com", "SampleCompany", "https://sample-company.com") groupId = "com.sample-company" } // 3. Central Portal configuration. // https://opensource.deepmedia.io/deployer/repos/central-portal centralPortalSpec { signing.key = secret("SIGNING_KEY") signing.password = secret("SIGNING_PASSPHRASE") auth.user = secret("UPLOAD_USERNAME") auth.password = secret("UPLOAD_PASSWORD") } }

Let's talk about what's happening:

  • Artifact definition: this part is left as blank because it depends on your project (is it Java-based? Is it Kotlin-based? Do you use KMP?). You can learn more about it in the plugin's documentation. Keep in mind that Maven Central requires your main artifact to be accompanied by a Javadoc and a sources JAR. MavenDeployer can help you with these, too.

  • Project details: these details will be used to configure the publication POM file, which goes through strict validation when uploaded to the Central Portal. Most of them are mandatory. For example, a deployment without developer information will be rejected. Check the plugin documentation for more options.

  • Portal coniguration: here we simply use the four variables that this guide helped you configure. Thanks to MavenDeployer's secret support, you can place them anywhere - in the system environment, in a Gradle property, even in a local.properties file - and the plugin will pick them up. Again, you can check the plugin documentation to learn more Central Portal options.

Once everything is properly configured, just run the deploy task:

shell
./gradlew deployCentralPortal

The plugin takes care of collecting all artifacts - even across different subprojects! - prepare a single bundle and upload it to the Central Portal using the credentials that you have provided. It will also wait for Portal's validation and provide meaningful errors in case anything goes wrong.

Bonus: other repositories

It is worth noting that, with just a couple of extra lines, the plugin can help you publish your artifacts to other repositories:

  • Sonatype Nexus repositories, which also include Maven Central sync, with nexusSpec { ... }
  • Sonatype Nexus snapshot repositories, with nexusSpec { repositoryUrl = ossrhSnapshots1 }
  • Github pcakages, with githubSpec { ... }
  • Local filesystem repositories, with localSpec { ... }

We recommend you check the documentation to learn more.

Conclusions

Congratulations on reaching the end of this guide to publishing on Maven Central through the new Central Portal mechanism!

In this article, we have covered everything from PGP key generation and Maven Central's stringent requirements to Gradle build configuration. We described the whole publishing process, breaking it down into manageable steps that both novice and experienced developers can follow, so you can focus on what truly matters – creating outstanding libraries and contributing to the open-source ecosystem.

At DeepMedia, we believe in the power of open source to drive innovation within the developer community. By sharing this guide and our Gradle plugin, we hope to lower the barriers to entry for publishing on Maven Central, encouraging more developers to share their work.

Subscribe to the DeepMedia Newsletter

The latest news about DeepMedia products, open source projects and software development at our company.

By clicking “Subscribe”, you agree that DeepMedia may use your email address to send you newsletters, including commercial communications, and to process your personal data for this purpose. You agree that DeepMedia may process said data using third-party services for this purpose in accordance with the DeepMedia Privacy Policy. You can revoke this consent at any time using the unsubscribe link included in each email or by writing at contact@deepmedia.io.