Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ All notable changes to this project are documented here. The format follows

## [Unreleased]

### Changed

- Added a privacy-minimized Nginx source-log example that omits client IPs,
referrers, and query arguments, and clarified the boundary between source-log
contents and Embertop's emitted-event redaction.
- Made SSH preview examples bind explicitly to loopback and documented direct
terminal, web-tunnel, service-status, journal, and `doctor` checks.

## [0.3.0] - 2026-07-28

### Added
Expand Down
23 changes: 17 additions & 6 deletions README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,14 @@ SSH 인증을 그대로 씁니다.
**서버에서**, 로그 읽기 권한만 가진 일반 사용자로:

```bash
embertop serve --host 127.0.0.1 --site example.com --log /var/log/nginx/access.log
embertop serve --host 127.0.0.1 --site example.com --log /var/log/nginx/embertop-access.log
```

**내 컴퓨터에서** 터널을 엽니다:

```bash
ssh -N -L 4318:127.0.0.1:4318 operator@example.com
ssh -N -o ExitOnForwardFailure=yes \
-L 127.0.0.1:4318:127.0.0.1:4318 operator@example.com
```

**다른 터미널에서** 불 앞에 앉습니다:
Expand All @@ -133,6 +134,10 @@ ssh -N -L 4318:127.0.0.1:4318 operator@example.com
embertop --endpoint http://127.0.0.1:4318/stream
```

로컬 주소를 명시하면 SSH 클라이언트 설정과 관계없이 전달 포트가 loopback에만
열립니다. `ExitOnForwardFailure=yes`는 터널을 만들지 못했을 때 즉시
종료합니다.

수집기는 `root`가 필요 없습니다. 로그 파일에 대한 읽기 전용 권한이면
충분합니다. 함께 제공되는 systemd 유닛은 `User=embertop`, `Group=adm`를
전제로 한 Linux 예제이므로, 로그 그룹이 다른 배포판에서는 값을 바꿔야
Expand Down Expand Up @@ -191,8 +196,8 @@ Linux에서 검증하므로, 다른 운영체제에 배포하거나 의존성

> [!IMPORTANT]
> Embertop에는 자체 로그인 기능이 없습니다. 웹 대시보드는 백오피스를 이미
> 보호하고 있는 인증 뒤에 두십시오. 방문자를 모두 익명화하더라도 요청
> 빈도와 트래픽 패턴 자체가 운영 정보입니다.
> 보호하고 있는 인증 뒤에 두십시오. 방문자 식별자를 제거해도 요청 빈도와
> 트래픽 패턴 자체가 운영 정보입니다.

리버스 프록시 구성, 하위 경로 배포, 기존 메트릭 API 재사용은
[연동 가이드](docs/INTEGRATION.ko.md)를 참고하십시오.
Expand All @@ -211,8 +216,8 @@ embertop --json >> telemetry.jsonl

## 개인정보

트래픽 데이터는 운영 정보이므로, 가리는 작업을 표시 단계가 아니라 수집
단계에서 수행합니다.
트래픽 데이터는 운영 정보입니다. Embertop은 각 이벤트를 내보내기 전에
민감한 값을 정제합니다.

- 클라이언트 IP 주소는 내보내지 않습니다.
- 쿼리 문자열은 제거합니다.
Expand All @@ -225,6 +230,12 @@ embertop --json >> telemetry.jsonl
- 업스트림 자격 증명은 서버에만 두며, 웹 프록시는 외부 SSE에서 받은 내용을
다시 한번 정제합니다.

이 과정은 원본 로그를 다시 쓰지 않습니다. `EMBERTOP_INCLUDE_PATHS=false`
(또는 `--hide-paths`)는 내보내는 이벤트의 경로만 바꾸며, Nginx가 이미
디스크에 기록한 줄에는 영향을 주지 않습니다. Embertop용 접근 로그에도 IP
주소·리퍼러·쿼리 문자열을 남기고 싶지 않다면 [연동
가이드](docs/INTEGRATION.ko.md)의 최소 수집 형식을 사용하세요.

공개 배포 전에 [SECURITY.md](SECURITY.md)를 읽어 주십시오.

## 개발
Expand Down
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,14 @@ credentials — SSH is already the authentication.
**On the server**, as an unprivileged user with read access to the log:

```bash
embertop serve --host 127.0.0.1 --site example.com --log /var/log/nginx/access.log
embertop serve --host 127.0.0.1 --site example.com --log /var/log/nginx/embertop-access.log
```

**On your machine**, open the tunnel:

```bash
ssh -N -L 4318:127.0.0.1:4318 operator@example.com
ssh -N -o ExitOnForwardFailure=yes \
-L 127.0.0.1:4318:127.0.0.1:4318 operator@example.com
```

**Then, in another terminal**, sit down in front of the fire:
Expand All @@ -136,6 +137,10 @@ ssh -N -L 4318:127.0.0.1:4318 operator@example.com
embertop --endpoint http://127.0.0.1:4318/stream
```

