Compare commits

...

4 Commits

5 changed files with 260 additions and 62 deletions

View File

@@ -1,59 +0,0 @@
name: Deploy docs for Site
run-name: ${{ gitea.actor }} is building out Gitea Actions 🚀
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x]
steps:
- name: Checkout repository code
uses: https://gitea.com/actions/checkout@v4
with:
ref: 'main'
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
# Skip pnpm cache to reduce overhead
- name: Install pnpm
run: |
if ! command -v pnpm &> /dev/null; then
npm install -g pnpm@9
else
echo "pnpm is already installed"
fi
- name: Check Node.js and pnpm versions
run: |
echo "pnpm version ===>" && pnpm -v
echo "node version ===>" && node -v
# Simplify node_modules handling without caching
- name: Install dependencies
run: |
if [ ! -d "node_modules" ] || [ "$(find package.json -newer node_modules)" ]; then
echo "Dependencies are outdated or missing, installing..."
pnpm install
else
echo "Dependencies are up-to-date, skipping installation."
fi
- name: Build site
run: pnpm build
- name: ssh deploy
uses: easingthemes/ssh-deploy@v5.1.0
with:
SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_PRIVATE_KEY }}
REMOTE_HOST: ${{ secrets.DEPLOY_HOST }}
REMOTE_USER: ${{ secrets.DEPLOY_USER }}
SOURCE: "/dist/"
TARGET: "/opt/1panel/apps/openresty/openresty/www/sites/zhaoguiyang.com/index/dist"
EXCLUDE: "/node_modules/"

3
.gitignore vendored
View File

@@ -24,3 +24,6 @@ pnpm-debug.log*
.idea/ .idea/
.trae/ .trae/
# deploy script
deploy.sh

View File

