Skip to content
Merged
23 changes: 22 additions & 1 deletion fern/products/cli-api-reference/pages/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ hideOnThisPage: true

<CodeBlock title="terminal">
```bash
fern generate [--group <group>] [--api <api>] [--version <version>] [--preview] [--fernignore <path>]
fern generate [--group <group>] [--api <api>] [--version <version>] [--preview] [--fernignore <path>] [--local]
```
</CodeBlock>

Expand All @@ -197,10 +197,15 @@ hideOnThisPage: true

# Run all groups defined in the "frontend" alias
fern generate --group frontend

# Run a specific group locally (self-hosted)
fern generate --group python-sdk --local
```

You can also set an alias as your `default-group` in `generators.yml`, so running `fern generate` without any arguments will run all groups in that alias.

The `--group` flag can be combined with other flags like `--local` for [self-hosted SDK generation](/learn/sdks/deep-dives/self-hosted), `--preview` for local testing, or `--version` to specify the SDK version.

### preview

Use `--preview` to test SDK changes locally before publishing. This is especially useful during development:
Expand Down Expand Up @@ -246,6 +251,22 @@ hideOnThisPage: true
fern generate --fernignore ./custom-fernignore
```

### local

Use `--local` to run SDK generation on your own machine instead of using Fern's cloud infrastructure. This is useful for organizations with strict security or compliance requirements. See [self-hosted SDKs](/learn/sdks/deep-dives/self-hosted) for setup instructions.

```bash
# Generate all SDKs locally
fern generate --local

# Generate specific SDK group locally
fern generate --group python-sdk --local
```

<Note>
A Docker daemon must be running on your machine, as SDK generation runs inside a Docker container.
</Note>

</Accordion>

<Accordion title="fern check">
Expand Down
165 changes: 136 additions & 29 deletions fern/products/sdks/guides/self-hosted.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,155 @@ description: Fern supports self-hosting SDK generation so that you can run SDK g

<Markdown src="/snippets/enterprise-plan.mdx" />

