Deploying Grafbase Gateway with Extensions

Julius de BruijnJulius de Bruijn
  • Docker installed for Docker deployment
  • Kubernetes cluster and kubectl for Kubernetes deployment
  • Helm installed for Kubernetes deployment
  • Grafbase Access Token (if using schema registry, or dashboard analytics)
  • Grafbase graph ref (if using schema registry), or a local federated schema file
  • Locally built or downloaded extensions (from grafbase extension install) and a configuration file (grafbase.toml) with an extensions section

Grafbase Gateway is a GraphQL federation gateway that can be extended with custom functionality through extensions. Extensions allow you to add custom resolvers, authentication logic, and more to your GraphQL API.

Extensions are implemented as WebAssembly components that are loaded by the gateway at runtime. The extensions are installed in a directory named grafbase_extensions, which must be available to the gateway when it starts. Alternatively, you can define the extension to be in a specific path in grafbase.toml under the extensions section. This path must have a valid extension WebAssembly component, and the manifest file.

To set up a Grafbase Gateway with extensions, you need:

  1. The grafbase-gateway binary
  2. A grafbase_extensions directory containing installed extensions
  3. A configuration file (typically grafbase.toml)
  4. Either environment variables to fetch the schema from Grafbase's registry, or a local federated GraphQL schema file

This approach uses the Schema Registry to fetch the graph schema based on a Graph Reference and Access Token. This method polls for changes to the schema automatically every ten seconds, and restarts the gateway with changes.

Create a Dockerfile in the root of your project.

FROM ghcr.io/grafbase/gateway:0.38.0 # or later version! # Create directories WORKDIR /app # Copy the configuration file COPY grafbase.toml /app/grafbase.toml # Copy the extensions directory if you have custom extensions COPY grafbase_extensions /app/grafbase_extensions # Set default command CMD ["--config", "/app/grafbase.toml"]

Create a grafbase.toml file in the root of your project.

[graph] introspection = true [network] listen_address = "0.0.0.0:5000" [extensions] rest = "0.4"

Before building the Docker image, install the extensions:

grafbase extension install

This will create or update the grafbase_extensions directory with the specified extensions.

Before deploying the gateway, create all subgraphs as needed, and publish them to the Schema Registry. For this simple example, we will create a subgraph that fetches country names from a public REST API.

Create a subgraph.graphql in the root of your project:

extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable"]) @link(url: "https://grafbase.com/extensions/rest/0.4.1", import: ["@restEndpoint", "@rest"]) @restEndpoint( name: "restCountries", baseURL: "https://restcountries.com/v3.1" ) type Country { name: String! } type Query { listAllCountries: [Country!]! @rest( method: GET endpoint: "restCountries" path: "/all" selection: "[.[] | { name: .name.official }]" ) }

Publish the subgraph to the Schema Registry:

grafbase publish \ --name restCountries \ your-org/your-graph@branch \ -m initx \ --virtual \ --schema subgraph.graphql

Create a compose.yml in the root of your project:

services: grafbase: build: . restart: always environment: GRAFBASE_GRAPH_REF: 'your-graph@branch' GRAFBASE_ACCESS_TOKEN: 'your-access-token' ports: - '5000:5000'

The access token should be created in the Grafbase dashboard, and scoped to have access to the graph.

docker-compose up -d

This approach uses a local federated GraphQL schema file instead of fetching it from the Schema Registry. This step requires you to manually fetch the federated schema when it is updated. You can replace the schema file in the running container without restarting the gateway. The gateway will automatically reload the schema when it changes.

Add the following content to the compose.yml file:

FROM ghcr.io/grafbase/gateway:0.38.0 # or later # Create directories WORKDIR /app # Copy the configuration file COPY grafbase.toml /app/grafbase.toml # Copy the federated schema COPY federated-graph.graphql /app/federated-graph.graphql # Copy the extensions directory COPY grafbase_extensions /app/grafbase_extensions # Set default command CMD ["--config", "/app/grafbase.toml", "--schema", "/app/federated-graph.graphql"]

Same as the previous example.

Same as the previous example.

Same as the previous example.

After successfully publishing a subgraph, fetch the federated schema using the following command:

