Skip to content
Open
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
25 changes: 25 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Keep secrets out of the Docker build context
docker/.env

# Git metadata
.git
.gitignore

# Python caches / build artifacts
__pycache__/
*.py[cod]
*.pyo
*.egg-info/
.pytest_cache/
dist/
build/

# Virtual environments (built fresh in the image)
hysteria2_venv/
venv/
.venv/

# Editor and OS files
.DS_Store
*.swp
*.swo
65 changes: 65 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Stage 1: Build Go auth server
FROM golang:1.22-bookworm AS go-builder

WORKDIR /build
COPY core/scripts/auth/user_auth.go .
RUN echo "precedence ::ffff:0:0/96 100" >> /etc/gai.conf && \
go mod init hysteria_auth && go mod tidy && go build -o user_auth .

# Stage 2: Runtime
FROM ubuntu:24.04

# TARGETARCH is set automatically by Docker (amd64, arm64, arm/v7, etc.)
ARG TARGETARCH

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
python3 \
python3-venv \
curl \
openssl \
jq \
lsof \
supervisor \
wireguard-tools \
iptables \
iproute2 \
&& rm -rf /var/lib/apt/lists/*

# Install Hysteria2 binary from GitHub Releases using Docker TARGETARCH
RUN HY_VERSION=$(curl -fsSL "https://api.github.com/repos/apernet/hysteria/releases/latest" \
| grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"//;s/".*//') && \
echo "Downloading hysteria ${HY_VERSION} for linux-${TARGETARCH}..." && \
curl -fsSL -o /usr/local/bin/hysteria \
"https://github.com/apernet/hysteria/releases/download/${HY_VERSION}/hysteria-linux-${TARGETARCH}" && \
chmod +x /usr/local/bin/hysteria

# Copy compiled Go auth server
COPY --chmod=755 --from=go-builder /build/user_auth /etc/hysteria/core/scripts/auth/user_auth

# Copy application source
COPY . /etc/hysteria/

# Create Python venv, install dependencies, and expose packages to system python3
RUN python3 -m venv /etc/hysteria/hysteria2_venv && \
/etc/hysteria/hysteria2_venv/bin/pip install --no-cache-dir -r /etc/hysteria/requirements.txt && \
find /etc/hysteria/hysteria2_venv/lib -name site-packages -type d \
> /usr/lib/python3/dist-packages/hysteria-venv.pth

# Download geo data at build time (same as bare-metal install.sh)
RUN curl -fsSL --max-time 30 -o /etc/hysteria/geosite.dat \
"https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geosite.dat" && \
curl -fsSL --max-time 30 -o /etc/hysteria/geoip.dat \
"https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geoip.dat"

# Preserve the repo config.json as a template (entrypoint symlinks config.json to volume)
RUN cp /etc/hysteria/config.json /etc/hysteria/config.json.template

# Install systemctl shim so existing scripts work in Docker
COPY --chmod=755 docker/systemctl-shim.sh /usr/local/bin/systemctl

# Copy entrypoint
COPY --chmod=755 docker/entrypoint.sh /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,36 @@ There is no need to execute the installation command again.



## 🐳 Docker Installation (Local Build)

> **Note:** This is a local build method for development and testing. A pre-built image on Docker Hub is planned for the future.

### Prerequisites

- [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/)

### Quick Start

```bash
# 1. Clone the repository
git clone https://github.com/ReturnFI/Blitz.git
cd Blitz

# 2. Create and configure your environment file
cp docker/.env.example docker/.env
nano docker/.env

# 3. Build and start
docker compose up -d --build

# 4. Get the admin password and web panel URL from the logs
docker logs blitz 2>&1 | grep -E "ADMIN PASSWORD|Access at"
```

For the full list of environment variables, architecture details, common operations, and troubleshooting, see [docker/README.md](docker/README.md).

---

## 💎 Sponsorship & Support 💖


Expand Down
25 changes: 25 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
services:
mongodb:
image: mongo:8.0
container_name: mongodb
restart: unless-stopped
network_mode: "host"
volumes:
- mongodb_data:/data/db

blitz:
build: .
container_name: blitz
restart: on-failure:5
network_mode: "host"
cap_add:
- NET_ADMIN # required for WARP (wireguard) and IP limiting (iptables)
env_file: docker/.env
volumes:
- blitz_data:/blitz-data
depends_on:
- mongodb

volumes:
blitz_data:
mongodb_data:
32 changes: 32 additions & 0 deletions docker/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Hysteria2 core
HYSTERIA_PORT=8080
# Domain or IP for TLS cert + subscription URIs (auto-detected from ip.sb if blank)
HYSTERIA_SNI=
SERVER_IPV6=

# OBFS Salamander — leave empty to disable
# Note: OBFS and MASQUERADE are mutually exclusive. If both are set, OBFS takes priority.
OBFS_PASSWORD=

# Masquerade — disguise Hysteria2 as a regular website when probed
# Set to a URL (e.g. https://example.com) to proxy requests to that site
# Set to "string" to return a generic HTTP 502 response
# Leave empty to disable (default)
MASQUERADE_URL=

# Web panel (always on)
WEBPANEL_PORT=2096
ADMIN_USERNAME=admin
# If blank, a random password is generated and printed to logs on first start
ADMIN_PASSWORD=
WEBPANEL_EXPIRATION_MINUTES=1440

# NormalSub subscription service (optional)
NORMALSUB_ENABLED=false
NORMALSUB_PORT=2095

# Telegram bot (optional)
TELEGRAM_ENABLED=false
TELEGRAM_BOT_TOKEN=
TELEGRAM_ADMIN_USER_IDS=
TELEGRAM_BACKUP_INTERVAL_HOUR=6
135 changes: 135 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Blitz — Docker Deployment

