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
57 changes: 14 additions & 43 deletions src/apps/relay-server/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,57 +1,28 @@
# Multi-stage build for BitFun Relay Server
FROM rust:1.82-slim AS builder
# BitFun Relay Server — standalone Docker build.
# Build context is relay-server root (Cargo.toml + src/), no workspace needed.
FROM rust:1.85-slim AS builder

WORKDIR /build

# Install build dependencies
RUN apt-get update && apt-get install -y pkg-config libssl-dev && rm -rf /var/lib/apt/lists/*

# Copy all workspace Cargo.toml files (including nested path deps in bitfun-core)
COPY Cargo.toml Cargo.lock ./
COPY src/crates/events/Cargo.toml src/crates/events/Cargo.toml
COPY src/crates/core/Cargo.toml src/crates/core/Cargo.toml
COPY src/crates/core/src/infrastructure/ai/ai_stream_handlers/Cargo.toml src/crates/core/src/infrastructure/ai/ai_stream_handlers/Cargo.toml
COPY src/crates/core/src/agentic/tools/implementations/tool-runtime/Cargo.toml src/crates/core/src/agentic/tools/implementations/tool-runtime/Cargo.toml
COPY src/crates/core/src/service/terminal/Cargo.toml src/crates/core/src/service/terminal/Cargo.toml
COPY src/crates/transport/Cargo.toml src/crates/transport/Cargo.toml
COPY src/crates/api-layer/Cargo.toml src/crates/api-layer/Cargo.toml
COPY src/apps/cli/Cargo.toml src/apps/cli/Cargo.toml
COPY src/apps/desktop/Cargo.toml src/apps/desktop/Cargo.toml
COPY src/apps/server/Cargo.toml src/apps/server/Cargo.toml
COPY src/apps/relay-server/Cargo.toml src/apps/relay-server/Cargo.toml

# Create dummy source files for dependency caching
RUN mkdir -p src/crates/events/src && echo "pub fn dummy() {}" > src/crates/events/src/lib.rs && \
mkdir -p src/crates/core/src && echo "pub fn dummy() {}" > src/crates/core/src/lib.rs && \
mkdir -p src/crates/core/src/infrastructure/ai/ai_stream_handlers/src && echo "pub fn dummy() {}" > src/crates/core/src/infrastructure/ai/ai_stream_handlers/src/lib.rs && \
mkdir -p src/crates/core/src/agentic/tools/implementations/tool-runtime/src && echo "pub fn dummy() {}" > src/crates/core/src/agentic/tools/implementations/tool-runtime/src/lib.rs && \
mkdir -p src/crates/core/src/service/terminal/src && echo "pub fn dummy() {}" > src/crates/core/src/service/terminal/src/lib.rs && \
mkdir -p src/crates/transport/src && echo "pub fn dummy() {}" > src/crates/transport/src/lib.rs && \
mkdir -p src/crates/api-layer/src && echo "pub fn dummy() {}" > src/crates/api-layer/src/lib.rs && \
mkdir -p src/apps/cli/src && echo "fn main() {}" > src/apps/cli/src/main.rs && \
mkdir -p src/apps/desktop/src && echo "fn main() {}" > src/apps/desktop/src/main.rs && \
mkdir -p src/apps/server/src && echo "fn main() {}" > src/apps/server/src/main.rs && \
mkdir -p src/apps/relay-server/src && echo "pub fn dummy() {}" > src/apps/relay-server/src/lib.rs && \
echo "fn main() {}" > src/apps/relay-server/src/main.rs

# Build dependencies only (cached layer)
RUN cargo build --release -p bitfun-relay-server 2>/dev/null || true

# Copy actual source code
COPY src/apps/relay-server/src src/apps/relay-server/src

# Build the relay server
RUN cargo build --release -p bitfun-relay-server

# ── Runtime stage ─────────────────────────────────────────
COPY Cargo.toml ./
RUN mkdir -p src && echo 'fn main() { println!("placeholder"); }' > src/main.rs
RUN cargo build --release 2>/dev/null || true

RUN rm -rf src target/release/bitfun-relay-server target/release/deps/bitfun*

COPY src/ src/

RUN cargo build --release

FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY --from=builder /build/target/release/bitfun-relay-server /app/bitfun-relay-server

COPY src/apps/relay-server/static /app/static
RUN mkdir -p /app/static

ENV RELAY_PORT=9700
ENV RELAY_STATIC_DIR=/app/static
Expand Down
63 changes: 56 additions & 7 deletions src/apps/relay-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,44 @@ Only desktop clients connect via WebSocket. Mobile clients use the HTTP endpoint

## Self-Hosted Deployment

1. Clone the repository
2. Navigate to `src/apps/relay-server/`
3. Run `bash deploy.sh`
4. Configure DNS/firewall as needed
5. In BitFun desktop, select "Custom Server" and enter your server URL
### Option A: Local Deploy (on the server itself)

### Deployment Checklist (Recommended)
If you have the repo cloned **on the server**:

```bash
cd src/apps/relay-server/
bash deploy.sh
```

This builds the Docker image locally and starts the container. It will **automatically stop any previously running relay container** before restarting.

### Option B: Remote Deploy (from your dev machine)

Push code changes from your local dev machine to a remote server via SSH:

```bash
cd src/apps/relay-server/

# First-time setup (creates /opt/bitfun-relay, copies static/)
bash remote-deploy.sh 116.204.120.240 --first

# Subsequent updates (syncs src + rebuilds)
bash remote-deploy.sh 116.204.120.240
```

The script will:
1. Test SSH connectivity
2. **Stop the old container** if running
3. Sync source code (`src/`), `Cargo.toml`, `Dockerfile`, `docker-compose.yml`
4. Rebuild the Docker image on the server
5. Start the new container
6. Run a health check

**Prerequisites:**
- SSH key-based auth to the server (configured in `~/.ssh/config`)
- Docker + Docker Compose installed on the server

### Deployment Checklist

1. Open required ports:
- `9700` (relay direct access, optional if only via reverse proxy)
Expand All @@ -134,7 +165,25 @@ Only desktop clients connect via WebSocket. Mobile clients use the HTTP endpoint
3. Configure your final URL strategy:
- root domain (`https://relay.example.com`) or
- path prefix (`https://relay.example.com/relay`)
4. Fill the same URL into BitFun Desktop "Custom Server".
4. Fill the same URL into BitFun Desktop "Custom Server"

### Directory Structure

```
relay-server/
├── src/ # Rust source code
├── static/ # Mobile-web static files
├── Cargo.toml # Crate manifest (standalone, no workspace deps)
├── Dockerfile # Docker build (standalone single-crate build)
├── docker-compose.yml # Docker Compose config
├── Caddyfile # Caddy reverse proxy config (optional)
├── deploy.sh # Local deploy (run on the server itself)
├── remote-deploy.sh # Remote deploy (run from dev machine via SSH)
└── README.md
```

Relay server is a **standalone crate** — one set of code, one Dockerfile, one docker-compose.yml.
Whether deployed as a public relay, LAN relay, or NAT traversal relay, the build and runtime are identical.

### About `src/apps/server` vs `src/apps/relay-server`

Expand Down
15 changes: 11 additions & 4 deletions src/apps/relay-server/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,23 @@ echo "=== BitFun Relay Server Deploy ==="
check_command docker
check_docker_compose

# Build and start containers
cd "$SCRIPT_DIR"

# Stop old containers if running
echo "[1/3] Stopping old containers (if running)..."
docker compose down 2>/dev/null || true
echo " Done."

# Build
if [ "$SKIP_BUILD" = true ]; then
echo "[1/2] Skipping Docker build (--skip-build)"
echo "[2/3] Skipping Docker build (--skip-build)"
else
echo "[1/2] Building Docker images..."
echo "[2/3] Building Docker images..."
docker compose build
fi

echo "[2/2] Starting services..."
# Start
echo "[3/3] Starting services..."
docker compose up -d

if [ "$SKIP_HEALTH_CHECK" = false ]; then
Expand Down
45 changes: 23 additions & 22 deletions src/apps/relay-server/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
version: '3.8'

services:
relay-server:
build:
context: ../../..
dockerfile: src/apps/relay-server/Dockerfile
context: .
dockerfile: Dockerfile
container_name: bitfun-relay
restart: unless-stopped
ports:
- "9700:9700"
environment:
- RELAY_PORT=9700
- RELAY_STATIC_DIR=/app/static
- RELAY_ROOM_WEB_DIR=/app/room-web
- RELAY_ROOM_TTL=3600
volumes:
- relay-data:/app/data
- ./static:/app/static:ro
- room-web:/app/room-web

# Caddy reverse proxy for automatic HTTPS
caddy:
image: caddy:2-alpine
container_name: bitfun-caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy-data:/data
- caddy-config:/config
depends_on:
- relay-server
# Optional: Caddy reverse proxy for automatic HTTPS.
# Uncomment if you need HTTPS / domain-based access.
# caddy:
# image: caddy:2-alpine
# container_name: bitfun-caddy
# restart: unless-stopped
# ports:
# - "80:80"
# - "443:443"
# volumes:
# - ./Caddyfile:/etc/caddy/Caddyfile
# - caddy-data:/data
# - caddy-config:/config
# depends_on:
# - relay-server

volumes:
relay-data:
caddy-data:
caddy-config:
room-web:
# caddy-data:
# caddy-config:
Loading