> For the complete documentation index, see [llms.txt](https://docs.p0.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.p0.dev/integrations/resource-integrations/postgresql/installing-an-rds-database.md).

# Installing an RDS instance

## Installing an RDS instance

Follow this guide to install P0 on an AWS-RDS-managed PostgreSQL instance. P0 manages individual PostgreSQL instances, PostgreSQL clusters, and Aurora PostgreSQL clusters in the same manner.

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

Before you begin, ensure you have:

* Admin access to the instance
* IAM authentication enabled on the instance
* AWS permissions that allow you to create IAM policies, and grant those policies to roles
* AWS permissions that allow you to create ECR repositories, add images to that repository, create Lambda functions, and create VPC endpoints and security groups within the instance's VPC
* A P0 [AWS RDS](https://docs.p0.dev/~/changes/198/integrations/resource-integrations/aws/managed-services/aws-rds) integration installed on the VPC that hosts the instance

### Installation <a href="#installation" id="installation"></a>

Follow these steps to install P0 on a PostgreSQL instance or cluster:

**Via the P0 app**

1. Navigate to **Integrations > PostgreSQL** in the P0 app
2. Select the **Access management** component
3. Click **Add instance**
4. Enter a unique identifier for the instance (this can be any value you like)
5. Choose **AWS RDS** hosting
   1. Enter the ARN of the AWS RDS instance
   2. Select the installed P0 AWS RDS VPC integration
6. Click **Next**
7. Run the supplied SQL command on the PostgreSQL instance
8. Run the supplied Terraform to deploy the P0 connector. See [P0 connectors](/readme/connectors.md).
9. Click **Next**
10. If desired, configure the port and default database
11. Click **Finish**

**Via the P0 Terraform provider**

1. Run the following SQL on the PostgreSQL instance to create the admin user. If the user already exists, you can skip the `CREATE USER` statement or ignore the error.

```sql
CREATE USER p0_iam_manager;
GRANT rds_iam TO p0_iam_manager;
GRANT rds_superuser TO p0_iam_manager;
```

2. Ensure you have configured the [P0 Terraform provider](https://registry.terraform.io/providers/p0-security/p0/latest/docs)
3. Use the [`p0_postgres_staged`](https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/postgres_staged) resource to begin integration install

```terraform
resource "p0_postgres_staged" "p0_postgres_cluster" {
  id = "exampleId"
  hosting = {
    type         = "aws-rds"
    instance_arn = <input>
    vpc_id = <input>
  }
}
```

4. Use the [p0-db/aws](https://registry.terraform.io/modules/p0-security/p0-db/aws/latest) and [p0-connector/aws](https://registry.terraform.io/modules/p0-security/p0-connector/aws/latest) modules to set up your AWS environment

```terraform
module "aws_db_connector_install" {
  source  = "p0-security/p0-connector/aws"
  version = "0.6.0"

  aws_role_name = "P0RoleIamManager"
  aws_services  = ["rds"]
  setup_vpc_endpoints = true

  service            = "pg"
  service_subnet_ids = <input>
  vpc_id             = <input>
  connector_arn = <input>
}
      
module "p0_aws_pg_install" {
  source  = "p0-security/p0-db/aws"
  version = "0.3.0"

  rds_instance_arn = <input>

  connector_security_group_id = <input>
  lambda_execution_role_name  = <input>
}
```

5. Use the [`p0_postgres`](https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/postgres) resource to finish integration install

```terraform
resource "p0_postgres" "p0_postgres_cluster" {
  depends_on = [module.p0_aws_pg_install]
  id         = p0_postgres_staged.p0_postgres_cluster.id
  default_db = "postgres"
}
```

6. Run `terraform init` and `terraform apply`

## Enabling SQL statement access (optional)

By default, P0 grants role-based access to the instance. To also let requestors request access to run specific SQL statements, the connector's `p0_iam_manager` role needs grant authority (`WITH GRANT OPTION`) on the tables and schemas you want P0 to manage. If you skip this section and a requestor asks for SQL statement access, P0 can't provision that request.

Set up table access, schema access, both, or neither, depending on what your requestors need to run.

### Table access

To let requestors act on specific tables, first identify the roles that own tables in the schema:

```sql
SELECT tableowner, array_agg(tablename) AS tables
FROM pg_tables
WHERE schemaname = 'public'
GROUP BY tableowner;
```

Then, for each role that owns a table, connect as that role and grant `p0_iam_manager` grant authority on its tables. The `ALTER DEFAULT PRIVILEGES` statement covers tables the role creates later:

```sql
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO p0_iam_manager WITH GRANT OPTION;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO p0_iam_manager WITH GRANT OPTION;
```

### Schema access

To let requestors perform schema-level actions on an existing schema, connect as the role that owns the schema and run the following once per schema you want P0 to manage. It grants `p0_iam_manager` `USAGE` (to reference the schema's tables) and `CREATE` (to create new tables in it), with grant option. Run it again whenever you add a schema:

```sql
GRANT USAGE, CREATE ON SCHEMA public TO p0_iam_manager WITH GRANT OPTION;
```

{% hint style="info" %}
These statements target the `public` schema. To manage a different schema, replace `public` with the schema's name.
{% endhint %}
