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

# 배포

> AgentEye 배포 문서.

이 가이드는 프로덕션 환경에서 AgentEye 서버와 대시보드를 배포하는 방법을 다룹니다.

***

## 아키텍처 개요

```
  [ AI agent machines ]                  [ Your infrastructure ]

    Python SDK
       |  writes JSONL                       +----------------------+
       v                                +--->| PostgreSQL 15+       |
 agenteye-collector --HTTP--+           |    | (relational store)   |
                            |           |    +----------------------+
                            v           |
                       +--------+       |    +----------------------+
                       | Server |<------+--->| ClickHouse 24+       |
                       +--------+       |    | (events / analytics) |
                            ^           |    +----------------------+
                        API |           |
                            |           |    +----------------------+
                      +-----------+     +- - >| Redis 7+ (optional) |
                      | Dashboard |           +----------------------+
                      +-----------+
```

* **Server**: Rust HTTP 서비스. 이벤트 배치를 수신하고 ClickHouse에 기록하며 PostgreSQL에서 관계형 상태를 유지합니다.
* **Dashboard**: Next.js 웹 앱. 서버 API를 통해서만 읽기/쓰기를 수행합니다.
* **agenteye-collector**: 서버 호스트가 아닌 에이전트 머신에 배포됩니다.
* **Postgres 15+**: 필수 항목입니다. (멀티테넌트 릴리스에서 14에서 상향; org 멤버십 스키마가 Postgres 15+ 전용인 컬럼 목록 `ON DELETE SET NULL` 외래 키를 사용합니다. 이 버전 배포 전에 Postgres를 업그레이드하세요.) OLTP 상태를 저장합니다: `api_keys`, `users`, `sessions`, `evaluation_jobs`(큐), `dashboards`, `saved_queries`, `otp_codes`, 그리고 멀티테넌트 테이블 `orgs`, `org_memberships`, `org_settings`.
* **ClickHouse 24+**: 필수 항목입니다. 수집된 모든 이벤트의 분석 저장소입니다. 엔진: `ReplacingMergeTree`, 월별 파티션, `(session_id, ts, dedup_key)` 순으로 정렬됩니다. 서버는 `CLICKHOUSE_URL`을 통해 연결합니다. 번들로 제공되는 `deploy/base/clickhouse/`에는 성능 최적화된 단일 노드 구성이 포함됩니다. **멀티테넌트 요구사항:** 번들 구성은 SQL 액세스 관리와 `users_without_row_policies_can_read_rows=false`를 활성화하여 서버가 조직마다 읽기 전용 ClickHouse 사용자와 행 정책을 생성할 수 있도록 합니다(SQL 에디터 및 AI 에이전트의 엔진 수준 격리 경계). 자체 ClickHouse 구성을 사용하는 경우 이 설정을 가져오세요(`deploy/base/clickhouse/configmap.yaml` 참조).
* **Redis 7+**: *선택적* 공유 캐시 + 속도 제한 백엔드입니다. 서버와 대시보드 모두 `REDIS_URL`을 통해 연결합니다. 없는 경우 두 서비스 모두 Postgres 전용 경로로 정상 저하됩니다. 아래 **Redis (선택적 캐시)** 섹션을 참조하세요.

***

## 서버

### 이미지 가져오기

```bash theme={null}
echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin
docker pull ghcr.io/agenteye-enterprise/server:beta-latest
```

