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
56 changes: 54 additions & 2 deletions src/apps/relay-server/Caddyfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@
# response. Keep reverse-proxy read/response timeouts above that, or the
# proxy returns HTTP 504 before Axum can.
#
# Option A: With a domain (Let's Encrypt auto-HTTPS)
# IMPORTANT: URL structure when using a /relay path prefix
# / → static homepage (from static/homepage/)
# /relay/* → relay service (prefix stripped before proxying)
# /relay/health → health check
# /relay/ws → WebSocket endpoint
# /relay/api/* → all API endpoints
#
# Option A: With a domain (Let's Encrypt auto-HTTPS), root path
# relay.yourdomain.com {
# reverse_proxy relay-server:9700 {
# transport http {
Expand All @@ -23,8 +30,10 @@
# }
# }
#
# Option A2: With a /relay path prefix
# Option A2: With a /relay path prefix (homepage at /, service at /relay/)
# relay.yourdomain.com {
# root * /app/homepage
# try_files {path} {path}/ /index.html
# handle_path /relay/* {
# reverse_proxy relay-server:9700 {
# transport http {
Expand Down Expand Up @@ -57,3 +66,46 @@
}
}
}

# ─────────────────────────────────────────────────────────────────────────
# Nginx equivalent (Option A2: /relay prefix, homepage at /)
# ─────────────────────────────────────────────────────────────────────────
#
# server {
# listen 80;
# server_name remote.yourdomain.com;
#
# # Homepage (static files from relay-server/static/homepage/)
# location / {
# root /path/to/relay-server/static/homepage;
# index index.html;
# try_files $uri $uri/ =404;
# }
#
# # Redirect /relay → /relay/
# location = /relay {
# return 301 /relay/;
# }
#
# # Relay service (strip /relay prefix, proxy to port 9700)
# location /relay/ {
# proxy_pass http://127.0.0.1:9700/;
# proxy_set_header Host $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;
#
# # WebSocket support (/relay/ws endpoint)
# proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";
#
# # Long timeouts for device RPC (up to 120s) and sync
# proxy_buffering off;
# proxy_read_timeout 130s;
# proxy_send_timeout 130s;
#
# # Sync POSTs can carry large encrypted session bundles
# client_max_body_size 100m;
# }
# }
6 changes: 4 additions & 2 deletions src/apps/relay-server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ FROM rust:1-slim AS builder
WORKDIR /build/src/apps/relay-server

# Optional: limit rustc parallelism on small or low-memory VPS hosts.
# docker compose build --build-arg CARGO_BUILD_JOBS=1
# Note: empty value must NOT be set as ENV — cargo chokes on empty string.
ARG CARGO_BUILD_JOBS=
ENV CARGO_BUILD_JOBS=${CARGO_BUILD_JOBS}
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update \
Expand Down Expand Up @@ -39,7 +40,8 @@ RUN rm -rf src ../../crates/services/relay-service/src \
COPY src/apps/relay-server/src/ ./src/
COPY src/crates/services/relay-service/src/ ../../crates/services/relay-service/src/

RUN cargo build --release \
RUN if [ -n "${CARGO_BUILD_JOBS}" ]; then export CARGO_BUILD_JOBS; fi \
&& cargo build --release \
&& (strip target/release/bitfun-relay-server target/release/relay-admin || true)

FROM debian:bookworm-slim
Expand Down
67 changes: 63 additions & 4 deletions src/apps/relay-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,11 @@ Relay URL examples:

- Direct: `http://<YOUR_SERVER_IP>:9700`
- Localhost: `http://127.0.0.1:9700`
- Behind a reverse proxy: `https://relay.example.com` (only add a path prefix
such as `/relay` if your proxy is configured that way)
- Behind a reverse proxy: `https://relay.example.com/relay`

The client appends paths (`/ws`, `/api/*`, `/r/*`) to the URL you enter. Use
the `/relay` suffix to match the official server format
(`https://remote.openbitfun.com/relay`). See **Reverse Proxy** for nginx config.

**Desktop**

Expand Down Expand Up @@ -256,13 +259,69 @@ RELAY_PORT=9700 ./target/release/bitfun-relay-server

## Deployment Checklist

1. Open ports: `9700` (direct), and `80/443` if using Caddy / another proxy.
2. Hit `http://<server-ip>:9700/health`.
1. Open ports: `9700` (direct), and `80/443` if using a reverse proxy.
2. Hit `http://<server-ip>:9700/health` (or `https://relay.example.com/relay/health` behind a proxy).
3. Confirm `RELAY_DB_PATH` if you need accounts (Compose does this for you).
4. Create at least one user with `relay-admin`.
5. Fill the same relay URL into Desktop / CLI and log in.
6. If you terminate TLS on a reverse proxy, raise body size and read timeouts
(see sync + device RPC notes below).
7. Use the `/relay` suffix in the relay URL (e.g. `https://relay.example.com/relay`)
to match the official server format. See **Reverse Proxy** for nginx config.

## Reverse Proxy

When deploying behind a reverse proxy (Caddy, nginx, etc.), configure:

- **Body size limit**: at least 100 MB (sync POSTs carry large encrypted bundles)
- **Read/response timeout**: at least 130s (device RPC waits up to 120s)
- **WebSocket upgrade**: the /ws endpoint requires Connection upgrade headers
- **Path prefix**: serve the relay at `/relay/*` (strip prefix before proxying
to port 9700); serve static homepage files at `/` via exact-match locations

### Nginx example (/relay prefix + homepage at /)

```nginx
server {
listen 80;
server_name relay.example.com;

# Homepage static files (exact match)
location = / {
root /path/to/relay-server/static/homepage;
try_files /index.html =404;
}
location = /i18n.json {
root /path/to/relay-server/static/homepage;
}
location = /i18n.shared.json {
root /path/to/relay-server/static/homepage;
}

# With /relay prefix: strip prefix, proxy to relay server
# For clients configured with https://relay.example.com/relay
location = /relay {
return 301 /relay/;
}
location /relay/ {
proxy_pass http://127.0.0.1:9700/;
proxy_set_header Host $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;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_read_timeout 130s;
proxy_send_timeout 130s;
client_max_body_size 100m;
}

}
```

See `Caddyfile` for the Caddy equivalent.

## Environment Variables

Expand Down
5 changes: 3 additions & 2 deletions src/apps/relay-server/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ echo ""
check_relay_accounts_or_remind
echo ""
echo "Point BitFun Desktop / CLI Auth Server URL to:"
echo " http://<YOUR_SERVER_IP>:9700"
echo "See README.md for sync, Peer Device Mode, and proxy timeouts."
echo " Direct: http://<YOUR_SERVER_IP>:9700"
echo " Proxy: https://<YOUR_DOMAIN>/relay (recommended, matches official server)"
echo "See README.md for reverse proxy setup, sync, and Peer Device Mode."
echo ""
echo "Check status: bash -c 'cd \"${SCRIPT_DIR}\" && ${COMPOSE[*]} ps'"
echo "Start: bash start.sh"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ mod tests {
.allowed_tool_names
.contains(&"ReviewPlatform".to_string()));
assert!(manifest
.collapsed_tool_names
.deferred_tool_names
.contains(&"ReviewPlatform".to_string()));
assert!(manifest
.tool_definitions
Expand Down
Loading