@@ -20,7 +20,7 @@ export const translations = {
}, },
hero: { hero: {
greeting: "Hello, I'm", greeting: "Hello, I'm",
viewProjects: 'View Projects', viewProjects: 'About Me',
contactMe: 'Contact Me', contactMe: 'Contact Me',
lookingForJob: 'Looking for a Frontend/TS Full-stack Engineer (Remote)? Contact me!', lookingForJob: 'Looking for a Frontend/TS Full-stack Engineer (Remote)? Contact me!',
digitalNomad: 'Exploring the freelance journey, striving to become a digital nomad', digitalNomad: 'Exploring the freelance journey, striving to become a digital nomad',
@@ -77,7 +77,7 @@ export const translations = {
}, },
hero: { hero: {
greeting: '你好,我是', greeting: '你好,我是',
viewProjects: '查看项目', viewProjects: '关于我',
contactMe: '联系我', contactMe: '联系我',
lookingForJob: '正在寻找前端/TS 全栈工程师(远程)?联系我!', lookingForJob: '正在寻找前端/TS 全栈工程师(远程)?联系我!',
digitalNomad: '探索自由职业道路,努力成为数字游民', digitalNomad: '探索自由职业道路,努力成为数字游民',

View File

@@ -0,0 +1,127 @@
---
layout: "@/layouts/BlogPostLayout.astro"
title: "1Panel Automated Deployment Notes: Say Goodbye to Manual Uploads, One-Command Takeoff from Local"
description: "Learn how to build a lightweight deployment pipeline using 1Panel with SSH key authentication and ACL permissions. Complete guide for solo developers to automate server deployments."
date: "2024-06-08"
image: "https://images.unsplash.com/photo-1558494949-ef010cbdcc31?q=80&w=1470&auto=format&fit=crop"
tags: ["1Panel", "DevOps", "Automation", "SSH", "Deployment"]
tagId: ["1panel", "devops", "automation", "ssh", "deployment"]
category: "DevOps"
categoryId: "devops"
readTime: "5 min read"
---
Updating code used to make me feel like a "human FTP client":
1. Package everything locally, sweat included
2. Open browser, log into 1Panel (forgot password again?)
3. Dig through file manager like an archaeologist
4. Manual upload, manual overwrite, plus manual cleanup of old files
This whole ritual took at least 5 minutes each time, and last week I actually brought the site down for 10 minutes because I forgot to upload a new config file. Enough is enough—I built this lightweight deployment pipeline. No heavy Jenkins setup needed, perfect for solo developers or small projects. Fast, reliable, and nobody else to blame.
## 1. Create a "Deployment Runner" Account
Running scripts as root? That's like performing surgery with a chainsaw. Let's create a dedicated account just for deployments.
```bash
# Create the deployment account
sudo adduser deploy_user
# Critical: disable password login, SSH keys only
# Even if someone guesses the password, they can't get in
# -l locks the password account (disabled password login)
# -u unlocks the password account (if you need enabled password login)
sudo passwd -l deploy_user
```
## 2. The Permission Puzzle: ACL to the Rescue
Here's the tricky part: 1Panel has its own permission system. If you `chown` everything to your deployment user, websites in the panel might start throwing 500 errors.
My solution: **ACL** (Access Control Lists). Think of it as giving your deployment user a "VIP backstage pass"—it can read/write files without messing with 1Panel's original file ownership.
```bash
# Install ACL tools first
sudo apt install acl -y
# Grant access to sites directory (make sure this is your web root)
# -R means recursive, but be careful if directory has other sites
sudo setfacl -R -m u:deploy_user:rwx /opt/1panel/www/sites
# Set default inheritance: new sites get access automatically
sudo setfacl -R -d -m u:deploy_user:rwx /opt/1panel/www/sites
```
## 3. SSH Key Access: No More Password Typing
Copy your local SSH public key to the server, and never type a password again.
```bash
# Create SSH directory for deployment user
sudo -u deploy_user mkdir -p /home/deploy_user/.ssh
# Append your public key (using >> not > to avoid overwriting)
echo "your-ssh-public-key-content" >> /home/deploy_user/.ssh/authorized_keys
# Permissions must be exact, or SSH will refuse
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
```
**Even lazier method**: If you have `ssh-copy-id` locally, just run `ssh-copy-id deploy_user@your-server-ip`.
## 4. SSH Aliases (For the Truly Lazy)
Memorize IP addresses? Not in this decade. Add this to your local `~/.ssh/config`:
```text
Host your-server-alias # Nickname for your server
HostName your-server-ip-address # Your server IP
User deploy_user # Login user
IdentityFile ~/.ssh/id_rsa # Private key path
```
Now just type `ssh your-server-alias` and you're in. Magic.
## 5. The Grand Finale: One-Command Deployment
Create `deploy.sh` in your project root:
```bash
#!/bin/bash
# For frontend projects, build first
# echo "📦 Building..."
# npm run build
echo "🚀 Syncing to production..."
# rsync for incremental updates
# -a: archive mode (preserves everything)
# -v: verbose (show me what's happening)
# -z: compress during transfer
# --delete: ⚠️ Warning: removes files on target that don't exist locally!
# Remove this flag for first sync to be safe
rsync -avz --delete --progress ./dist/ your-server-alias:/opt/1panel/www/sites/your-project-directory/
echo "✅ Deployment complete!"
echo "⏱️ Next time just run: ./deploy.sh"
```
Make it executable: `chmod +x deploy.sh`. Now deploying is literally one command.
## 6. Pitfalls I Stepped In (So You Don't Have To)
1. **Skip `--delete` on first sync**: Do a dry run first. This flag can delete important files if you're not careful.
2. **Check ACL permissions**: If files still have permission issues, run `getfacl /opt/1panel/www/sites/your-project` to verify.
3. **Verify paths**: 1Panel's default path is `/opt/1panel/www/sites/`, but check if you customized it.
4. **Frontend projects**: Don't upload `node_modules`. Your server doesn't need that 200MB baggage.
## Wrapping Up
I've been using this setup for weeks, and it just works. What used to be a 5-minute chore is now a 30-second command. The mental load is gone—no more "did I forget that one file?" anxiety.
For small to medium projects that don't need full CI/CD complexity, this lightweight approach is perfect. A few minutes to set up, a lifetime of easy deployments.
**Final reminder**: Automation is powerful but dangerous. Test with a dummy directory first, especially before using `--delete`. Happy deploying, and may your uptime be forever!

View File

@@ -0,0 +1,127 @@
---
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又被手动上传困扰试试这个方案吧。
**最后提醒**:任何自动化操作都有风险,尤其是删除操作。第一次在生产环境用的时候,建议先找个测试目录跑一遍,确认无误再上。祝大家部署顺利,永不宕机!