mirror of
https://github.com/sartoopjj/thefeed.git
synced 2026-05-18 02:14:43 +03:00
feat: add Docker support for server deployment
Add Docker deployment option for the server with multi-stage build. Changes: - Dockerfile: multi-stage build (golang:1.26-alpine → alpine:3.21, ~23MB) - docker-compose.yml: server service on port 5300/udp with iptables redirect - .env.example: documented environment variables template - .dockerignore: optimized build context - README.md & README-FA.md: Docker deployment guide, port 53 safety checks, and troubleshooting instructions (both EN and FA) - configs: added more Telegram channels and X accounts The container listens on port 5300 to avoid conflict with systemd-resolved. External DNS traffic (port 53) is redirected via iptables PREROUTING. No changes to existing Go source code.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
# Build outputs
|
||||
build/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Git
|
||||
.git/
|
||||
.gitignore
|
||||
|
||||
# Data (user-specific, mounted as volume)
|
||||
data/
|
||||
thefeeddata/
|
||||
.thefeed/
|
||||
|
||||
# Environment secrets
|
||||
.env
|
||||
|
||||
# Session data
|
||||
session.json
|
||||
|
||||
# Agent config
|
||||
.agent/
|
||||
|
||||
# Temporary
|
||||
tmp/
|
||||
todo
|
||||
todo.md
|
||||
|
||||
# Documentation (not needed in image)
|
||||
README.md
|
||||
README-FA.md
|
||||
LICENSE
|
||||
docs/
|
||||
|
||||
# Android (not relevant for server)
|
||||
android/
|
||||
|
||||
# Tests (not needed in production image)
|
||||
test/
|
||||
|
||||
# Scripts (not needed in image)
|
||||
scripts/
|
||||
@@ -0,0 +1,40 @@
|
||||
# ============================================================
|
||||
# thefeed-server — Docker Environment Variables
|
||||
# ============================================================
|
||||
# Copy this file to .env and fill in your values:
|
||||
# cp .env.example .env
|
||||
# ============================================================
|
||||
|
||||
# ----- Required -----
|
||||
|
||||
# Your DNS domain (e.g., t.example.com)
|
||||
THEFEED_DOMAIN=t.example.com
|
||||
|
||||
# Encryption passphrase (shared between server and client)
|
||||
THEFEED_KEY=your-secret-passphrase
|
||||
|
||||
# ----- Telegram Mode -----
|
||||
# Default: --no-telegram (public channels only, no login needed)
|
||||
# To use Telegram API, uncomment these AND remove --no-telegram from compose:
|
||||
|
||||
#TELEGRAM_API_ID=12345
|
||||
#TELEGRAM_API_HASH=your-api-hash
|
||||
#TELEGRAM_PHONE=+1234567890
|
||||
#TELEGRAM_PASSWORD=your-2fa-password
|
||||
|
||||
# ----- Optional Settings -----
|
||||
|
||||
# Max messages per channel (default: 15)
|
||||
#THEFEED_MSG_LIMIT=15
|
||||
|
||||
# Allow remote channel management via DNS (default: disabled)
|
||||
#THEFEED_ALLOW_MANAGE=0
|
||||
|
||||
# Nitter RSS instances for X/Twitter (comma-separated)
|
||||
#THEFEED_X_RSS_INSTANCES=http://nitter.net,https://nitter.net
|
||||
|
||||
# Max random padding bytes in DNS responses (anti-DPI, default: 32)
|
||||
#THEFEED_PADDING=32
|
||||
|
||||
# Log every decoded DNS query (default: disabled)
|
||||
#THEFEED_DEBUG=0
|
||||
@@ -23,6 +23,7 @@ session.json
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
|
||||
todo
|
||||
todo.md
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
# ============================================================
|
||||
# thefeed-server — Multi-stage Docker build
|
||||
# ============================================================
|
||||
# Build: docker compose build
|
||||
# Run: docker compose up -d
|
||||
# Login: docker compose run -it --rm server --login-only \
|
||||
# --data-dir /data --domain $THEFEED_DOMAIN \
|
||||
# --key $THEFEED_KEY --api-id $TELEGRAM_API_ID \
|
||||
# --api-hash $TELEGRAM_API_HASH --phone $TELEGRAM_PHONE
|
||||
# ============================================================
|
||||
|
||||
# ---- Stage 1: Build ----
|
||||
FROM golang:1.26-alpine AS builder
|
||||
|
||||
RUN apk add --no-cache git ca-certificates tzdata
|
||||
|
||||
WORKDIR /src
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
|
||||
# Build-time version info (overridable via --build-arg)
|
||||
ARG VERSION=docker
|
||||
ARG COMMIT=unknown
|
||||
ARG DATE=unknown
|
||||
|
||||
RUN CGO_ENABLED=0 go build -trimpath \
|
||||
-ldflags="-s -w \
|
||||
-X github.com/sartoopjj/thefeed/internal/version.Version=${VERSION} \
|
||||
-X github.com/sartoopjj/thefeed/internal/version.Commit=${COMMIT} \
|
||||
-X github.com/sartoopjj/thefeed/internal/version.Date=${DATE}" \
|
||||
-o /thefeed-server ./cmd/server
|
||||
|
||||
# ---- Stage 2: Runtime ----
|
||||
FROM alpine:3.21
|
||||
|
||||
# Copy ca-certificates and tzdata from builder (avoids second apk fetch
|
||||
# which can fail on restricted networks).
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
||||
# Non-root user for security
|
||||
RUN adduser -D -u 1000 -h /data thefeed
|
||||
|
||||
COPY --from=builder /thefeed-server /usr/local/bin/thefeed-server
|
||||
|
||||
# Data directory: channels.txt, x_accounts.txt, session.json, cache
|
||||
VOLUME /data
|
||||
|
||||
# DNS listen port (mapped to host:53 via docker-compose)
|
||||
EXPOSE 5300/udp
|
||||
|
||||
USER thefeed
|
||||
WORKDIR /data
|
||||
|
||||
ENTRYPOINT ["thefeed-server"]
|
||||
CMD ["--data-dir", "/data", "--listen", ":5300"]
|
||||
+119
@@ -107,6 +107,125 @@ sudo bash install.sh --login
|
||||
sudo bash install.sh --uninstall
|
||||
```
|
||||
|
||||
## 🐳 نصب با Docker (سرور)
|
||||
|
||||
اجرای سرور با Docker — بدون نیاز به نصب Go.
|
||||
|
||||
### شروع سریع (کانالهای عمومی، بدون لاگین تلگرام)
|
||||
|
||||
```bash
|
||||
# ۱. تنظیم محیط
|
||||
cp .env.example .env
|
||||
nano .env # مقادیر THEFEED_DOMAIN و THEFEED_KEY را وارد کنید
|
||||
|
||||
# ۲. آمادهسازی دایرکتوری داده
|
||||
mkdir -p data
|
||||
cp configs/channels.txt data/
|
||||
cp configs/x_accounts.txt data/ # اختیاری
|
||||
|
||||
# ۳. ساخت و اجرا
|
||||
docker compose up -d
|
||||
|
||||
# ۴. هدایت ترافیک DNS خارجی به کانتینر
|
||||
# نام اینترفیس شبکه خود را با ip a پیدا کنید و eth0 را جایگزین کنید
|
||||
sudo iptables -t nat -I PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300
|
||||
sudo iptables -I INPUT -p udp --dport 5300 -j ACCEPT
|
||||
sudo ip6tables -t nat -I PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300
|
||||
sudo ip6tables -I INPUT -p udp --dport 5300 -j ACCEPT
|
||||
|
||||
# ماندگار کردن قوانین iptables بعد از ریبوت
|
||||
sudo apt install -y iptables-persistent
|
||||
sudo netfilter-persistent save
|
||||
|
||||
# ۵. مشاهده لاگها
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
> **توجه:** کانتینر روی پورت 5300 listen میکند (نه 53) تا با `systemd-resolved` تداخل نداشته باشد.
|
||||
> قانون `iptables PREROUTING` فقط ترافیک DNS **خارجی** (پورت 53) را به کانتینر هدایت میکند
|
||||
> و DNS محلی سرور بدون مشکل کار میکند.
|
||||
|
||||
### با تلگرام (لاگین یکباره)
|
||||
|
||||
```bash
|
||||
# ۱. تنظیم محیط (متغیرهای تلگرام را در .env از حالت کامنت خارج کنید)
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
|
||||
# ۲. لاگین یکباره (تعاملی — کد تأیید را وارد کنید)
|
||||
docker compose run -it --rm server \
|
||||
--login-only --data-dir /data \
|
||||
--domain YOUR_DOMAIN --key YOUR_KEY \
|
||||
--api-id YOUR_API_ID --api-hash YOUR_HASH \
|
||||
--phone YOUR_PHONE
|
||||
|
||||
# ۳. در docker-compose.yml فلگ --no-telegram را حذف و فلگهای تلگرام را اضافه کنید
|
||||
# ۴. اجرای سرور
|
||||
docker compose up -d
|
||||
# ۵. تنظیم iptables redirect (مشابه قدم ۴ در شروع سریع)
|
||||
```
|
||||
|
||||
### جزئیات Docker
|
||||
|
||||
| مورد | مقدار |
|
||||
|------|-------|
|
||||
| ایمیج پایه | `alpine:3.21` (حدود ۲۳ مگابایت) |
|
||||
| ساخت | دو مرحلهای (`golang:1.26-alpine` → `alpine`) |
|
||||
| کاربر | `thefeed` (UID 1000، غیر root) |
|
||||
| پورت کانتینر | `:5300/udp` (هاست `:5300/udp` + iptables redirect از `:53`) |
|
||||
| داده | ولوم `./data` (کانالها، session، کش) |
|
||||
| تنظیمات | فایل `.env` (در git ذخیره نمیشود) |
|
||||
|
||||
```bash
|
||||
# ساخت مجدد بعد از تغییرات کد
|
||||
docker compose build
|
||||
|
||||
# توقف
|
||||
docker compose down
|
||||
```
|
||||
|
||||
### ایمنی پورت ۵۳ و سرویسها
|
||||
|
||||
کانتینر روی پورت **5300** (نه 53) listen میکند تا با `systemd-resolved` یا سرویسهای DNS دیگر سرور تداخل نداشته باشد. ترافیک DNS خارجی توسط `iptables PREROUTING` هدایت میشود که **فقط** بستههای ورودی از اینترفیس شبکه خارجی را تحت تأثیر قرار میدهد — DNS محلی سرور **دستنخورده** باقی میماند.
|
||||
|
||||
**قبل از راهاندازی — بررسی پورت ۵۳:**
|
||||
|
||||
```bash
|
||||
# چه سرویسی از پورت 53 استفاده میکند؟
|
||||
ss -ulnp | grep ':53 '
|
||||
|
||||
# نتیجه مورد انتظار: فقط systemd-resolved روی 127.0.0.53 (بیخطر)
|
||||
# UNCONN 127.0.0.53%lo:53 users:(("systemd-resolve",...))
|
||||
```
|
||||
|
||||
**بعد از راهاندازی — بررسی سلامت سرویسها:**
|
||||
|
||||
```bash
|
||||
# ۱. DNS محلی سرور هنوز کار میکند
|
||||
dig +short google.com @127.0.0.53
|
||||
|
||||
# ۲. کانتینر thefeed در حال اجراست
|
||||
docker ps --filter name=thefeed
|
||||
|
||||
# ۳. کانالها در حال دریافت هستند
|
||||
docker logs thefeed-server --tail 5
|
||||
|
||||
# ۴. قانون iptables فعال است
|
||||
iptables -t nat -L PREROUTING -n | grep 5300
|
||||
|
||||
# ۵. بقیه کانتینرها سالم هستند
|
||||
docker ps --format 'table {{.Names}}\t{{.Status}}' | head -10
|
||||
```
|
||||
|
||||
**اگر مشکلی پیش آمد — حذف فوری redirect:**
|
||||
|
||||
```bash
|
||||
# حذف قانون iptables (بازگشت به حالت اولیه)
|
||||
sudo iptables -t nat -D PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300
|
||||
sudo iptables -D INPUT -p udp --dport 5300 -j ACCEPT
|
||||
sudo netfilter-persistent save
|
||||
```
|
||||
|
||||
## 🖥️ نصب کلاینت
|
||||
|
||||
### لینوکس / macOS / ویندوز
|
||||
|
||||
@@ -80,6 +80,125 @@ sudo bash -c "$(curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/mai
|
||||
Re-login: `curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh | sudo bash -s -- --login`
|
||||
Uninstall: `curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh | sudo bash -s -- --uninstall`
|
||||
|
||||
## Docker Deployment (Server)
|
||||
|
||||
Run the server with Docker — no Go toolchain needed.
|
||||
|
||||
### Quick Start (public channels, no Telegram login)
|
||||
|
||||
```bash
|
||||
# 1. Configure environment
|
||||
cp .env.example .env
|
||||
nano .env # set THEFEED_DOMAIN and THEFEED_KEY
|
||||
|
||||
# 2. Prepare data directory with your channels
|
||||
mkdir -p data
|
||||
cp configs/channels.txt data/
|
||||
cp configs/x_accounts.txt data/ # optional
|
||||
|
||||
# 3. Build and run
|
||||
docker compose up -d
|
||||
|
||||
# 4. Redirect external DNS traffic to the container
|
||||
# Replace eth0 with your network interface (check with: ip a)
|
||||
sudo iptables -t nat -I PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300
|
||||
sudo iptables -I INPUT -p udp --dport 5300 -j ACCEPT
|
||||
sudo ip6tables -t nat -I PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300
|
||||
sudo ip6tables -I INPUT -p udp --dport 5300 -j ACCEPT
|
||||
|
||||
# Make iptables rules persistent across reboots
|
||||
sudo apt install -y iptables-persistent
|
||||
sudo netfilter-persistent save
|
||||
|
||||
# 5. View logs
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
> **Note:** The container listens on port 5300 (not 53) to avoid conflict with `systemd-resolved`.
|
||||
> The `iptables PREROUTING` rule redirects only **external** DNS traffic (port 53) to the container,
|
||||
> while local DNS resolution on the server continues to work normally.
|
||||
|
||||
### With Telegram (one-time interactive login)
|
||||
|
||||
```bash
|
||||
# 1. Configure environment (uncomment Telegram vars in .env)
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
|
||||
# 2. One-time login (interactive — enter auth code when prompted)
|
||||
docker compose run -it --rm server \
|
||||
--login-only --data-dir /data \
|
||||
--domain YOUR_DOMAIN --key YOUR_KEY \
|
||||
--api-id YOUR_API_ID --api-hash YOUR_HASH \
|
||||
--phone YOUR_PHONE
|
||||
|
||||
# 3. Edit docker-compose.yml: remove --no-telegram and add Telegram flags
|
||||
# 4. Start the server
|
||||
docker compose up -d
|
||||
# 5. Set up iptables redirect (same as Quick Start step 4)
|
||||
```
|
||||
|
||||
### Docker Details
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Base image | `alpine:3.21` (~23 MB total) |
|
||||
| Build | Multi-stage (`golang:1.26-alpine` → `alpine`) |
|
||||
| User | `thefeed` (UID 1000, non-root) |
|
||||
| Container port | `:5300/udp` (host `:5300/udp` + iptables redirect from `:53`) |
|
||||
| Data | `./data` volume (channels, session, cache) |
|
||||
| Config | `.env` file (gitignored) |
|
||||
|
||||
```bash
|
||||
# Rebuild after code changes
|
||||
docker compose build
|
||||
|
||||
# Stop
|
||||
docker compose down
|
||||
```
|
||||
|
||||
### Port 53 & Service Safety
|
||||
|
||||
The container listens on port **5300** (not 53) to avoid conflicts with `systemd-resolved` or other DNS services on the host. External DNS traffic is redirected via `iptables PREROUTING` which only affects packets arriving on the external network interface — local DNS resolution is **not** affected.
|
||||
|
||||
**Before setup — check what uses port 53:**
|
||||
|
||||
```bash
|
||||
# Check if port 53 is in use
|
||||
ss -ulnp | grep ':53 '
|
||||
|
||||
# Expected: systemd-resolved on 127.0.0.53 only (safe)
|
||||
# UNCONN 127.0.0.53%lo:53 users:(("systemd-resolve",...))
|
||||
```
|
||||
|
||||
**After setup — verify nothing is broken:**
|
||||
|
||||
```bash
|
||||
# 1. Local DNS still works (server can resolve domains)
|
||||
dig +short google.com @127.0.0.53
|
||||
|
||||
# 2. thefeed container is running
|
||||
docker ps --filter name=thefeed
|
||||
|
||||
# 3. thefeed is fetching channels
|
||||
docker logs thefeed-server --tail 5
|
||||
|
||||
# 4. iptables rule is active
|
||||
iptables -t nat -L PREROUTING -n | grep 5300
|
||||
|
||||
# 5. Other containers are healthy
|
||||
docker ps --format 'table {{.Names}}\t{{.Status}}' | head -10
|
||||
```
|
||||
|
||||
**If something goes wrong — remove the redirect instantly:**
|
||||
|
||||
```bash
|
||||
# Remove the iptables rule (restores original behavior)
|
||||
sudo iptables -t nat -D PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300
|
||||
sudo iptables -D INPUT -p udp --dport 5300 -j ACCEPT
|
||||
sudo netfilter-persistent save
|
||||
```
|
||||
|
||||
## Manual Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
# Telegram channel usernames (one per line, with or without @)
|
||||
# Channel numbers are assigned in order: first = channel 1, second = channel 2, etc.
|
||||
# Lines starting with # are comments
|
||||
@networkt
|
||||
@thefeedconfig
|
||||
@VahidOnline
|
||||
@ThMahiar
|
||||
@Media_HB
|
||||
@rastadco
|
||||
@Indypersian
|
||||
@bbcpersian
|
||||
@radiofarda
|
||||
@IraneAzad_News
|
||||
@farsivoa
|
||||
@IranintlTV
|
||||
@jangaavaran1390
|
||||
|
||||
@@ -2,4 +2,12 @@
|
||||
# Lines starting with # are comments
|
||||
PahlaviReza
|
||||
RezaVaisi
|
||||
|
||||
IranIntlbrk
|
||||
indypersian
|
||||
IDFFarsi
|
||||
IranIntl
|
||||
pouriazeraati
|
||||
CENTCOMFarsi
|
||||
IsraelPersian
|
||||
Vahid
|
||||
euronews_pe
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# ============================================================
|
||||
# thefeed-server — Docker Compose
|
||||
# ============================================================
|
||||
#
|
||||
# Quick start (public channels, no Telegram login):
|
||||
# 1. cp .env.example .env (edit with your domain & key)
|
||||
# 2. mkdir -p data && cp configs/channels.txt data/
|
||||
# 3. docker compose up -d
|
||||
# 4. Set up iptables to redirect external port 53 to 5300:
|
||||
# sudo iptables -t nat -I PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300
|
||||
# sudo iptables -I INPUT -p udp --dport 5300 -j ACCEPT
|
||||
# (replace eth0 with your network interface — check with: ip a)
|
||||
#
|
||||
# With Telegram (one-time login first):
|
||||
# 1. cp .env.example .env (uncomment Telegram vars)
|
||||
# 2. docker compose run -it --rm server \
|
||||
# --login-only --data-dir /data \
|
||||
# --domain ${THEFEED_DOMAIN} --key ${THEFEED_KEY} \
|
||||
# --api-id ${TELEGRAM_API_ID} --api-hash ${TELEGRAM_API_HASH} \
|
||||
# --phone ${TELEGRAM_PHONE}
|
||||
# 3. Remove --no-telegram from the command below
|
||||
# 4. docker compose up -d
|
||||
#
|
||||
# Logs: docker compose logs -f
|
||||
# Stop: docker compose down
|
||||
# ============================================================
|
||||
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
VERSION: ${VERSION:-docker}
|
||||
COMMIT: ${COMMIT:-unknown}
|
||||
DATE: ${DATE:-unknown}
|
||||
container_name: thefeed-server
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "5300:5300/udp"
|
||||
volumes:
|
||||
- ./data:/data
|
||||
env_file:
|
||||
- .env
|
||||
command: >-
|
||||
--data-dir /data
|
||||
--listen :5300
|
||||
--domain ${THEFEED_DOMAIN}
|
||||
--key ${THEFEED_KEY}
|
||||
--no-telegram
|
||||
# To enable Telegram mode:
|
||||
# 1. Run login-only first (see instructions above)
|
||||
# 2. Replace the command above with:
|
||||
# command: >-
|
||||
# --data-dir /data
|
||||
# --listen :5300
|
||||
# --domain ${THEFEED_DOMAIN}
|
||||
# --key ${THEFEED_KEY}
|
||||
# --api-id ${TELEGRAM_API_ID}
|
||||
# --api-hash ${TELEGRAM_API_HASH}
|
||||
# --phone ${TELEGRAM_PHONE}
|
||||
Reference in New Issue
Block a user