AI 服务器部署与权限隔离-从零搭建到生产校验完整教程
AI 服务器部署与权限隔离:从零搭建到生产校验完整教程
本文使用一个完全虚构的案例进行讲解,不包含任何真实服务器 IP、SSH Key、用户名、项目路径或其他敏感信息。
假设我们有一个 AI 助手叫 小明,需要让它登录 Linux 服务器完成“检查”和“部署”工作,但又不能让它拥有服务器管理员权限。
01. 先确定我们的目标
假设服务器管理员叫:
serveradmin
AI 叫:
小明
服务器示例 IP:
192.0.2.10
网站项目:
demo-site
我们不允许出现这种结构:
小明
↓
serveradmin
↓
sudo
↓
root
↓
整台服务器
因为一旦 AI 执行错误命令,理论上可能影响整台服务器。
我们要做成:
Linux Server
│
┌───────────┴───────────┐
│ │
serveradmin 小明
│ │
sudo ┌──────┴──────┐
│ │ │
root xiaoming-audit xiaoming-deploy
│ │
只读 有限部署
核心原则只有一句:
不是禁止 AI 工作,而是只给 AI 完成当前任务所必需的权限。
这就是最小权限原则:
Least Privilege
02. 为什么要给同一个 AI 两个账号
虽然它们背后都是“小明”,但服务器不应该把“小明”当成一个万能身份。
我们把它拆成:
xiaoming-audit
负责:
查看
检查
审计
读取日志
检查待发布文件
但是:
不能修改
不能部署
不能 sudo
另一个:
xiaoming-deploy
负责:
上传部署候选文件
修改部署缓冲区
准备新版本
但是:
不能直接修改正式网站
不能 sudo
不能获得 root
于是同一个 AI:
小明
│
├── xiaoming-audit
│ └── 只读身份
│
└── xiaoming-deploy
└── 部署身份
拿哪把 SSH Key 登录,就获得哪套权限。
03. 创建权限组
先不要创建账号。
先创建两个“角色组”。
审计组:
sudo groupadd demo-audit
部署组:
sudo groupadd demo-deploy
验证:
getent group demo-audit demo-deploy
正常会看到类似:
demo-audit:x:1001:
demo-deploy:x:1002:
这一步的思想是:
权限尽量赋予“角色”,而不是散落到某个具体用户身上。
以后再增加其他 AI,只需要把它加入对应组。
04. 创建小明的两个 Linux 身份
创建审计账号:
sudo adduser --disabled-password --gecos "" --ingroup demo-audit xiaoming-audit
创建部署账号:
sudo adduser --disabled-password --gecos "" --ingroup demo-deploy xiaoming-deploy
这里:
--disabled-password
表示不准备让这些 AI 用户使用普通 Linux 密码登录。
后面我们使用:
SSH Public Key Authentication
也就是 SSH 公钥认证。
05. 检查身份是否正确
执行:
id xiaoming-audit
应该看到类似:
uid=1001(xiaoming-audit)
gid=1001(demo-audit)
groups=1001(demo-audit)
再检查部署账号:
id xiaoming-deploy
应该类似:
uid=1002(xiaoming-deploy)
gid=1002(demo-deploy)
groups=1002(demo-deploy)
于是:
xiaoming-audit
↓
demo-audit
xiaoming-deploy
↓
demo-deploy
06. 检查 AI 有没有 sudo
这一关非常重要。
检查审计账号:
sudo -l -U xiaoming-audit
检查部署账号:
sudo -l -U xiaoming-deploy
理想结果:
User xiaoming-audit is not allowed to run sudo
以及:
User xiaoming-deploy is not allowed to run sudo
绝对不要出现:
ALL=(ALL) ALL
或者:
NOPASSWD: ALL
否则前面的身份隔离意义会大幅降低。
07. 把“上传区”和“正式网站”彻底分开
这是整套方案非常重要的一层。
不要让 AI 直接把网站上传到:
/var/www/
而是准备两个区域。
AI 部署缓冲区
/srv/demo-deploy/
└── incoming/
创建:
sudo mkdir -p /srv/demo-deploy/incoming
正式生产区
/var/www/demo-site/
└── releases/
创建:
sudo mkdir -p /var/www/demo-site/releases
于是整个过程变成:
小明
↓
incoming
↓
检查
↓
发布 Gate
↓
releases
↓
current
↓
正式网站
而不是:
小明
↓
直接覆盖正式网站
08. 给 Deploy 身份开放 incoming
先把部署目录组设为:
demo-deploy
执行:
sudo chown root:demo-deploy /srv/demo-deploy /srv/demo-deploy/incoming
设置上层目录:
sudo chmod 0750 /srv/demo-deploy
设置 incoming:
sudo chmod 2770 /srv/demo-deploy/incoming
检查:
sudo ls -ld /srv/demo-deploy /srv/demo-deploy/incoming
应该类似:
drwxr-x--- root demo-deploy /srv/demo-deploy
drwxrws--- root demo-deploy /srv/demo-deploy/incoming
09. 为什么 incoming 使用 2770
这里:
2770
中的:
2
表示:
setgid
它的作用是:
在这个目录中新创建的内容,会自动继承目录所属的 Group。
例如小明部署账号创建:
build.zip
最终可能是:
owner:xiaoming-deploy
group:demo-deploy
以后即使再增加另一个部署 Agent,只要也属于:
demo-deploy
就能按部署组规则协作。
10. 第一次做越权测试
千万不要只看:
chmod
chown
然后觉得“应该没问题”。
真正的权限体系一定要实际攻击一次。
让部署账号在允许位置创建文件:
sudo -u xiaoming-deploy touch /srv/demo-deploy/incoming/deploy-test.txt
这条应该:
成功
然后让它尝试直接碰生产区:
sudo -u xiaoming-deploy touch /var/www/demo-site/should-fail.txt
应该得到:
Permission denied
于是我们真正证明:
xiaoming-deploy
incoming ✅ 可以写
production ❌ 不可以写
11. 使用 ACL 做更细粒度权限控制
Linux 普通权限主要有:
Owner
Group
Other
对于复杂的协作场景,有时不够精细。
所以安装 ACL:
sudo apt update
sudo apt install -y acl
确认:
command -v setfacl
正常:
/usr/bin/setfacl
12. 给部署区设置默认 ACL
设置当前权限:
sudo setfacl -m g::rwx,m::rwx /srv/demo-deploy/incoming
再设置以后新内容自动继承:
sudo setfacl -d -m u::rwx,g::rwx,m::rwx,o::--- /srv/demo-deploy/incoming
检查:
sudo getfacl /srv/demo-deploy/incoming
应该类似:
user::rwx
group::rwx
mask::rwx
other::---
default:user::rwx
default:group::rwx
default:mask::rwx
default:other::---
这样部署区的新内容会自动继承部署协作权限。
13. 给 Audit 身份只读权限
现在让:
xiaoming-audit
能够检查 incoming。
但只能读。
执行:
sudo setfacl -m g:demo-audit:rx /srv/demo-deploy /srv/demo-deploy/incoming
再给未来新文件设置继承规则:
sudo setfacl -d -m g:demo-audit:rx /srv/demo-deploy/incoming
检查:
sudo getfacl /srv/demo-deploy/incoming
应该出现:
group:demo-audit:r-x
以及:
default:group:demo-audit:r-x
注意:
r = read
x = traverse / 进入目录
没有:
w
所以审计组不能写。
14. 真正验证“Audit 能看不能改”
先让部署身份创建文件:
sudo -u xiaoming-deploy sh -c 'echo "production candidate" > /srv/demo-deploy/incoming/audit-test.txt'
再让审计身份读取:
sudo -u xiaoming-audit cat /srv/demo-deploy/incoming/audit-test.txt
应该输出:
production candidate
然后尝试修改:
sudo -u xiaoming-audit sh -c 'echo "illegal change" >> /srv/demo-deploy/incoming/audit-test.txt'
必须失败:
Permission denied
再尝试创建:
sudo -u xiaoming-audit touch /srv/demo-deploy/incoming/audit-should-fail.txt
仍然必须:
Permission denied
于是:
xiaoming-audit
读取 incoming ✅
修改 incoming ❌
创建文件 ❌
15. 正式生产版本必须收归 root
假设 incoming 中的内容已经检查通过。
现在创建一个正式版本:
sudo mkdir -p /var/www/demo-site/releases/v1
把候选内容复制进去:
sudo cp -a /srv/demo-deploy/incoming/. /var/www/demo-site/releases/v1/
然后正式收归:
sudo chown -R root:root /var/www/demo-site/releases/v1
设置常见静态网站权限:
目录:
sudo find /var/www/demo-site/releases/v1 -type d -exec chmod 755 {} \;
文件:
sudo find /var/www/demo-site/releases/v1 -type f -exec chmod 644 {} \;
检查:
sudo ls -la /var/www/demo-site/releases/v1
生产区应该由:
root:root
控制。
这一步意味着:
AI 创建的候选内容一旦正式进入生产区,就失去了继续修改正式版本的能力。
16. 使用 releases + current 管理版本
生产目录设计成:
/var/www/demo-site/
│
├── releases/
│ ├── v1/
│ ├── v2/
│ └── v3/
│
└── current
Web Server 永远只看:
/var/www/demo-site/current
比如第一次上线:
sudo ln -s releases/v1 /var/www/demo-site/current
查看:
sudo readlink -f /var/www/demo-site/current
结果:
/var/www/demo-site/releases/v1
于是:
current → v1
17. 为什么不直接覆盖网站
假设现在发布:
v2
如果直接覆盖:
v1
一旦新版本有问题,旧版本已经被改掉了。
而 Release 模型是:
releases/
├── v1
└── v2
current → v1
准备好 v2 后:
current → v2
v2 出问题:
current → v1
旧版本从来没有被覆盖。
18. 原子切换 current
不建议:
rm current
ln -s releases/v2 current
因为删除和重建之间存在短暂空档。
更好的方法:
先准备:
sudo ln -s releases/v2 /var/www/demo-site/current.new
然后:
sudo mv -Tf /var/www/demo-site/current.new /var/www/demo-site/current
检查:
sudo readlink -f /var/www/demo-site/current
现在应该:
current → v2
19. 回滚
假设 v2 上线后发现故障。
建立:
sudo ln -s releases/v1 /var/www/demo-site/current.rollback
原子替换:
sudo mv -Tf /var/www/demo-site/current.rollback /var/www/demo-site/current
检查:
sudo readlink -f /var/www/demo-site/current
重新变成:
current → v1
这就是快速回滚。
20. 再攻击一次生产区
让部署身份尝试修改 current:
sudo -u xiaoming-deploy touch /var/www/demo-site/current/deploy-should-fail.txt
应该:
Permission denied
让部署身份直接创建 release:
sudo -u xiaoming-deploy touch /var/www/demo-site/releases/illegal-release.txt
也应该:
Permission denied
Audit:
sudo -u xiaoming-audit touch /var/www/demo-site/current/audit-should-fail.txt
仍然:
Permission denied
到这里生产边界才算真正验证完成。
21. 给 AI 准备独立 SSH 入口
建立:
sudo install -d -m 700 -o xiaoming-audit -g demo-audit /home/xiaoming-audit/.ssh
部署账号:
sudo install -d -m 700 -o xiaoming-deploy -g demo-deploy /home/xiaoming-deploy/.ssh
检查:
sudo ls -ld /home/xiaoming-audit/.ssh /home/xiaoming-deploy/.ssh
应该:
drwx------
22. 在 Windows 本地生成两把 SSH Key
注意:
私钥必须生成在本地电脑,不是在服务器上。
Windows CMD:
mkdir "%USERPROFILE%\.ssh\demo"
审计钥匙:
ssh-keygen -t ed25519 -f "%USERPROFILE%\.ssh\demo\xiaoming-audit" -C "xiaoming-audit@demo"
部署钥匙:
ssh-keygen -t ed25519 -f "%USERPROFILE%\.ssh\demo\xiaoming-deploy" -C "xiaoming-deploy@demo"
最后得到:
xiaoming-audit
xiaoming-audit.pub
xiaoming-deploy
xiaoming-deploy.pub
其中:
没有 .pub = 私钥
带 .pub = 公钥
最重要的原则
私钥:
只留本地
公钥:
可以放服务器
不要把 AI 私钥放进 GitHub。
不要发到聊天群。
不要上传到服务器。
23. 把公钥装进服务器
Windows 查看审计公钥:
type "%USERPROFILE%\.ssh\demo\xiaoming-audit.pub"
复制整行。
服务器写入:
printf '%s\n' '这里放 xiaoming-audit 公钥' | sudo tee /home/xiaoming-audit/.ssh/authorized_keys >/dev/null
然后:
sudo chown xiaoming-audit:demo-audit /home/xiaoming-audit/.ssh/authorized_keys
sudo chmod 600 /home/xiaoming-audit/.ssh/authorized_keys
部署身份同理:
printf '%s\n' '这里放 xiaoming-deploy 公钥' | sudo tee /home/xiaoming-deploy/.ssh/authorized_keys >/dev/null
然后:
sudo chown xiaoming-deploy:demo-deploy /home/xiaoming-deploy/.ssh/authorized_keys
sudo chmod 600 /home/xiaoming-deploy/.ssh/authorized_keys
24. 从 Windows 真正登录 Audit
在 Windows:
ssh -i "%USERPROFILE%\.ssh\demo\xiaoming-audit" xiaoming-audit@192.0.2.10
登录以后:
whoami
必须:
xiaoming-audit
读候选文件:
cat /srv/demo-deploy/incoming/audit-test.txt
应该成功。
尝试修改:
echo "illegal" >> /srv/demo-deploy/incoming/audit-test.txt
应该:
Permission denied
尝试碰生产区:
touch /var/www/demo-site/current/should-fail.txt
应该:
Permission denied
25. 从 Windows 真正登录 Deploy
执行:
ssh -i "%USERPROFILE%\.ssh\demo\xiaoming-deploy" xiaoming-deploy@192.0.2.10
确认:
whoami
输出:
xiaoming-deploy
写 incoming:
echo "deploy test" > /srv/demo-deploy/incoming/real-deploy-test.txt
应该成功。
再碰生产:
touch /var/www/demo-site/releases/should-fail.txt
应该:
Permission denied
26. 管理员必须有自己的 Break-glass Key
AI 的 Key 不能当管理员 Key 使用。
管理员:
serveradmin
应该单独生成:
ssh-keygen -t ed25519 -f "%USERPROFILE%\.ssh\demo\admin-breakglass" -C "admin-breakglass@demo"
这把 Key 建议设置:
Passphrase
因为它对应:
admin-breakglass
↓
serveradmin
↓
sudo
↓
root
这是最高权限钥匙。
27. 安装 Break-glass 时不要覆盖旧公钥
先看:
sudo wc -l /home/serveradmin/.ssh/authorized_keys
先备份:
sudo cp -a /home/serveradmin/.ssh/authorized_keys /home/serveradmin/.ssh/authorized_keys.backup
然后添加新公钥必须使用:
tee -a
例如:
printf '%s\n' '这里放 admin-breakglass 公钥' | sudo tee -a /home/serveradmin/.ssh/authorized_keys >/dev/null
注意:
-a = append
也就是追加。
不是覆盖。
然后:
sudo chmod 700 /home/serveradmin/.ssh
sudo chmod 600 /home/serveradmin/.ssh/authorized_keys
28. 验证管理员救援链
Windows:
ssh -i "%USERPROFILE%\.ssh\demo\admin-breakglass" serveradmin@192.0.2.10
登录以后:
whoami
应该:
serveradmin
再:
sudo whoami
应该:
root
于是管理员链:
本地电脑
↓
admin-breakglass
↓
serveradmin
↓
sudo
↓
root
只有管理员拥有这一条链。
29. SSH 最终加固
注意:
一定要先验证管理员 Break-glass 能登录,再改 SSH。
查看真正生效配置:
sudo sshd -T | grep -E '^(port|permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|maxauthtries|x11forwarding|allowtcpforwarding|allowagentforwarding) '
推荐目标:
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
MaxAuthTries 3
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
30. 先备份 SSH 配置
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
然后创建独立配置:
sudo tee /etc/ssh/sshd_config.d/00-demo-hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
MaxAuthTries 3
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
EOF
31. SSH 配置绝不能直接 reload
先:
sudo sshd -t
如果:
没有任何输出
说明语法通过。
再查看:
sudo sshd -T | grep -E '^(permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|maxauthtries|x11forwarding|allowtcpforwarding|allowagentforwarding) '
确认正确以后才:
sudo systemctl reload ssh
检查:
sudo systemctl is-active ssh
应该:
active
32. 为什么旧 Admin 窗口不能关
修改 SSH 时最重要的安全习惯之一:
旧 admin SSH 会话
│
│ 保持在线
▼
修改 SSH
│
▼
reload
│
▼
新开 Windows 窗口
│
▼
重新登录 admin
如果新窗口失败:
旧窗口还在
就还能修。
如果一改配置就把旧窗口也关了:
可能把自己锁服务器外面
33. SSH 加固后重新验证
管理员:
ssh -i "%USERPROFILE%\.ssh\demo\admin-breakglass" serveradmin@192.0.2.10
检查:
whoami
sudo whoami
必须:
serveradmin
root
然后重新抽查小明 Deploy:
ssh -i "%USERPROFILE%\.ssh\demo\xiaoming-deploy" xiaoming-deploy@192.0.2.10
写 incoming:
echo "post hardening test" > /srv/demo-deploy/incoming/post-hardening-test.txt
成功。
写 production:
touch /var/www/demo-site/releases/should-fail.txt
必须:
Permission denied
说明 SSH 加固没有破坏 AI 正常工作链路。
34. 最后进行重启验收
所有操作完成以后:
sudo reboot
服务器恢复后重新登录:
ssh -i "%USERPROFILE%\.ssh\demo\admin-breakglass" serveradmin@192.0.2.10
检查:
whoami
sudo whoami
sudo systemctl is-active ssh
正确:
serveradmin
root
active
再抽查一次:
xiaoming-audit
和:
xiaoming-deploy
确认权限重启以后仍然存在。
35. 最终架构
整个系统最后应该是:
Linux Server
│
┌───────────────┴───────────────┐
│ │
serveradmin 小明
│ │
admin-breakglass ┌───────┴────────┐
│ │ │
sudo xiaoming-audit xiaoming-deploy
│ │ │
root 只读 有限写入
│ │ │
│ 检查 incoming 写 incoming
│ │ │
│ └──────┬─────────┘
│ │
│ 部署缓冲区
│ │
└────────── 发布 Gate ─────────┘
│
releases
│
root:root
│
current
│
Web Server
36. 日常真正让 AI 工作时怎么用
如果只是让小明检查:
ssh -i "%USERPROFILE%\.ssh\demo\xiaoming-audit" xiaoming-audit@192.0.2.10
此时:
能看 ✅
能检查 ✅
能改 ❌
能 sudo ❌
如果需要部署:
ssh -i "%USERPROFILE%\.ssh\demo\xiaoming-deploy" xiaoming-deploy@192.0.2.10
此时:
写 incoming ✅
修改 incoming ✅
写 releases ❌
修改 current ❌
sudo ❌
管理员:
ssh -i "%USERPROFILE%\.ssh\demo\admin-breakglass" serveradmin@192.0.2.10
只有管理员:
serveradmin
↓
sudo
↓
root
37. 最终校验清单
身份层
-
serveradmin是管理员 -
xiaoming-audit是审计身份 -
xiaoming-deploy是部署身份 - 三者使用不同 SSH Key
- AI 不使用管理员 SSH Key
Audit
- 可以 SSH 登录
- 可以读取 incoming
- 不可以修改 incoming
- 不可以创建文件
- 不可以修改 production
- 没有 sudo
Deploy
- 可以 SSH 登录
- 可以写 incoming
- ACL 正常
- setgid 正常
- 不可以直接写 releases
- 不可以修改 current
- 没有 sudo
Production
-
releases由root:root控制 - 使用独立 Release
-
current使用软链接 - 支持原子发布
- 支持快速回滚
管理员
- 独立 Break-glass Key
- 私钥设置 Passphrase
- 可以 SSH 登录
- 可以 sudo → root
- AI 不拥有管理员私钥
SSH
- Public Key 登录正常
- PasswordAuthentication no
- PermitRootLogin no
- KbdInteractiveAuthentication no
- MaxAuthTries 已收紧
- X11Forwarding no
- AllowTcpForwarding no
- AllowAgentForwarding no
-
sshd -t通过 - SSH 服务 active
最终验收
- 实际使用 Audit SSH 登录测试过
- 实际使用 Deploy SSH 登录测试过
- 实际做过 Permission denied 越权测试
- 管理员 Break-glass 真登录测试过
- 整机重启后再次验证过
38. 最后理解这套系统真正解决了什么
最危险的服务器 AI 使用方式是:
AI
↓
管理员账号
↓
root
而真正合理的模型应该是:
AI
↓
独立身份
↓
独立 SSH Key
↓
职责角色
↓
最小权限
↓
部署缓冲区
↓
验证
↓
发布 Gate
↓
生产环境
假设未来:
小明执行错命令
AI 提示词失控
某一把部署私钥泄露
部署脚本发生异常
攻击者或者错误程序得到的不是:
整台服务器
而只是:
xiaoming-deploy 本来就被允许操作的范围
例如:
/srv/demo-deploy/incoming
生产区仍然由:
root
控制。
这才是整个权限隔离系统真正的价值:
不是相信 AI 永远不会犯错,而是即使它犯错,系统也不给它把错误无限扩大的权限。