The explicit local bind keeps the forwarded port on loopback even if the SSH
client is configured otherwise. `ExitOnForwardFailure=yes` exits immediately
when the tunnel cannot be established.

The collector needs no root. Read-only access to the log file is enough. The
bundled systemd unit is a Linux example and assumes `User=embertop`,
`Group=adm`; distributions that assign logs to another group need that value
Expand Down Expand Up @@ -195,8 +200,8 @@ deploying elsewhere or after changing the dependency graph.
> [!IMPORTANT]
> Embertop has no login of its own. Put the web dashboard behind the
> authentication that already protects your backoffice. Request rates and
> traffic patterns are operational information even when every visitor is
> anonymous.
> traffic patterns are operational information even after visitor identifiers
> are removed.

See [the integration guide](docs/INTEGRATION.md) for reverse-proxy layouts,
subpath deployment, and reusing an existing metrics API.
Expand All @@ -215,8 +220,8 @@ stream reachability, collector bind safety — without starting the UI.

## Privacy

Traffic data is operational data, so the redaction happens at collection, not
at display:
Traffic data is operational data. Embertop sanitizes each event before it is
emitted:

- Client IP addresses are never emitted.
- Query strings are dropped.
Expand All @@ -229,6 +234,12 @@ at display:
- Upstream credentials stay server-side; the web proxy re-sanitizes anything
it receives from a custom SSE source.

This does not rewrite the source log. `EMBERTOP_INCLUDE_PATHS=false` (or
`--hide-paths`) changes the path in emitted events, not a line Nginx already
wrote to disk. Use the privacy-minimized source log in the
[integration guide](docs/INTEGRATION.md) when you do not want IP addresses,
referrers, or query strings in Embertop's own access log.

Read [SECURITY.md](SECURITY.md) before any public deployment.

## Development
Expand Down
5 changes: 5 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ Embertop treats telemetry as sensitive operational data.
- Terminal mode uses the same redaction path as the collector.
- Tokens passed with `--token` may be visible in operating-system process
listings. Prefer `EMBERTOP_TOKEN` or `EMBERTOP_COLLECTOR_TOKEN`.
- Redaction applies to the event Embertop emits, not to an existing Nginx
source log. A combined log can retain client IPs, referrers, and query strings
before Embertop reads it. `EMBERTOP_INCLUDE_PATHS=false` and `--hide-paths`
change emitted data only. Prefer a privacy-minimized source log, restrict
access to it, and keep retention short.

Embertop does not implement user authentication. Deploy it behind the
authentication and authorization already protecting your backoffice. A public
Expand Down
15 changes: 15 additions & 0 deletions deploy/nginx-access-log.example.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Privacy-minimized Nginx source log for Embertop.
#
# `log_format` belongs in the Nginx `http` context. `access_log` is valid in
# `http`, `server`, or `location`; move it to the server or location you want
# Embertop to observe when a global log is not appropriate.
#
# This format omits the client IP, referrer, and query arguments. The normalized
# path and User-Agent remain operational data: restrict access to this file and
# configure an appropriate rotation and retention policy.

log_format embertop '- - - [$time_local] '
'"$request_method $uri $server_protocol" $status $body_bytes_sent '
'"-" "$http_user_agent" $request_time';

