---
layout: "@/layouts/BlogPostLayout.astro"
title: "1Panel 自动化部署笔记：告别\"手动操作\"，本地一键起飞"
description: "学习如何基于 1Panel 构建轻量级部署流水线，配合 SSH 密钥认证和 ACL 权限管理。本文为单兵作战的开发者提供了完整的自动化部署方案。"
date: "2024-06-08"
image: "https://images.unsplash.com/photo-1558494949-ef010cbdcc31?q=80&w=1470&auto=format&fit=crop"
tags: ["1Panel", "DevOps", "自动化", "SSH", "部署"]
tagId: ["1panel", "devops", "automation", "ssh", "deployment"]
category: "DevOps"
categoryId: "devops"
readTime: "5 min read"
---

以前每次更新代码，都感觉自己像个"人肉传输带"：

1. 本地吭哧吭哧打包
2. 打开浏览器，输密码登录 1Panel 面板
3. 在文件管理器里翻来覆去找目录
4. 手动上传、手动覆盖，有时候还得手动删服务器上的旧文件，就怕哪个缓存文件没清干净

这一套流程下来，没个三五分钟搞不定，关键还特别容易漏文件。上周就因为我忘记上传一个新加的配置文件，线上挂了十分钟才反应过来。痛定思痛，我决定搞一套轻量级部署方案——不用整 Jenkins 那种大炮打蚊子，特别适合我这种单兵作战的小项目，要的就是快、稳、不求人。

## 1. 先整个"跑腿小弟"账号

用 root 跑脚本？那太野了，万一脚本写崩了，服务器直接原地升天。得建个专门干这活的"小弟账号"。

```bash
# 创建专门负责部署的账号
sudo adduser deploy_user

# 关键一步：禁用这个账号的密码登录，只认 SSH 密钥
# 这样就算有人猜到密码也进不来，安全第一
# -l 锁定账号密码（禁用密码登录）
# -u 解锁账号密码（如需恢复密码登录）
sudo passwd -l deploy_user
```

## 2. 权限难题的"优雅解法"：ACL 授权

这里有个坑：1Panel 管理的文件有自己的一套权限体系，如果你用 `chown` 强行改属主，面板里的网站可能就直接 500 错误了。

我的解决方案是 **ACL**（访问控制列表）。这玩意就像给文件加了张"访客通行证"，让 `deploy_user` 这个账号能读写文件，但又不会破坏 1Panel 原本的文件归属关系。

```bash
# 先安装 ACL 工具
sudo apt install acl -y

# 给 sites 目录开绿灯（注意：确认这是你的网站根目录）
# -R 表示递归，但如果目录里已有其他站点，建议先备份或确认操作
sudo setfacl -R -m u:deploy_user:rwx /opt/1panel/www/sites

# 设置默认权限继承：以后在面板里新建的站点，自动给 deploy_user 权限
sudo setfacl -R -d -m u:deploy_user:rwx /opt/1panel/www/sites
```

## 3. SSH 免密登录：从此进出如风

把你本地电脑的 SSH 公钥塞到服务器上，以后就不用输密码了。

```bash
# 切换到部署账号的家目录
sudo -u deploy_user mkdir -p /home/deploy_user/.ssh

# 追加你的公钥（用 >> 而不是 >，避免覆盖别人的密钥）
echo "your-ssh-public-key-content" >> /home/deploy_user/.ssh/authorized_keys

# 权限必须严格设置，否则 SSH 会拒绝连接
sudo chown -R deploy_user:deploy_user /home/deploy_user/.ssh
sudo chmod 700 /home/deploy_user/.ssh
sudo chmod 600 /home/deploy_user/.ssh/authorized_keys
```

**更懒的方法**：如果你本地有 `ssh-copy-id` 命令，直接 `ssh-copy-id deploy_user@your-server-ip-address`。

## 4. SSH 别名配置（懒癌患者的福音）

记 IP 地址？不存在的。在本地 `~/.ssh/config` 文件里加一段：

```text
Host your-server-alias  # 给你服务器起的外号，随便起，好记就行
    HostName your-server-ip-address  # 你的服务器 IP
    User deploy_user  # 登录用户
    IdentityFile ~/.ssh/id_rsa  # 私钥路径
```

配置完，以后登录就直接 `ssh your-server-alias`，爽！

## 5. 终极一击：一键部署脚本

在项目根目录创建 `deploy.sh`：

```bash
#!/bin/bash

# 如果是前端项目，先打包
# echo "📦 正在打包..."
# npm run build

echo "🚀 开始同步到生产环境..."
# 使用 rsync 增量同步
# -a: 归档模式，保持文件属性
# -v: 显示详细过程
# -z: 压缩传输
# --delete: ⚠️ 注意：这会删除目标端有而源端没有的文件！
#          首次同步建议先去掉这个参数，确认无误后再加上
rsync -avz --delete --progress ./dist/ your-server-alias:/opt/1panel/www/sites/your-project-directory/

echo "✅ 部署完成！"
echo "⏱️ 下次更新只需: ./deploy.sh"
```

给脚本执行权限：`chmod +x deploy.sh`，以后部署就是一行命令的事儿。

## 6. 我踩过的坑和注意事项

1. **首次同步别用 `--delete`**：先完整同步一次，确认文件都对，再加这个参数。不然可能把服务器上的重要文件删了。
2. **ACL 权限检查**：如果同步后还是没权限，可以用 `getfacl /opt/1panel/www/sites/your-project-directory` 看看 ACL 设置是否生效。
3. **文件路径要对**：1Panel 的默认站点路径是 `/opt/1panel/www/sites/`，但如果你改过，记得调整。
4. **前端项目注意**：打包前清理 `node_modules`，这玩意别传到服务器。

## 总结

这套方案我从上周用到现在，真香！以前更新一次至少折腾5分钟，现在30秒搞定。关键是心理负担小了——再也不用担心漏传文件，`rsync` 会帮我搞定一切。

对于还没到需要 CI/CD 的中小型项目，这种轻量级方案简直完美。几分钟配置，一劳永逸。如果你也在用 1Panel，又被手动上传困扰，试试这个方案吧。

**最后提醒**：任何自动化操作都有风险，尤其是删除操作。第一次在生产环境用的时候，建议先找个测试目录跑一遍，确认无误再上。祝大家部署顺利，永不宕机！
