본문 바로가기
AI

Nitter 셀프호스팅 완벽 가이드 - 프라이버시와 X 크롤링

by IsaacOth 2026. 2. 3.

 

1. Nitter란?

GitHub에서 12,300개 이상의 스타를 기록하며 오픈소스 커뮤니티의 열광적인 지지를 받고 있는 Nitter는 단순한 트위터(X) 뷰어가 아닙니다.

*"A free and open source alternative Twitter front-end focused on privacy and performance."*

트위터가 X로 브랜드가 변경되고, 로그인이 강제되며, 무거운 자바스크립트와 광고로 뒤덮이는 동안, Nitter는 정반대의 길을 걸어왔습니다. 자바스크립트 없이 작동하는 초경량 인터페이스, 추적기(Tracker) 차단, 그리고 개발자 계정 없이도 작동하는 마법 같은 아키텍처를 자랑합니다.

트위터의 공식 웹 클라이언트가 약 784KB의 데이터를 로드하는 반면, Nitter는 단 60KB면 충분합니다. 이는 13배 이상의 성능 차이입니다. 하지만 Nitter의 진정한 가치는 '성능'이 아닌 '자유'에 있습니다. 사용자는 빅테크의 알고리즘과 감시로부터 자유로운 상태에서, 오직 콘텐츠 그 자체에만 집중할 수 있습니다.

이제 여러분의 로컬 서버에 이 강력한 '자유의 날개'를 직접 달아볼 시간입니다.

2. 핵심 개념 및 아키텍처

Nitter가 어떻게 트위터의 폐쇄적인 API 정책을 우회하고 사용자에게 데이터를 전달하는지 이해하는 것은 셀프 호스팅의 첫걸음입니다.

2.1 프라이버시 프록시의 원리

일반적인 트위터 클라이언트는 사용자의 브라우저가 직접 트위터 서버와 통신합니다. 이 과정에서 사용자의 IP 주소, 브라우저 핑거프린트, 쿠키 정보가 고스란히 노출됩니다.

반면, Nitter는 중개자(Proxy) 역할을 수행합니다.

  1. Client Request: 사용자가 Nitter 서버에 접속합니다.
  2. Server-Side Request: Nitter 서버가 사용자를 대신하여 트위터 서버에 데이터를 요청합니다.
  3. Sanitization: 트위터가 보낸 데이터에서 추적 스크립트, 광고, 불필요한 메타데이터를 제거합니다.
  4. Rendering: 순수 HTML/CSS로 변환하여 사용자에게 전달합니다.

이로 인해 트위터는 요청을 보낸 Nitter 서버의 IP만 알 수 있을 뿐, 실제 사용자가 누구인지는 알 수 없습니다.

2.2 기술 스택 (The Nim Advantage)

Nitter는 Nim 프로그래밍 언어로 작성되었습니다. 이는 매우 의도적인 선택입니다.

  • Nim (67%): 파이썬처럼 읽기 쉽지만, C언어 수준의 성능을 내는 컴파일 언어입니다. 적은 메모리로도 수천 건의 동시 접속을 처리할 수 있게 해주는 핵심 동력입니다.
  • Redis/Valkey: 트위터 API의 엄격한 속도 제한(Rate Limit)을 극복하기 위해 공격적인 캐싱을 수행합니다. 한 번 불러온 트윗, 프로필 정보, RSS 피드는 설정된 시간 동안 Redis에 저장되어 불필요한 외부 요청을 차단합니다.
  • HMAC Signing: 이미지나 비디오 URL을 프록시할 때 암호화 서명을 사용하여, 미디어 서버가 무분별하게 악용되는 것을 방지합니다.

2.3 아키텍처 다이어그램

graph TD
    User[User Browser] -- HTTP/HTTPS --> Nginx[Nginx Reverse Proxy]
    Nginx -- Proxy Pass --> Nitter[Nitter App (Nim)]

    subgraph "Internal Network"
    Nitter -- Read/Write --> Redis[(Redis Cache)]
    Nitter -- Read Auth --> JSON[sessions.jsonl]
    end

    subgraph "External Internet"
    Nitter -- Authenticated Req --> Twitter[Twitter/X Servers]
    Twitter -- JSON Data --> Nitter
    end

    style Nitter fill:#f9f,stroke:#333,stroke-width:2px
    style Redis fill:#ff9,stroke:#333,stroke-width:2px

