> For the complete documentation index, see [llms.txt](https://docs.tibero.com/tmaxopensql/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tibero.com/tmaxopensql/tmax-openproxy/tmax-openproxy.md).

# OpenProxy 설정 레퍼런스

> 버전: 1.1.3

***

### 1. 설정 파일 구조

OpenProxy는 TOML 형식의 설정 파일을 사용합니다. 기본 파일 이름은 `openproxy.toml`이며, 실행 시 경로를 지정할 수 있습니다.

설정 파일은 다음 섹션으로 구성됩니다.

<table><thead><tr><th width="287">섹션</th><th>설명</th></tr></thead><tbody><tr><td><code>[general]</code></td><td>전역 설정 (네트워크, 타임아웃, 관리자 계정 등)</td></tr><tr><td><code>[general.etcd]</code></td><td>etcd 연동 설정 (선택)</td></tr><tr><td><code>[general.virtual_router]</code></td><td>VRRP / VIP 설정 (선택)</td></tr><tr><td><code>[general.default_pool]</code></td><td>글로벌 Pool (선택)</td></tr><tr><td><code>[pools.&#x3C;name>]</code></td><td>풀 설정. <code>&#x3C;name></code>은 클라이언트가 접속할 데이터베이스 이름</td></tr><tr><td><code>[pools.&#x3C;name>.users.&#x3C;n>]</code></td><td>풀별 사용자 설정 (<code>&#x3C;n></code>은 0부터 시작하는 인덱스)</td></tr><tr><td><code>[pools.&#x3C;name>.shards.&#x3C;n>]</code></td><td>풀별 서버 연결 설정 (<code>&#x3C;n></code>은 0부터 시작하는 인덱스)</td></tr></tbody></table>

***

### 2. \[general] 섹션

#### 네트워크

<table><thead><tr><th width="132">파라미터</th><th width="141">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>host</code></td><td><code>"0.0.0.0"</code></td><td>수신 IP 주소. <code>0.0.0.0</code>은 모든 인터페이스에서 수신</td></tr><tr><td><code>port</code></td><td><code>5432</code></td><td>수신 포트. PgBouncer와 동일하게 <code>6432</code>를 관례적으로 사용</td></tr></tbody></table>

#### 관리자 계정

<table><thead><tr><th width="194">파라미터</th><th width="124">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>admin_username</code></td><td><code>"admin"</code></td><td>관리자 콘솔 접속 계정</td></tr><tr><td><code>admin_password</code></td><td><code>"admin"</code></td><td>관리자 콘솔 접속 패스워드. 운영 환경에서는 반드시 변경</td></tr></tbody></table>

#### 커넥션 및 타임아웃

<table><thead><tr><th>파라미터</th><th width="140">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>connect_timeout</code></td><td><code>1000</code> (ms)</td><td>서버 연결 수립 대기 시간. 초과 시 해당 서버를 일시 차단</td></tr><tr><td><code>idle_timeout</code></td><td><code>600000</code> (ms)</td><td>유휴 서버 연결 유지 시간. 초과 시 연결 종료</td></tr><tr><td><code>server_lifetime</code></td><td><code>3600000</code> (ms)</td><td>서버 연결 최대 유지 시간. 초과 시 유휴 연결 종료</td></tr><tr><td><code>idle_client_in_transaction_timeout</code></td><td><code>0</code> (ms)</td><td>트랜잭션 내 유휴 클라이언트 대기 시간. <code>0</code>은 무제한</td></tr><tr><td><code>ban_time</code></td><td><code>60</code> (s)</td><td>오류 발생 서버를 일시 차단하는 시간</td></tr><tr><td><code>shutdown_timeout</code></td><td><code>60000</code> (ms)</td><td>종료 시 진행 중인 트랜잭션 완료 대기 시간</td></tr><tr><td><code>healthcheck_timeout</code></td><td><code>1000</code> (ms)</td><td>서버 헬스체크 타임아웃</td></tr><tr><td><code>healthcheck_delay</code></td><td><code>30000</code> (ms)</td><td>헬스체크 주기</td></tr></tbody></table>

#### 성능

<table><thead><tr><th width="215">파라미터</th><th width="80">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>worker_threads</code></td><td><code>4</code></td><td>Tokio 비동기 워커 스레드 수. PostgreSQL과 같은 노드에서 실행하는 경우 CPU 코어 수의 절반 권장</td></tr><tr><td><code>server_round_robin</code></td><td><code>true</code></td><td>서버 선택 시 라운드로빈 사용 여부</td></tr></tbody></table>

#### TLS (클라이언트 연결)

<table><thead><tr><th width="199">파라미터</th><th width="122">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>tls_certificate</code></td><td>없음</td><td>TLS 인증서 파일 경로. 설정 시 클라이언트와의 TLS 연결 활성화</td></tr><tr><td><code>tls_private_key</code></td><td>없음</td><td>TLS 개인 키 파일 경로</td></tr></tbody></table>

#### TLS (서버 연결)

<table><thead><tr><th width="283">파라미터</th><th width="113">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>server_tls</code></td><td><code>false</code></td><td>PostgreSQL 서버와의 TLS 연결 사용 여부</td></tr><tr><td><code>verify_server_certificate</code></td><td><code>false</code></td><td>서버 TLS 인증서 검증 여부</td></tr></tbody></table>

***

### 3. \[general.etcd] 섹션

etcd 연동을 설정합니다. etcd를 사용하지 않는 경우 이 섹션을 설정 파일에서 제거합니다.

<table><thead><tr><th width="191">파라미터</th><th width="112">필수</th><th width="133">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>enabled</code></td><td>예</td><td><code>true</code></td><td>etcd 연동 활성화 여부</td></tr><tr><td><code>endpoints</code></td><td>예</td><td>—</td><td>etcd 엔드포인트 목록. 예: <code>["192.168.1.1:2379", "192.168.1.2:2379"]</code></td></tr><tr><td><code>patroni_scope</code></td><td>예</td><td>—</td><td>Patroni 클러스터 scope. Patroni의 <code>PATRONI_SCOPE</code> 환경변수와 일치해야 함</td></tr><tr><td><code>patroni_namespace</code></td><td>아니오</td><td><code>"/service"</code></td><td>Patroni DCS namespace. Patroni의 <code>PATRONI_NAMESPACE</code> 환경변수와 일치해야 함</td></tr><tr><td><code>username</code></td><td>아니오</td><td>없음</td><td>etcd 인증 사용자 이름</td></tr><tr><td><code>password</code></td><td>아니오</td><td>없음</td><td>etcd 인증 패스워드</td></tr></tbody></table>

```toml
[general.etcd]
enabled = true
endpoints = [
    "192.168.1.1:2379",
    "192.168.1.2:2379",
    "192.168.1.3:2379",
]
patroni_namespace = "/service"
patroni_scope = "postgres-cluster"

# etcd 인증이 설정된 경우
# username = "etcduser"
# password = "etcdpassword"
```

> **⚠️ 주의: `enabled` 변경 시 프로세스 재시작 필요**
>
> `enabled` 값을 변경하면 설정 파일 자동 reload가 변경을 감지하더라도 etcd 연동이 활성화되거나 비활성화되지 않습니다. 반드시 OpenProxy 프로세스를 재시작해야 합니다.

***

### 4. \[general.virtual\_router] 섹션

VRRP 기반 가상 IP(VIP)를 설정합니다. 여러 OpenProxy 인스턴스에 VIP를 적용할 때 사용합니다. VIP가 필요 없는 경우 이 섹션을 설정 파일에서 제거합니다.

<table><thead><tr><th width="204">파라미터</th><th width="121">필수</th><th>설명</th></tr></thead><tbody><tr><td><code>interface</code></td><td>예</td><td>네트워크 인터페이스 이름. 예: <code>"eth0"</code></td></tr><tr><td><code>router_id</code></td><td>예</td><td>VRRP 라우터 ID (1~255). 동일 네트워크 내 다른 VRRP 그룹과 중복되지 않아야 함</td></tr><tr><td><code>priority</code></td><td>예</td><td>VRRP 우선순위 (1~255). 값이 높을수록 VIP를 우선 소유</td></tr><tr><td><code>advert_int</code></td><td>예</td><td>VRRP 광고 패킷 전송 주기 (초)</td></tr><tr><td><code>vip_addresses</code></td><td>예</td><td>가상 IP 목록. CIDR 표기법 사용. 예: <code>["192.168.1.100/24"]</code></td></tr><tr><td><code>pre_promote_script</code></td><td>아니오</td><td>MASTER 승격 직전 실행할 스크립트 경로</td></tr><tr><td><code>pre_demote_script</code></td><td>아니오</td><td>MASTER 강등 직전 실행할 스크립트 경로</td></tr><tr><td><code>unicast_peers</code></td><td>아니오</td><td>유니캐스트 VRRP를 사용하는 경우 상대 노드 IP 목록</td></tr></tbody></table>

```toml
[general.virtual_router]
interface = "eth0"
router_id = 50
priority = 100
advert_int = 1
vip_addresses = ["192.168.1.100/24"]
```

> **참고**: VRRP 기능은 `CAP_NET_ADMIN`, `CAP_NET_RAW` 권한을 필요로 합니다. systemd 서비스 파일의 `AmbientCapabilities` 설정을 확인하십시오.

> **참고**: `virtual_router` 설정은 etcd에 동기화되지 않습니다. 각 노드의 설정 파일에서 개별적으로 관리해야 합니다.

***

### 5. \[general.default\_pool] 섹션

명시적으로 Pool로 등록되지 않은 사용자 이름 - DB 이름 쌍을 가진 사용자 요청을 처리할 글로벌 Connection Pool을 정의합니다. 사용자 이름과 비밀번호를 정의할 수 없으므로 PostgreSQL 에 정의된 사용자 정보를 가져와 클라이언트 요청을 인증하는 auth\_passthrough 방식만을 지원합니다. 정의한 `auth_query` 는 이 Pool의 첫번째Shard에 정의한 데이터베이스에서 실행됩니다.

기타 Users, Shards 설정은 이름이 정의된 Explicit Pool 에서의 설정과 동일합니다. 사용자 정의는 첫번째 사용자 정의를 참조하며 `pool_size`, `statement_timeout` 정의만을 참조합니다.

#### 인증

<table><thead><tr><th width="193">파라미터</th><th width="180">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>auth_query</code></td><td>—</td><td><p>사용자 이름과 패스워드 해시를 가져올 쿼리.</p><p>예: <code>SELECT usename, password FROM pg_shadow WHERE usename = '$1'</code></p></td></tr><tr><td><code>auth_query_user</code></td><td>—</td><td><code>auth_query</code> 를 실행할 사용자 이름</td></tr><tr><td><code>auth_query_password</code></td><td>—</td><td><code>auth_query</code> 를 실행할 사용자 비밀번호</td></tr></tbody></table>

***

### 6. \[pools.\<name>] 섹션

풀을 정의합니다. `<name>`은 클라이언트가 `-d` 옵션으로 지정하는 데이터베이스 이름이 됩니다. 풀은 여러 개 정의할 수 있습니다.

#### 풀링 모드

<table><thead><tr><th width="173">파라미터</th><th width="180">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>pool_mode</code></td><td><code>"transaction"</code></td><td>풀링 모드. <code>"transaction"</code> 또는 <code>"session"</code></td></tr></tbody></table>

#### 인증

<table><thead><tr><th width="182">파라미터</th><th width="150">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>auth_type</code></td><td><code>"md5"</code></td><td>클라이언트 인증 방식. <code>"md5"</code> 또는 <code>"scram-sha-256"</code></td></tr></tbody></table>

#### 읽기/쓰기 분리

<table><thead><tr><th>파라미터</th><th width="99">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>query_parser_enabled</code></td><td><code>false</code></td><td>SQL 파싱을 통한 자동 역할 결정 활성화</td></tr><tr><td><code>query_parser_read_write_splitting</code></td><td><code>false</code></td><td>읽기/쓰기 분리 활성화. <code>query_parser_enabled = true</code> 필요</td></tr><tr><td><code>primary_reads_enabled</code></td><td><code>false</code></td><td>읽기 쿼리 대상에 primary 포함 여부</td></tr><tr><td><code>default_role</code></td><td><code>"any"</code></td><td>역할 결정 불가 시 기본 라우팅 대상. <code>"primary"</code>, <code>"replica"</code>, <code>"any"</code></td></tr></tbody></table>

#### 로드 밸런싱

<table><thead><tr><th width="291">파라미터</th><th width="142">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>load_balancing_mode</code></td><td><code>"random"</code></td><td>로드 밸런싱 방식. <code>"random"</code> 또는 <code>"least_outstanding_connections"</code></td></tr><tr><td><code>prepared_statements_cache_size</code></td><td><code>0</code></td><td>풀 단위의 Prepared Statements를 저장할 Cache 크기. 0인 경우 클라이언트 별로 Prepared Statements를 관리함.</td></tr></tbody></table>

#### 타임아웃 (풀별 오버라이드)

`[general]` 섹션의 값을 풀별로 오버라이드할 수 있습니다. 설정하지 않으면 `[general]`의 값을 따릅니다.

<table><thead><tr><th width="221">파라미터</th><th>설명</th></tr></thead><tbody><tr><td><code>connect_timeout</code></td><td>서버 연결 수립 대기 시간 (ms)</td></tr><tr><td><code>idle_timeout</code></td><td>유휴 서버 연결 유지 시간 (ms)</td></tr><tr><td><code>server_lifetime</code></td><td>서버 연결 최대 유지 시간 (ms)</td></tr></tbody></table>

```toml
[pools.mydb]
pool_mode = "transaction"
auth_type = "scram-sha-256"
query_parser_enabled = true
query_parser_read_write_splitting = true
```

***

### 7. \[pools.\<name>.users.\<n>] 섹션

풀에 접속할 수 있는 사용자를 정의합니다. `<n>`은 0부터 시작합니다. 사용자는 여러 명 정의할 수 있습니다.

<table><thead><tr><th width="203">파라미터</th><th width="124">필수</th><th width="157">기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>username</code></td><td>예</td><td>—</td><td>클라이언트가 사용하는 계정 이름. 지정되지 않은 사용자 이름에 대한 연결을 허용하고자 하는 경우 와일드카드 문자열 <code>*</code> 을 지정한 사용자 정의를 생성합니다.</td></tr><tr><td><code>password</code></td><td>예</td><td>—</td><td>클라이언트 인증 패스워드</td></tr><tr><td><code>pool_size</code></td><td>예</td><td>—</td><td>이 사용자를 위해 유지할 서버 연결 최대 수</td></tr><tr><td><code>server_username</code></td><td>아니오</td><td><code>username</code>과 동일</td><td>PostgreSQL 서버에 접속하는 계정 이름. 클라이언트 계정과 다를 수 있음</td></tr><tr><td><code>server_password</code></td><td>아니오</td><td>—</td><td>PostgreSQL 서버 접속 패스워드</td></tr><tr><td><code>min_pool_size</code></td><td>아니오</td><td><code>0</code></td><td>유지할 서버 연결 최소 수</td></tr><tr><td><code>statement_timeout</code></td><td>아니오</td><td><code>0</code> (ms)</td><td>쿼리 실행 제한 시간. <code>0</code>은 무제한</td></tr><tr><td><code>pool_mode</code></td><td>아니오</td><td>풀의 <code>pool_mode</code></td><td>사용자별 풀링 모드 오버라이드</td></tr></tbody></table>

> **pool\_size 계산 방법**
>
> `(PostgreSQL max_connections - 슈퍼유저 연결 수) / 풀 수`
>
> 예: `max_connections = 100`, 풀 2개인 경우 → `pool_size = 45`

```toml
[pools.mydb.users.0]
username = "appuser"
password = "apppassword"
server_username = "appuser"
server_password = "apppassword"
pool_size = 20
statement_timeout = 0

[pools.mydb.users.1]
username = "*"
pool_size = 10
statement_timeout = 0
```

***

### 8. \[pools.\<name>.shards.\<n>] 섹션 — 서버 연결 설정

OpenProxy가 연결할 PostgreSQL 서버 목록을 정의합니다. `<n>`은 0부터 시작합니다. 샤딩을 사용하지 않는 일반 환경에서는 `shards.0` 하나만 정의합니다.

<table><thead><tr><th width="180">파라미터</th><th width="127">필수</th><th>설명</th></tr></thead><tbody><tr><td><code>servers</code></td><td>예</td><td>PostgreSQL 서버 목록. 각 항목은 <code>["호스트", 포트, "역할"]</code> 형식</td></tr><tr><td><code>database</code></td><td>예</td><td>접속할 PostgreSQL 데이터베이스 이름</td></tr><tr><td><code>use_patroni</code></td><td>아니오</td><td>Patroni 연동 활성화 여부. <code>true</code>로 설정하면 역할을 Patroni가 관리</td></tr><tr><td><code>patroni_port</code></td><td>아니오</td><td>Patroni REST API 포트. 기본값: <code>8008</code></td></tr></tbody></table>

**servers 역할 값**

<table><thead><tr><th width="217">값</th><th>설명</th></tr></thead><tbody><tr><td><code>"primary"</code></td><td>쓰기 서버로 고정</td></tr><tr><td><code>"replica"</code></td><td>읽기 서버로 고정</td></tr><tr><td><code>"Auto"</code></td><td>Patroni 연동 시 사용. Patroni가 역할을 자동으로 결정</td></tr></tbody></table>

**Patroni 연동 없이 직접 역할 지정**

```toml
[pools.mydb.shards.0]
servers = [
    ["192.168.1.10", 5432, "primary"],
    ["192.168.1.11", 5432, "replica"],
    ["192.168.1.12", 5432, "replica"],
]
database = "mydb"
```

**Patroni 연동 (역할 자동 감지)**

```toml
[pools.mydb.shards.0]
servers = [
    ["192.168.1.10", 5432, "Auto"],
    ["192.168.1.11", 5432, "Auto"],
    ["192.168.1.12", 5432, "Auto"],
]
database = "mydb"
use_patroni = true
```

***

### 9. 설정 예시

#### 파일 단독 모드 (standalone)

읽기/쓰기 분리 없이 단일 primary에만 연결하는 가장 단순한 구성입니다.

```toml
[general]
host = "0.0.0.0"
port = 6432
admin_username = "openproxy_admin"
admin_password = "adminpassword"

[pools.mydb]
pool_mode = "transaction"
auth_type = "scram-sha-256"

[pools.mydb.users.0]
username = "appuser"
password = "apppassword"
server_username = "appuser"
server_password = "apppassword"
pool_size = 20

[pools.mydb.shards.0]
servers = [
    ["192.168.1.10", 5432, "primary"],
]
database = "mydb"
```

#### etcd 연동 모드 (HA)

Patroni HA 클러스터와 연동하여 읽기/쓰기 분리 및 자동 Failover를 사용하는 구성입니다.

```toml
[general]
host = "0.0.0.0"
port = 6432
admin_username = "openproxy_admin"
admin_password = "adminpassword"
worker_threads = 4

[general.etcd]
enabled = true
endpoints = [
    "192.168.1.1:2379",
    "192.168.1.2:2379",
    "192.168.1.3:2379",
]
patroni_namespace = "/service"
patroni_scope = "postgres-cluster"

# VRRP를 사용하는 경우 활성화
# [general.virtual_router]
# interface = "eth0"
# router_id = 50
# priority = 100
# advert_int = 1
# vip_addresses = ["192.168.1.100/24"]

[pools.mydb]
pool_mode = "transaction"
auth_type = "scram-sha-256"
query_parser_enabled = true
query_parser_read_write_splitting = true

[pools.mydb.users.0]
username = "appuser"
password = "apppassword"
server_username = "appuser"
server_password = "apppassword"
pool_size = 20

[pools.mydb.shards.0]
servers = [
    ["192.168.1.10", 5432, "Auto"],
    ["192.168.1.11", 5432, "Auto"],
    ["192.168.1.12", 5432, "Auto"],
]
database = "mydb"
use_patroni = true
```

#### Global Pool 예시

`[pools.{pool_name}]` 형태로 정의되지 않은 사용자 요청을 처리할 Global 레벨의 Default Pool을 정의하는 예시입니다. Default Pool의 경우 임의 사용자에 대한 비밀번호를 설정할 수 없어 인증을 PostgreSQL로 위임하므로 `auth_query` 관련 설정이 반드시 필요합니다.

또한 `scram-sha-256` 타입 인증을 사용하면서 `auth_query` 를 함께 사용하는 경우는 OpenProxy에서 PostgreSQL로 접속하기 위한 패스워드를 알 수 없으므로 PostgreSQL 로의 연결이 반드시 `trust` 레벨로 설정되어야 합니다.

```toml
[general.default_pool]
pool_mode = "transaction"

## 기타 Pool General 설정
auth_type = "scram-sha-256"
auth_query = "SELECT usename, passwd FROM pg_shadow WHERE usename = '$1'"
auth_query_user = "opensql"
auth_query_password = "opensql"

[general.default.pool.users.0]
## 이 값은 실제로 참조되지 않습니다. 클라이언트의 username을 참조하여 DB 연결을 생성합니다.
username = "*"
pool_size = 20
statement_timeout = 0

[general.default_pool.shards.0]
servers = [
    [ "pg-1", 5432, "auto" ],
    [ "pg-2", 5432, "auto" ]
]
## auth_query를 실행할 때만 참조되며 클라이언트 연결 시에는 실제로 참조되지 않습니다.
## 클라이언트의 DB name을 참조하여 DB 연결을 생성합니다.
database = "postgres"
use_patroni = true

```

#### Wildcard User 예시

정의된 Pool 밑에 모든 사용자 요청을 처리할 Wildcard `*` 사용자를 생성하는 예시입니다. 마찬가지로 `auth_query` 정의가 필요하며 해당 쿼리는 첫번째 `shards` 의 데이터베이스에서 실행됩니다.

또한 `scram-sha-256` 타입 인증을 사용하면서 `auth_query` 를 함께 사용하는 경우는 OpenProxy에서 PostgreSQL로 접속하기 위한 패스워드를 알 수 없으므로 PostgreSQL 로의 연결이 반드시 `trust` 레벨로 설정되어야 합니다.

```toml
[pools.mydb]
## 기존 Pool 정의
auth_type = "scram-sha-256"
auth_query = "SELECT usename, passwd FROM pg_shadow WHERE usename = '$1'"
auth_query_user = "opensql"
auth_query_password = "opensql"

[pools.mydb.users.0]
username = "*"
pool_size = 35
statement_timeout = 0
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.tibero.com/tmaxopensql/tmax-openproxy/tmax-openproxy.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
