From a41ca7ff2c7fef5451518eb95592a64e3142a712 Mon Sep 17 00:00:00 2001 From: Khoa Vo Date: Tue, 12 May 2026 08:56:30 +0700 Subject: [PATCH] Update Dockerfile, docker-compose, and README for Synology NAS deployment --- Dockerfile | 66 +++---- README.md | 417 +++++++++++++++++++++++---------------------- docker-compose.yml | 55 ++---- 3 files changed, 250 insertions(+), 288 deletions(-) diff --git a/Dockerfile b/Dockerfile index dd6a7de..04af285 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,39 +1,27 @@ -# Build Stage for Frontend -FROM node:18-alpine as frontend-build -WORKDIR /app/frontend -COPY frontend/package*.json ./ -RUN npm ci -COPY frontend/ ./ -RUN npm run build - -# Runtime Stage for Backend -FROM python:3.11-slim - -# Install system dependencies required for Playwright and compiled extensions -RUN apt-get update && apt-get install -y \ - curl \ - git \ - build-essential \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /app - -# Install Python dependencies -COPY backend/requirements.txt backend/ -RUN pip install --no-cache-dir -r backend/requirements.txt - -# Install Playwright browsers (Chromium only to save space) -RUN playwright install chromium -RUN playwright install-deps chromium - -# Copy Backend Code -COPY backend/ backend/ - -# Copy Built Frontend Assets -COPY --from=frontend-build /app/frontend/dist /app/frontend/dist - -# Expose Port -EXPOSE 8002 - -# Run Application -CMD ["python", "backend/main.py"] +# Build Stage for Frontend +FROM --platform=linux/amd64 node:18-alpine AS frontend-build +WORKDIR /app/frontend +COPY frontend/package*.json ./ +RUN npm ci +COPY frontend/ ./ +RUN npm run build + +# Runtime Stage +FROM --platform=linux/amd64 mcr.microsoft.com/playwright/python:v1.49.1-jammy + +WORKDIR /app + +RUN pip install --no-cache-dir -U yt-dlp fastapi uvicorn requests python-multipart websockets python-dotenv httpx crawl4ai playwright-stealth + +COPY backend/requirements.txt backend/ +RUN pip install --no-cache-dir -r backend/requirements.txt + +COPY backend/ backend/ + +COPY --from=frontend-build /app/frontend/dist /app/frontend/dist + +RUN playwright install chromium --with-deps + +EXPOSE 8002 + +CMD ["python", "backend/main.py"] \ No newline at end of file diff --git a/README.md b/README.md index 80e929d..4469ac4 100644 --- a/README.md +++ b/README.md @@ -1,263 +1,264 @@ -# 🎵 PureStream +# kv-tiktok -**Distraction-free TikTok viewing** - A clean, ad-free TikTok client with a beautiful minimal interface. +**Self-hosted TikTok viewer** — A clean, ad-free TikTok client you can run on your own NAS or server. -![PureStream Demo](https://img.shields.io/badge/Platform-Web-blue) ![Docker](https://img.shields.io/badge/Docker-Ready-blue) ![License](https://img.shields.io/badge/License-MIT-green) +## Features -## ✨ Features +- **For You Feed** — Video feed from popular TikTok creators +- **Search** — Search videos and users +- **Following** — Track your favorite creators +- **Liked Videos** — Save favorites to a persistent Liked tab +- **Download** — Download videos directly +- **Autoplay** — Muted autoplay with tap-to-unmute +- **Mobile-friendly** — Responsive design for any screen +- **Docker-ready** — Single container, easy deployment on Synology NAS -- 🎬 **Clean Video Feed** - No ads, no distractions, just content -- 🔍 **Powerful Search** - Search by username, video URL, or keywords -- 👥 **Follow System** - Keep track of your favorite creators -- 💾 **Tab Persistence** - Switch tabs without losing your place -- 👆 **Swipe Navigation** - Swipe left/right to switch tabs (mobile) -- ⌨️ **Keyboard Controls** - Arrow keys for tabs, Space for pause, Up/Down for scroll -- ❤️ **Heart Animations** - Double-tap to show love -- 🔇 **Smart Autoplay** - Videos autoplay muted (tap to unmute) -- 📱 **Responsive Design** - Works on desktop and mobile -- 🐳 **Docker Ready** - Easy deployment on any platform +## Architecture -## 🚀 Quick Start +- **Backend**: Python FastAPI with Playwright for TikTok interaction +- **Frontend**: React + Vite +- **Platform**: `linux/amd64` (compatible with Synology NAS x86/x64 models) -### Option 1: Docker Compose (Recommended) +## Prerequisites -The easiest way to run PureStream on your server or Synology NAS. +- Docker and Docker Compose installed +- For Synology NAS: Container Manager (Docker) package installed +- Minimum 2GB RAM recommended for browser automation + +## Quick Start + +### Clone and Run ```bash -# Create a directory -mkdir purestream && cd purestream - -# Download docker-compose.yml -curl -O https://raw.githubusercontent.com/YOUR_USERNAME/purestream/main/docker-compose.yml - -# Start the application -docker-compose up -d - -# View logs -docker-compose logs -f +git clone https://github.com/vndangkhoa/kv-tiktok.git +cd kv-tiktok +docker compose up -d --build ``` -Access the app at: `http://your-server-ip:8002` +Access at `http://your-server-ip:8002` -### Option 2: Docker Run +--- -```bash -docker run -d \ - --name purestream \ - -p 8002:8002 \ - --shm-size=2g \ - -v purestream_cache:/app/cache \ - -v purestream_session:/app/backend/session \ - vndangkhoa/purestream:latest -``` +## Synology NAS Deployment -### Option 3: Development Setup +### Option 1: Build on NAS via SSH (Recommended) -```bash -# Clone the repository -git clone https://github.com/YOUR_USERNAME/purestream.git -cd purestream - -# Backend setup -cd backend -python -m venv venv -source venv/bin/activate # or `venv\Scripts\activate` on Windows -pip install -r requirements.txt -playwright install chromium - -# Start backend -uvicorn main:app --host 0.0.0.0 --port 8002 --reload - -# Frontend setup (new terminal) -cd frontend -npm install -npm run dev -``` - -## 🖥️ Synology NAS Deployment - -### Using Container Manager (Docker) - -1. **Open Container Manager** → **Registry** -2. Search for `vndangkhoa/purestream` and download the `latest` tag -3. Go to **Container** → **Create** -4. Configure: - - **Port Settings**: Local `8002` → Container `8002` - - **Volume**: Create a folder for cache and map to `/app/cache` - - **Environment**: Add `PYTHONUNBUFFERED=1` - - **Resources**: Allocate at least 2GB RAM (for browser) -5. **Apply** and start the container - -### Using docker-compose on Synology +**Requirements**: SSH access enabled on your NAS (Control Panel → Terminal & SNMP → Enable SSH) ```bash # SSH into your NAS ssh admin@your-nas-ip -# Create directory -mkdir -p /volume1/docker/purestream -cd /volume1/docker/purestream +# Navigate to your shared folder +cd /volume1/docker -# Create docker-compose.yml (paste the content from this repo) -nano docker-compose.yml +# Clone the repository +git clone https://github.com/vndangkhoa/kv-tiktok.git +cd kv-tiktok -# Start -docker-compose up -d +# Build and start +docker compose up -d --build + +# Watch logs to confirm it's running +docker compose logs -f ``` -## ⌨️ Keyboard Shortcuts +Once running, access at `http://your-nas-ip:8002` -| Key | Action | -|-----|--------| -| `←` `→` | Switch tabs | -| `↑` `↓` | Scroll videos | -| `Space` | Play/Pause | -| `M` | Mute/Unmute | +### Option 2: Build on PC, Deploy via GUI -## 🔧 Environment Variables +If your NAS has limited resources: -| Variable | Default | Description | -|----------|---------|-------------| -| `CACHE_DIR` | `/app/cache` | Video cache directory | -| `MAX_CACHE_SIZE_MB` | `500` | Maximum cache size in MB | -| `CACHE_TTL_HOURS` | `24` | Cache expiration time | +**Step 1: Build on your PC** -## 📁 Project Structure - -``` -purestream/ -├── backend/ -│ ├── api/ -│ │ └── routes/ -│ │ ├── auth.py # Authentication endpoints -│ │ └── feed.py # Feed & video proxy endpoints -│ ├── core/ -│ │ └── playwright_manager.py # Browser automation -│ └── main.py # FastAPI application -├── frontend/ -│ ├── src/ -│ │ ├── components/ -│ │ │ ├── Feed.tsx # Main feed component -│ │ │ └── VideoPlayer.tsx # Video player -│ │ └── App.tsx -│ └── package.json -├── Dockerfile -├── docker-compose.yml -└── README.md +```bash +git clone https://github.com/vndangkhoa/kv-tiktok.git +cd kv-tiktok +docker build -t kv-tiktok:latest . +docker save kv-tiktok:latest -o kv-tiktok.tar ``` -## 🔐 Authentication (Admin Setup) +**Step 2: Transfer to NAS** -PureStream uses your TikTok session cookies. Once configured by the admin, **all users can access the feed without logging in** - on desktop or mobile. +Copy `kv-tiktok.tar` to your NAS using File Station or SCP: -> **Important**: Admin setup should be done from a **desktop/laptop computer** (not a phone) because you need a browser extension to export cookies. +```bash +scp kv-tiktok.tar admin@your-nas-ip:/volume1/docker/ +``` -### First-Time Setup (Desktop Required) +**Step 3: Import via Container Manager** -1. **Set your admin password** in `docker-compose.yml`: - ```yaml - environment: - - ADMIN_PASSWORD=your_secure_password - ``` +1. Open **Container Manager** on your Synology +2. Go to **Registry** → **Image** → **Import** +3. Select `kv-tiktok.tar` from the shared folder +4. Wait for import to complete -2. **Start/restart the container**: +**Step 4: Create Container** + +1. Go to **Container** → **Create** +2. Select image: `kv-tiktok:latest` +3. Configure: + + | Setting | Value | + |---------|-------| + | Container Name | `kv-tiktok` | + | Port Settings | Local: `8002` → Container: `8002` | + | Memory Limit | Minimum `2GB` | + | Shared Memory | `2GB` | + +4. **Volume Settings**: Click **Add Folder** + - Create a folder named `kv-tiktok-cache` in your shared folder + - Mount path: `/app/cache` + +5. **Environment Variables**: Click **Add** + - `PYTHONUNBUFFERED` = `1` + - `ADMIN_PASSWORD` = `your_secure_password` + +6. **Restart Policy**: Select `unless-stopped` + +7. Click **Apply** + +**Step 5: Verify** + +```bash +# Check container is running +docker ps + +# Check logs +docker logs kv-tiktok +``` + +### Option 3: Via docker-compose (SSH) + +```bash +# On your NAS via SSH +cd /volume1/docker/kv-tiktok +docker compose up -d +docker compose logs -f +``` + +--- + +## First-Time Setup (TikTok Cookies) + +The app requires TikTok session cookies to load the feed. + +### Get Your Cookies (Desktop Recommended) + +1. Install [Cookie-Editor](https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) browser extension + +2. Go to [tiktok.com](https://www.tiktok.com) and log in to your account + +3. Click the Cookie-Editor icon → **Export** → **Copy** (select "Export as JSON") + +4. Save the exported JSON to `cookies.json` file in the project directory + +5. Restart the container: ```bash - docker-compose up -d --force-recreate + docker compose restart ``` -3. **Access the admin page**: `http://your-server-ip:8002/admin` - - Enter your admin password (default: `admin123`) +### Alternative: Setup via Admin Page -4. **Get your TikTok cookies** (from a desktop browser): - - Install [Cookie-Editor](https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) browser extension - - Go to [tiktok.com](https://www.tiktok.com) and login to your account - - Click Cookie-Editor icon → **Export** → **Copy** +1. Start the container and visit `http://your-server-ip:8002/admin` +2. Login with default password: `admin123` (change this!) +3. Follow on-screen instructions to paste cookies -5. **Paste cookies** in the admin page text area and click **Save Cookies** - -6. ✅ **Done!** Now anyone can access `http://your-server-ip:8002/` on any device (including phones) - -### Getting Cookies on Mobile (If No Desktop Available) - -#### 📱 Android Phone - -1. **Install Kiwi Browser** from [Google Play Store](https://play.google.com/store/apps/details?id=com.kiwibrowser.browser) - - Kiwi Browser supports Chrome extensions on Android - -2. **Install Cookie-Editor extension**: - - In Kiwi, go to: `chrome://extensions` - - Enable "Developer mode" (toggle in top right) - - Go to [Cookie-Editor on Chrome Web Store](https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) - - Click "Add to Chrome" - -3. **Get cookies**: - - Go to [tiktok.com](https://www.tiktok.com) in Kiwi Browser - - Login to your TikTok account - - Tap the 3-dot menu → Extensions → Cookie-Editor - - Tap **Export** → **Copy** - -4. **Paste in admin page**: - - Go to `http://your-server-ip:8002/admin` - - Login with admin password - - Paste cookies and save - -#### 🍎 iOS/iPhone - -Unfortunately, iOS Safari doesn't support browser extensions. Options: - -1. **Use a desktop computer** (recommended) - borrow a friend's laptop for 5 minutes - -2. **Use Orion Browser** (limited): - - Install [Orion Browser](https://apps.apple.com/app/orion-browser-by-kagi/id1484498200) from App Store - - It has some extension support, but Cookie-Editor may not work perfectly - -3. **Manual method** (advanced): - - On iOS Safari, go to tiktok.com and login - - In Safari: Settings → Safari → Advanced → Web Inspector (enable) - - Connect to Mac with Safari → Develop menu → your phone - - In console: `document.cookie` - copy the sessionid value - - Format as: `[{"name":"sessionid","value":"YOUR_VALUE_HERE"}]` - -> **Tip**: The easiest option for iOS users is to use any desktop/laptop computer (Windows, Mac, Linux, Chromebook) to do the one-time cookie setup. +--- +## Configuration ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| +| `PYTHONUNBUFFERED` | `1` | Real-time Python logging | | `ADMIN_PASSWORD` | `admin123` | Password for `/admin` page | -| `CACHE_DIR` | `/app/cache` | Video cache directory | -| `MAX_CACHE_SIZE_MB` | `500` | Maximum cache size | -| `CACHE_TTL_HOURS` | `24` | Cache expiration | -> **Security Note**: Cookies are stored locally in the `session/` volume. Anyone with the admin password can view/update them. +### Volumes +| Path | Description | +|------|-------------| +| `/app/cache` | Video cache (LRU, max usage limited by disk space) | +| `/app/cookies.json` | TikTok session cookies (persist across restarts) | -## 🐛 Troubleshooting +### Health Check -### Videos not loading? -- Check if the backend is running: `curl http://localhost:8002/health` -- Check logs: `docker-compose logs -f` -- Try re-logging in (sessions can expire) +The container includes a health check endpoint. You can verify with: -### Browser errors on headless server? -- Ensure `shm_size: '2gb'` is set in docker-compose -- Xvfb is included in the Docker image for virtual display - -### Cache issues? -- Clear cache: `docker exec purestream rm -rf /app/cache/*` -- Restart container: `docker-compose restart` - -## 📄 License - -MIT License - feel free to use, modify, and distribute. - -## 🙏 Acknowledgments - -- Built with [FastAPI](https://fastapi.tiangolo.com/) & [React](https://react.dev/) -- Browser automation by [Playwright](https://playwright.dev/) -- Video extraction by [yt-dlp](https://github.com/yt-dlp/yt-dlp) +```bash +curl http://localhost:8002/health +# Expected: {"status":"ok"} +``` --- -**Made with ❤️ for distraction-free viewing** +## Troubleshooting + +### Videos Not Loading + +```bash +# Check backend health +curl http://localhost:8002/health + +# View logs +docker compose logs -f + +# Verify cookies exist +cat cookies.json +``` + +### Container Won't Start + +```bash +# Check logs +docker compose logs + +# Verify port 8002 is not in use +netstat -tlnp | grep 8002 +``` + +### Out of Memory + +Increase memory limits or clear cache: + +```bash +# Clear video cache +rm -rf ./cache/* +docker compose restart +``` + +### Update to Latest Version + +```bash +git pull +docker compose up -d --build +``` + +--- + +## Project Structure + +``` +kv-tiktok/ +├── backend/ +│ ├── api/routes/ # API endpoints +│ ├── core/ # Core services (Playwright, Crawler) +│ └── main.py # FastAPI application +├── frontend/ +│ ├── src/ +│ │ ├── components/ # React components +│ │ └── App.tsx +│ └── package.json +├── Dockerfile # Multi-stage build +├── docker-compose.yml # Container orchestration +└── README.md +``` + +## Synology NAS Compatibility + +Tested on Synology models with x86/x64 processors. For ARM-based models (e.g., DS220+, DS920+), the `linux/amd64` image works via emulation, but performance may be slower. + +## License + +MIT License \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 12d6664..4f45725 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,54 +1,27 @@ -version: '3.8' +name: kv-tiktok services: - purestream: - image: vndangkhoa/purestream:latest - container_name: purestream + kv-tiktok: + image: kv-tiktok:latest + build: + context: . + dockerfile: Dockerfile + platforms: + - linux/amd64 + container_name: kv-tiktok restart: unless-stopped ports: - "8002:8002" volumes: - ./cache:/app/cache - - ./session:/app/backend/session + - ./cookies.json:/app/cookies.json environment: - PYTHONUNBUFFERED=1 - - CACHE_DIR=/app/cache - - MAX_CACHE_SIZE_MB=500 - - CACHE_TTL_HOURS=24 - - ADMIN_PASSWORD=admin123 # Change this to your secure password - shm_size: '2gb' - networks: - - purestream_net + - ADMIN_PASSWORD=admin123 + shm_size: 2gb healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:8002/health" ] + test: ["CMD", "curl", "-f", "http://localhost:8002/health"] interval: 30s timeout: 10s retries: 3 - start_period: 60s - labels: - - "com.centurylinklabs.watchtower.enable=true" - - # Auto-updater: Checks for new images every 5 minutes - watchtower: - image: containrrr/watchtower - container_name: watchtower - restart: unless-stopped - volumes: - - /var/run/docker.sock:/var/run/docker.sock - environment: - - WATCHTOWER_CLEANUP=true # Remove old images - - WATCHTOWER_POLL_INTERVAL=300 # Check every 5 minutes - - WATCHTOWER_INCLUDE_RESTARTING=true - - WATCHTOWER_ROLLING_RESTART=true # Graceful restart - - WATCHTOWER_LABEL_ENABLE=true # Only update labeled containers - networks: - - purestream_net - -networks: - purestream_net: - driver: bridge - ipam: - driver: default - config: - # Using 10.10.0.0 is much safer and less likely to overlap - - subnet: 10.10.0.0/16 + start_period: 60s \ No newline at end of file