skip to content
自建部署系统

Vercel Too Slow? Build Your Own

2 min read

This page was translated by AI

1. Why I Did This

A few days ago, I got in touch with a developer. I really liked a theme from his earlier blog, but unfortunately it was not open source at the time.

He has now made the theme’s source code public on GitHub, so I immediately started deploying the blog with plans to replace my current one.

Taco is a Next.js project. I used the convenient Node.js Docker deployment environment provided by the 1Panel dashboard.

Unfortunately, every time I modified the source code, I had to package it into a ZIP file, upload it to the server, extract it, overwrite the existing files, compile it again, and run it. It was extremely tedious!

Later, the author suggested an edge-computing platform such as Vercel. I tried it and liked it, but access from China was unreliable. After tinkering with it for a while, I realized that I already had two servers and did not need to pay extra for an edge-computing service. So I decided to build my own “DevOps” setup.

2. Preparation

Because my code is on GitHub, I decided to use GitHub Actions. Let’s create the workflow file.

First, let’s model Vercel’s workflow: repository update → Vercel is triggered → the project is rebuilt.

We can turn that flow into a workflow:

  • When the repository is updated, trigger an action.
  • Connect to the server.
  • Change to the project directory.
  • Update the files with Git.
  • Enter the Node.js Docker container.
  • Build the project.
  • Restart the container.

3. Configuration

Here are two workflow options:

  1. Connect to the server with an SSH key:
# workflow:
name: Server Update
on:
push:
branches:
- main
jobs:
deploy:
runs-on: self-hosted
steps:
- name: Deploy using direct SSH with key
run: |
# 创建SSH目录(如果不存在)
mkdir -p ~/.ssh
# 将私钥保存到临时文件
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa_deploy
chmod 600 ~/.ssh/id_rsa_deploy
# 添加服务器到known_hosts以避免提示
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
# 执行SSH命令
ssh -i ~/.ssh/id_rsa_deploy \
-o StrictHostKeyChecking=accept-new \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} \
-p ${{ secrets.SERVER_PORT }} \
'
echo "🚀 正在进入项目目录..."
cd /opt/node/Taco || { echo "❌ 项目目录不存在,请检查路径"; exit 1; }
echo "🔄 正在拉取最新代码..."
git fetch origin main && git reset --hard origin/main
echo "📦 正在进入 Docker 容器 [Taco] 并构建项目..."
docker exec Taco sh -c "npm run build"
echo "🔁 正在重启容器 [Taco]..."
docker restart Taco
echo "✅ 部署完成"
'
# 清理临时密钥文件
rm -f ~/.ssh/id_rsa_deploy`
  1. Connect with password authentication (requires sshpass):
# workflow:
name: Server Update
on:
push:
branches:
- main
jobs:
deploy:
runs-on: self-hosted
steps:
- name: Install sshpass if needed
run: |
if ! command -v sshpass &> /dev/null; then
echo "sshpass not found, installing..."
sudo apt-get update && sudo apt-get install -y sshpass
fi
- name: Deploy using direct SSH with password
run: |
# 使用sshpass进行密码认证
sshpass -p "${{ secrets.SERVER_PASSWORD }}" \
ssh -o StrictHostKeyChecking=no \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} \
-p ${{ secrets.SERVER_PORT }} \
'
echo "🚀 正在进入项目目录..."
cd /opt/node/Taco || { echo "❌ 项目目录不存在,请检查路径"; exit 1; }
echo "🔄 正在拉取最新代码..."
git fetch origin main && git reset --hard origin/main
echo "📦 正在进入 Docker 容器 [Taco] 并构建项目..."
docker exec Taco sh -c "npm run build"
echo "🔁 正在重启容器 [Taco]..."
docker restart Taco
echo "✅ 部署完成"
'

With that, the automated deployment setup is complete!

4. Summary

If, like me, you use 1Panel to deploy a Node.js project but do not want to upload everything again for every update, you can try this approach.

The workflow uses a local runner by default. If you need to use a GitHub-hosted runner, adjust it yourself.