Improve Meilisearch and CrowdSec documentation

incus-meilisearch-manual.md:
- Add production config file settings (config.toml)
- Add Master Key requirements (min 16 bytes, 32 recommended)
- Add API key management section (Master/Admin/Search separation)
- Add snapshot and dump backup/restore procedures
- Add client usage examples (JavaScript, Python)

incus-crowdsec-architecture.md:
- Add Bouncer auto-registration via environment variables
- Add Docker Compose example with BOUNCER_KEY_<name>
- Add Docker Secrets approach for secure key management
- Add acquisition directory structure (/etc/crowdsec/acquis.d/)
- Add service-specific acquisition file examples

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-16 00:48:02 +09:00
parent bafc79c81b
commit 76f8f421af
2 changed files with 287 additions and 3 deletions

View File

@@ -152,6 +152,40 @@ labels:
type: nginx
```
**Acquisition 디렉토리 구조화** (권장):
```bash
# /etc/crowdsec/acquis.d/ 디렉토리에 서비스별 파일 분리
/etc/crowdsec/acquis.d/
├── nginx.yaml # Nginx 로그
├── apache.yaml # Apache 로그 (필요시)
├── sshd.yaml # SSH 로그
└── traefik.yaml # Traefik 로그 (필요시)
```
**nginx.yaml 예시**:
```yaml
filenames:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
labels:
type: nginx
---
# JSON 형식 로그 (별도 처리)
filenames:
- /var/log/nginx/json_access.log
labels:
type: nginx
format: json
```
**sshd.yaml 예시**:
```yaml
filenames:
- /var/log/auth.log
labels:
type: syslog
```
### Layer 2: OpenAppSec ML WAF
**Container**: `openappsec`
@@ -206,12 +240,77 @@ nginx-logs: /var/log/nginx
### Security Configuration
#### CrowdSec Bouncer
#### CrowdSec Bouncer (수동 등록)
```yaml
API_URL: http://10.90.135.49:8080
API_KEY: s0ENc/6Tw+6m6tr0Qkjt/WAYU1QlC5/MzH7SQOCJX50
```
#### Bouncer 자동 등록 (권장)
> 컨테이너 시작 시 환경변수로 Bouncer 자동 등록. 수동 `cscli bouncers add` 불필요.
**환경변수 방식**:
```bash
# CrowdSec 컨테이너 시작 시 Bouncer 자동 등록
incus launch docker.io/crowdsecurity/crowdsec crowdsec \
--config environment.BOUNCER_KEY_openresty=my-secure-bouncer-key-here \
--config environment.BOUNCER_KEY_firewall=another-bouncer-key-here
```
**Docker Compose 예시**:
```yaml
services:
crowdsec:
image: crowdsecurity/crowdsec:latest
environment:
# Bouncer 자동 등록 (BOUNCER_KEY_<name>=<key>)
- BOUNCER_KEY_openresty=${OPENRESTY_BOUNCER_KEY}
- BOUNCER_KEY_firewall=${FIREWALL_BOUNCER_KEY}
# 컬렉션 자동 설치
- COLLECTIONS=crowdsecurity/nginx crowdsecurity/http-cve
volumes:
- crowdsec-data:/var/lib/crowdsec/data
- crowdsec-config:/etc/crowdsec
- /var/log/nginx:/var/log/nginx:ro
restart: unless-stopped
openresty:
image: openresty/openresty:latest
environment:
- CROWDSEC_API_URL=http://crowdsec:8080
- CROWDSEC_API_KEY=${OPENRESTY_BOUNCER_KEY}
depends_on:
- crowdsec
```
**Docker Secret 방식 (더 안전)**:
```yaml
services:
crowdsec:
image: crowdsecurity/crowdsec:latest
secrets:
- bouncer_key_openresty
- bouncer_key_firewall
# Secret 파일은 /run/secrets/bouncer_key_<name> 으로 마운트됨
secrets:
bouncer_key_openresty:
file: ./secrets/openresty_bouncer_key
bouncer_key_firewall:
file: ./secrets/firewall_bouncer_key
```
```bash
# Secret 파일 생성
mkdir -p secrets
openssl rand -base64 32 > secrets/openresty_bouncer_key
openssl rand -base64 32 > secrets/firewall_bouncer_key
chmod 600 secrets/*
```
> **주의**: 환경변수/Secret 방식은 초기 배포 시에만 동작. 기존 Bouncer 업데이트는 `cscli` 사용.
#### OpenResty Configuration
```nginx
upstream openappsec_backend {

View File

@@ -295,13 +295,198 @@ echo "Access URL: http://localhost:7700"
---
## 8. 프로덕션 보안 설정
### Master Key 요구사항
> Master Key는 최소 16바이트(128비트) 이상 권장. 짧은 키는 보안 취약점.
```bash
# 안전한 Master Key 생성 (32바이트)
openssl rand -base64 32
# 또는 hex 형식 (64자)
openssl rand -hex 32
```
### 프로덕션 설정 파일
`/etc/meilisearch/config.toml` 또는 환경변수로 설정:
```toml
# 프로덕션 모드 (필수)
env = "production"
# 강력한 Master Key (필수, 최소 16자 이상)
master_key = "your-secure-master-key-here"
# 데이터 경로
db_path = "/var/lib/meilisearch/data"
dump_dir = "/var/lib/meilisearch/dumps"
snapshot_dir = "/var/lib/meilisearch/snapshots"
# 스냅샷 자동 생성 (백업용)
schedule_snapshot = true
snapshot_interval_sec = 86400 # 24시간마다
# 로깅
log_level = "INFO"
# 성능 설정
max_indexing_memory = "2 GiB"
max_indexing_threads = 4
```
### Incus 환경변수로 프로덕션 설정
```bash
incus config set meilisearch-prod \
environment.MEILI_ENV=production \
environment.MEILI_MASTER_KEY="$(openssl rand -base64 32)" \
environment.MEILI_DB_PATH=/data.ms \
environment.MEILI_DUMP_DIR=/data.ms/dumps \
environment.MEILI_SNAPSHOT_DIR=/data.ms/snapshots \
environment.MEILI_SCHEDULE_SNAPSHOT=true \
environment.MEILI_SNAPSHOT_INTERVAL_SEC=86400 \
environment.MEILI_LOG_LEVEL=INFO \
environment.MEILI_MAX_INDEXING_MEMORY="2 GiB"
```
---
## 9. API 키 관리
> Master Key는 절대 클라이언트에 노출하지 말 것. Admin/Search 키 분리 사용 필수.
### 키 유형
| 키 유형 | 권한 | 용도 |
|---------|------|------|
| **Master Key** | 전체 권한 | 서버 관리자만 사용, 절대 노출 금지 |
| **Admin Key** | 인덱스 관리 | 백엔드 서버에서 데이터 인덱싱 |
| **Search Key** | 검색만 | 프론트엔드/클라이언트 검색 |
### 기본 API 키 조회
```bash
# Master Key로 API 키 목록 조회
curl -X GET 'http://localhost:7700/keys' \
-H 'Authorization: Bearer YOUR_MASTER_KEY'
```
### 응답 예시
```json
{
"results": [
{
"name": "Default Search API Key",
"key": "d0552b...",
"actions": ["search"],
"indexes": ["*"],
"expiresAt": null
},
{
"name": "Default Admin API Key",
"key": "380689...",
"actions": ["*"],
"indexes": ["*"],
"expiresAt": null
}
]
}
```
### 커스텀 API 키 생성
```bash
# 특정 인덱스만 검색 가능한 키 생성
curl -X POST 'http://localhost:7700/keys' \
-H 'Authorization: Bearer YOUR_MASTER_KEY' \
-H 'Content-Type: application/json' \
--data-binary '{
"name": "Products Search Key",
"description": "Search products index only",
"actions": ["search"],
"indexes": ["products"],
"expiresAt": "2026-12-31T23:59:59Z"
}'
```
### 클라이언트 사용 예시
```javascript
// 프론트엔드: Search Key만 사용 (노출 OK)
const client = new MeiliSearch({
host: 'https://search.example.com',
apiKey: 'search-only-key-here' // Search Key
});
// 검색만 가능
const results = await client.index('products').search('query');
```
```python
# 백엔드: Admin Key 사용 (환경변수로 관리)
import os
from meilisearch import Client
client = Client(
'http://localhost:7700',
os.environ['MEILI_ADMIN_KEY'] # Admin Key
)
# 인덱싱 가능
client.index('products').add_documents(documents)
```
---
## 10. 백업 및 복구
### 스냅샷 (자동 백업)
```bash
# 스냅샷 수동 생성
curl -X POST 'http://localhost:7700/snapshots' \
-H 'Authorization: Bearer YOUR_MASTER_KEY'
# 스냅샷 파일 위치
ls /var/lib/meilisearch/snapshots/
```
### 덤프 (이식 가능한 백업)
```bash
# 덤프 생성 (JSON 형식, 버전 간 호환)
curl -X POST 'http://localhost:7700/dumps' \
-H 'Authorization: Bearer YOUR_MASTER_KEY'
# 덤프 상태 확인
curl -X GET 'http://localhost:7700/tasks?types=dumpCreation' \
-H 'Authorization: Bearer YOUR_MASTER_KEY'
```
### 덤프에서 복구
```bash
# 새 인스턴스에서 덤프 복구
incus launch docker.io/getmeili/meilisearch meilisearch-restore \
--config environment.MEILI_MASTER_KEY=your-key \
--config environment.MEILI_IMPORT_DUMP=/dumps/20260116-123456.dump
```
---
## 참고 사항
- Meilisearch 기본 포트: 7700
- 프로덕션 환경에서는 반드시 `MEILI_MASTER_KEY` 설정
- **프로덕션 모드**: `MEILI_ENV=production` 필수 (개발 모드는 Master Key 없이 실행됨)
- **Master Key**: 최소 16바이트 이상, 32바이트 권장
- **API 키 분리**: Master Key 노출 금지, Admin/Search 키 분리 사용
- 데이터 영속성을 위해 볼륨 마운트 권장
- 리소스 제한 설정으로 시스템 안정성 확보
- 정기적인 백업 필요 (데이터 디렉토리 백업)
- **백업 전략**: 스냅샷(빠른 복구) + 덤프(버전 간 호환) 병행
---