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:
@@ -152,6 +152,40 @@ labels:
|
|||||||
type: nginx
|
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
|
### Layer 2: OpenAppSec ML WAF
|
||||||
|
|
||||||
**Container**: `openappsec`
|
**Container**: `openappsec`
|
||||||
@@ -206,12 +240,77 @@ nginx-logs: /var/log/nginx
|
|||||||
|
|
||||||
### Security Configuration
|
### Security Configuration
|
||||||
|
|
||||||
#### CrowdSec Bouncer
|
#### CrowdSec Bouncer (수동 등록)
|
||||||
```yaml
|
```yaml
|
||||||
API_URL: http://10.90.135.49:8080
|
API_URL: http://10.90.135.49:8080
|
||||||
API_KEY: s0ENc/6Tw+6m6tr0Qkjt/WAYU1QlC5/MzH7SQOCJX50
|
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
|
#### OpenResty Configuration
|
||||||
```nginx
|
```nginx
|
||||||
upstream openappsec_backend {
|
upstream openappsec_backend {
|
||||||
|
|||||||
@@ -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
|
- Meilisearch 기본 포트: 7700
|
||||||
- 프로덕션 환경에서는 반드시 `MEILI_MASTER_KEY` 설정
|
- **프로덕션 모드**: `MEILI_ENV=production` 필수 (개발 모드는 Master Key 없이 실행됨)
|
||||||
|
- **Master Key**: 최소 16바이트 이상, 32바이트 권장
|
||||||
|
- **API 키 분리**: Master Key 노출 금지, Admin/Search 키 분리 사용
|
||||||
- 데이터 영속성을 위해 볼륨 마운트 권장
|
- 데이터 영속성을 위해 볼륨 마운트 권장
|
||||||
- 리소스 제한 설정으로 시스템 안정성 확보
|
- 리소스 제한 설정으로 시스템 안정성 확보
|
||||||
- 정기적인 백업 필요 (데이터 디렉토리 백업)
|
- **백업 전략**: 스냅샷(빠른 복구) + 덤프(버전 간 호환) 병행
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user