> This page is for SDKs, version Legacy.
> For other versions, use one of these documentation indexes:
> - Current (default): https://buildwithfern.com/learn/sdks/current/llms.txt
> - Legacy: https://buildwithfern.com/learn/sdks/legacy/llms.txt

> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://buildwithfern.com/learn/llms.txt.

# Publishing to Maven Central

> Learn how to publish your Fern-generated Java SDK to Maven Central. Complete guide covering authentication, GPG signatures, and automated releases.

> **You're viewing the legacy SDK docs**
>
> These pages cover SDK generation configured with `generators.yml`. New projects use `sdk-config.yml`, so see [the Current version of this page](/learn/sdks/generators/java/publishing) for up-to-date guidance. To move an existing project, follow the [SDK Config migration guide](/learn/sdks/legacy/generators/migration-guides/sdk-config), which walks through `fern sdk migrate`, and review the [`sdk-config.yml` reference](/learn/sdks/reference/sdk-config).

> **Enterprise feature**
>
> This feature is available only for the [Enterprise plan](https://buildwithfern.com/pricing). To get started, reach out to [support@buildwithfern.com](mailto:support@buildwithfern.com).

Publish your public-facing Fern Java SDK to the [Maven Central registry](https://central.sonatype.com/). After following the steps on this
page, you'll have a versioned package published on Maven Central. To distribute
the SDK internally instead, generate to the local file system (optionally
[self-hosted](/learn/sdks/legacy/deep-dives/self-hosted)) and build a JAR with
[`fern generate --package`](/learn/cli-api-reference/cli-reference/sdk-commands#package).

> **Info**
>
> This page assumes that you have:
>
> * An initialized `fern` folder, a GitHub repository for your Java SDK, and a Java generator group in `generators.yml`. See [Generating an SDK (Java)](/learn/sdks/legacy/generators/java/quickstart).

## Configure Maven Central publication

You'll need to update your `generators.yml` file to configure the output location, target repository, and publishing mode. Your `generators.yml` [should live in your source repository](/learn/sdks/legacy/overview/project-structure) (or on your local machine), not the repository that contains your Java SDK code.

#### Configure \`output\` location

In the `group` for your Java SDK, change the output location in `generators.yml` from `local-file-system` (the default) to `maven` to indicate that Fern should publish your package directly to the Maven Central registry.

Then, add `publish-to: central` to indicate that the publish target is the new Maven Central Portal (Sonatype). To publish to the legacy Nexus Repository, use `publish-to: ossrh`.

**`generators.yml`**

```yaml {6-9} title="generators.yml"
groups: 
  java-sdk:
    generators:
      - name: fern-java-sdk
        version: 4.32.4
        output:
          location: maven
        config:
          publish-to: central
```

#### Add repository location

Add the path to the GitHub repository containing your Java SDK:

**`generators.yml`**

```yaml {10-11} title="generators.yml"
groups: 
  java-sdk:
    generators:
      - name: fern-java-sdk
        version: 4.32.4
        output:
          location: maven
        config:
          publish-to: central
        github: 
          repository: your-org/company-java
```

#### Choose your publishing mode

Optionally set the mode to control how Fern handles SDK publishing:

* `mode: release` (default): Fern generates code, commits to the default branch (or the `branch` you specify), and tags a release automatically
* `mode: pull-request` (recommended):  Fern generates code and creates a PR for you to review before release
* `mode: push`: Fern generates code and pushes to a branch you specify for you to review before release

You can also configure other settings, like the reviewers or license. Refer to the [full `github` (`generators.yml`) reference](/learn/sdks/legacy/reference/generators-yml#github) for more information.

**`generators.yml`**

```yaml title="generators.yml" {12-13}
groups: 
  java-sdk:
	generators:
	  - name: fern-java-sdk
		version: 4.32.4
		output:
		  location: maven
		config:
		  publish-to: central
		github: 
		  repository: your-org/company-java
		  mode: push
		  branch: your-branch-name # Required for mode: push
```

## Set up Maven Central publishing authentication

#### Log into Maven Central

Log into [Maven Central](https://central.sonatype.com/) or create a new account.

#### Verify your namespace

1. Click on your username, then select **View Namespaces**. Click **Register New Namespace**.
2. Enter your company website or GitHub account in reverse domain name format and go through the verification process.

#### Configure Maven Coordinate

Add the namespace you just verified in Maven Central to the `coordinate` field. This specifies how your Java SDK will be
published and referenced in the Maven Central respository.

**`generators.yml`**

```yaml {8} title="generators.yml"
groups: 
  java-sdk:
    generators:
      - name: fern-java-sdk
        version: 4.32.4
        output:
          location: maven
          coordinate: com.company:sdk-name # groupId:artifactId
        config:
          publish-to: central
        github: 
          repository: your-org/company-java
```

#### Generate user tokens

1. Back in Maven Central, click on your username, then select **View Account**
2. Click on **Generate User Token**, then click **Ok** to confirm
   generation. This will invalidate any existing token.

   > **Warning**
   >
   > Save your username and password tokens –  they won’t be displayed after you leave the page.

#### Configure Maven Central authentication token

Add `username: ${MAVEN_USERNAME}` and `password: ${MAVEN_PASSWORD}` to `generators.yml` to tell Fern to use the `MAVEN_USERNAME` and `MAVEN_PASSWORD` environment variable for authentication when publishing to the Maven Central registry.

**`generators.yml`**

```yaml {9-10} title="generators.yml"
groups: 
  java-sdk:
    generators:
      - name: fern-java-sdk
        version: 4.32.4
        output:
          location: maven
          coordinate: com.company:sdk-name
          username: ${MAVEN_USERNAME}
          password: ${MAVEN_PASSWORD}
        config:
          publish-to: central
        github: 
          repository: your-org/company-java
```

## Generate GPG Signature

Next, set up code signing credentials by generating or identifying a GPG key ID, password, and secret key.  Maven Central requires all artifacts to be digitally signed with PGP/GPG keys.

> **Info**
>
> If you don't have gpg installed, you can download the binary from [https://gnupg.org/download/index.html](https://gnupg.org/download/index.html), or install it via package manager.

#### Find your key

If you already have a GPG key, you can list your keys:

```sh
gpg --list-secret-keys --keyid-format LONG
```

If you don't have a GPG key, you can generate a new one:

```sh
gpg --gen-key
```

You'll be prompted to create a new username and passphrase.

#### Export your key

Export your key so you can store it in an environment variable later on:

```sh
gpg --export-secret-keys --armor YOUR_KEY_ID
```

Be sure to replace `YOUR_KEY_ID` with the key ID of the key you want to export.

> **Info**
>
> More information is available on [Maven Central's GPG validation page](https://central.sonatype.org/publish/requirements/gpg/).

#### Configure GPG Signature

Add the `keyId`, `password`, and `secretKey` from the previous step to `generators.yml`:

**`generators.yml`**

```yaml {11-14} title="generators.yml"
groups: 
  java-sdk:
    generators:
      - name: fern-java-sdk
        version: 4.32.4
        output:
          location: maven
          coordinate: com.company:sdk-name
          username: ${MAVEN_USERNAME}
          password: ${MAVEN_PASSWORD}
          signature:
            keyId: ${MAVEN_SIGNATURE_SECRET_KEY_ID}
            password: ${MAVEN_SIGNATURE_PASSWORD}
            secretKey: ${MAVEN_SIGNATURE_SECRET_KEY}
        config:
          publish-to: central
        github: 
          repository: your-org/company-java
```

#### Upload your key to public key servers

Finally, upload your key to public key servers so Maven Central can access the signature:

```bash
# Upload to multiple key servers
gpg --keyserver keyserver.ubuntu.com --send-keys YOUR_KEY_ID
gpg --keyserver keys.openpgp.org --send-keys YOUR_KEY_ID
gpg --keyserver pgp.mit.edu --send-keys YOUR_KEY_ID
```

## Publish your SDK

Decide how you want to publish your SDK to Maven Central. You can use GitHub workflows for automated releases or publish directly via the CLI.

#### Release via a GitHub workflow

Set up a release workflow via [GitHub Actions](https://docs.github.com/en/actions/get-started/quickstart) so you can trigger new SDK releases directly from your source repository.

#### Set up authentication

Open your source repository in GitHub. Click on the **Settings** tab. Then, under the **Security** section, open **Secrets and variables** > **Actions**.

You can also use the url `https://github.com/<your-repo>/settings/secrets/actions`.

#### Add secret for your Fern API key

1. Select **New repository secret**.
2. Name your secret `FERN_TOKEN`.
3. Add your Fern API key. If you don't already have one, generate one by
   running `fern token`. By default, the API key is generated for the
   organization listed in `fern.config.json`.
4. Click **Add secret**.

#### Add secrets for Maven Central

Add the following repository secrets by selecting **New repository secret** for each:

1. `MAVEN_USERNAME` - Your Maven Central username
2. `MAVEN_PASSWORD` - Your Maven Central password
3. `MAVEN_SIGNATURE_SECRET_KEY_ID` - Your GPG key ID
4. `MAVEN_SIGNATURE_PASSWORD` - Your GPG passphrase
5. `MAVEN_SIGNATURE_SECRET_KEY` - Your GPG secret key

#### Set up a new workflow

Set up a CI workflow that you can manually trigger from the GitHub UI. In your repository, navigate to **Actions**. Select **New workflow**, then **Set up workflow yourself**. Add a workflow that's similar to this:

**`.github/workflows/publish.yml`**

```yaml title=".github/workflows/publish.yml" maxLines=0
name: Publish Java SDK

on:
  workflow_dispatch:
    inputs:
      version:
        description: "The version of the Java SDK that you would like to release"
        required: true
        type: string

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v4

      - name: Install Fern CLI
        run: npm install -g fern-api

      - name: Release Java SDK
        env:
          FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
          MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
          MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
          MAVEN_SIGNATURE_SECRET_KEY_ID: ${{ secrets.MAVEN_SIGNATURE_SECRET_KEY_ID }}
          MAVEN_SIGNATURE_PASSWORD: ${{ secrets.MAVEN_SIGNATURE_PASSWORD }}
          MAVEN_SIGNATURE_SECRET_KEY: ${{ secrets.MAVEN_SIGNATURE_SECRET_KEY }}
        run: |
          fern generate --group java-sdk --version ${{ inputs.version }} --log-level debug
```

> **Note**
>
> You can alternatively configure your workflow to execute `on: [push]`.

#### Regenerate and release your SDK

Navigate to the **Actions** tab, select the workflow you just created, specify a version number, and click **Run workflow**. This regenerates your SDK.

The rest of the release process depends on your chosen mode:

* **Release mode (default):** If you didn't specify a `mode` or set `mode: release`, no further action is required. Fern automatically tags the new release with your specified version number and initiates the publishing workflow in your SDK repository.

* **Pull request or push mode:** If you set `mode: pull-request` or `mode: push`, Fern creates a pull request or pushes to a branch respectively. Review and merge the PR (`pull-request`) or branch (`push`), then [tag a new release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository) to initiate the publishing workflow in your SDK repository.

Once the workflow completes, you can view your new release by logging into Maven Central and navigating to **View Deployments**.

#### Release via CLI and environment variables

#### Set Maven environment variables

Set the Maven Central environment variables on your local machine:

```bash
export MAVEN_USERNAME=your-maven-username
export MAVEN_PASSWORD=your-maven-password
export MAVEN_SIGNATURE_SECRET_KEY_ID=your-gpg-key-id
export MAVEN_SIGNATURE_PASSWORD=your-gpg-passphrase
export MAVEN_SIGNATURE_SECRET_KEY=your-gpg-secret-key
```

#### Regenerate and release your SDK

Regenerate your SDK, specifying the version:

```bash
fern generate --group java-sdk --version <version>
```

The rest of the release process depends on your chosen mode:

* **Release mode (default):** If you didn't specify a `mode` or set `mode: release`, no further action is required. Fern automatically tags the new release with your specified version number and initiates the publishing workflow in your SDK repository.

* **Pull request or push mode:** If you set `mode: pull-request` or `mode: push`, Fern creates a pull request or pushes to a branch respectively. Review and merge the PR (`pull-request`) or branch (`push`), then [tag a new release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository) to initiate the publishing workflow in your SDK repository.

Once the command completes, you can view your new release by logging into Maven Central and navigating to **View Deployments**.