3. 준비물 (Prerequisites)

Nitter를 호스팅하기 위해 거창한 서버는 필요 없습니다. 라즈베리 파이(Raspberry Pi) 수준의 기기에서도 충분히 돌아갑니다.

  • 하드웨어: 1 CPU Core, 512MB RAM 이상 (권장 1GB RAM)
  • OS: Linux (Ubuntu 22.04/24.04, Debian 12 권장)
  • 도메인: SSL 인증서 발급 및 외부 접속을 위한 도메인 (필수는 아니지만 권장)
  • 필수 소프트웨어:
    • Docker & Docker Compose (가장 쉬운 설치 방법)
    • Git
    • Python 3 (세션 토큰 생성용)

4. 빠른 시작 (Docker Quick Start)

가장 빠르게 Nitter를 실행하는 방법은 Docker를 사용하는 것입니다. 아래 명령어들을 터미널에 복사하여 붙여넣으세요.

먼저 작업 디렉토리를 생성하고 기본 설정 파일을 다운로드합니다.

# 작업 디렉토리 생성
mkdir -p ~/nitter && cd ~/nitter

# 기본 설정 파일 다운로드 (또는 생성)
wget https://raw.githubusercontent.com/zedeus/nitter/master/nitter.example.conf -O nitter.conf

# Redis 데이터 저장을 위한 볼륨 디렉토리 생성은 docker-compose가 처리합니다.

다음은 docker-compose.yml 파일을 작성합니다.

cat <<EOF > docker-compose.yml
version: "3"

services:
  nitter:
    image: zedeus/nitter:latest
    container_name: nitter
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - ./nitter.conf:/src/nitter.conf:Z,ro
      - ./sessions.jsonl:/src/sessions.jsonl:Z,ro
    depends_on:
      - nitter-redis
    user: "998:998"
    read_only: true
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL

  nitter-redis:
    image: redis:6-alpine
    container_name: nitter-redis
    command: redis-server --save 60 1 --loglevel warning
    volumes:
      - nitter-redis:/data
    restart: unless-stopped
    user: "999:1000"
    read_only: true
    security_opt:
      - no-new-privileges:true

volumes:
  nitter-redis:
EOF

주의: 2024년 이후 트위터의 정책 변경으로 인해, 단순히 컨테이너를 띄우는 것만으로는 트윗이 보이지 않을 수 있습니다. 반드시 5.4 섹션의 '세션 토큰 생성' 과정을 거쳐 sessions.jsonl 파일을 생성해야 합니다. 지금은 구조만 잡아두고 넘어갑니다.

5. 심화 가이드

여기서는 프로덕션 환경에서 안정적으로 운영하기 위한 상세 설정과 설치 방법을 다룹니다.

5.1 네이티브 설치 (Native Installation)

Docker 오버헤드조차 허용하고 싶지 않다면, 소스코드에서 직접 빌드할 수 있습니다. Nim 컴파일러 설치가 필요합니다.

# 1. 전용 사용자 생성
sudo useradd -m nitter
sudo su - nitter

# 2. 의존성 라이브러리 설치 (Debian/Ubuntu 기준)
# libpcre, libsass, redis 등이 필요합니다.
sudo apt install libpcre3-dev libsass-dev redis-server git

# 3. 소스코드 클론
git clone https://github.com/zedeus/nitter
cd nitter

# 4. 빌드 (릴리즈 모드)
# Nimble은 Nim의 패키지 매니저입니다.
nimble build -d:danger --mm:refc
nimble scss
nimble md

# 5. 설정 파일 복사
cp nitter.example.conf nitter.conf

# 6. 실행
./nitter

네이티브 설치 시에는 Redis가 백그라운드에서 실행 중이어야 합니다 (systemctl enable --now redis-server).

systemd 서비스 등록

서버 재부팅 시에도 Nitter가 자동으로 실행되도록 systemd 서비스 파일로 등록하는 것이 좋습니다.

# /etc/systemd/system/nitter.service
[Unit]
Description=Nitter (Twitter Frontend)
After=network.target redis.service

[Service]
Type=simple
User=nitter
WorkingDirectory=/home/nitter/nitter
ExecStart=/home/nitter/nitter/nitter
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

