Allow remote Web UI bootstrap with auth

This change updates the server default bind to 127.0.0.1 for safer local-only access while documenting how to expose the Web UI via --bind 0.0.0.0 --auth for remote or Docker use. It also removes the previous restriction that blocked first-time admin bootstrap on non-loopback addresses, allowing authenticated remote initialization and bumping the workspace version to 1.2.4.
This commit is contained in:
ForgQi committed 2026-08-24 01:13:29 +08:00
1 parent c351c39771
commit 03b7a84f55
6 files changed
+63 -37

No files matched your search

Generated
+4 -4
View File
@@ -387,7 +387,7 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "biliup"
version = "1.2.3"
version = "1.2.4"
dependencies = [
"async-trait",
"base64",
@@ -426,7 +426,7 @@ dependencies = [
[[package]]
name = "biliup-cli"
version = "1.2.3"
version = "1.2.4"
dependencies = [
"async-channel",
"async-trait",
@@ -1015,7 +1015,7 @@ dependencies = [
[[package]]
name = "danmaku"
version = "1.2.3"
version = "1.2.4"
dependencies = [
"async-trait",
"base64",
@@ -4109,7 +4109,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
[[package]]
name = "stream-gears"
version = "1.2.3"
version = "1.2.4"
dependencies = [
"async-channel",
"async-trait",
+1 -1
View File
@@ -8,7 +8,7 @@ members = [
resolver = "3"
[workspace.package]
version = "1.2.3"
version = "1.2.4"
[workspace.dependencies]
serde = { version = "1.0", features = ["derive"] }
+3
View File
@@ -129,3 +129,6 @@ RUN set -eux; \
WORKDIR /opt
ENTRYPOINT ["biliup"]
# 容器内必须监听 0.0.0.0,否则宿主机的端口映射无法转发进容器。
# CLI 默认的 127.0.0.1 只适用于直接在本机运行的场景。
CMD ["server", "--bind", "0.0.0.0", "--auth"]
+45 -6
View File
@@ -79,13 +79,18 @@ Options:
Usage: biliup server [OPTIONS]
Options:
-b, --bind <BIND> Specify bind address [default: 0.0.0.0]
-p, --port <PORT> Port to use [default: 19159]
--auth 开启登录密码认证
-c, --config <FILE> 使用 biliup 1.0.7 风格配置文件启动录制
-h, --help Print help
-b, --bind <BIND> Specify bind address [default: 127.0.0.1]
-p, --port <PORT> Port to use [default: 19159]
--auth 开启登录密码认证
--secure-session-cookie 为会话 Cookie 附加 Secure 属性。仅当通过 HTTPS 反向代理访问 Web UI 时开启; 直接通过 HTTP 远程访问时开启会导致浏览器丢弃登录态
-c, --config <FILE> 使用 biliup 1.0.7 风格配置文件启动录制
-h, --help Print help
```
> [!IMPORTANT]
> 自 [#1660](https://github.com/biliup/biliup/pull/1660) 起,`--bind` 的默认值由 `0.0.0.0` 改为 `127.0.0.1`,即**默认只监听本机**,局域网/公网无法直接访问。
> 如需从其他设备访问,请加上 `--bind 0.0.0.0 --auth`,详见下方「🔓 远程访问」一节。Docker 镜像已内置该参数,不受影响。
- [使用文档 »](https://docs.biliup.rs)
## 🚀 快速开始
@@ -97,13 +102,47 @@ Options:
1. 安装 [uv](https://docs.astral.sh/uv/getting-started/installation/)
2. 安装:`uv tool install biliup`
3. 启动:`biliup server --auth`
4. 访问 WebUI:`http://your-ip:19159`
4. 访问 WebUI:`http://127.0.0.1:19159`(默认只监听本机,远程访问见下方说明)
* 后台运行
1. `nohup biliup server --auth &`
2. [请查看参考](https://biliup.github.io/biliup/docs/guide/introduction/#linuxxia-pei-zhi-kai-ji-zi-qi)
### Termux
- 详见[Wiki](https://github.com/biliup/biliup/wiki/Termux-%E4%B8%AD%E4%BD%BF%E7%94%A8-biliup)
### 🔓 远程访问(监听 0.0.0.0)
默认的 `127.0.0.1` 只允许本机访问。需要从其他设备访问时,显式指定 `--bind 0.0.0.0` 并开启 `--auth`:
```shell
biliup server --bind 0.0.0.0 --auth
```
首次打开 `http://your-ip:19159` 会引导设置管理员密码(用户名固定为 `biliup`),之后即可正常登录使用。
> [!NOTE]
> 绑定非回环地址时必须同时开启 `--auth`,否则会拒绝启动,避免无认证的 Web API 被暴露:
>
> ```
> refusing to expose the unauthenticated Web API on 0.0.0.0:19159; use a loopback bind address or enable --auth
> ```
> [!WARNING]
> 将 Web UI 暴露到公网存在风险,建议仅在可信局域网内使用,或置于反向代理之后。
> 若通过 **HTTPS** 反向代理访问,请加上 `--secure-session-cookie`;直接以 HTTP 远程访问时**不要**加,否则浏览器会丢弃登录态(见 [#1669](https://github.com/biliup/biliup/pull/1669))。
#### Docker
镜像已内置 `--bind 0.0.0.0 --auth`,开箱即用,无需额外配置:
```shell
docker compose up -d
```
打开 `http://your-ip:19159` 设置管理员密码即可。
> [!IMPORTANT]
> 若要自定义 `command`,必须带上 `--bind 0.0.0.0`。容器内若监听 `127.0.0.1`,宿主机的端口映射无法转发进容器,Web UI 将完全无法访问。
---
## 🧑‍💻开发
+8 -25
View File
@@ -16,7 +16,6 @@ use crate::server::infrastructure::models::upload_streamer::{
};
use crate::server::infrastructure::repositories;
use crate::server::infrastructure::service_register::ServiceRegister;
use crate::server::infrastructure::users::Backend;
use clap::ValueEnum;
use error_stack::{Report, ResultExt, bail};
use std::net::{SocketAddr, ToSocketAddrs};
@@ -73,7 +72,6 @@ pub async fn run_with_cookie(
let conn_pool = ConnectionManager::new_pool("data/data.sqlite3")
.await
.attach("could not initialize the database connection pool")?;
validate_remote_auth_bootstrap(addr, auth, Backend::new(conn_pool.clone()).exists().await?)?;
if let Some(configuration) =
repositories::register_bilibili_cookie(&conn_pool, &user_cookie).await?
@@ -128,20 +126,6 @@ fn validate_server_exposure(addr: SocketAddr, auth: bool) -> AppResult<()> {
Ok(())
}
fn validate_remote_auth_bootstrap(
addr: SocketAddr,
auth: bool,
administrator_exists: bool,
) -> AppResult<()> {
if auth && !addr.ip().is_loopback() && !administrator_exists {
bail!(AppError::Custom(
"refusing remote first-user bootstrap; initialize the Web administrator on a loopback bind before exposing the authenticated server"
.into(),
));
}
Ok(())
}
async fn import_config_streamers(path: &Path, service_register: &ServiceRegister) -> AppResult<()> {
let streamers: Vec<_> = {
let config = service_register.config.read().unwrap();
@@ -380,7 +364,7 @@ pub enum UploadLine {
#[cfg(test)]
mod server_exposure_tests {
use super::{validate_remote_auth_bootstrap, validate_server_exposure};
use super::validate_server_exposure;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
#[test]
@@ -400,17 +384,16 @@ mod server_exposure_tests {
);
}
/// The Web administrator is bootstrapped over the network on first visit, so
/// an authenticated server must start on a non-loopback bind even when no
/// administrator exists yet — a container or headless host has no way to
/// reach a loopback-only bind to initialize one.
#[test]
fn authenticated_server_can_bind_non_loopback_after_local_bootstrap() {
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 19159);
assert!(validate_server_exposure(addr, true).is_ok());
assert!(validate_remote_auth_bootstrap(addr, true, false).is_err());
assert!(validate_remote_auth_bootstrap(addr, true, true).is_ok());
fn authenticated_server_can_bind_non_loopback_before_bootstrap() {
assert!(
validate_remote_auth_bootstrap(
SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 19159),
validate_server_exposure(
SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 19159),
true,
false,
)
.is_ok()
);
+2 -1
View File
@@ -8,4 +8,5 @@ services:
- "<HOST_ADDRESS>:<HOST_PORT>:19159"
volumes:
- /path/to/save_folder:/opt
command: server --auth
# 容器内必须监听 0.0.0.0,否则上面的端口映射无法转发进容器
command: server --bind 0.0.0.0 --auth