> 현재 빌드는 `beta-latest`로 게시됩니다. `latest`는 안정 릴리스에만 할당됩니다. 프로덕션에서는 특정 `:v<version>` 태그를 지정하세요. [사용 가능한 이미지 태그](#available-image-tags)를 참조하세요.

### 환경 변수

| 변수                                            | 필수 여부                       | 기본값                  | 설명                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| --------------------------------------------- | --------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DATABASE_URL`                                | 예                           | 없음                   | Postgres DSN. `postgres://` 스킴을 사용하는 표준 libpq 연결 문자열 형식. `?sslmode=require` 및 기타 libpq 파라미터를 지원합니다. 비밀번호에 `/`, `+`, `=`가 포함되면 안 됩니다. URL 안전 비밀번호 생성에는 `openssl rand -hex`를 사용하세요.                                                                                                                                                                                                                                                                   |
| `ADMIN_KEY`                                   | 아니오                         | 없음                   | 부트스트랩 관리자 API 키. 시작 시마다 모든 권한으로 upsert됩니다. 값을 변경하고 재시작하면 교체됩니다.                                                                                                                                                                                                                                                                                                                                                                                     |
| `LISTEN_ADDR`                                 | 아니오                         | `0.0.0.0:8080`       | 바인딩할 TCP 주소                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `MAX_BODY_BYTES`                              | 아니오                         | `134217728` (128 MB) | 최대 요청 본문 크기                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `ADMIN_EMAIL`                                 | 아니오                         | 없음                   | 부트스트랩 관리자 사용자 이메일. 시작 시마다 모든 권한으로 upsert되며 보호됨으로 표시됩니다: 대시보드/API를 통해 비활성화하거나 권한을 수정할 수 없습니다. 부트스트랩 관리자를 교체하려면 `ADMIN_EMAIL`을 변경하고 재시작하세요. 새 이메일이 보호됨으로 upsert되며, 이전 이메일은 데이터베이스에서 수동으로 초기화할 때까지 보호 상태를 유지합니다.                                                                                                                                                                                                                                       |
| `ALLOWED_EMAILS`                              | 아니오                         | 없음 (모두 차단)           | 사용자 생성 및 로그인이 허용된 이메일의 쉼표 구분 목록. 정확한 주소(`user@example.com`)와 도메인 와일드카드(`*@example.com`)를 지원합니다. 설정하지 않으면 사용자를 생성하거나 로그인할 수 없습니다. **첫 번째 부팅 시드 전용**: 첫 번째 부팅 시 기본 org의 허용 목록을 시드합니다. 이후에는 각 org의 [`/<org>/settings`](#operational-settings) 페이지가 신뢰 소스가 되며, 이 환경 변수를 변경해도 효과가 없습니다.                                                                                                                                                                  |
| `SMTP_HOST`                                   | 아니오                         | 없음                   | OTP 이메일 발송을 위한 SMTP 서버 호스트명. 설정하지 않으면 OTP 코드가 stdout에 로깅됩니다.                                                                                                                                                                                                                                                                                                                                                                                        |
| `SMTP_PORT`                                   | 아니오                         | `587`                | SMTP 서버 포트                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `SMTP_USERNAME`                               | 아니오                         | 없음                   | SMTP 인증 사용자명                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `SMTP_PASSWORD`                               | 아니오                         | 없음                   | SMTP 인증 비밀번호                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `SMTP_FROM`                                   | 아니오                         | 없음                   | OTP 이메일의 발신자 이메일 주소                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `SMTP_TLS`                                    | 아니오                         | STARTTLS             | 명시적으로 비활성화하지 않으면 STARTTLS가 사용됩니다: `false` 또는 `0`은 평문(TLS 없음)으로 전송하며, 설정하지 않은 경우를 포함한 다른 모든 값은 STARTTLS를 활성화합니다.                                                                                                                                                                                                                                                                                                                                     |
| `DASHBOARD_URL`                               | 아니오                         | 내장 기본값               | OTP 이메일 매직 링크와 알림의 인시던트 매직 링크를 구성하는 데 사용되는 대시보드 오리진. 설정하지 않으면 내장 기본값으로 폴백하며(OTP만의 경우 대시보드에서 파생된 요청 오리진으로 먼저 폴백). 이메일과 Slack/인시던트 링크가 모두 대시보드를 가리키도록 스플릿 도메인 설정에서 사용하세요. 아래 **이메일 매직 링크 URL** 참조. 대부분의 운영자는 설정할 필요가 없습니다.                                                                                                                                                                                                                            |
| `SESSION_TTL_SECS`                            | 아니오                         | `86400` (24시간)       | 대시보드 세션 유지 시간(초). **첫 번째 부팅 시드 전용**: 첫 번째 배포 후 [`/<org>/settings`](#operational-settings)에서 org별로 편집하세요.                                                                                                                                                                                                                                                                                                                                            |
| `OTP_TTL_SECS`                                | 아니오                         | `600` (10분)          | OTP 코드 유효 기간(초). **첫 번째 부팅 시드 전용**: 첫 번째 배포 후 [`/<org>/settings`](#operational-settings)에서 org별로 편집하세요.                                                                                                                                                                                                                                                                                                                                             |
| `REDIS_URL`                                   | 아니오                         | 없음                   | 선택적 공유 캐시 + 속도 제한 백엔드, 예: `redis://redis:6379/0`. 설정 시 서버는 인증된 API 키 조회, 대시보드의 `/models` 집계, 세션 목록, env 목록 패싯을 캐시합니다. OTP 요청 속도 제한도 Postgres COUNT 대신 Redis INCR로 이동합니다. 설정하지 않거나 연결할 수 없는 경우 서버는 캐시 없이 실행됩니다(OTP 제한은 Postgres로 폴백하고 다른 모든 캐시 호출은 신뢰 소스로 폴백). 아래 **Redis (선택적 캐시)** 참조.                                                                                                                                                             |
| `CLICKHOUSE_URL`                              | **예**                       | 없음                   | ClickHouse 인스턴스의 기본 URL, 예: `http://clickhouse:8123`. 서버는 시작 시 이 데이터베이스에 이벤트 스키마를 적용하며, ClickHouse에 연결할 수 없으면 부팅을 거부합니다. 아래 **ClickHouse (필수 분석 저장소)** 참조.                                                                                                                                                                                                                                                                                          |
| `CLICKHOUSE_DATABASE`                         | 아니오                         | `agenteye`           | ClickHouse 데이터베이스(스키마) 이름. 존재하지 않으면 서버가 시작 시 생성합니다.                                                                                                                                                                                                                                                                                                                                                                                                 |
| `ORG_CH_SECRET`                               | 아니오(단일 테넌트) / **예(멀티 org)** | 개발 기본값               | 각 조직의 테넌트별 ClickHouse 비밀번호를 파생하는 HMAC 키. SQL 에디터 및 AI 에이전트의 `run_query`는 org의 자체 읽기 전용 ClickHouse 사용자로 실행되며, 행 정책이 엔진에서 테넌트 격리를 적용합니다. 단일 테넌트 배포는 내장 개발 기본값으로도 정상 부팅됩니다. **두 번째 org를 프로비저닝하기 전에 강력하고 안정적인 값을 반드시 설정해야 합니다.** `agenteye-orgctl org create` CLI는 내장 개발 기본값에서 실행을 거부합니다. 교체하면 다음 시작 시 부팅 시간 조정이 자동으로 복구할 때까지 모든 org의 ClickHouse 사용자가 고아 상태가 됩니다. 복제본 전체에서 비밀로 유지하고 변경하지 마세요. org 프로비저닝 자체는 운영자 전용입니다. 아래 **Organizations (멀티테넌시)** 참조. |
| `DEFAULT_ORG_NAME`                            | 아니오                         | `Default`            | 내장 기본 org에 시드되는 표시 이름. **첫 번째 부팅 시드 전용**, org가 새로 마이그레이션된 일반 ID를 유지하는 동안에만 시작 시 적용되고 이후 무시됩니다. org를 이름 변경(`agenteye-orgctl org rename`)하면 그것이 권위 있는 값이 되고 이 환경 변수는 효과가 없습니다.                                                                                                                                                                                                                                                                        |
| `DEFAULT_ORG_SLUG`                            | 아니오                         | `default`            | 내장 기본 org의 URL 슬러그, 대시보드 경로(`/<slug>/…`). `DEFAULT_ORG_NAME`과 동일한 첫 번째 부팅 전용/초기 상태 전용 의미론. 단일 내부 하이픈을 포함한 1-40자의 소문자 영숫자여야 하며 [예약어](#organizations-multi-tenancy)가 아니어야 합니다. 잘못된 값은 무시됩니다(org는 `default`를 유지). 사후 배포 CLI 단계 없이 단일 테넌트 설치가 `/default` 대신 `/acme`로 표시되도록 할 수 있습니다.                                                                                                                                                                    |
| `RUST_LOG`                                    | 아니오                         | `info`               | 로그 상세도(`debug`, `warn`, `error`, `agenteye_server=trace`)                                                                                                                                                                                                                                                                                                                                                                                           |
| `EVALUATOR_ENDPOINT`                          | 아니오                         | 없음                   | 평가자 서비스의 기본 URL(예: `http://evaluator:9000`). 설정하지 않으면 전체 평가 파이프라인이 no-op가 됩니다. 큐 행이 기록되지 않고 워커가 실행되지 않습니다. [평가 스위트](/ko/agenteye/evaluation-suite) 참조.                                                                                                                                                                                                                                                                                              |
| `EVALUATOR_TOKEN`                             | 아니오                         | 없음                   | 평가자에게 `Authorization: Bearer <token>`으로 전송됩니다. **평가자 서비스에 구성된 것과 동일한 값이어야 합니다.** 평가자가 토큰 없이 구성된 경우에만 선택 사항입니다.                                                                                                                                                                                                                                                                                                                                      |
| `EVALUATOR_WORKERS`                           | 아니오                         | `2`                  | 동시성: 평가를 디스패치하는 서버 인스턴스당 워커 태스크 수. 수평 확장된 여러 서버에서 안전하게 실행할 수 있습니다.                                                                                                                                                                                                                                                                                                                                                                                  |
| `EVALUATOR_CLAIM_BATCH`                       | 아니오                         | `4`                  | 단일 워커가 틱당 요청하는 최대 평가 수. 배치는 **동시에** 디스패치되므로 평가자 엔드포인트의 총 동시성은 `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`입니다.                                                                                                                                                                                                                                                                                                                                       |
| `EVALUATOR_POLL_IDLE_SECS`                    | 아니오                         | `2`                  | 대기 중인 항목이 없을 때 워커가 디스패치 시도 사이에 대기하는 시간.                                                                                                                                                                                                                                                                                                                                                                                                             |
| `EVALUATOR_POLLING_INTERVAL_SECS`             | 아니오                         | `10`                 | 평가자가 응답별 `next_poll_secs`를 반환하지 않고 `GET /config`에서 `default_poll_interval_secs`도 알리지 않을 때 `GET /evaluate/{id}` 폴링의 최종 폴백 주기(초).                                                                                                                                                                                                                                                                                                                     |
| `EVALUATOR_REQUEST_TIMEOUT_MS`                | 아니오                         | `30000`              | 평가자에 대한 HTTP 요청별 타임아웃(밀리초).                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `EVALUATOR_MAX_ATTEMPTS`                      | 아니오                         | `5`                  | 이 횟수만큼 실패하면 평가가 최종 `error`(또는 실패가 요청 타임아웃이었으면 `timeout`)로 기록됩니다.                                                                                                                                                                                                                                                                                                                                                                                    |
| `EVALUATOR_CONFIG_REFRESH_SECS`               | 아니오                         | `300` (5분)           | 서버가 평가자에서 `GET /config`를 다시 가져오는 빈도.                                                                                                                                                                                                                                                                                                                                                                                                                |
| `EVALUATOR_MAX_POLL_DURATION_SECS`            | 아니오                         | `3600` (1시간)         | 세션이 폴링 큐에 남아 있을 수 있는 최대 벽시계 시간. 이를 초과하면 AgentEye가 `timeout`으로 종료합니다. 평가자가 영구적으로 `pending`을 반환하는 경우를 방지합니다.                                                                                                                                                                                                                                                                                                                                          |
| `ALERT_WORKERS`                               | 아니오                         | `1`                  | 동시성: 알림 규칙을 평가하는 서버 인스턴스당 워커 태스크 수. [알림](/ko/agenteye/alerts) 참조.                                                                                                                                                                                                                                                                                                                                                                                   |
| `ALERT_CLAIM_BATCH`                           | 아니오                         | `16`                 | 단일 워커가 틱당 요청하는 최대 알림 수.                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `ALERT_POLL_IDLE_SECS`                        | 아니오                         | `5`                  | 큐가 비었을 때 알림 워커가 대기하는 시간.                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `ALERT_REQUEST_TIMEOUT_MS`                    | 아니오                         | `15000`              | 트리거 평가별 타임아웃(ClickHouse 쿼리 + 아웃바운드 채널 HTTP).                                                                                                                                                                                                                                                                                                                                                                                                        |
| `ALERT_MAX_ATTEMPTS`                          | 아니오                         | `5`                  | 지수 백오프 대신 정상 주기로 알림이 재예약되기 전 연속 일시적 실패 횟수.                                                                                                                                                                                                                                                                                                                                                                                                          |
| `AUDIT_WORKERS`                               | 아니오                         | `1`                  | 동시성: 감사를 실행하는 서버 인스턴스당 워커 태스크 수. [감사](/ko/agenteye/audits) 참조.                                                                                                                                                                                                                                                                                                                                                                                      |
| `AUDIT_CLAIM_BATCH`                           | 아니오                         | `1`                  | 단일 워커가 틱당 요청하는 최대 감사 수. 에이전틱 조사는 하나의 긴 루프이므로 기본값은 1입니다.                                                                                                                                                                                                                                                                                                                                                                                             |
| `AUDIT_POLL_IDLE_SECS`                        | 아니오                         | `30`                 | 예정된 감사가 없을 때 감사 워커가 대기하는 시간.                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `AUDIT_REQUEST_TIMEOUT_MS`                    | 아니오                         | `30000`              | ClickHouse에 대한 정책 쿼리별 타임아웃(밀리초).                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `AUDIT_LLM_TIMEOUT_MS`                        | 아니오                         | `1440000`            | AI 어시스턴트 서비스에 대한 에이전틱 조사 호출 타임아웃. 전체 에이전트 루프는 수 분 동안 실행됩니다. 에이전트가 부분 결과를 반환하기 전에 서버가 포기하지 않도록 에이전트 자체의 `AGENTEYE_AUDIT_TIMEOUT_MS`보다 높게 유지하세요.                                                                                                                                                                                                                                                                                                      |
| `AUDIT_MAX_ATTEMPTS`                          | 아니오                         | `5`                  | 지수 백오프 대신 정상 주기로 감사가 재예약되기 전 연속 일시적 실패 횟수.                                                                                                                                                                                                                                                                                                                                                                                                          |
| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | 아니오                         | —                    | 감사의 에이전틱 조사는 어시스턴트와 동일한 연결을 재사용하는 AI 어시스턴트 `agent` 서비스를 호출합니다. 따라서 이 두 값을 **서버**에도 설정해야 합니다(번들 매니페스트/컴포즈가 이를 수행). 둘 다 설정 → 감사가 AI 조사를 실행합니다. 둘 중 하나라도 설정되지 않으면 → per-audit `llm_enabled` 플래그와 관계없이 감사가 **정책 전용**(결정론적 SQL 정책 패스만 실행)으로 실행됩니다. 에이전트에도 LLM이 구성되어 있어야 합니다 — [assistant.md](/ko/agenteye/assistant) 참조.                                                                                                                                 |

**AI 어시스턴트 서비스 — 감사 + 샌드박스 설정.** 에이전틱 조사 및 파드 내 Python 샌드박스는 서버가 아닌 **에이전트 서비스**에서 `AGENTEYE_AUDIT_*` 접두사로 튜닝되며, 모두 선택 사항입니다:

| 변수                                                                                                        | 기본값                                        | 의미                                                                |
| --------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------- |
| `AGENTEYE_AUDIT_MAX_STEPS`                                                                                | `200`                                      | 조사당 최대 에이전트 턴 수.                                                  |
| `AGENTEYE_AUDIT_TIMEOUT_MS`                                                                               | `1200000`                                  | 단일 조사의 벽시계 시간(20분). 서버의 `AUDIT_LLM_TIMEOUT_MS`보다 **낮게** 유지해야 합니다. |
| `AGENTEYE_AUDIT_MAX_CONCURRENCY`                                                                          | `1`                                        | 에이전트 파드당 동시 조사 수(채팅 어시스턴트 예산과 별도).                                |
| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | bubblewrap 샌드박스의 스크립트별 제한.                                        |

**샌드박스 플랫폼 요구사항.** 감사 코드 샌드박스는 모델의 Python을 bubblewrap 감옥 내에서 실행하며, 이는 **비권한 사용자 네임스페이스**가 필요합니다. 에이전트 파드는 `clone()` 플래그를 허용해야 합니다 — 에이전트에 `seccompProfile: Unconfined`(k8s) 또는 `security_opt: [seccomp:unconfined]`(컴포즈)를 설정하세요. 노드 커널이 비권한 사용자 네임스페이스를 비활성화하는 경우(예: 일부 GKE COS 이미지), 샌드박스 **사전 점검이 실패하고 감사기는 SQL 전용으로 자동 저하**됩니다 — 오류 없이 에이전트의 `/health`에 `sandbox_available: false`만 표시됩니다.

### 실행

환경에 `DATABASE_URL`을 설정한 다음 컨테이너에 전달하세요:

```bash theme={null}
docker run -d --restart unless-stopped \
  --name agenteye-server \
  -e DATABASE_URL="$DATABASE_URL" \
  -e ADMIN_KEY="$ADMIN_KEY" \
  -p 8080:8080 \
  ghcr.io/agenteye-enterprise/server:beta-latest
```

서버는 시작 시 데이터베이스 마이그레이션을 자동으로 실행합니다. 별도의 마이그레이션 단계가 필요하지 않습니다.

### 헬스 체크

```
GET /health    # 활성 상태 - 프로세스가 시작되면 항상 {"status":"ok"}
GET /ready     # 준비 상태 - Postgres + ClickHouse에 연결 가능하면 200, 아니면 503
```

인증이 필요하지 않습니다. **활성 상태** 프로브에는 `/health`를, **준비 상태**/로드밸런서 프로브에는 `/ready`를 사용하세요. `/ready`는 서버가 제공할 수 없는 필수 종속성(Postgres + ClickHouse)을 확인합니다. 따라서 실행 중이지만 데이터베이스에 연결할 수 없는 서버는 순환에서 제외되고 `NotReady`로 표시됩니다. Redis는 보고되지만 준비 상태를 실패시키지 않습니다. 번들 Kubernetes 매니페스트에서 준비 상태 프로브는 이미 `/ready`를 가리키고 활성 상태는 `/health`를 유지합니다. 전체 내용(Slack에 대한 옵트인 Kubernetes 네이티브 파드 장애 알림 포함)은 [enterprise-docs/health-monitoring.md](/ko/agenteye/health-monitoring)를 참조하세요.

### 이메일 매직 링크 URL

OTP 로그인 이메일에는 원탭 **대시보드 열기** 버튼이 포함됩니다. 클릭하면 `/login?token=<code>&email=<address>`로 이동합니다. 대시보드는 해당 쌍을 세션으로 교환하고 앱으로 리디렉션하며, 수동 코드 재입력이 필요하지 않습니다. 서버는 링크를 구성하는 데 사용할 대시보드 오리진을 세 단계로 확인합니다:

1. **`X-AgentEye-Dashboard-Url` 헤더**: 대시보드의 `/api/auth/otp/request` 프록시가 자체 공개 오리진에서 자동으로 설정합니다. 동일 오리진 배포(서버와 대시보드가 프록시 헤더를 전달하는 하나의 인그레스 뒤에서 호스트를 공유)에서는 **구성이 필요하지 않습니다**.
2. **`DASHBOARD_URL` 환경 변수**: 대시보드가 서버의 OTP 요청 엔드포인트가 보는 것과 다른 오리진에서 접근 가능하거나(`api.example.com` / `app.example.com` 분리), 인그레스가 공개 호스트를 대시보드 파드에 전파하지 않는 경우(그러면 `request.nextUrl.origin`이 `0.0.0.0:3000`과 같은 와일드카드 바인드로 확인됨) 설정하세요. 예: `DASHBOARD_URL=https://app.example.com`.
3. **기본값**: 위 두 가지가 모두 없을 때만 사용되는 `https://app.befailproof.ai`.

헤더 값의 유효성이 검사됩니다: `https://*` 및 루프백(`http://localhost*`, `http://127.0.0.1*`) 오리진만 허용되며, 와일드카드 바인드 주소(`0.0.0.0`, `[::]`)는 `https://` 스킴이 있어도 거부됩니다. 그 외의 것은 2단계로 폴백됩니다.

한 줄 명령으로 실행 중인 클러스터에 설정합니다. 파일이나 kustomize 재빌드가 필요하지 않습니다:

```bash theme={null}
kubectl set env deployment/server -n agenteye \
  DASHBOARD_URL=https://app.example.com
```

이는 롤아웃을 트리거합니다. 새 파드는 첫 번째 요청 시 값을 가져옵니다. 재정의는 Deployment에만 존재한다는 점에 유의하세요. 오버레이에 대해 `kustomize build | kubectl apply`를 이후에 실행하면 오버레이의 `server-env.yaml` 패치에 동일한 환경 변수를 추가하지 않는 한 제거됩니다.

***

## 대시보드

### 이미지 가져오기

```bash theme={null}
docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest
```

### 환경 변수

| 변수                      | 필수 여부 | 기본값    | 설명                                                                                                                                                                                                                                                          |
| ----------------------- | ----- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AGENTEYE_SERVER_URL`   | 예     | 없음     | 서버의 기본 URL, 예: `http://localhost:8080`                                                                                                                                                                                                                      |
| `AGENTEYE_API_KEY`      | 예     | 없음     | 대시보드가 서버에 인증하는 데 사용하는 API 키. 모든 권한이 필요합니다(관리자 키 권장).                                                                                                                                                                                                        |
| `AE_LOG_LEVEL`          | 아니오   | `info` | 서버 측 로그 상세도: `debug`, `info`, `warn`, `error`. 문제 진단 시 업스트림 요청/응답 라인과 세션 유효성 검사 추적을 보려면 `debug`로 설정하세요.                                                                                                                                                     |
| `AE_LOG_JSON`           | 아니오   | 자동     | `1`은 JSON 라인별 출력을 강제합니다. `0`은 사람이 읽을 수 있는 출력을 강제합니다. 설정하지 않으면 `NODE_ENV=production`일 때 JSON이 자동으로 활성화됩니다. 프로덕션에서는 `jq` 또는 로그 집계기로 깔끔하게 파싱할 수 있도록 JSON을 권장합니다.                                                                                               |
| `AE_ANALYTICS_DISABLED` | 아니오   | 없음     | `1`/`true`로 설정하면 대시보드의 익명 제품 사용 텔레메트리가 비활성화됩니다. 아래 [텔레메트리 및 개인정보](#telemetry--privacy)를 참조하세요.                                                                                                                                                              |
| `REDIS_URL`             | 아니오   | 없음     | 선택적 공유 캐시 백엔드, 예: `redis://redis:6379/0`. 설정 시 대시보드는 복제본 간에 `validateSession()` 결과를 캐시하고 레이턴시 집계/env 목록 프록시 경로에 대한 Next.js 페치 캐시를 공유합니다. 엣지 측 OTP 요청 및 확인 속도 제한도 Redis가 있으면 사용합니다(Redis에 연결할 수 없으면 열린 상태로 폴백하며, 서버 측 제한이 보안 백스톱). 아래 **Redis (선택적 캐시)** 참조. |
| `AGENTEYE_AGENT_URL`    | 아니오   | 없음     | 선택적 AI 어시스턴트 `agent` 서비스의 기본 URL, 예: `http://agent:9100`. **설정하지 않으면 어시스턴트가 완전히 숨겨집니다**: 대시보드에 어시스턴트 버블이 표시되지 않습니다. [enterprise-docs/assistant.md](/ko/agenteye/assistant) 참조.                                                                              |
| `AGENTEYE_AGENT_TOKEN`  | 아니오   | 없음     | 대시보드가 `agent` 서비스에 제시하는 공유 시크릿. 에이전트에 구성된 `AGENTEYE_AGENT_TOKEN`과 일치해야 합니다. [enterprise-docs/assistant.md](/ko/agenteye/assistant) 참조.                                                                                                                      |

### 실행

```bash theme={null}
docker run -d --restart unless-stopped \
  --name agenteye-dashboard \
  -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \
  -e AGENTEYE_API_KEY="$ADMIN_KEY" \
  -p 3000:3000 \
  ghcr.io/agenteye-enterprise/dashboard:beta-latest
```

### 텔레메트리 및 개인정보

대시보드는 **익명 제품 사용 분석**을 Exosphere의 분석 서비스(PostHog)로 전송합니다: 어떤 대시보드 페이지가 조회되었는지, API 키 생성 또는 세션 재평가와 같은 몇 가지 UI 동작이 포함됩니다. 이 사용 신호는 어떤 기능을 우선순위에 둘지 결정하는 데 활용됩니다.

* **에이전트, 세션 또는 이벤트 데이터는 절대 인프라 밖으로 나가지 않습니다.** 대시보드 UI 사용만 보고됩니다. 페이지 URL은 전송 전에 식별자가 제거되며, 운영자는 이메일이 아닌 불투명한 내부 ID로만 식별됩니다.
* 텔레메트리는 **기본적으로 활성화**되어 있습니다. 완전히 끄려면 대시보드 컨테이너에 `AE_ANALYTICS_DISABLED=1`을 설정하고 재시작하세요.
* 분석은 대시보드의 `/ingest` 경로로 전송되며, 대시보드가 이를 PostHog(`https://us.i.posthog.com`)로 역방향 프록시합니다. 요청을 퍼스트파티로 유지하면 브라우저 광고 차단기가 이를 차단하지 않습니다. **대시보드 컨테이너**는 PostHog로 아웃바운드 접근이 필요합니다. 차단된 경우 텔레메트리는 조용히 동작하지 않으며 대시보드는 영향을 받지 않습니다.

***

## AI 어시스턴트 (선택 사항)

대시보드 내 AI 어시스턴트를 통해 팀이 에이전트 데이터를 자연어로 질의할 수 있습니다(세션 요약, `/queries` 에디터용 SQL 초안 작성, 저장된 쿼리를 대시보드 타일로 변환). 대시보드를 벗어날 필요가 없습니다. Claude Agents SDK 기반의 별도 내부 `agent` 컨테이너로 실행되며 대시보드만 접근할 수 있고, **LLM 엔드포인트를 구성할 때까지 비활성화 상태**로 유지됩니다.

활성화하려면 `agent` 서비스에 LLM 연결(**Portkey** via `PORTKEY_API_KEY` + 모델 카탈로그 슬러그 `AGENTEYE_AGENT_MODEL=@<slug>/<model>`, 직접 Anthropic via `ANTHROPIC_API_KEY`, 다른 게이트웨이 via `ANTHROPIC_BASE_URL`, 또는 Bedrock/Vertex), **전용** 데이터 키, 대시보드와 일치하는 공유 `AGENTEYE_AGENT_TOKEN`을 설정합니다. 대시보드 사용자에게는 추가로 `agent:use` 권한이 필요합니다.

어시스턴트의 데이터 키는 직접 생성할 필요가 없습니다: 임의의 시크릿을 선택하여 `agent`에는 `AGENTEYE_API_KEY`로, `server`에는 `AGENT_API_KEY`로 설정하면 서버가 시작 시 고정된 권한 세트로 시드합니다. 데이터 접근은 읽기 전용(`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`)이며, 승인이 필요한 저작 범위(`dashboards:write`, `queries:write`, `queries:run`)도 보유하여 사용자를 대신해 저장된 쿼리를 초안 작성, 검증하고 대시보드 타일을 구축할 수 있습니다. 모든 SQL은 여전히 org의 읽기 전용 ClickHouse 역할을 통해 실행되므로, 어시스턴트가 저작할 수 있는 내용이 넓어지는 것이지 접근 가능한 데이터가 넓어지는 것이 아닙니다. 범위는 코드에 고정되어 있으며 구성으로 넓힐 수 없습니다. 해당 키는 보호되어 있으며 API를 통해 비활성화하거나 재생성할 수 없고, 값을 변경하고 재시작하는 방식으로만 교체할 수 있습니다. 어시스턴트에 관리자/대시보드 키를 재사용하지 마세요.

전체 설정, 완전한 환경 변수 참조, 텔레메트리 옵션, 보안 모델은 \*\*[enterprise-docs/assistant.md](/ko/agenteye/assistant)\*\*에 있습니다.

***

## ClickHouse (필수 분석 저장소)

ClickHouse는 높은 이벤트 볼륨에서도 대시보드를 빠르게 유지하며, `/queries` SQL 에디터가 단일 저장소에서 이벤트, 평가, 세션을 조인할 수 있게 합니다. 수집된 모든 이벤트, 모든 최종 평가 결과, 파생된 세션별 집계의 필수 표준 저장소입니다. PostgreSQL은 관계형/가변 상태 테이블(api\_keys, users, otp\_codes, evaluation\_jobs, dashboards, saved\_queries)을 보유하며, 분석 표면은 ClickHouse에 있어 대시보드 롤업과 자체 SQL 쿼리가 크로스 데이터베이스 왕복 없이 네이티브로 스캔하고 조인할 수 있습니다. 서버는 `CLICKHOUSE_URL` 없이 부팅을 거부합니다.

### 스키마

서버 시작 시 세 가지 ClickHouse 객체가 생성됩니다. 모두 멱등적입니다(`CREATE IF NOT EXISTS`):

* **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, `toYYYYMM(ts)`로 파티션됨, `(session_id, ts, dedup_key)` 순 정렬. 중복 삽입(수집기 재시도)은 병합 시 단일 행으로 축소됩니다. 서버는 모든 이벤트에 대해 결정론적 SHA-256 `dedup_key`를 계산하므로 재시도가 안전합니다.
* **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, `toYYYYMM(finished_at)`로 파티션됨, `(session_id, finished_at, dedup_key)` 순 정렬. 평가자 파이프라인이 최종 평가 결과당 한 번 씁니다. `events`와 동일한 중복 제거 키 모델.
* **`agenteye.agent_sessions`**: 물리적 테이블이 아닌 `agenteye.events`에 대한 **VIEW**. 모든 컬럼이 파생됩니다(`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()` 등). 이벤트별 upsert와 별도 백필이 없으며, 뷰는 `events`에 있는 내용을 자동으로 반영합니다.

`analytics.evaluations` / `analytics.sessions`를 참조하는 저장된 쿼리와의 하위 호환성을 위해 서버는 `agenteye.*` 테이블에 대한 뷰가 포함된 `analytics` ClickHouse 데이터베이스도 생성합니다. `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions`가 모두 올바르게 확인됩니다.

### 구성

번들 docker-compose 및 `deploy/base/clickhouse/`는 AgentEye 워크로드에 맞게 최적화된 ClickHouse 서비스를 제공합니다:

* 제공된 기본 오버레이에서 요청 2 GiB / 제한 4 GiB 메모리(소규모 POC/스테이징 노드에 맞게 크기 조정). 프로덕션 고객은 오버레이를 업사이징해야 합니다. 권장 최소 사양은 요청 2c/4Gi, 제한 6c/8Gi입니다. `max_server_memory_usage_to_ram_ratio=0.9`
* 5 GiB 마크 캐시 + 8 GiB 비압축 캐시
* `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2`
* MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000`
* `local_io_method=auto` (지원되는 커널에서 io\_uring)
* `fsync_metadata=0`: 최소 한 번 수집 + ReplacingMergeTree 중복 제거 때문에 허용됨
* 30일 TTL을 가진 `query_log` 활성화. 높은 QPS에서 비용이 많이 드는 `query_thread_log` 제거됨
* 사용자 측 쿼리에 대한 `max_execution_time=30`
* StatefulSet 템플릿에 100 GiB PVC (고객 오버레이는 프로덕션을 위해 빠른 SSD 스토리지 클래스로 재정의해야 함)

### 백업

전체 데이터셋이 매일 밤 단일 복원 가능한 아카이브로 캡처되므로 클러스터 또는 스토리지 손실에서 복구할 수 있습니다. ClickHouse는 일별 `agenteye-backup` CronJob에 의해 자동으로 백업되며, 이는 PostgreSQL과 ClickHouse를 한 번에 덤프합니다. ClickHouse는 HTTP API를 통해 읽힙니다: `agenteye.events`와 `agenteye.evaluations`가 ClickHouse 네이티브 형식으로 덤프되고(뷰와 행 정책은 서버 시작 시 재생성되므로 테이블 데이터가 완전한 그림), Postgres 덤프와 함께 단일 압축 아카이브로 번들되어 객체 스토리지에 업로드됩니다.

대상 버킷과 클라우드 자격증명은 오버레이별로 구성됩니다. 업로드 구성 및 복원 단계는 [enterprise-docs/kubernetes-deployment.md](/ko/agenteye/kubernetes-deployment)의 **백업** 섹션을 참조하세요.

***

## Redis (선택적 캐시)

Redis는 서버와 대시보드에서 사용하는 **선택적** 공유 캐시 + 속도 제한 백엔드입니다. Redis를 배포하고 두 서비스 모두에 `REDIS_URL`을 설정하면:

* **서버**는 인증된 API 키 조회, `/events/environments` + `/evaluations/environments` 목록, `/events/latency_aggregate` 롤업(대시보드가 폴링하는 가장 무거운 쿼리), `/sessions` 목록을 캐시하고, OTP 요청 속도 제한을 Postgres `COUNT(*)`에서 Redis `INCR + EXPIRE`로 전환합니다.
* **대시보드**는 `validateSession()` 결과를 캐시하여 일반적인 페이지 로드에서 발생하는 10-20개의 인증된 API 호출이 모두 하나의 업스트림 세션 확인을 공유합니다. 또한 대시보드 엣지에서 OTP 요청 및 확인을 속도 제한합니다.

**두 서비스 모두 Redis에 연결할 수 없는 경우 정상적으로 저하됩니다.** 모든 캐시 호출은 제한된 타임아웃 내에 `Err`를 반환하고 호출자는 신뢰 소스(서버의 경우 Postgres, 대시보드의 경우 업스트림 Rust 서버)로 폴백합니다. OTP 속도 제한은 서버의 Postgres `COUNT(*)` 경로로 폴백합니다(보안 속성은 유지됨). 대시보드의 엣지 OTP 제한은 열린 상태로 실패하지만 서버 측 제한은 여전히 유지됩니다. Redis가 다운되면 정확성이 아닌 레이턴시가 저하됩니다.

### 구성

docker-compose 번들에는 이미 Redis 서비스가 포함되어 있으며 서버와 대시보드에 `REDIS_URL=redis://redis:6379/0`이 연결되어 있습니다. 외부 Redis를 사용하려면 `REDIS_URL`을 해당 엔드포인트로 설정하고 컴포즈 파일에서 `redis` 서비스를 제거하세요.

### 메모리 + 지속성

번들 Redis 이미지는 `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`로 실행됩니다. AOF 지속성은 캐시가 컨테이너 재시작 후에도 살아남도록 합니다. `everysec`은 마지막 1초의 캐시 쓰기 손실이 무해하므로 올바른 내구성/성능 균형입니다. LRU 축출은 메모리 증가를 제한합니다.

### Redis를 배포하지 않아야 할 때

* 단일 인스턴스 개발/QA 환경. 서버의 인프로세스 캐시만으로도 복제본별 이점의 대부분을 제공합니다. Redis는 단일 인스턴스 설정에서 필요하지 않은 복제본 간 공유를 추가합니다.
* 추가 서비스 운영 비용이 레이턴시 이점보다 큰 에어갭 설치 환경.

***

## Docker Compose (권장)

`docker-compose.yml`은 `agenteye-enterprise/releases` 저장소에서 사용할 수 있습니다. 단일 명령으로 Postgres, 서버, 대시보드를 시작합니다.

```bash theme={null}
GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \
  --repo agenteye-enterprise/releases \
  --pattern 'docker-compose.yml' \
  --dir ./agenteye
cd agenteye
```

**`.env`를 통해 기본값 재정의:**

```
# Use URL-safe passwords (no /, +, or = characters).
# Generate with: openssl rand -hex 24
POSTGRES_PASSWORD=your-db-password
ADMIN_KEY=your-admin-secret

# Dashboard authentication
ADMIN_EMAIL=admin@yourcompany.com
ALLOWED_EMAILS=*@yourcompany.com

# SMTP for OTP emails (omit to log OTP codes to stdout)
# SMTP_HOST=smtp.yourprovider.com
# SMTP_PORT=587
# SMTP_USERNAME=your-smtp-user
# SMTP_PASSWORD=your-smtp-password
# SMTP_FROM=noreply@yourcompany.com

RUST_LOG=info
```

```bash theme={null}
docker compose up -d
```

**중지(데이터 볼륨 유지):**

```bash theme={null}
docker compose down
```

**중지 및 모든 데이터 삭제:**

```bash theme={null}
docker compose down -v
```

***

## 운영 설정

환경 변수로 고정되던 일부 운영 설정은 이제 대시보드의 **`/<org>/settings`** 페이지에서 조직별로 편집할 수 있습니다. 각 org가 자체적으로 구성합니다. 변경 사항은 재시작이나 재배포 없이 수 초 내에 적용됩니다.

| 설정           | 부트스트랩 환경 변수                | 제어 내용                                                                                                                                                                                                                                                 |
| ------------ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 허용된 로그인      | `ALLOWED_EMAILS`           | OTP를 받고 사용자로 추가될 수 있는 이메일(또는 `*@domain.com` 와일드카드)                                                                                                                                                                                                    |
| 기본 사용자 권한    | `DEFAULT_USER_PERMISSIONS` | 관리자가 **+ 새 사용자**를 열 때 미리 선택되는 쉼표 구분 권한 토큰. 각 토큰은 [API 키 권한](/ko/agenteye/api-keys)에 나열된 문자열 중 하나여야 합니다. 기본값은 `standard` 프리셋: 읽기 전용 접근 및 일상적인 온콜 작업(재평가 트리거, 쿼리 실행, 인시던트 확인, 어시스턴트 사용).                                                                |
| 세션 유효 기간     | `SESSION_TTL_SECS`         | 재인증 전 대시보드 로그인 유효 시간. 대시보드는 5초마다 업스트림 세션을 재확인하므로 `/<org>/users`에서의 권한 업데이트는 재로그인 없이 다음 요청에서 해당 사용자에게 적용됩니다.                                                                                                                                           |
| 일회용 코드 유효 기간 | `OTP_TTL_SECS`             | OTP/매직 링크의 사용 가능 시간                                                                                                                                                                                                                                   |
| 알림 채널        | `ALERTS_ENABLED_CHANNELS`  | 알림 디스패처가 사용할 수 있는 채널 종류의 쉼표 구분 목록: `email`, `slack`, `webhook`. 알림별 구성은 여전히 `/<org>/alerts/<id>`에서 작성되지만, 디스패처는 모든 아웃바운드 전달을 이 집합을 통해 필터링합니다. 여기서 비활성화된 채널은 `skipped_disabled` 감사 행으로 단락됩니다. `dashboard` 채널(로컬 감사 삽입)은 항상 허용됩니다. 기본값은 세 가지 모두 활성화입니다. |

### 부트스트랩 작동 방식

설정은 `org_settings`에 조직별로 저장됩니다. 첫 번째 부팅 시 서버는 일치하는 환경 변수(환경 변수가 설정되지 않은 경우 적절한 기본값)에서 기본 org의 누락된 행을 시드합니다. 이후 **저장된 값이 신뢰 소스가 되고 환경 변수는 무시됩니다**. 이후 재시작 시 환경 변수를 변경해도 라이브 org의 값에 영향을 미치지 않으며, 추가 org는 기본값에서 시작하여 자체적으로 구성합니다.

즉:

* 새 배포의 경우 위에 표시된 대로 환경 변수를 설정하면 기본 org가 첫 번째 부팅 시 읽습니다.
* 나중에 값을 변경하려면 대시보드에 로그인하고 `/<org>/settings`에서 편집하세요. 변경 사항은 수 초 내에 모든 서버 복제본에 적용됩니다. 재시작이 필요하지 않습니다.
* 시작 로그 라인에 시드된 것과 이미 존재하는 것이 기록되므로 부트스트랩이 적용되었는지 확인할 수 있습니다:

  ```text theme={null}
  INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true
  ```

#### 조직 간 로그인 의미론

세션과 OTP는 단일 org가 아닌 사용자에게 전역적이므로, 로그인 시 org별 설정을 조율하는 두 가지 규칙이 있습니다:

* **세션/OTP 유효 기간**: 사용자가 속한 org 중 가장 엄격한(가장 짧은) 유효 기간이 적용됩니다.
* **허용된 로그인**: 게이트는 모든 org의 허용 목록과 org 멤버십을 OR로 결합합니다. 이메일이 어느 org의 허용 목록에든 허용되거나 이미 어느 org의 멤버이면 OTP를 요청할 수 있습니다.

### 권한

`/<org>/settings` 페이지 접근은 두 가지 권한으로 제한됩니다:

* `settings:read`: 페이지와 현재 값을 볼 수 있습니다.
* `settings:write`: 변경 사항을 저장할 수 있습니다.

부트스트랩 관리자 사용자(`ADMIN_EMAIL`에서 시드됨)는 다른 모든 권한과 함께 자동으로 둘 다 부여받습니다. 필요에 따라 `/<org>/users`에서 다른 사용자에게 부여하세요.

***

## Organizations (멀티테넌시)

단일 배포가 여러 격리된 **조직**(테넌트)을 제공할 수 있습니다. 모든 데이터 행은 정확히 하나의 org에 속하며 격리는 데이터베이스 엔진에서 적용됩니다. 단일 테넌트 설치에서는 아무것도 필요하지 않습니다. 모든 데이터는 내장된 `default` org에 있습니다. (첫