작성한 서비스를 활성화하고 상태를 확인합니다:

sudo systemctl daemon-reload
sudo systemctl enable --now nitter
sudo systemctl status nitter

5.2 nitter.conf 상세 설정

Nitter의 모든 동작은 nitter.conf 파일로 제어됩니다. Docker Compose 사용 시 hostnamenitter-redis로 변경하는 것을 잊지 마세요.

[Server]
hostname = "nitter.mytserver.com"  # RSS 피드 등에 사용될 도메인
title = "My Private Nitter"
address = "0.0.0.0"
port = 8080
https = false  # Nginx가 SSL을 처리한다면 false로 설정
httpMaxConnections = 100
staticDir = "./public"

[Cache]
listMinutes = 240  # 프로필/리스트 캐시 시간 (길수록 좋음)
rssMinutes = 10    # RSS 피드 갱신 주기
redisHost = "nitter-redis"  # Docker Compose 서비스 이름
redisPort = 6379
redisPassword = ""     # Redis 비밀번호가 있다면 입력
redisConnections = 20  # 최소 연결 수
redisMaxConnections = 30

[Config]
hmacKey = "CHANGEME_SECRET_KEY"  # 미디어 URL 서명용 키 (반드시 변경!)
base64Media = false
enableRSS = true
enableDebug = false
proxy = ""       # http://user:pass@host:port (HTTP 프록시 필요 시)
apiProxy = ""    # 별도 API 프록시 서버 사용 시
disableTid = false # 쿠키 기반 인증 실패 시 true 시도
maxConcurrentReqs = 2 # 세션당 동시 요청 제한

[Preferences]
theme = "Dracula"  # 기본 테마 (Nitter, Twitter, Dracula 등)
replaceTwitter = "nitter.mytserver.com"
replaceYouTube = "piped.video"  # 유튜브 링크를 Piped로 리다이렉트
replaceReddit = "libreddit.herokuapp.com"
proxyVideos = true  # 비디오 트래픽도 프록시 (대역폭 주의)
hlsPlayback = false
infiniteScroll = true # 무한 스크롤 활성화 여부

5.3 세션 토큰 생성 (The Critical Step)

이 부분이 가장 중요합니다. 트위터는 이제 비로그인 사용자의 게시물 열람을 차단하거나 극도로 제한합니다. Nitter가 작동하려면 실제 트위터 계정의 인증 정보가 담긴 sessions.jsonl 파일이 필요합니다.

준비물:

  • 사용하지 않는(막혀도 상관없는) 트위터 부계정 (새 계정은 금방 정지당하므로, 30일 이상 된 계정 권장)
  • Python 3 환경

생성 스크립트 실행:

Nitter 공식 저장소에 포함된 도구를 사용하거나 별도로 가져옵니다. Docker 환경이라면 호스트 머신에서 실행해서 파일만 넘겨주면 됩니다.

# 1. Nitter 저장소 클론 (스크립트 확보용)
git clone https://github.com/zedeus/nitter
cd nitter

# 2. 파이썬 의존성 설치
pip3 install -r requirements.txt

# 3. 세션 생성 (브라우저 에뮬레이션 방식)
# 2FA가 설정된 계정을 권장합니다.
python3 create_session_browser.py "트위터아이디" "비밀번호" --append sessions.jsonl

# 만약 2FA(TOTP)를 사용 중이라면 시크릿 키도 함께 입력
# python3 create_session_browser.py "username" "password" "TOTP_SECRET" --append sessions.jsonl

생성된 sessions.jsonl 파일은 아래와 같은 형식을 띱니다:

{"kind":"cookie","auth_token":"...","ct0":"...","username":"...","id":"..."}

이 파일을 docker-compose.yml이 있는 디렉토리로 복사하고, 권한을 설정합니다. Nitter 컨테이너가 이 파일을 읽을 수 있어야 합니다.

5.4 Nginx 리버스 프록시 설정

보안과 HTTPS 적용을 위해 Nitter 앞단에 Nginx를 두는 것이 표준입니다.

