deploy: limit installer to supported modes

This commit is contained in:
fawney19
2026-05-14 15:26:58 +08:00
parent d2831ec6f0
commit e61aa46dad
2 changed files with 28 additions and 117 deletions

View File

@@ -55,82 +55,16 @@ docker compose pull && docker compose up -d
docker compose -f docker-compose.sqlite.yml pull && docker compose -f docker-compose.sqlite.yml up -d docker compose -f docker-compose.sqlite.yml pull && docker compose -f docker-compose.sqlite.yml up -d
``` ```
### 一键安装(可选部署方式) ### 一键安装(可选部署方式 Linux: systemd; Mac: launchd
```bash ```bash
curl -fsSL https://raw.githubusercontent.com/fawney19/Aether/main/install.sh | sudo bash curl -fsSL https://raw.githubusercontent.com/fawney19/Aether/main/install.sh | sudo bash
``` ```
```text
请选择安装语言 / Choose installer language:
1) 中文
2) 英语 / English
请输入选项 / Enter choice [1]:
请选择 Aether 版本:
1) 最新正式版
2) 最新 RC 预发布版
3) 最新 Beta 预发布版
4) 指定 tag例如 v0.7.0-rc.1
请输入选项 [1]:
请选择 Aether 部署模式:
1) Docker Compose: 应用 + Postgres + Redis
2) 单机服务: systemd/launchd + SQLite + 进程内运行时
3) 集群节点服务: systemd/launchd + 共享数据库 + Redis
4) Docker Compose: 应用 + SQLite
请输入选项 [2]:
是否使用下载加速源?
1) 否,使用原始 GitHub 地址
2) 是,手动填写新的下载 URL
请输入选项 [1]:
```
安装后的常用命令Linux systemd
```bash
sudo systemctl status aether-gateway --no-pager
sudo journalctl -u aether-gateway -f
sudo systemctl restart aether-gateway
```
安装后的常用命令macOS launchd
```bash
sudo launchctl print system/com.aether.gateway
sudo launchctl kickstart -k system/com.aether.gateway
sudo launchctl bootout system /Library/LaunchDaemons/com.aether.gateway.plist
tail -f /var/log/aether/aether-gateway.out.log /var/log/aether/aether-gateway.err.log
```
macOS 原生安装使用系统级 LaunchDaemon默认以专用 `_aether` 服务账号运行;配置和密钥写入 `/etc/aether/aether-gateway.env`,数据和应用日志仍在 `/opt/aether`launchd stdout/stderr 在 `/var/log/aether`
默认单机数据和应用日志都在安装目录内:
```text
/opt/aether/data/aether.db
/opt/aether/logs
```
多节点不能使用 SQLite 或 `AETHER_RUNTIME_BACKEND=memory`。如果先只生成了多节点模板,编辑 `/etc/aether/aether-gateway.env` 后重跑安装脚本即可:
```env
AETHER_GATEWAY_DEPLOYMENT_TOPOLOGY=multi-node
AETHER_GATEWAY_NODE_ROLE=frontdoor
DATABASE_URL=postgresql://...
REDIS_URL=redis://...
```
## Aether Proxy (可选) ## Aether Proxy (可选)
Aether Proxy 是配套的正向代理节点,部署在海外 VPS 上,为墙内的 Aether 实例中转 API 流量。或者部署在其他服务器为指定的提供商、账号、Key使用不同的节点访问。支持 TUI 向导一键配置、systemd 服务管理、TLS 加密、DNS 缓存及连接池调优。 Aether Proxy 是配套的正向代理节点,部署在海外 VPS 上,为墙内的 Aether 实例中转 API 流量。
- Docker Compose 部署或下载预编译二进制直接运行
- 通过 `aether-proxy setup` 完成交互式配置,自动注册为系统服务 - 通过 `aether-proxy setup` 完成交互式配置,自动注册为系统服务
- 详细文档见 [apps/aether-proxy/README.md](apps/aether-proxy/README.md) - 详细文档见 [apps/aether-proxy/README.md](apps/aether-proxy/README.md)
@@ -141,29 +75,18 @@ Aether Proxy 是配套的正向代理节点,部署在海外 VPS 上,为墙
## 环境变量 ## 环境变量
部署建议:
- Docker Compose根目录 [`.env.example`](.env.example)
- systemd 二进制部署:使用根目录 `install.sh` 生成 `/etc/aether/aether-gateway.env`
当前主链路真正要关注的是这组变量:
- `APP_PORT``aether-gateway` 唯一监听端口,固定绑定 `0.0.0.0:${APP_PORT}` - `APP_PORT``aether-gateway` 唯一监听端口,固定绑定 `0.0.0.0:${APP_PORT}`
- `AETHER_DATABASE_DRIVER` / `AETHER_DATABASE_URL`:二进制单机部署可用 `sqlite`,例如 `sqlite:///opt/aether/data/aether.db` - `DATABASE_URL`数据库连接串SQLite 例如 `sqlite:///opt/aether/data/aether.db`Postgres 例如 `postgresql://postgres:aether@postgres:5432/aether`
- `DATABASE_URL` / `REDIS_URL`:共享后端连接串;多节点必须配置共享数据库和 Redis - `REDIS_URL`Redis 连接串;仅 Postgres + Redis 的 Docker Compose 部署需要配置
- `AETHER_RUNTIME_BACKEND=memory|redis`:运行时缓存/协调后端。单机 SQLite 默认用 `memory`,不会连接 Redis;显式设为 `redis` 或多节点部署才会把 `REDIS_URL` 注入运行时 Redis 后端 - `AETHER_RUNTIME_BACKEND=memory|redis`:运行时缓存/协调后端。SQLite 默认用 `memory`,不会连接 Redis
- `AETHER_GATEWAY_AUTO_PREPARE_DATABASE`:常规启动前自动执行挂起的 schema migration 和 backfill仓库自带的 `docker-compose.yml` 默认开启 - `AETHER_GATEWAY_AUTO_PREPARE_DATABASE`:常规启动前自动执行挂起的 schema migration 和 backfill仓库自带的 `docker-compose.yml` 默认开启
- `JWT_SECRET_KEY` / `ENCRYPTION_KEY`:认证和敏感数据加密所需密钥 - `JWT_SECRET_KEY` / `ENCRYPTION_KEY`:认证和敏感数据加密所需密钥
- `API_KEY_PREFIX`:用户和管理员新建 API Key 时使用的前缀,默认 `sk` - `API_KEY_PREFIX`:用户和管理员新建 API Key 时使用的前缀,默认 `sk`
- `ADMIN_USERNAME` / `ADMIN_PASSWORD` / `ADMIN_EMAIL`:首次启动时自举首个本地管理员;`install.sh` 会提示输入管理员密码 - `ADMIN_USERNAME` / `ADMIN_PASSWORD` / `ADMIN_EMAIL`:首次启动时自举首个本地管理员;`install.sh` 会提示输入管理员密码
- `CORS_ORIGINS` / `CORS_ALLOW_CREDENTIALS`:前端跨域来源控制;如果要跨域带登录 Cookie`CORS_ORIGINS` 不能写 `*` - `CORS_ORIGINS` / `CORS_ALLOW_CREDENTIALS`:前端跨域来源控制;如果要跨域带登录 Cookie`CORS_ORIGINS` 不能写 `*`
- `AETHER_GATEWAY_DEPLOYMENT_TOPOLOGY=single-node|multi-node`
- `AETHER_GATEWAY_NODE_ROLE=all|frontdoor|background`
- `RUST_LOG`Rust 日志过滤,例如 `aether_gateway=info``aether_gateway=debug,sqlx=warn` - `RUST_LOG`Rust 日志过滤,例如 `aether_gateway=info``aether_gateway=debug,sqlx=warn`
- Docker Compose 的 `DB_PASSWORD` / `REDIS_PASSWORD` 默认使用 `aether` - Docker Compose 的 `DB_PASSWORD` / `REDIS_PASSWORD` 默认使用 `aether`
systemd 的 `.env` 必须保持简单 `KEY=VALUE` 形式,不要写 `export``${VAR}` 或命令替换。
--- ---
## 许可证 ## 许可证