Fern SDK generation [runs on Fern's infrastructure by default](/sdks/overview/how-it-works). Self-hosting allows you to run SDK generation on your own infrastructure to meet specific security or compliance requirements.
Fern SDK generation [runs on Fern's infrastructure by default](/sdks/overview/how-it-works). Self-hosting allows you to run SDK generation on your own infrastructure. Use self-hosting if your organization:

## When to use self-hosting
- Operates without internet access
- Has strict compliance or security requirements
- Needs full control over your SDK generation process

Self-hosting is typically required for organizations that operate without internet access, have strict compliance requirements, or need full control over their SDK generation process.
When you self-host, you're responsible for infrastructure management and SDK distribution. Self-hosted SDK generation includes [all Fern SDK features](/learn/sdks/overview/capabilities).

When you self-host, you're responsible for server setup, security, maintenance, and deciding how to distribute your generated SDKs. Self-hosted SDK generation includes [all Fern SDK features](/learn/sdks/overview/capabilities).

<Warning>
<Info>
Unless you have specific requirements that prevent using Fern's default hosting, we recommend **using our managed cloud generation solution** for easier setup and maintenance.
</Warning>
</Info>

## How it works
## Setup

<Info>
This page assumes that you have:

* An initialized `fern` folder. See [Set up the `fern` folder](/sdks/overview/quickstart).
* SDK generators configured in `generators.yml`. See language-specific quickstarts: [TypeScript](/sdks/generators/typescript/quickstart), [Python](/sdks/generators/python/quickstart), [Go](/sdks/generators/go/quickstart), [Java](/sdks/generators/java/quickstart), etc.
</Info>

Self-hosted SDK generation allows you to output to your local file system or push directly to a GitHub repository you control. Follow these steps to set up and run local generation:

<Steps>
<Step title="Ensure Docker is running">

Verify that a Docker daemon is running on your machine, as SDK generation runs inside a Docker container:

```bash
docker ps
```

</Step>

<Step title="Generate a Fern token">

Generate a Fern token, which is required for local generation to verify your organization.

```bash
fern token
```

The token is specific to your organization defined in `fern.config.json` and doesn't expire.

</Step>

<Step title="Configure output location">

Configure your `generators.yml` to output SDKs to your local file system or a GitHub repository you control.

<Tabs>
<Tab title="Local file system" language="local">

Output generated SDKs directly to a local directory:

```yaml title="generators.yml" {7-8}
groups:
python-sdk:
generators:
- name: fernapi/fern-python-sdk
version: 4.0.0
output:
location: local-file-system
path: ../sdks/python
```

</Tab>
<Tab title="GitHub repository" language="github">

When you run `fern generate`, Fern uses Docker containers to execute SDK generation logic. By default, Fern runs **cloud generation** by allocating compute space and running the container remotely. With **self-hosted (local) generation**, you download and run the same Docker container on your own infrastructure.
To push generated SDKs to your GitHub repository, configure the `github` property with `uri` and `token`. Set the [publishing `mode`](/learn/sdks/reference/generators-yml#github) to `push` for direct commits or `pull-request` to create PRs.

Both approaches generate partial SDK files to your configured output location, then Fern verifies your organization registration and completes the SDK by adding package distribution files.
```yaml title="generators.yml" {4-8}
groups:
python-sdk:
generators:
- name: fernapi/fern-python-sdk
version: 4.0.0
github:
uri: https://github.com/your-org/python-sdk
token: ${GITHUB_TOKEN}
mode: push
branch: main
```

</Tab>
</Tabs>
</Step>

<Step title="Set up authentication">

Configure authentication based on your chosen output location.

<Tabs>
<Tab title="Local file system" language="local">

Set your Fern token as an environment variable:

The self-hosted process works as follows:
```bash
export FERN_TOKEN=your-generated-token
```

</Tab>
<Tab title="GitHub repository" language="github">

Set up GitHub secrets for authentication. In your repository's **Settings** > **Secrets and variables** > **Actions**, add:

1. **Download the Docker image** - Fern provides the location of the most up-to-date Docker image containing the SDK generation logic
1. **Upload your fern folder** - Add your API definition and other configuration files to the container
1. **Run the container** - Execute SDK generation using standard Docker commands
1. **Partial SDK output** - Core SDK files are generated and saved to your configured output location (local file system, GitHub repository, package registry, etc.)
1. **Organization verification** - Fern verifies your organization registration and completes SDK generation by adding package distribution files like `pyproject.toml`, READMEs, and dependency configurations
1. **Receive updated Docker images** - Fern releases new versions of the Docker image that your team can evaluate and deploy when ready
- `FERN_TOKEN`: The token you generated above
- `GITHUB_TOKEN`: A [GitHub personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with repository write access

### Architecture diagram
</Tab>
</Tabs>
</Step>

<Step title="Run generation locally">

Use the `--local` flag to generate SDKs locally instead of using Fern's cloud infrastructure. You can combine `--local` with `--group` to generate specific SDKs locally.

```bash
fern generate --local
fern generate --group python-sdk --local
```

</Step>
</Steps>

## How it works

When you run `fern generate --local`, the Fern CLI executes SDK generation on your local machine instead of using Fern's cloud infrastructure. The self-hosted process works as follows:

1. **Organization verification** (network call) - The CLI verifies your organization registration with Fern
1. **Download generator image** (network call if not cached) - The CLI downloads the generator's Docker image if not already available locally
1. **Generate SDK** (local) - The CLI runs the generator container locally to produce SDK files based on your API definition and `generators.yml` configuration
1. **Output SDK** (local) - Generated SDK files are saved to your configured output location (local file system or GitHub repository)

These are the only network calls made when using the `--local` flag. No API definition or specification data is sent over the network: all SDK generation happens locally on your machine.

<Accordion title="Architecture diagram">

```mermaid
sequenceDiagram
autonumber
participant F as Fern
participant C as Customer
participant S as Customer Server
F->>C: Provides Docker image
C->>S: Uploads fern folder
C->>S: Runs Docker command
S->>S: Output partial SDK
F->>F: Checks organization registration
F->>S: Completes SDK generation
F->>C: Releases updated Docker image
C->>C: Evaluates new version
C->>S: Deploys updated image
participant CLI as Fern CLI
participant F as Fern
C->>CLI: fern generate --local
CLI->>F: Verify org
CLI->>F: Pull image (if needed)
CLI->>CLI: Run container, generate SDK
CLI->>CLI: Push to output (local/GitHub)
```

</Accordion>
39 changes: 35 additions & 4 deletions fern/products/sdks/reference/generators-yml-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -737,11 +737,9 @@ Local directory path where generated files will be saved
#### `github`

Specify how your SDKs are generated in GitHub using the `github` configuration.
Designate the `mode` to specifiy how Fern handles your code changes. For all of the
modes, you must specify the GitHub repository in which you want to store your
SDK code. You can also configure a branch name, license, and reviewers.
Designate the `mode` to specify how Fern handles your code changes. For cloud generation, specify the GitHub repository using `repository`. For [self-hosted generation](/learn/sdks/deep-dives/self-hosted), use `uri` and `token` instead.

<Note>Make sure the [Fern GitHub app](https://github.com/apps/fern-api) is installed on your destination repository</Note>
<Note>Make sure the [Fern GitHub app](https://github.com/apps/fern-api) is installed on your destination repository (not required for self-hosted generation)</Note>

<AccordionGroup>
<Accordion title="Release (recommended)">
Expand Down Expand Up @@ -846,6 +844,39 @@ Software license for the generated SDK.
Specify which teams and users should review generated code. See [reviewers configuration](#reviewers-1).
</ParamField>
</Accordion>
<Accordion title="Self-hosted">

For [self-hosted SDK generation](/learn/sdks/deep-dives/self-hosted), configure the `github` property with `uri` and `token` instead of `repository`.

```yml {6-10}
groups:
ts-sdk:
generators:
- name: fernapi/fern-typescript-sdk
...
github:
uri: "https://github.com/your-org/your-repo-name"
token: "${GITHUB_TOKEN}"
mode: "push"
branch: "main"
```

<ParamField path="uri" type="string" required={true} toc={true}>
Full URL to your GitHub repository (e.g., `https://github.com/your-org/your-repo`).
</ParamField>

<ParamField path="token" type="string" required={true} toc={true}>
GitHub Personal Access Token with repository write permissions. Use an environment variable reference (e.g., `${GITHUB_TOKEN}`).
</ParamField>

<ParamField path="mode" type="'push' | 'pull-request'" required={false} toc={true}>
How to publish changes: `push` commits directly to the branch, `pull-request` opens a PR for review.
</ParamField>

<ParamField path="branch" type="string" required={false} toc={true}>
Target branch for commits or pull requests.
</ParamField>
</Accordion>
</AccordionGroup>

#### `metadata`
Expand Down
Loading