access_log /var/log/nginx/embertop-access.log embertop;
29 changes: 26 additions & 3 deletions docs/CLI.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,14 @@ EMBERTOP_COLLECTOR_TOKEN=secret \
embertop serve \
--host 127.0.0.1 \
--site example.com \
--log /var/log/nginx/access.log
--log /var/log/nginx/embertop-access.log
```

내 컴퓨터의 터미널 하나에서:

```bash
ssh -N -L 4318:127.0.0.1:4318 operator@example.com
ssh -N -o ExitOnForwardFailure=yes \
-L 127.0.0.1:4318:127.0.0.1:4318 operator@example.com
```

다른 터미널에서:
Expand All @@ -121,6 +122,28 @@ ssh -N -L 4318:127.0.0.1:4318 operator@example.com
embertop --endpoint http://127.0.0.1:4318/stream
```

로컬 주소를 명시하면 SSH 클라이언트 설정과 관계없이 전달 포트가 loopback에만
열립니다. `ExitOnForwardFailure=yes`는 터널을 만들지 못했을 때 즉시
종료합니다.

서버에 Embertop과 수집기가 이미 실행 중이라면 터미널 프리뷰를 바로 열 수도
있습니다.

```bash
ssh -t operator@example.com \
'EMBERTOP_LANG=ko embertop --endpoint http://127.0.0.1:4318/stream'
```

loopback에만 열린 웹 대시보드는 포트를 전달해서 확인합니다.

```bash
ssh -N -o ExitOnForwardFailure=yes \
-L 127.0.0.1:13000:127.0.0.1:3000 operator@example.com
```

브라우저에서 `http://127.0.0.1:13000`을 여세요. 터널은 `Ctrl+C`로
종료합니다.

수집기에는 `root` 권한이 필요하지 않습니다. 계정에 로그 파일 읽기 전용
권한만 주면 되며, 함께 제공되는 `collector/embertop.service.example`도
`User=embertop`, `Group=adm`를 전제로 합니다.
Expand All @@ -139,7 +162,7 @@ embertop --endpoint http://127.0.0.1:4318/stream
UI를 시작하지 않고 현재 설정을 확인합니다.

```bash
embertop doctor --log /var/log/nginx/access.log
embertop doctor --log /var/log/nginx/embertop-access.log
EMBERTOP_TOKEN=secret embertop doctor -e https://host.example/stream
```

Expand Down
28 changes: 25 additions & 3 deletions docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,14 @@ On the server:
embertop serve \
--host 127.0.0.1 \
--site example.com \
--log /var/log/nginx/access.log
--log /var/log/nginx/embertop-access.log
```

On your machine, in one terminal:

```bash
ssh -N -L 4318:127.0.0.1:4318 operator@example.com
ssh -N -o ExitOnForwardFailure=yes \
-L 127.0.0.1:4318:127.0.0.1:4318 operator@example.com
```

And in another:
Expand All @@ -122,6 +123,27 @@ And in another:
embertop --endpoint http://127.0.0.1:4318/stream
```

The explicit local bind keeps the forwarded port on loopback even if the SSH
client is configured otherwise. `ExitOnForwardFailure=yes` exits immediately
when the tunnel cannot be established.

For a quick terminal preview when Embertop and the collector are already
running on the server:

```bash
ssh -t operator@example.com \
'embertop --endpoint http://127.0.0.1:4318/stream'
```

To preview a loopback-only web dashboard, forward its port:

```bash
ssh -N -o ExitOnForwardFailure=yes \
-L 127.0.0.1:13000:127.0.0.1:3000 operator@example.com
```

Then open `http://127.0.0.1:13000`. Stop either tunnel with `Ctrl+C`.

The collector does not need `root`. Give its account read-only access to the
log file — the bundled `collector/embertop.service.example` assumes
`User=embertop`, `Group=adm`.
Expand All @@ -140,7 +162,7 @@ Additional options:
Validate the current setup without starting the UI:

```bash
embertop doctor --log /var/log/nginx/access.log
embertop doctor --log /var/log/nginx/embertop-access.log
EMBERTOP_TOKEN=secret embertop doctor -e https://host.example/stream
```

Expand Down
55 changes: 45 additions & 10 deletions docs/INTEGRATION.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,31 @@ UI는 기존 백오피스 인증과 접근 제어 뒤에 둡니다. 수집기는