View File

@@ -49,11 +49,10 @@ Usage: install.sh [options]
Install Aether Gateway. Install Aether Gateway.
Options: Options:
--mode MODE Deployment mode: compose, compose-sqlite, single, or cluster --mode MODE Deployment mode: compose, compose-sqlite, or single
compose: Docker Compose app + Postgres + Redis compose: Docker Compose app + Postgres + Redis
compose-sqlite: Docker Compose app + SQLite compose-sqlite: Docker Compose app + SQLite
single: system service with SQLite + in-process runtime single: system service with SQLite
cluster: system service connected to shared database + Redis
Linux services use systemd; macOS services use launchd Linux services use systemd; macOS services use launchd
--channel CHANNEL Release channel to resolve when --version is omitted: stable, latest, rc, or beta --channel CHANNEL Release channel to resolve when --version is omitted: stable, latest, rc, or beta
stable/latest resolves the latest stable tag (default) stable/latest resolves the latest stable tag (default)
@@ -81,7 +80,6 @@ Environment overrides:
AETHER_IMAGE_REPO, AETHER_APP_IMAGE AETHER_IMAGE_REPO, AETHER_APP_IMAGE
INSTALL_ROOT, AETHER_COMPOSE_DIR, CONFIG_DIR, SERVICE_USER, SERVICE_GROUP INSTALL_ROOT, AETHER_COMPOSE_DIR, CONFIG_DIR, SERVICE_USER, SERVICE_GROUP
ADMIN_PASSWORD (required for non-interactive first install when generating a new env) ADMIN_PASSWORD (required for non-interactive first install when generating a new env)
DATABASE_URL, REDIS_URL (required when generating a cluster env)
EOF EOF
} }
@@ -445,56 +443,52 @@ select_mode() {
return return
;; ;;
cluster|multi|multi-node) cluster|multi|multi-node)
MODE="cluster" if ui_is_zh; then
return die "集群部署模式暂未开放;请先选择 compose、compose-sqlite 或 single"
else
die "cluster deployment mode is temporarily disabled; choose compose, compose-sqlite, or single"
fi
;; ;;
auto|"") auto|"")
;; ;;
*) *)
die "unsupported install mode: ${MODE}; expected compose, compose-sqlite, single, or cluster" die "unsupported install mode: ${MODE}; expected compose, compose-sqlite, or single"
;; ;;
esac esac
if interactive_tty_available; then if interactive_tty_available; then
local service_manager
service_manager="$(service_manager_name)"
if ui_is_zh; then if ui_is_zh; then
cat >/dev/tty <<EOF cat >/dev/tty <<EOF
请选择 Aether 部署模式: 请选择 Aether 部署模式:
1) Docker Compose: 应用 + Postgres + Redis 1) Docker Compose 应用: Postgres + Redis
2) 单机服务: ${service_manager} + SQLite + 进程内运行时 3) Docker Compose 应用: 仅SQLite
3) 集群节点服务: ${service_manager} + 共享数据库 + Redis 4) 系统服务: 仅SQLite
4) Docker Compose: 应用 + SQLite
请输入选项 [2]: 请输入选项 [4]:
EOF EOF
else else
cat >/dev/tty <<EOF cat >/dev/tty <<EOF
Choose Aether deployment mode: Choose Aether deployment mode:
1) Docker Compose: app + Postgres + Redis 1) Docker Compose app: Postgres + Redis
2) Single-node service: ${service_manager} + SQLite + in-process runtime 3) Docker Compose app: SQLite only
3) Cluster node service: ${service_manager} + shared database + Redis 4) System service: SQLite only
4) Docker Compose: app + SQLite
Enter choice [2]: Enter choice [4]:
EOF EOF
fi fi
local choice local choice
IFS= read -r choice </dev/tty || choice="" IFS= read -r choice </dev/tty || choice=""
case "${choice:-2}" in case "${choice:-4}" in
1) 1)
MODE="compose" MODE="compose"
;; ;;
2)
MODE="single"
;;
3) 3)
MODE="cluster" MODE="compose-sqlite"
;; ;;
4) 4)
MODE="compose-sqlite" MODE="single"
;; ;;
*) *)
if ui_is_zh; then if ui_is_zh; then
@@ -945,16 +939,13 @@ AETHER_LOG_RETENTION_DAYS=7
AETHER_LOG_MAX_FILES=30 AETHER_LOG_MAX_FILES=30
APP_PORT=${APP_PORT:-8084} APP_PORT=${APP_PORT:-8084}
AETHER_GATEWAY_DEPLOYMENT_TOPOLOGY=single-node
AETHER_GATEWAY_NODE_ROLE=all
AETHER_GATEWAY_STATIC_DIR=${INSTALL_ROOT}/current/frontend AETHER_GATEWAY_STATIC_DIR=${INSTALL_ROOT}/current/frontend
AETHER_GATEWAY_VIDEO_TASK_TRUTH_SOURCE_MODE=rust-authoritative AETHER_GATEWAY_VIDEO_TASK_TRUTH_SOURCE_MODE=rust-authoritative
AETHER_GATEWAY_AUTO_PREPARE_DATABASE=true AETHER_GATEWAY_AUTO_PREPARE_DATABASE=true
AETHER_RUNTIME_BACKEND=memory AETHER_RUNTIME_BACKEND=memory
API_KEY_PREFIX=sk API_KEY_PREFIX=sk
AETHER_DATABASE_DRIVER=sqlite DATABASE_URL=sqlite://${INSTALL_ROOT}/data/aether.db
AETHER_DATABASE_URL=sqlite://${INSTALL_ROOT}/data/aether.db
JWT_SECRET_KEY=${jwt_key} JWT_SECRET_KEY=${jwt_key}
ENCRYPTION_KEY=${encryption_key} ENCRYPTION_KEY=${encryption_key}
@@ -1074,16 +1065,13 @@ AETHER_LOG_MAX_FILES=30
APP_IMAGE=$(compose_image) APP_IMAGE=$(compose_image)
APP_PORT=${APP_PORT:-8084} APP_PORT=${APP_PORT:-8084}
AETHER_GATEWAY_DEPLOYMENT_TOPOLOGY=single-node
AETHER_GATEWAY_NODE_ROLE=all
AETHER_GATEWAY_STATIC_DIR=/srv/frontend AETHER_GATEWAY_STATIC_DIR=/srv/frontend
AETHER_GATEWAY_VIDEO_TASK_TRUTH_SOURCE_MODE=rust-authoritative AETHER_GATEWAY_VIDEO_TASK_TRUTH_SOURCE_MODE=rust-authoritative
AETHER_GATEWAY_AUTO_PREPARE_DATABASE=true AETHER_GATEWAY_AUTO_PREPARE_DATABASE=true
AETHER_RUNTIME_BACKEND=memory AETHER_RUNTIME_BACKEND=memory
API_KEY_PREFIX=sk API_KEY_PREFIX=sk
AETHER_DATABASE_DRIVER=sqlite DATABASE_URL=sqlite:///app/data/aether.db
AETHER_DATABASE_URL=sqlite:///app/data/aether.db
JWT_SECRET_KEY=${JWT_SECRET_KEY:-${jwt_key}} JWT_SECRET_KEY=${JWT_SECRET_KEY:-${jwt_key}}
ENCRYPTION_KEY=${ENCRYPTION_KEY:-${encryption_key}} ENCRYPTION_KEY=${ENCRYPTION_KEY:-${encryption_key}}
@@ -1242,7 +1230,7 @@ ensure_env_matches_requested_mode() {
[[ "${topology}" == "multi-node" ]] || die "existing env ${file} is ${topology}; set AETHER_GATEWAY_DEPLOYMENT_TOPOLOGY=multi-node or use --mode single" [[ "${topology}" == "multi-node" ]] || die "existing env ${file} is ${topology}; set AETHER_GATEWAY_DEPLOYMENT_TOPOLOGY=multi-node or use --mode single"
cluster_env_has_required_backends "${file}" || die "existing multi-node env ${file} must define DATABASE_URL and REDIS_URL" cluster_env_has_required_backends "${file}" || die "existing multi-node env ${file} must define DATABASE_URL and REDIS_URL"
elif [[ "${mode}" == "single" && "${topology}" == "multi-node" ]]; then elif [[ "${mode}" == "single" && "${topology}" == "multi-node" ]]; then
die "existing env ${file} is multi-node; use --mode cluster or edit the env file" die "existing env ${file} is multi-node; cluster mode is temporarily disabled, edit the env file"
fi fi
} }
@@ -1381,7 +1369,7 @@ validate_env_file() {
[[ -z "${video_task_store_path}" ]] || die "multi-node deployment must not set AETHER_GATEWAY_VIDEO_TASK_STORE_PATH" [[ -z "${video_task_store_path}" ]] || die "multi-node deployment must not set AETHER_GATEWAY_VIDEO_TASK_STORE_PATH"
else else
if [[ "${node_role}" != "all" ]]; then if [[ "${node_role}" != "all" ]]; then
warn "single-node deployment usually uses AETHER_GATEWAY_NODE_ROLE=all; split roles are only useful for cluster drills" warn "single-node deployment usually uses AETHER_GATEWAY_NODE_ROLE=all; split roles are not enabled by this installer"
fi fi
if [[ "${runtime_backend}" == "redis" && -z "${redis_url}" ]]; then if [[ "${runtime_backend}" == "redis" && -z "${redis_url}" ]]; then
die "AETHER_RUNTIME_BACKEND=redis requires REDIS_URL or AETHER_GATEWAY_DATA_REDIS_URL" die "AETHER_RUNTIME_BACKEND=redis requires REDIS_URL or AETHER_GATEWAY_DATA_REDIS_URL"