server {
    listen 80;
    server_name nitter.example.com;

    # HTTPS 리다이렉트 (Certbot 사용 시 자동 생성됨)
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name nitter.example.com;

    ssl_certificate /etc/letsencrypt/live/nitter.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/nitter.example.com/privkey.pem;

    # 보안 헤더 설정
    add_header X-Frame-Options "DENY";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 정적 파일 캐싱 (선택 사항)
        location ~* ^/(pic|video|css|js)/ {
            proxy_pass http://127.0.0.1:8080;
            expires 1M;
            access_log off;
        }
    }
}

5.5 보안 및 주의사항

  1. 공개 노출 최소화: 개인적인 용도라면 nitter.conf나 Nginx에서 Basic Auth를 걸거나, VPN 내부망에서만 접속하도록 설정하는 것이 안전합니다. 공개 인스턴스는 트래픽 과다로 인해 트위터로부터 IP 밴을 당할 확률이 매우 높습니다.
  2. hmacKey 변경: 기본값을 그대로 사용하면 누군가가 여러분의 서버를 미디어 프록시로 악용할 수 있습니다. 반드시 복잡한 문자열로 변경하세요.
  3. Redis 보안: Docker Compose 내부 네트워크를 사용하므로 외부에 포트를 노출하지 마세요 (YAML 파일에서 Redis 포트 매핑 제거).

6. 트러블슈팅 (Troubleshooting)

운영하다 보면 마주치게 될 흔한 문제들과 해결책입니다.

Q1. "No tweets found" 또는 "Instance has been rate limited" 오류가 뜹니다.

가장 흔한 문제입니다.

  • 원인: 사용 중인 세션(계정)이 트위터의 속도 제한에 걸렸거나, 세션이 만료되었습니다.
  • 해결:
    1. create_session_browser.py로 새로운 세션을 생성하여 sessions.jsonl에 추가합니다. 여러 계정을 등록하면 Nitter가 로드 밸런싱을 수행합니다.
    2. Redis 캐시를 비워봅니다: docker exec -it nitter-redis redis-cli FLUSHALL

Q2. 동영상 재생이 안 됩니다.

  • 원인: proxyVideos = true 설정 시 서버 대역폭이 부족하거나, 트위터가 미디어 요청을 차단한 경우입니다.
  • 해결: nitter.conf에서 proxyVideos = false로 설정하면 사용자의 브라우저가 직접 트위터 서버에서 영상을 받아옵니다. 프라이버시는 약간 희생되지만 재생 안정성은 높아집니다.

Q3. Docker 컨테이너가 계속 재시작됩니다.

  • 원인: 권한 문제일 가능성이 높습니다.
  • 해결: docker logs nitter로 로그를 확인하세요. permission denied가 보인다면 chown -R 998:998 . 명령어로 호스트 디렉토리의 권한을 컨테이너 사용자에 맞춰주어야 합니다. sessions.jsonl 파일 권한도 확인하세요.

Q4. Docker 헬스체크 실패

wget 명령어가 컨테이너 내부에 없거나(알파인 이미지가 아닌 경우), 포트가 다를 수 있습니다. 로그에 Server running on... 메시지가 뜨는지 확인하세요.

7. 결론

Nitter를 셀프 호스팅하는 것은 단순히 광고를 피하는 것 이상의 의미가 있습니다. 그것은 데이터 주권을 되찾는 행위입니다.

여러분은 이제 어떤 알고리즘의 간섭도 받지 않고, 여러분의 IP 주소를 거대 기업의 데이터베이스에 넘겨주지 않으면서, 전 세계의 소식을 실시간으로 확인할 수 있는 강력한 도구를 손에 넣었습니다. 비록 트위터의 API 정책이 계속해서 창과 방패의 싸움을 강요하겠지만, 오픈소스 커뮤니티와 Nitter는 언제나 우회로를 찾아낼 것입니다.

이제 터미널을 열고, 여러분만의 조용한 관측소를 구축해 보세요.

8. TL;DR

  1. Nitter는 자바스크립트 없는 프라이버시 중심의 트위터 프론트엔드다.
  2. Redis가 필수이며, 성능이 매우 가볍다 (60KB vs 784KB).
  3. Docker Compose가 가장 쉬운 설치 방법이다.
  4. 트위터 정책 변경으로 인해 sessions.jsonl (세션 토큰) 생성이 필수가 되었다.
  5. Nginx 리버스 프록시와 함께 사용하여 HTTPS를 적용하라.
  6. hmacKey 변경 등 최소한의 보안 설정을 잊지 마라.

9. 참고 링크