## Quick Start

```bash
# 1. Copy and edit the environment file
cp docker/.env.example docker/.env
nano docker/.env

# 2. Build and start
docker compose up -d --build

# 3. Check logs for the admin password and web panel URL
docker logs blitz 2>&1 | grep -E "ADMIN PASSWORD|Access at"

# 4. Check all services are running
docker exec blitz supervisorctl -c /tmp/supervisord.conf status
```

## Environment Variables

Create `docker/.env` from `docker/.env.example` and configure the following:

### Hysteria2 Core

| Variable | Default | Description |
|----------|---------|-------------|
| `HYSTERIA_PORT` | `8080` | UDP port for the Hysteria2 server. Must be open in the firewall (the entrypoint opens it automatically via iptables). |
| `HYSTERIA_SNI` | *(auto-detected)* | Domain or IP used as the TLS certificate CN and in client URIs. If blank, the public IP is auto-detected via `ip.sb`. |
| `SERVER_IPV6` | *(empty)* | Server IPv6 address. Used in `.configs.env` for client URI generation. |

### Traffic Obfuscation

OBFS and Masquerade are **mutually exclusive**. If both are set, OBFS takes priority.

| Variable | Default | Description |
|----------|---------|-------------|
| `OBFS_PASSWORD` | *(random)* | Salamander obfuscation password. If blank, a random 32-char password is generated. Set explicitly to share across reinstalls. |
| `MASQUERADE_URL` | *(empty)* | Disguise Hysteria2 when probed by non-clients. Set to a URL (e.g. `https://example.com`) to proxy requests to that site, or `string` to return a generic HTTP 502 response. **Only works when `OBFS_PASSWORD` is not set.** |

### Web Panel

| Variable | Default | Description |
|----------|---------|-------------|
| `WEBPANEL_PORT` | `2096` | TCP port for the web panel. Opened automatically in iptables. |
| `ADMIN_USERNAME` | `admin` | Web panel admin username. |
| `ADMIN_PASSWORD` | *(random)* | Web panel admin password. If blank, a random 16-char password is generated and printed to the container logs on first start. |
| `WEBPANEL_EXPIRATION_MINUTES` | `1440` | Admin session expiration time in minutes (1440 = 24 hours). |

### NormalSub (Optional)

| Variable | Default | Description |
|----------|---------|-------------|
| `NORMALSUB_ENABLED` | `false` | Set to `true` to enable the NormalSub subscription service. |
| `NORMALSUB_PORT` | `2095` | TCP port for the NormalSub service. |

### Telegram Bot (Optional)

| Variable | Default | Description |
|----------|---------|-------------|
| `TELEGRAM_ENABLED` | `false` | Set to `true` to enable the Telegram bot. |
| `TELEGRAM_BOT_TOKEN` | *(empty)* | Telegram Bot API token from @BotFather. Required if enabled. |
| `TELEGRAM_ADMIN_USER_IDS` | *(empty)* | Comma-separated Telegram user IDs with admin access (e.g. `123456,789012`). |
| `TELEGRAM_BACKUP_INTERVAL_HOUR` | `6` | Automatic backup interval in hours. |

## Architecture

The Docker deployment runs everything in **two containers**:

| Container | Description |
|-----------|-------------|
| `mongodb` | MongoDB 8.0 database |
| `blitz` | All Blitz services managed by supervisord |

Services inside the `blitz` container:

| Service | Description |
|---------|-------------|
| `hysteria-server` | Hysteria2 proxy server |
| `hysteria-auth` | Go-based authentication server |
| `hysteria-scheduler` | Traffic tracking and user expiration scheduler |
| `hysteria-webpanel` | Web management panel (hypercorn/FastAPI) |
| `hysteria-normalsub` | Subscription service (if enabled) |
| `hysteria-telegrambot` | Telegram bot (if enabled) |

Both containers use `network_mode: "host"` for direct access to host networking.

## Data Persistence

All persistent data is stored in the `blitz_data` Docker volume:

- `config.json` — Hysteria2 server configuration
- `ca.crt` / `ca.key` — TLS certificates
- `.configs.env` — Server IP/SNI configuration
- `webpanel.env` — Web panel credentials and settings
- `normalsub.env` — NormalSub settings
- `telegrambot.env` — Telegram bot settings
- `.initialized` — First-run marker

## Common Operations

```bash
# View service status
docker exec blitz supervisorctl -c /tmp/supervisord.conf status

# Restart Hysteria2 server
docker exec blitz supervisorctl -c /tmp/supervisord.conf restart hysteria-server

# View logs
docker logs blitz

# List users
docker exec blitz python3 /etc/hysteria/core/cli.py list-users

# Get user connection URI
docker exec blitz python3 /etc/hysteria/core/cli.py show-user-uri -u <username> -ip 4

# Full rebuild (reset all data)
docker compose down
docker volume rm blitz_blitz_data
docker compose up -d --build
```

## Troubleshooting

**Web panel not accessible externally:** Ensure `WEBPANEL_PORT` is open. The entrypoint opens it via iptables, but some cloud providers have separate firewall rules.

**Hysteria2 clients can't connect:** Ensure `HYSTERIA_PORT` is open for **UDP** traffic. The entrypoint opens it via iptables automatically.

**Forgot admin password:** Remove the volume and rebuild to regenerate credentials:
```bash
docker compose down && docker volume rm blitz_blitz_data && docker compose up -d --build
```

**Services show FATAL:** Check `docker logs blitz` for error details. Common causes: port already in use, invalid config.json.
Loading