# Storage block

Cerbos supports multiple backends for storing policies. Which storage driver to use is defined by the `driver` setting.

## Disk driver

The disk driver is a way to serve the policies from a directory on the filesystem. Any `.yaml`, `.yml` or `.json` files in the directory tree rooted at the given path will be read and parsed as policies.

Static fileset with no change detection

```yaml
storage:
  driver: disk
  disk:
    directory: /etc/cerbos/policies
```

Dynamic fileset with change detection

```yaml
storage:
  driver: disk
  disk:
    directory: /etc/cerbos/policies
    watchForChanges: true
```

### Archive Files

Alternatively, you can opt to archive and/or compress your policies directory into a Zip (`.zip`), Tar (`.tar`) or Gzip file (`.tgz` or `.tar.gz`). The archive is assumed to be laid out like a standard policy directory. It must contain no non-policy YAML files.

Archived fileset using a Zip file

```yaml
storage:
  driver: disk
  disk:
    directory: /etc/cerbos/policies.zip
```

## Blob driver

Cerbos policies can be stored in AWS S3, Google Cloud Storage, or any other S3-compatible storage systems such as [Minio](https://www.minio.io/).

Configuration keys

- `bucket`: Required. A URL specifying the service (e.g. S3, GCS), the storage bucket and any other configuration parameters required by the provider.

- AWS S3: `s3://my-bucket?region=us-west-1`. Must specify region in the URL.

- Google Cloud Storage: `gs://my-bucket`

- S3-compatible (e.g. Minio): `s3://my-bucket?endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true&region=local`. Must specify region in the URL.

- `prefix`: Optional. Look for policies only under this key prefix.

- `workDir`: Optional. Path to the local directory to download the policies to. Defaults to the system cache directory if not specified.

- `updatePollInterval`: Optional. How frequently the blob store should be checked to discover new or updated policies. Defaults to 0 — which disables polling.

- `requestTimeout`: Optional. HTTP request timeout.

- `downloadTimeout`: Optional. Timeout to download all policies from the the storage provider. Must be greater than the `requestTimeout`. Defaults to 60s.

### AWS S3

```yaml
storage:
  driver: "blob"
  blob:
    bucket: "s3://my-bucket-name?region=us-east-2"
    prefix: policies
    workDir: ${HOME}/tmp/cerbos/work
    updatePollInterval: 15s
    downloadTimeout: 30s
    requestTimeout: 10s
```

### Google Cloud Storage

```yaml
storage:
  driver: "blob"
  blob:
    bucket: "gs://my-bucket-name"
    workDir: ${HOME}/tmp/cerbos/work
    updatePollInterval: 10s
```

### Git driver

Git is the preferred method of storing Cerbos policies. The server is smart enough to detect when new commits are made to the git repository.

- Git repositories can be local (`file` protocol) or remote (`ssh` or `https`).

- If no `branch` is specified, the default branch would be the `master` branch.

- If no `subDir` is specified, the entire repository would be scanned for policies (`.yaml`, `.yml` or `.json`).

- The `checkoutDir` is the working directory of the server and must be writable by the server process.

Local git repository

```yaml
storage:
  driver: "git"
  git:
    protocol: file
    url: file://${HOME}/tmp/cerbos/policies
    checkoutDir: ${HOME}/tmp/cerbos/work
    updatePollInterval: 10s
```

Remote git repository accessed over HTTPS

```yaml
storage:
  driver: "git"
  git:
    protocol: https
    url: https://github.com/cerbos/policy-test.git
    branch: main
    subDir: policies
    checkoutDir: ${HOME}/tmp/work/policies
    updatePollInterval: 60s
    operationTimeout: 30s
    https:
      username: cerbos
      password: ${GITHUB_TOKEN}
```

## SQLite3 Driver

The SQLite3 storage backend is one of the dynamic stores that supports adding or updating policies at runtime through the [Admin API](https://docs.cerbos.dev/cerbos/0.32.0/configuration/server#admin-api).

In-memory ephemeral database

```yaml
storage:
  driver: "sqlite3"
  sqlite3:
    dsn: ":memory:"
```

On-disk persistent database

```yaml
storage:
  driver: "sqlite3"
  sqlite3:
    dsn: "file:/tmp/cerbos.sqlite?mode=rwc&cache=shared&_fk=true"
```

## Postgres Driver

The Postgres storage backend is one of the dynamic stores that supports adding or updating policies at runtime through the [Admin API](https://docs.cerbos.dev/cerbos/0.32.0/configuration/server#admin-api).

```yaml
storage:
  driver: "postgres"
  postgres:
    url: "postgres://${PG_USER}:${PG_PASSWORD}@localhost:5432/postgres?sslmode=disable&search_path=cerbos"
```

### Connection pool

Cerbos uses a connection pool when connecting to a database. You can configure the connection pool settings by adding a `connPool` section to the driver configuration.

```yaml
storage:
  driver: "postgres"
  postgres:
    url: "postgres://${PG_USER}:${PG_PASSWORD}@localhost:5432/postgres?sslmode=disable&search_path=cerbos"
    connPool:
      maxLifeTime: 5m
      maxIdleTime: 3m
      maxOpen: 10
      maxIdle: 5
```

### Database object definitions

```sql
CREATE SCHEMA IF NOT EXISTS cerbos;

SET search_path TO cerbos;

CREATE TABLE IF NOT EXISTS policy (
    id bigint NOT NULL PRIMARY KEY,
    kind VARCHAR(128) NOT NULL,
    name VARCHAR(1024) NOT NULL,
    version VARCHAR(128) NOT NULL,
    scope VARCHAR(512),
    description TEXT,
    disabled BOOLEAN default false,
    definition BYTEA
);

CREATE TABLE IF NOT EXISTS policy_revision (
    revision_id SERIAL PRIMARY KEY,
    action VARCHAR(64),
    id BIGINT,
    kind VARCHAR(128),
    name VARCHAR(1024),
    version VARCHAR(128),
    scope VARCHAR(512),
    description TEXT,
    disabled BOOLEAN,
    definition BYTEA,
    update_timestamp TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
```

## MySQL Driver

The MySQL storage backend is one of the dynamic stores that supports adding or updating policies at runtime through the [Admin API](https://docs.cerbos.dev/cerbos/0.32.0/configuration/server#admin-api).

```yaml
storage:
  driver: "mysql"
  mysql:
    dsn: "${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(localhost:3306)/cerbos"
```

### Connection pool

```yaml
storage:
  driver: "mysql"
  mysql:
    dsn: "${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(localhost:3306)/cerbos"
    connPool:
      maxLifeTime: 5m
      maxIdleTime: 3m
      maxOpen: 10
      maxIdle: 5
```

### Database object definitions

```sql
CREATE DATABASE IF NOT EXISTS cerbos CHARACTER SET utf8mb4;

USE cerbos;

CREATE TABLE IF NOT EXISTS policy (
    id BIGINT PRIMARY KEY,
    kind VARCHAR(128) NOT NULL,
    name VARCHAR(1024) NOT NULL,
    version VARCHAR(128) NOT NULL,
    scope VARCHAR(512),
    description TEXT,
    disabled BOOLEAN default false,
    definition BLOB);
```

## Microsoft SQL Server Driver

The SQL Server storage backend is one of the dynamic stores that supports adding or updating policies at runtime through the [Admin API](https://docs.cerbos.dev/cerbos/0.32.0/configuration/server#admin-api).

```yaml
storage:
  driver: "sqlserver"
  sqlserver:
    url: "sqlserver://${SQL_SERVER_USERNAME}:${SQL_SERVER_PASSWORD}@host/instance?database=cerbos&param1=value&param2=value"
```

### Connection pool

```yaml
storage:
  driver: "sqlserver"
  sqlserver:
    url: "sqlserver://${SQL_SERVER_USERNAME}:${SQL_SERVER_PASSWORD}@host/instance?database=cerbos&param1=value&param2=value"
    connPool:
      maxLifeTime: 5m
      maxIdleTime: 3m
      maxOpen: 10
      maxIdle: 5
```

### Database object definitions

```sql
IF SUSER_ID('cerbos_user') IS NULL
CREATE LOGIN cerbos_user WITH PASSWORD = 'ChangeMe(1!!);'

IF NOT EXISTS (
    SELECT [name]
        FROM sys.databases
        WHERE [name] = N'cerbos'
)
CREATE DATABASE cerbos;
USE cerbos;

CREATE TABLE [dbo].[policy] (
    id BIGINT PRIMARY KEY,
    kind VARCHAR(128) NOT NULL,
    name VARCHAR(1024) NOT NULL,
    version VARCHAR(128) NOT NULL,
    scope VARCHAR(512),
    description NVARCHAR(MAX),
    disabled BIT default 'FALSE',
    definition VARBINARY(MAX));
```

## Redundancy

You can provide redundancy by configuring an `overlay` driver, which wraps a `base` and a `fallback` driver. Under normal operation, the base driver will be targeted as usual. However, if the driver consistently errors, the PDP will start targeting the fallback driver instead.
