# 服务器基础环境

公共基础设施脚本，提供以下功能：

- **系统初始化**：安装常用工具、设置时区
- **Docker 安装**：使用阿里云镜像源，配置国内加速
- **Nginx 安装**：反向代理服务器，统一管理 HTTPS
- **Certbot 安装**：Let's Encrypt SSL 证书自动申请与续期
- **防火墙配置**：开放 SSH / HTTP / HTTPS 端口

## 设计理念

- **幂等性**：每个安装步骤都会先检查是否已安装，避免重复操作
- **可复用**：既可以独立运行，也可以被其他服务的部署脚本 `source` 调用
- **国内优化**：Docker 使用阿里云 APT 源安装，镜像拉取使用国内加速

## 使用方式

### 方式一：独立运行（安装全部基础环境）

```bash
# 上传到服务器
scp -r base/ root@<服务器IP>:/opt/base

# 登录服务器执行
cd /opt/base
cp .env.example .env
# 编辑 .env 配置 Docker 镜像加速（可选）
# 配置 SSH_PUBLIC_KEY 可实现密钥登录（推荐）
bash setup.sh
```

### 配置 SSH 密钥认证（推荐）

首次部署前，将本地公钥填入 `base/.env`，`setup.sh` 运行时会自动配置服务器，后续 SSH/SCP 无需再输入密码。

**第一步：生成本地 SSH 密钥（如果还没有）**

```powershell
# Windows PowerShell
ssh-keygen -t ed25519
```

**第二步：将公钥写入 base/.env**

```powershell
# Windows PowerShell：复制公钥内容
Get-Content ~/.ssh/id_ed25519.pub
```

将输出的内容（形如 `ssh-ed25519 AAAA... comment`）填入 `base/.env`：

```env
SSH_PUBLIC_KEY=ssh-ed25519 AAAA...（你的公钥内容）
```

**第三步：上传 .env 并运行 setup.sh**

正常执行上传和 `bash setup.sh` 后，SSH 密钥即自动配置完成。后续连接直接：

```bash
ssh root@<服务器IP>         # 无需密码
scp -r ... root@<服务器IP>  # 无需密码
```

### 方式二：被其他服务脚本调用

```bash
#!/usr/bin/env bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BASE_DIR="$(cd "$SCRIPT_DIR/../base" && pwd)"
source "$BASE_DIR/setup.sh"

# 现在可以使用 base 提供的所有函数
check_root
init_system
install_docker
install_nginx
# ...
```

## 提供的函数

| 函数 | 说明 |
|------|------|
| `check_root` | 检查是否 root 用户 |
| `init_system` | 系统初始化，安装基础工具 |
| `install_docker` | 安装 Docker + Compose V2 |
| `configure_docker_mirrors` | 配置 Docker 镜像加速 |
| `install_nginx` | 安装配置 Nginx |
| `install_certbot` | 安装 Certbot |
| `setup_firewall_base` | 开放 22/80/443 端口 |
| `firewall_allow_port <port> [desc]` | 开放额外端口 |
| `setup_ssh_key <pubkey>` | 配置 SSH 公钥认证 |
| `setup_ssl_cert <domain> <email> [name]` | 申请 SSL 证书 |
| `deploy_nginx_conf <template> <domain> <name>` | 部署 Nginx 反向代理配置 |
| `load_base_env [dir]` | 加载 base/.env |

## 目录结构

```
base/
├── setup.sh          # 主脚本（函数库 + 独立运行入口）
├── .env.example      # 配置模板
├── .env              # 实际配置（从 .env.example 复制）
└── README.md         # 本文件
```
