初版功能完成
ci / Go checks (ubuntu-latest) (push) Has been cancelled
ci / Go checks (windows-latest) (push) Has been cancelled

This commit is contained in:
qsc
2026-08-29 13:12:17 +08:00
commit 142e5dc7d6
217 changed files with 21313 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
REMLINK_WG_ENDPOINT=vpn.example.com:51820
REMLINK_WG_PORT=51820
REMLINK_HTTP_BIND=127.0.0.1
REMLINK_ADMIN_TOKEN=replace-with-a-long-random-value
REMLINK_APT_FORCE_IPV4=1
REMLINK_APT_DEBIAN_MIRROR=http://mirrors.tuna.tsinghua.edu.cn/debian
REMLINK_APT_SECURITY_MIRROR=http://mirrors.tuna.tsinghua.edu.cn/debian-security
+7
View File
@@ -0,0 +1,7 @@
REMLINK_WG_ENDPOINT=vpn.example.com:51820
REMLINK_WG_PORT=51820
REMLINK_HTTP_BIND=127.0.0.1
REMLINK_ADMIN_TOKEN=replace-with-a-long-random-value
REMLINK_APT_FORCE_IPV4=1
REMLINK_APT_DEBIAN_MIRROR=
REMLINK_APT_SECURITY_MIRROR=
+47
View File
@@ -0,0 +1,47 @@
# syntax=docker/dockerfile:1.7
FROM node:24.14.0-bookworm-slim AS frontend
WORKDIR /src
COPY frontend/package.json frontend/package-lock.json ./frontend/
RUN npm ci --prefix frontend
COPY frontend ./frontend
RUN npm run typecheck --prefix frontend && npm run build --prefix frontend
FROM golang:1.26.7-bookworm AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
COPY --from=frontend /src/frontend/engineer/dist ./frontend/engineer/dist
COPY --from=frontend /src/frontend/server/dist ./frontend/server/dist
ARG REMLINK_VERSION=1.0.0
ARG REMLINK_COMMIT=container
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath \
-ldflags "-s -w -X remlink/internal/version.Version=${REMLINK_VERSION} -X remlink/internal/version.Commit=${REMLINK_COMMIT}" \
-o /out/remlink-server ./cmd/server
FROM debian:bookworm-slim
ARG APT_FORCE_IPV4=1
ARG APT_DEBIAN_MIRROR=
ARG APT_SECURITY_MIRROR=
RUN apt_options="-o Acquire::Retries=5 -o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30"; \
if [ -n "$APT_SECURITY_MIRROR" ]; then sed -i "s|http://deb.debian.org/debian-security|$APT_SECURITY_MIRROR|g" /etc/apt/sources.list.d/debian.sources; fi; \
if [ -n "$APT_DEBIAN_MIRROR" ]; then sed -i "s|http://deb.debian.org/debian|$APT_DEBIAN_MIRROR|g" /etc/apt/sources.list.d/debian.sources; fi; \
if [ -n "$APT_DEBIAN_MIRROR" ] || [ -n "$APT_SECURITY_MIRROR" ]; then \
apt_options="$apt_options -o Acquire::http::Pipeline-Depth=0"; \
fi; \
if [ "$APT_FORCE_IPV4" = "1" ]; then apt_options="$apt_options -o Acquire::ForceIPv4=true"; fi; \
apt-get $apt_options update \
&& apt-get $apt_options install -y --no-install-recommends \
ca-certificates curl iproute2 iptables wireguard-tools \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /out/remlink-server /usr/local/bin/remlink-server
COPY deploy/docker/preflight.sh /usr/local/bin/remlink-preflight
COPY THIRD_PARTY_NOTICES.md /usr/share/doc/remlink/THIRD_PARTY_NOTICES.md
RUN chmod 0755 /usr/local/bin/remlink-server /usr/local/bin/remlink-preflight \
&& mkdir -p /app/data
VOLUME ["/app/data"]
EXPOSE 8080/tcp 51820/udp
HEALTHCHECK --interval=15s --timeout=3s --start-period=10s --retries=4 \
CMD curl --fail --silent --show-error http://127.0.0.1:8080/api/v1/server/info >/dev/null || exit 1
ENTRYPOINT ["/usr/local/bin/remlink-preflight"]
CMD ["/usr/local/bin/remlink-server", "-config", "/etc/remlink/server.yaml"]
+31
View File
@@ -0,0 +1,31 @@
# syntax=docker/dockerfile:1.7
FROM debian:bookworm-slim
ARG APT_FORCE_IPV4=1
ARG APT_DEBIAN_MIRROR=
ARG APT_SECURITY_MIRROR=
RUN apt_options="-o Acquire::Retries=5 -o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30"; \
if [ -n "$APT_SECURITY_MIRROR" ]; then sed -i "s|http://deb.debian.org/debian-security|$APT_SECURITY_MIRROR|g" /etc/apt/sources.list.d/debian.sources; fi; \
if [ -n "$APT_DEBIAN_MIRROR" ]; then sed -i "s|http://deb.debian.org/debian|$APT_DEBIAN_MIRROR|g" /etc/apt/sources.list.d/debian.sources; fi; \
if [ -n "$APT_DEBIAN_MIRROR" ] || [ -n "$APT_SECURITY_MIRROR" ]; then \
apt_options="$apt_options -o Acquire::http::Pipeline-Depth=0"; \
fi; \
if [ "$APT_FORCE_IPV4" = "1" ]; then apt_options="$apt_options -o Acquire::ForceIPv4=true"; fi; \
apt-get $apt_options update \
&& apt-get $apt_options install -y --no-install-recommends \
ca-certificates curl iproute2 iptables wireguard-tools \
&& rm -rf /var/lib/apt/lists/*
COPY linux-amd64/remlink-server /usr/local/bin/remlink-server
COPY docker/preflight.sh /usr/local/bin/remlink-preflight
COPY linux-amd64/THIRD_PARTY_NOTICES.md /usr/share/doc/remlink/THIRD_PARTY_NOTICES.md
RUN chmod 0755 /usr/local/bin/remlink-server /usr/local/bin/remlink-preflight \
&& mkdir -p /app/data
VOLUME ["/app/data"]
EXPOSE 8080/tcp 51820/udp
HEALTHCHECK --interval=15s --timeout=3s --start-period=10s --retries=4 \
CMD curl --fail --silent --show-error http://127.0.0.1:8080/api/v1/server/info >/dev/null || exit 1
ENTRYPOINT ["/usr/local/bin/remlink-preflight"]
CMD ["/usr/local/bin/remlink-server", "-config", "/etc/remlink/server.yaml"]
+43
View File
@@ -0,0 +1,43 @@
# Server Docker 部署
完整生产流程见 `docs/deployment-and-usage.md`;在源码仓库中该文件位于 `../../docs/deployment-and-usage.md`,在发布包中位于 `../docs/deployment-and-usage.md`
Compose 基线删除全部 Linux capability 后只增加 `NET_ADMIN`,映射 `/dev/net/tun`,从不启用 privileged。入口预检会在启动 Server 前检查 TUN、内核 WireGuard、capability 和 IPv4 forwarding。
## 从发布包部署
在解压后的 `RemLink-Server-v1.0.0-linux-amd64/docker` 目录:
~~~bash
cp .env.example .env
chmod 600 .env
# 编辑 .env 与 server.yaml
mkdir -p data
docker compose --env-file .env -f compose.release.yaml config --quiet
docker compose --env-file .env -f compose.release.yaml up --build -d
docker compose --env-file .env -f compose.release.yaml exec server remlink-server -config /etc/remlink/server.yaml -print-join-token
~~~
`compose.release.yaml` 使用发布包中的 `linux-amd64/remlink-server`,不会要求完整源码。
中国大陆网络建议改为 `cp .env.china.example .env`。该模板把 Debian 主仓库和安全仓库切换到清华 TUNA,同时强制 IPv4、关闭 apt HTTP pipelining,并保留超时/重试。Debian 12 容器使用 `/etc/apt/sources.list.d/debian.sources` 的 DEB822 格式,Dockerfile 会通过构建参数替换其中 URI。TUNA 也提示安全镜像可能有同步延迟;网络允许时可把 `REMLINK_APT_SECURITY_MIRROR` 留空以继续使用 Debian 官方安全源。详情见 [TUNA Debian 帮助](https://mirrors.tuna.tsinghua.edu.cn/help/debian/) 和 [TUNA Debian Security 帮助](https://mirrors.tuna.tsinghua.edu.cn/help/debian-security/)。
## 从源码仓库构建
在仓库 `deploy/docker` 目录:
~~~bash
cp .env.example .env
chmod 600 .env
docker compose --env-file .env -f compose.yaml up --build -d
~~~
源码 Compose 会构建前端和 Go Server。
若构建停在 Debian `apt-get`,先用 `docker run --rm debian:bookworm-slim sh -c "apt-get -o Acquire::ForceIPv4=true -o Acquire::Retries=2 -o Acquire::http::Timeout=30 update"` 验证容器网络。Dockerfile 默认强制 IPv4,并为 apt 配置 30 秒超时和 5 次重试;确认环境只有 IPv6 时才把 `REMLINK_APT_FORCE_IPV4` 改为 `0`。中国大陆环境优先使用 `.env.china.example`;测试命令仍超时时,应修复 Docker daemon 的 DNS/代理或在 Ubuntu 上用 `docker build --network=host`,而不是扩大容器权限。
只映射 `8080/tcp` 和配置的 WireGuard UDP 端口。Control `7001/tcp` 与 Session `6200/udp` 只绑定 Overlay,不发布。数据库、密钥和日志写入 `/app/data`,由宿主机 `./data` 持久化。
v1.0 的 `8080/tcp` 不内置 TLS。将 `REMLINK_HTTP_BIND` 设为 `127.0.0.1` 并使用外部 HTTPS 反向代理,或绑定到可信管理接口;不要把未加密 Bootstrap/Admin 直接暴露到 Internet。
管理页修改 WireGuard 端口后,必须同步更新 `REMLINK_WG_PORT``REMLINK_WG_ENDPOINT`,再强制重建服务,使宿主机与容器映射跟随数据库中的新端口。`./data` 不会因容器重建丢失。
+30
View File
@@ -0,0 +1,30 @@
services:
server:
build:
context: ..
dockerfile: docker/Dockerfile.release
args:
APT_FORCE_IPV4: "${REMLINK_APT_FORCE_IPV4:-1}"
APT_DEBIAN_MIRROR: "${REMLINK_APT_DEBIAN_MIRROR:-}"
APT_SECURITY_MIRROR: "${REMLINK_APT_SECURITY_MIRROR:-}"
image: remlink/server:1.0.0
restart: unless-stopped
cap_drop:
- ALL
cap_add:
- NET_ADMIN
security_opt:
- no-new-privileges:true
devices:
- /dev/net/tun:/dev/net/tun
sysctls:
net.ipv4.ip_forward: "1"
ports:
- "${REMLINK_HTTP_BIND:-0.0.0.0}:8080:8080/tcp"
- "${REMLINK_WG_PORT:-51820}:${REMLINK_WG_PORT:-51820}/udp"
environment:
REMLINK_WG_ENDPOINT: ${REMLINK_WG_ENDPOINT:?set REMLINK_WG_ENDPOINT to the public host and published UDP port}
REMLINK_ADMIN_TOKEN: ${REMLINK_ADMIN_TOKEN:-}
volumes:
- ./server.yaml:/etc/remlink/server.yaml:ro
- ./data:/app/data
+31
View File
@@ -0,0 +1,31 @@
services:
server:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile
args:
REMLINK_VERSION: "1.0.0"
APT_FORCE_IPV4: "${REMLINK_APT_FORCE_IPV4:-1}"
APT_DEBIAN_MIRROR: "${REMLINK_APT_DEBIAN_MIRROR:-}"
APT_SECURITY_MIRROR: "${REMLINK_APT_SECURITY_MIRROR:-}"
image: remlink/server:1.0.0
restart: unless-stopped
cap_drop:
- ALL
cap_add:
- NET_ADMIN
security_opt:
- no-new-privileges:true
devices:
- /dev/net/tun:/dev/net/tun
sysctls:
net.ipv4.ip_forward: "1"
ports:
- "${REMLINK_HTTP_BIND:-0.0.0.0}:8080:8080/tcp"
- "${REMLINK_WG_PORT:-51820}:${REMLINK_WG_PORT:-51820}/udp"
environment:
REMLINK_WG_ENDPOINT: ${REMLINK_WG_ENDPOINT:?set REMLINK_WG_ENDPOINT to the public host and published UDP port}
REMLINK_ADMIN_TOKEN: ${REMLINK_ADMIN_TOKEN:-}
volumes:
- ./server.yaml:/etc/remlink/server.yaml:ro
- ./data:/app/data
+32
View File
@@ -0,0 +1,32 @@
#!/bin/sh
set -eu
if [ ! -c /dev/net/tun ]; then
echo "RemLink preflight: /dev/net/tun is missing; map the TUN device into the container" >&2
exit 1
fi
probe_interface="rl-wg-probe"
cleanup() {
ip link delete dev "$probe_interface" >/dev/null 2>&1 || true
}
trap cleanup EXIT INT TERM
if probe_error="$(ip link add dev "$probe_interface" type wireguard 2>&1)"; then
:
else
echo "RemLink preflight: kernel WireGuard or CAP_NET_ADMIN is unavailable" >&2
if [ -n "$probe_error" ]; then
echo "RemLink preflight: ip link error: $probe_error" >&2
fi
exit 1
fi
cleanup
trap - EXIT INT TERM
if [ "$(cat /proc/sys/net/ipv4/ip_forward)" != "1" ]; then
echo "RemLink preflight: net.ipv4.ip_forward must be 1" >&2
exit 1
fi
exec "$@"
+13
View File
@@ -0,0 +1,13 @@
server:
http_listen: "0.0.0.0:8080"
control_listen: "10.88.0.1:7001"
wireguard_port: 51820
data:
directory: "/app/data"
network:
overlay_cidr: "10.88.0.0/16"
server_overlay_ip: "10.88.0.1"
session_udp_port: 6200
mtu: 1280