> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formal.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Deploy your first Formal Connector and secure a database in 10 minutes

Get production-ready access controls running in minutes. This guide walks you through deploying your first Connector and connecting to a protected resource.

## Overview

Deploying Formal consists of four main steps:

1. **Add a Resource**: Define the database, API, or infrastructure you want to protect
2. **Add a Native User**: Create a user account for authentication
3. **Configure a Connector**: Create a Connector with listeners in the Control Plane
4. **Deploy the Connector**: Run the Connector container in your infrastructure

## Step 1: Add a Resource

The first step is to register the resource you want to protect in Formal.

<Tabs>
  <Tab title="Web Console">
    1. Navigate to [Resources](https://app.formal.ai/resources) in the Formal console
    2. Click **New Resource**
    3. Fill in the connection details:
       * **Name**: A friendly name for your resource
       * **Type**: Select your technology (PostgreSQL, MySQL, MongoDB, Snowflake, HTTP, SSH, etc.)
       * **Host**: Your service hostname or IP
       * **Port**: Service port (e.g., 5432 for PostgreSQL, 27017 for MongoDB)
       * **Space**: (Optional) Logical grouping for access control
    4. Enable **Termination Protection** to prevent accidental deletion (recommended for production)
    5. Click **Create Resource**
  </Tab>

  <Tab title="Terraform">
    ```hcl theme={null}
    resource "formal_resource" "postgres" {
      name        = "production-database"
      hostname    = "db.internal.company.com"
      port        = 5432
      technology  = "postgres"
      termination_protection = true
    }
    ```

    **Apply:**

    ```bash theme={null}
    terraform apply
    ```
  </Tab>
</Tabs>

<Tip>
  Your resource doesn't need to be publicly accessible. The Connector will reach
  it from within your VPC.
</Tip>

## Step 2: Add a Native User to your Resource

Add a native user account that will be used to authenticate connections to your resource.

<Tabs>
  <Tab title="Web Console">
    1. Navigate to [Resources](https://app.formal.ai/resources) in the Formal console
    2. Click on your resource to open its details
    3. Go to the **Native Users** tab
    4. Click **Add Native User**
    5. Fill in the user details:
       * **Username**: resource username (e.g., `app_user`)
       * **Password**: resource password
       * **Description**: Optional description for the user
    6. Click **Create Native User**
  </Tab>

  <Tab title="Terraform">
    ```hcl theme={null}
    resource "formal_native_user" "app_user" {
      resource_id         = formal_resource.postgres.id
      native_user_id      = "app_user"
      native_user_secret  = var.native_user_secret
      use_as_default = true
    }

    variable "native_user_secret" {
      description = "Resource password for native user"
      type        = string
      sensitive   = true
    }
    ```

    **Apply:**

    ```bash theme={null}
    terraform apply
    ```
  </Tab>
</Tabs>

## Step 3: Configure a Connector

Next, create a Connector in the Control Plane to define how clients will connect.

<Tabs>
  <Tab title="Web Console">
    1. Navigate to [Connectors](https://app.formal.ai/connectors) in the Formal console
    2. Click **New Connector**
    3. Enter a **Name** for your Connector
    4. Add a **Listener**:
       * **Port**: The port clients will connect to (e.g., 5432 for PostgreSQL)
       * **Rule Type**: Choose how to route connections:
         * **Resource**: Route to a specific resource
         * **Technology**: Route to all resources of a type (e.g., all PostgreSQL databases)
         * **Any**: Auto-detect protocol and route intelligently
    5. Click **Create Connector**
    6. **Save the API Token** that appears—you'll need it for deployment
  </Tab>

  <Tab title="Terraform">
    ```hcl theme={null}
    resource "formal_connector" "main" {
      name = "production-connector"
    }

    resource "formal_connector_listener" "main" {
      connector_id = formal_connector.main.id
      port = 5432
    }

    resource "formal_connector_listener_rule" "main" {
      connector_listener_id = formal_connector_listener.main.id
      type = "resource"
      resource_id = formal_resource.postgres.id
    }
    ```

    After applying, retrieve the API token:

    ```bash theme={null}
    terraform output connector_api_token
    ```
  </Tab>
</Tabs>

<Note>
  The Connector supports **smart routing**: a single listener on one port can
  handle multiple protocols and automatically route to the correct resource.
</Note>

## Step 4: Deploy the Connector

Now deploy the Connector container in your infrastructure.

### Connector Container Image

Use either registry when you set the Connector image in ECS, Helm, or Docker:

* AWS ECR: `654654333078.dkr.ecr.<region>.amazonaws.com/formalco-prod-connector:<tag>`
* GCP Artifact Registry: `us-docker.pkg.dev/formal-public-assets/formalco-prod-connector/formalco-prod-connector:<tag>`

<Tabs>
  <Tab title="AWS ECS Fargate (Terraform)">
    The recommended deployment for AWS environments.

    ### Quick Start

    1. Clone the Formal Terraform examples:

    ```bash theme={null}
    git clone https://github.com/formalco/terraform-provider-formal.git
    cd terraform-provider-formal/examples/deployments/aws/connector
    ```

    2. Create a `terraform.tfvars` file:

    ```hcl theme={null}
    region             = "us-west-2"
    availability_zones = ["us-west-2a", "us-west-2b"]
    formal_api_key     = "your-formal-api-key"
    formal_org_name    = "your-org-name"
    ```

    3. Deploy:

    ```bash theme={null}
    terraform init
    terraform apply
    ```

    This creates:

    * ECS Fargate service across multiple availability zones
    * Network Load Balancer for high availability
    * CloudWatch logging for monitoring
    * IAM roles and Secrets Manager for secure key storage

    <Tip>
      For production, integrate the Connector into your existing VPC and networking setup instead of using the demo VPC.
    </Tip>
  </Tab>

  <Tab title="Kubernetes (Helm)">
    Universal deployment for any Kubernetes cluster (AWS EKS, GCP GKE, Azure AKS, on-prem).

    <Info>
      The
      [Formal Helm Charts](https://github.com/formalco/helm-charts) repository
      hosts the official Connector and helper charts with current values and
      release notes.
    </Info>

    ### Prerequisites

    If operating outside an AWS or GCP environment, install ECR credentials:

    ```bash theme={null}
    helm repo add formal https://formalco.github.io/helm-charts
    helm show values formal/ecr-cred > ecr-values.yaml
    # Edit ecr-values.yaml with your ECR credentials
    helm install formal-ecr-cred formal/ecr-cred \
      --namespace formal \
      --create-namespace \
      -f ecr-values.yaml
    ```

    ### Deploy the Connector

    1. Get the default values:

    ```bash theme={null}
    helm show values formal/connector > values.yaml
    ```

    2. Edit `values.yaml` and edit these three sections:

    ```yaml theme={null}
    # API key for the Connector configured in Formal Control Plane
    apiKey: ""

    # Set to true only if pulling from AWS ECR outside an AWS or GCP environment to 
    # use the ECR credentials job (ecr-cred Helm chart) to fetch ECR credentials
    pullWithCredentials: false

    # Define the ports of the connector depending on the listeners you've
    # configured in Formal Control Plane
    ports:
      # - name: postgres-listener
      #   port: 5432
    ```

    <Tip>
      You can download a pre-filled `values.yaml` file directly on the Formal console when viewing your Connector details and clicking **Deploy Connector**.
    </Tip>

    3. Install:

    ```bash theme={null}
    helm install formal-connector formal/connector \
      --namespace formal \
      --create-namespace \
      -f values.yaml
    ```

    4. Verify deployment:

    ```bash theme={null}
    kubectl get pods -n formal
    kubectl logs -n formal -l app.kubernetes.io/name=formal-connector
    ```
  </Tab>

  <Tab title="Docker (Local Testing)">
    For local testing and development only.

    ```bash theme={null}
    export FORMAL_CONNECTOR_IMAGE="654654333078.dkr.ecr.us-east-1.amazonaws.com/formalco-prod-connector:latest"
    # Or use GCP Artifact Registry:
    # export FORMAL_CONNECTOR_IMAGE="us-docker.pkg.dev/formal-public-assets/formalco-prod-connector/formalco-prod-connector:latest"

    docker run -d \
      --name formal-connector \
      -p 5432:5432 \
      -v formal-logs:/formal/logs \
      -e FORMAL_CONTROL_PLANE_API_KEY=your-connector-api-token \
      "$FORMAL_CONNECTOR_IMAGE"
    ```

    <Warning>
      This is not recommended for production use. Always deploy with proper orchestration (ECS, Kubernetes) and high availability.
    </Warning>
  </Tab>
</Tabs>

### Network Requirements

Ensure your Connector can reach:

* **Outbound to Formal Control Plane**: `api.joinformal.com` (gRPC)
* **Inbound from clients**: Port(s) configured in your listeners
* **Outbound to resources**: Your database/API endpoints

## Step 5: Configure DNS and TLS (Optional)

For production deployments, add a custom domain and TLS:

<Tabs>
  <Tab title="Web Console">
    1. Navigate to [Connectors](https://app.formal.ai/connectors) in the Formal console
    2. Select your Connector and go to **Hostnames**
    3. Click **Add Hostname**
    4. Enter your custom domain (e.g., `db.yourcompany.com`)
    5. Choose TLS management:
       * **Formal-managed**: Automatic TLS certificates and DNS records (recommended)
       * **Custom certificates**: Upload your own TLS certificate and private key in PEM format
  </Tab>

  <Tab title="Terraform">
    **Option 1: Formal-managed TLS (Recommended and default option)**

    ```hcl theme={null}
    resource "formal_connector_hostname" "main" {
      connector_id = formal_connector.main.id
      hostname     = "db.yourcompany.com"
    }
    ```

    **Option 2: Custom TLS certificates**

    ```hcl theme={null}
    resource "formal_connector_hostname" "main" {
      connector_id = formal_connector.main.id
      hostname     = "db.yourcompany.com"
      certificate  = var.tls_certificate
      private_key  = var.tls_private_key
    }

    variable "tls_certificate" {
      description = "TLS certificate in PEM format"
      type        = string
      sensitive   = true
    }

    variable "tls_private_key" {
      description = "TLS private key in PEM format"
      type        = string
      sensitive   = true
    }
    ```

    **Apply:**

    ```bash theme={null}
    terraform apply
    ```
  </Tab>
</Tabs>

## Step 6: Connect Through Formal

You're ready to connect! Route your database connections through the Connector:

<CodeGroup>
  ```bash PostgreSQL theme={null}
  psql -h your-connector-hostname.com -p 5432 -U your-username -d your-database
  ```

  ```bash MongoDB theme={null}
  mongosh "mongodb://your-connector-hostname.com:27017/your-database"
  ```

  ```bash MySQL theme={null}
  mysql -h your-connector-hostname.com -P 3306 -u your-username -p
  ```
</CodeGroup>

The Connector will:

* ✅ Authenticate your identity
* ✅ Evaluate policies in real-time
* ✅ Log all queries and responses
* ✅ Apply data masking and redaction rules
* ✅ Route to the correct resource

## Next Steps

Now that your first Connector is running, explore these features:

<CardGroup cols={2}>
  <Card title="Write Access Policies" icon="shield-check" href="/docs/guides/policies/introduction">
    Control who can access what with policy-as-code
  </Card>

  <Card title="View Audit Logs" icon="file-lines" href="/docs/guides/observability/logs">
    Monitor all queries and sessions in real-time
  </Card>
</CardGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Connector won't start">
    1. Verify your API token is valid
    2. Check connectivity to `api.joinformal.com`
    3. Review logs in CloudWatch (ECS) or kubectl logs (Kubernetes)
    4. Ensure no port conflicts (port 8080 is reserved for health checks)
  </Accordion>

  {" "}

  <Accordion title="Can't connect to resources">
    1. Verify the resource is reachable from the Connector's network
    2. Check security group rules allow outbound connections
    3. Confirm the resource host and port are correct in Formal console
    4. Test direct connectivity from the Connector container
  </Accordion>

  <Accordion title="Clients can't reach the Connector">
    1. Verify DNS is resolving correctly
    2. Check security group/firewall rules allow inbound traffic
    3. Confirm the listener port matches your client connection string
    4. Test the Connector health endpoint: `http://connector:8080/health`
  </Accordion>
</AccordionGroup>

<Note>
  Need help? Contact support at
  [support@joinformal.com](mailto:support@joinformal.com) or check the [full
  deployment guides](/docs/guides/core-concepts/connectors).
</Note>