## 접근 로그 연결

Nginx combined 형식은 그대로 사용할 수 있습니다.
Embertop은 Nginx와 구조화된 JSON 접근 로그를 읽습니다. Nginx에서는 Embertop
전용 원본 로그의 수집 항목을 최소화하는 다음 형식을 권장합니다.

```nginx
log_format embertop '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" $request_time';
log_format embertop '- - - [$time_local] '
'"$request_method $uri $server_protocol" $status $body_bytes_sent '
'"-" "$http_user_agent" $request_time';

access_log /var/log/nginx/embertop-access.log embertop;
```

수집기는 IP가 포함된 원문을 읽지만, 파싱 결과에는 IP 필드가 존재하지
않습니다. 쿼리 문자열도 즉시 제거됩니다. 로그 파일 읽기 권한만 부여하고 쓰기
권한은 부여하지 마세요.
이 전용 로그에는 클라이언트 IP·리퍼러·쿼리 문자열이 기록되지 않습니다.
`$uri`는 쿼리 인자를 제외한 Nginx의 정규화된 현재 경로입니다. 경로와
User-Agent는 원본 로그에 남습니다. Embertop은 User-Agent 원문을 사람·크롤러·
미상이라는 상위 분류로 줄여서 사용합니다.

기존 combined 로그도 읽을 수 있지만, Embertop이 읽기 전에 클라이언트 IP,
리퍼러, 쿼리 문자열이 포함된 전체 요청 줄을 디스크에 남길 수 있습니다.
Embertop은 내보내는 이벤트에서 해당 값을 제거하거나 가리며, 이미 기록된 원본
로그를 다시 쓰지는 않습니다.

수집기에는 로그 읽기 전용 권한만 부여하세요. 다른 계정의 읽기 권한도 제한하고
운영에 필요한 기간보다 오래 보관하지 마세요. 수집기에 쓰기 권한은 필요하지
않습니다. 바로 조정해서 쓸 수 있는 예시는
`deploy/nginx-access-log.example.conf`에 있습니다.

## 리버스 프록시

Expand All @@ -70,6 +84,25 @@ location /internal/embertop-stream {
환경 변수를 Nginx 설정에 직접 보간하는 방식은 배포 환경마다 다릅니다. 실제
토큰은 저장소에 커밋하지 마세요.

## 배포 상태 점검

다음 명령은 흔히 쓰는 유닛 이름을 예로 듭니다. 실제로 설치한 이름이 다르면
바꾸세요.

```bash
sudo systemctl status embertop-collector embertop-web
sudo journalctl -f -u embertop-collector -u embertop-web
```

UI를 띄우지 않고 로그 접근과 파싱을 확인합니다.

```bash
embertop doctor --log /var/log/nginx/embertop-access.log
```

`doctor`는 Node.js 버전, 로그 읽기 가능 여부, 로컬 지표 또는 원격 스트림 연결,
수집기 바인딩 안전성을 보고합니다.

## 직접 SSE 제공

기존 백오피스가 이미 이벤트 스트림을 만들 수 있다면 수집기를 생략할 수
Expand All @@ -81,6 +114,8 @@ location /internal/embertop-stream {

1. UI 경로에 기존 백오피스 인증이 적용되는지 확인합니다.
2. 브라우저 개발자 도구에 수집기 토큰이 나타나지 않는지 확인합니다.
3. 샘플 로그에 쿼리 문자열, 숫자 ID, UUID가 남지 않는지 확인합니다.
4. `/api/stream`이 CDN에서 캐시되지 않는지 확인합니다.
5. 연결이 끊겼을 때 UI가 `RECONNECTING`으로 바뀌는지 확인합니다.
3. 원본 로그의 필드·권한·순환·보관 기간이 의도한 설정인지 확인합니다.
4. 쿼리 문자열, 숫자 ID, UUID, 긴 토큰이 포함된 경로가 이벤트에서 정제되는지
확인합니다.
5. `/api/stream`이 CDN에서 캐시되지 않는지 확인합니다.
6. 연결이 끊겼을 때 UI가 `RECONNECTING`으로 바뀌는지 확인합니다.
Loading