grafbase schema your-org/your-graph@branch > federated-graph.graphql
version: '3' services: grafbase: build: . restart: always ports: - '5000:5000' # keep the environment variables if you want dashboard # analytics. remove, if you want to run the gateway # totally air-gapped environment: GRAFBASE_GRAPH_REF: 'your-graph@branch' GRAFBASE_ACCESS_TOKEN: 'your-access-token' volumes: # Mount the schema file as a volume for easy updates - ./federated-graph.graphql:/app/federated-graph.graphql
docker-compose up -d

This method uses Helm to deploy the Grafbase Gateway that fetches the schema from the Schema Registry.

Create a custom values.yaml file for Helm:

replicaCount: 2 image: repository: ghcr.io/grafbase/gateway tag: 0.38.0 # or later version pullPolicy: Always service: type: ClusterIP port: 80 targetPort: 5000 gateway: externalSchema: true externalConfig: false config: | [graph] introspection = true [network] listen_address = "0.0.0.0:5000" [extensions] rest = "0.4" secrets: enabled: true values: GRAFBASE_GRAPH_REF: "your-graph@branch" GRAFBASE_ACCESS_TOKEN: "your-access-token" # Create a ConfigMap to store extensions volumes: - name: extensions configMap: name: grafbase-extensions volumeMounts: - name: extensions mountPath: /app/grafbase_extensions

Install the extensions locally:

grafbase extension install

Create a ConfigMap from the extensions directory:

kubectl create configmap grafbase-extensions --from-file=grafbase_extensions/

Or define it in a YAML file:

apiVersion: v1 kind: ConfigMap metadata: name: grafbase-extensions data: # Content of each extension file, converted to base64 # This would be automatically populated when using the kubectl create command
helm install grafbase-gateway oci://ghcr.io/grafbase/helm-charts/gateway --version 0.2.5 -f values.yaml

This method uses a local federated GraphQL schema file stored in a ConfigMap.

Create a custom values.yaml file for Helm:

replicaCount: 2 image: repository: ghcr.io/grafbase/gateway tag: 0.38.0 # or lateer pullPolicy: Always service: type: ClusterIP port: 80 targetPort: 5000 gateway: externalSchema: true externalConfig: false config: | [graph] introspection = true [network] listen_address = "0.0.0.0:5000" [extensions] rest = "0.4" args: - --config - /etc/grafbase/config/grafbase.toml - --schema - /etc/grafbase/schema/federated-graph.graphql # Create volumes for config, schema, and extensions volumes: - name: schema configMap: name: grafbase-schema - name: extensions configMap: name: grafbase-extensions volumeMounts: - name: schema mountPath: /etc/grafbase/schema - name: extensions mountPath: /app/grafbase_extensions

Create ConfigMaps for the configuration, schema, and extensions:

# For the schema kubectl create configmap grafbase-schema --from-file=federated-graph.graphql # For extensions grafbase extension install kubectl create configmap grafbase-extensions --from-file=grafbase_extensions/
helm install grafbase-gateway oci://ghcr.io/grafbase/helm-charts/gateway --version 0.2.5 -f values.yaml

You can customize extensions by modifying your grafbase.toml file. For example, to configure the JWT extension:

[extensions.jwt] version = "1.0" [extensions.jwt.config] jwks.url = "https://example.com/.well-known/jwks.json" jwks.issuer = "example.com" jwks.audience = "my-project" jwks.poll_interval = 60 [extensions.jwt.config.header] name = "Authorization" value_prefix = "Bearer "

Configure health checks in your grafbase.toml:

[health] enabled = true listen = "0.0.0.0:9668" path = "/health"

For production environments, you might want to set up telemetry:

[telemetry] service_name = "my-federated-graph" [telemetry.tracing] enabled = true sampling = 1 [telemetry.tracing.exporters.otlp] enabled = true endpoint = "http://my-otel-collector:4317" protocol = "grpc" timeout = 5

This guide has demonstrated how to deploy Grafbase Gateway with extensions in both Docker and Kubernetes environments. By following these instructions, you can set up a flexible and extensible GraphQL federation gateway that meets your specific needs, whether you're using Grafbase's Schema Registry or a local schema file.

Get Started

Deploy your Grafbase Gateway with Extensions to Docker, Kubernetes, or any other platform.