셀프 호스팅 Chorus 운영하기
이 가이드는 배포를 마친 셀프 호스팅 Chorus의 운영을 다룹니다. 첫 사용자 로그인, 인증 구성, 안전한 업그레이드, 그리고 HTTPS 환경에서 중요한 쿠키와 리버스 프록시 설정을 설명합니다. 배포를 구축하는 방법은 프로덕션 배포 또는 Docker로 배포를 참고하세요.
첫 접근을 부트스트랩하기
섹션 제목: “첫 접근을 부트스트랩하기”새 배포에서는 ID 제공자 없이 관리형 로컬 계정을 사용할 수 있습니다. 아래 슈퍼 관리자 자격 증명을 설정한 뒤 로컬 계정 워크스페이스를 만들고 첫 워크스페이스 관리자를 초대하세요. 이는 선택적인 Default Auth 데모·부트스트랩 경로와 다릅니다. 기존 경로를 활성화하려면 두 변수를 모두 설정합니다.
DEFAULT_USER='admin@example.com' \DEFAULT_PASSWORD='choose-a-strong-password'두 변수를 모두 설정하면 지정한 이메일로 Default Auth를 사용할 수 있습니다. 첫 로그인에 성공하면 필요한 사용자와 워크스페이스가 생성되지만 관리형 로컬 계정이나 로컬 워크스페이스 관리자 역할은 생성되지 않습니다. 로그인은 이메일 또는 사용자 이름 입력으로 시작하며, 여러 역할이나 워크스페이스가 일치하면 원하는 항목을 선택합니다.
내장 로그인 끄기
섹션 제목: “내장 로그인 끄기”관리형 로컬 계정 또는 OIDC 접근과 슈퍼 관리자 로그인을 확인한 뒤 앱 환경에서 DEFAULT_USER와 DEFAULT_PASSWORD를 제거하고 앱을 다시 만들거나 재시작하세요. Default Auth만 비활성화되며 관리형 로컬 계정의 비밀번호 로그인은 유지됩니다. 이 작업만으로 이미 발급된 세션이 취소되지는 않습니다.
설치 프로그램이 관리하는 Compose 스택에서는 기본 파일의 변수 치환에 필요하므로 비공개 env 파일의 두 값을 비우지 마세요. 대신 다음 컨테이너 환경 오버라이드를 비공개 디렉터리의 oidc-only.yml에 저장합니다.
services: app: environment: DEFAULT_USER: "" DEFAULT_PASSWORD: ""완전한 dc 명령에서 "$@" 앞에 -f "$HOME/.config/chorus-self-host/$PROJECT/oidc-only.yml"을 추가하고 dc config --quiet와 dc up -d --wait --force-recreate app을 실행하세요. 이후 모든 시작과 업그레이드에도 이 오버라이드를 유지해야 합니다. 저장된 로컬 래퍼는 oidc-only.yml을 불러오지 않습니다. 이 단계 이후에는 수정하지 않은 래퍼 대신 원하는 앱 이미지를 준비하고 완전한 Compose 호출을 사용하세요. 로컬 가이드의 터널 예시는 이 파일이 있으면 포함합니다.
배포 측 인증 구성하기
섹션 제목: “배포 측 인증 구성하기”Default Auth와 슈퍼 관리자 자격 증명은 배포 환경에서 가져옵니다. 관리형 로컬 계정과 OIDC는 워크스페이스별로 데이터베이스에 설정하며, 별도의 새 로컬 인증 환경 변수는 없습니다.
슈퍼 관리자 부트스트랩
섹션 제목: “슈퍼 관리자 부트스트랩”/admin 슈퍼 관리자 패널은 데이터베이스 계정이 아니라 환경 변수에서 부트스트랩됩니다.
| 변수 | 설명 |
|---|---|
SUPER_ADMIN_EMAIL | /admin 패널에 접근할 수 있는 슈퍼 관리자 계정의 이메일. |
SUPER_ADMIN_PASSWORD_HASH | 슈퍼 관리자 비밀번호의 bcrypt 해시(평문이 아님). |
해시를 생성해 SUPER_ADMIN_PASSWORD_HASH로 전달합니다.
node -e "console.log(require('bcryptjs').hashSync('your-password', 10))"관리형 로컬 계정 워크스페이스
섹션 제목: “관리형 로컬 계정 워크스페이스”슈퍼 관리자로 로컬 계정 워크스페이스를 만들고 첫 워크스페이스 관리자를 초대하세요. 일회용 링크는 비공개로 전달합니다. Chorus는 초대나 비밀번호 재설정 이메일을 보내지 않습니다. 수신자는 비밀번호를 설정한 뒤 별도로 로그인합니다. 초대 및 재설정 링크는 24시간 동안 유효하며 새로 발급하면 기존 링크가 무효화됩니다. 이후 사용자와 재설정은 활성 상태의 로컬 워크스페이스 관리자가 관리합니다. 이 역할은 배포 슈퍼 관리자와 다르며 DEFAULT_USER로 부여되지 않습니다.
동일한 워크스페이스에서 로컬 계정과 OIDC는 함께 사용할 수 없습니다. 만들 때 적합한 유형을 선택하세요. 기존 워크스페이스의 인증 모드를 수정하여 전환할 수는 없습니다. 데이터베이스와 영구적인 NEXTAUTH_SECRET을 백업하세요. 로컬 비밀번호는 데이터베이스에 bcrypt 해시(작업 계수 12)로 저장되며 로컬 세션은 이 키로 서명됩니다. 비밀번호는 최소 8자, UTF-8 기준 최대 72바이트입니다. 공유 접근에는 HTTPS와 COOKIE_SECURE=true를 사용하세요. 계정 절차는 인증 설정을 참고하세요.
위의 기존 파일명 oidc-only.yml은 Default Auth만 비활성화합니다. 관리형 로컬 계정에도 사용할 수 있으며 OIDC를 활성화하지 않습니다.
싱글 사인온(OIDC)
섹션 제목: “싱글 사인온(OIDC)”싱글 사인온은 환경 변수로 구성하지 않습니다. 슈퍼 관리자가 /admin 패널에서 워크스페이스별로 OIDC를 구성하며, 그 설정은 데이터베이스에 저장됩니다. 각 워크스페이스는 자체 발급자(issuer) URL과 클라이언트 ID를 가지며, 둘 다 설정하면 그 워크스페이스에서 SSO가 켜집니다. Chorus는 PKCE를 사용하며 클라이언트 시크릿(client secret)을 요구하지 않습니다. 배포 수준의 부트스트랩은 슈퍼 관리자가 로그인할 수 있게 하는 역할만 하며, 이후 슈퍼 관리자가 관리 패널에서 워크스페이스별로 SSO를 구성합니다. 배포 계층에서 시크릿을 따로 준비할 필요는 없습니다.
마이그레이션 실행과 안전한 업그레이드
섹션 제목: “마이그레이션 실행과 안전한 업그레이드”Chorus는 시작 시 보류 중인 데이터베이스 마이그레이션을 자동으로 적용합니다(prisma migrate deploy). 마이그레이션을 직접 실행할 필요가 없습니다. 새 버전을 시작하면 웹 애플리케이션이 요청을 처리하기 전에 아직 적용되지 않은 마이그레이션이 모두 적용됩니다.
업그레이드하려면:
- 먼저 데이터베이스를 백업하세요. 외부 PostgreSQL이면 데이터베이스 백업을 만들고, 내장 또는 볼륨 기반 데이터베이스면 데이터 볼륨을 백업합니다.
- 새 버전을 가져옵니다. npm 패키지는
npm update -g @chorus-aidlc/chorus, Docker 배포는 새 컨테이너 이미지를 가져옵니다(pull). - Chorus를 재시작합니다. 마이그레이션은 부팅 시 자동으로 적용되고, 그런 다음 앱이 시작됩니다.
래퍼가 필요한 오버라이드를 모두 불러오는 로컬 모드에서는 bash ./default_deploy_local.sh를 실행하세요(pull 모드는 먼저 CHORUS_IMAGE 갱신). 터널 모드나 oidc-only.yml 등 사용자 설정이 있다면 원하는 앱 이미지를 준비하고 완전한 Compose 호출을 사용하세요. 업그레이드를 위해 설치 프로그램을 다시 실행하지 마세요. PostgreSQL 메이저 업그레이드는 별도의 오프라인 마이그레이션이 필요합니다. 로컬 머신에 셀프 호스팅을 참고하세요.
0.19.1 업그레이드 순서
섹션 제목: “0.19.1 업그레이드 순서”0.19.1에는 nullable 컬럼 하나만 추가하는 마이그레이션이 포함되어 있으므로 기존 데이터는 변경되지 않습니다. 에이전트 데몬을 실행하는 chorus CLI를 업그레이드하기 전에 Chorus 서버를 먼저 업그레이드하세요. 이전 버전의 데몬도 새 서버에서 계속 동작하며, 아이디어 생성 요청과 리서치 요청을 기존에 처리할 수 있는 형식으로 받습니다. 새 요청 형식을 긴급히 되돌려야 한다면 CHORUS_DEDICATED_OPERATION_WRITES=false를 설정하고 서버를 재시작하세요. 새 요청은 이전 형식을 사용하고, 이미 대기열에 있는 요청도 그대로 전달됩니다. CLI는 필요하면 따로 롤백하세요. 0.19.1이 만든 요청이 아직 대기 중이거나 실행 중인 동안에는 서버를 0.19.1보다 오래된 버전으로 롤백하지 말고, 새 컬럼도 제거하지 마세요.
0.18.1 업그레이드 시 세션 비밀 키
섹션 제목: “0.18.1 업그레이드 시 세션 비밀 키”데이터베이스와 함께 서명 비밀 키도 백업하고, 키를 바꾸지 말고 유지하세요. 자동 생성된 키를 유지하려면 외부 PostgreSQL을
사용하더라도 Docker에 영구적인 /app/data 볼륨이 필요합니다. npm 런처는 기본적으로 ~/.chorus-data/.secret을
사용합니다. 이전에 공개 자리 표시자를 사용했다면 키가 새 값으로 바뀌므로 내장 이메일/비밀번호 로그인 사용자와 슈퍼 관리자가 다시 로그인해야 합니다.
명시적으로 설정한 안전한 키는 그대로 유지됩니다. CDK 재배포에서는 같은 nextAuthSecret을
지정하세요. 생략하면 synth마다 새 값이 생성됩니다. API 키와 OIDC 토큰은 이 교체의 영향을 받지 않습니다. Docker 배포 가이드의 세션 비밀 키를 참고하세요.
쿠키와 리버스 프록시
섹션 제목: “쿠키와 리버스 프록시”Chorus가 TLS 종료나 리버스 프록시 뒤에서 실행될 때 중요한 설정이 두 가지 있습니다.
| 변수 | 설정 값 | 경우 |
|---|---|---|
COOKIE_SECURE | true | 사이트가 HTTPS로 제공됩니다(TLS를 종료하는 프록시 뒤 포함). 보안 쿠키는 암호화된 연결에서만 전송됩니다. |
COOKIE_SECURE | false | 신뢰할 수 있는 내부 HTTP 전용 네트워크에서만 사용합니다. 이 경우 쿠키가 암호화되지 않은 HTTP로 전송되므로, 공용 인터넷에서는 절대 사용하지 마세요. |
NEXTAUTH_URL | 외부 공개 기본 URL | Chorus가 리버스 프록시 뒤에서 실행됩니다. 리디렉션과 링크가 올바르게 해석되도록 외부에서 보이는 주소(예: https://chorus.example.com)로 설정합니다. |
공유 인증 요청 제한
섹션 제목: “공유 인증 요청 제한”Redis는 두 가지 독립적인 역할을 수행합니다. Pub/Sub는 SSE 실시간 업데이트를 전파하고 별도의 요청용 연결은 공유 인증 카운터를 저장합니다. 일관된 제한을 위해 모든 레플리카가 같은 Redis를 사용해야 합니다. SSE가 정상이라고 인증 카운터도 정상인 것은 아닙니다.
- 식별자 조회는 60초당 30회, 로컬 비밀번호 로그인과 초대·재설정 확정은 각각 60초당 10회입니다. 고정값이며 환경 변수로 변경할 수 없습니다.
- 신뢰할 수 있는 클라이언트 주소가 없으면 정규화된 식별자, 로컬 로그인의 워크스페이스와 식별자 조합, 또는 확정할 자격 증명 토큰별로 제한합니다. 모든 사용자가 하나의 전역 한도를 공유하는 것은 아닙니다. 신뢰할 수 있는 주소가 있으면 작업별로 주소·식별자 조합과 주소 단독 카운터를 모두 적용하므로 식별자를 바꿔도 주소 제한을 우회할 수 없습니다.
- 초과하면 HTTP
429,RATE_LIMITED, 초 단위Retry-After(올림, 최소 1)를 반환합니다. 모든 로그인·API 엔드포인트를 보호하지는 않으므로 전체 인증 경로에 에지 제한도 유지하세요.
설정과 기본값:
- 비어 있지 않은
REDIS_URL이 우선합니다. 그렇지 않으면REDIS_HOST가 TLS(rediss)를 활성화하며REDIS_PORT기본값은6379,REDIS_USERNAME은default,REDIS_PASSWORD는 선택 사항입니다. 사용자 이름은 비밀번호를 지정할 때 사용됩니다. 비 TLS Redis에는 명시적인redis://URL을 사용하세요. URL과 host가 모두 없을 때 Redis가 미설정 상태입니다. AUTH_TRUST_PROXY는 정확히true일 때만 활성화됩니다.AUTH_TRUST_PROXY_HOPS는 기본1이며 1~16의 정수여야 합니다.X-Forwarded-For의 오른쪽부터 주소를 셉니다. 누락되거나 너무 짧거나 잘못된 체인은 주소 제한만 비활성화하며 식별자 제한은 유지합니다. 추가·덮어쓰기가 강제되고 직접 또는 중간 우회가 불가능한 프록시 체인에서만 신뢰를 켜세요. HTTPS만으로 신뢰가 성립하지는 않습니다.- 번들 CDK의 ALB 모드는 신뢰
true, 홉1을 설정합니다. CloudFront 모드는 신뢰false, 홉2입니다. VPC 트래픽이 CloudFront를 우회해 비공개 오리진에 도달할 수 있기 때문입니다. 해당 우회를 차단하기 전에는 2홉 신뢰를 켜지 마세요.
장애 시 경계
섹션 제목: “장애 시 경계”Redis를 설정하지 않으면 프로세스 내부 카운터를 사용하고 경고를 기록합니다. 설정한 Redis가 연결 중이거나 사용 불가이거나 READONLY/OOM 등으로 명령을 거부하면 공유 카운터 대신 프로세스별 메모리 보조 카운터를 사용합니다. 명령 시간 제한은 500 ms이며 미완료 명령에 대한 응답이 없는 소켓은 2,000 ms 후 다시 연결합니다. 재연결 시 미완료 명령은 재전송하지 않습니다. 500 ms는 명령별 상한이지 전체 요청 응답 시간 보장은 아닙니다.
auth-throttle 로그에서 성능 저하와 복구를 확인하세요. 보조 카운터 경고는 60초에 한 번으로 제한되며 최초 연결에는 5초 유예가 있습니다. 메모리 카운터의 총 용량은 10,000개 키이며 가장 오래 사용하지 않은 키를 제거하는 최선형 보호입니다. 재시작하면 초기화되고 복구 시 Redis에 병합되지 않습니다. 정상적인 보조 처리 이외의 예상치 못한 제한 백엔드 오류는 기록한 뒤 해당 검사를 허용합니다(fail-open). Redis 장애만으로 모든 로그인을 의도적으로 차단하지 않습니다.
계정 검증은 별도이며 실패하면 접근을 거부합니다(fail-closed). 비활성화·삭제된 로컬 사용자, 호환되지 않는 워크스페이스 모드, 오래된 세션 버전은 로컬 세션을 승인할 수 없습니다. 계정 상태를 읽지 못해도 접근을 허용하지 않습니다. 보조 카운터는 인스턴스 간 SSE도 복구하지 못합니다. 로컬 이벤트는 계속되더라도 인스턴스 간 업데이트는 중단될 수 있습니다. Redis를 복구한 뒤 인증 카운터와 실시간 업데이트를 각각 확인하세요.