Reactive Resume 自托管简历构建器部署教程:开源 Resume.io 替代方案

在求职过程中,一份精美的简历往往能带来关键优势。Reactive Resume 是一款完全开源、支持自托管的在线简历构建工具,功能对标 Resume.io 和 Canva 等商业产品,但完全免费且数据由你自己掌控。它提供多种精心设计的简历模板,支持实时预览编辑、多语言界面、PDF 高保真导出,以及通过公开链接分享简历。项目采用 MIT 协议开源,代码托管在 GitHub 上,拥有活跃的社区维护。

与 Resume.io 等 SaaS 工具相比,自托管 Reactive Resume 的核心优势在于隐私保护——你的简历数据存储在自己的服务器上,不会被第三方服务商扫描或泄露。此外,自托管版本没有功能限制,无需订阅付费,所有高级模板均可免费使用。对于需要统一管理团队成员简历的 HR 部门,或希望为学生提供简历工具的教育机构,私有化部署也有明显优势。

本教程将使用 Docker Compose 部署 Reactive Resume v4,并配置 Caddy 作为反向代理,实现自动 HTTPS,整个部署过程约需 15-20 分钟。


服务器配置

Reactive Resume 采用前后端分离架构,后端依赖 PostgreSQL 数据库和 Minio 对象存储,需要一定的基础资源。

推荐使用雨云服务器 rainyun-com,注册填优惠码 2026off 领 5 折优惠券。1 核 2GB 机型可满足个人或小团队使用,在空载状态下内存占用约为 800MB(包含 PostgreSQL、Minio、后端 API 和前端服务)。操作系统推荐 Ubuntu 22.04 LTS,并提前准备好一个解析到服务器 IP 的域名(Caddy 自动 HTTPS 需要)。


安装准备工作

安装 Docker 和 Docker Compose

# 更新系统
sudo apt update && sudo apt upgrade -y

# 安装 Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker

# 验证安装
docker --version
docker compose version

安装 Caddy

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
    | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
    | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy

准备项目目录

mkdir -p ~/reactive-resume
cd ~/reactive-resume

详细配置

创建 Docker Compose 文件

nano ~/reactive-resume/docker-compose.yml
version: "3.8"

services:
  # PostgreSQL 数据库
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: reactive_resume
      POSTGRES_USER: rxresume
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U rxresume -d reactive_resume"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Minio 对象存储(用于存储上传的图片等文件)
  minio:
    image: minio/minio:latest
    restart: unless-stopped
    command: server /data --console-address ":9001"
    volumes:
      - minio_data:/data
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Minio 初始化(创建 bucket)
  minio-init:
    image: minio/mc:latest
    depends_on:
      minio:
        condition: service_healthy
    entrypoint: >
      /bin/sh -c "
      mc alias set local http://minio:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD};
      mc mb --ignore-existing local/reactive-resume;
      mc anonymous set download local/reactive-resume;
      exit 0;
      "

  # Chrome(用于生成 PDF)
  chrome:
    image: browserless/chrome:latest
    restart: unless-stopped
    environment:
      TIMEOUT: 30000
      CONCURRENT: 5
      TOKEN: ${CHROME_TOKEN}

  # Reactive Resume 后端 API
  backend:
    image: amruthpillai/reactive-resume:server-latest
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
      minio:
        condition: service_healthy
    environment:
      # 应用配置
      PORT: 3000
      NODE_ENV: production
      PUBLIC_URL: https://${DOMAIN}
      STORAGE_URL: https://${DOMAIN}/storage

      # 数据库
      DATABASE_URL: postgresql://rxresume:${POSTGRES_PASSWORD}@postgres:5432/reactive_resume

      # JWT 认证
      ACCESS_TOKEN_SECRET: ${ACCESS_TOKEN_SECRET}
      REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET}

      # Minio 存储
      STORAGE_ENDPOINT: minio
      STORAGE_PORT: 9000
      STORAGE_SSL: "false"
      STORAGE_ACCESS_KEY: ${MINIO_ROOT_USER}
      STORAGE_SECRET_KEY: ${MINIO_ROOT_PASSWORD}
      STORAGE_BUCKET: reactive-resume

      # Chrome PDF 生成
      CHROME_URL: http://chrome:3000?token=${CHROME_TOKEN}

      # 邮件(可选,用于找回密码)
      MAIL_FROM: noreply@${DOMAIN}
      # SMTP_URL: smtp://user:pass@smtp.example.com:587

  # Reactive Resume 前端
  frontend:
    image: amruthpillai/reactive-resume:client-latest
    restart: unless-stopped
    depends_on:
      - backend
    environment:
      PUBLIC_SERVER_URL: https://${DOMAIN}/api
      VITE_SERVER_URL: https://${DOMAIN}/api

volumes:
  postgres_data:
  minio_data:

创建环境变量文件

nano ~/reactive-resume/.env
# 域名
DOMAIN=resume.yourdomain.com

# 数据库密码(使用强密码)
POSTGRES_PASSWORD=your_strong_db_password_here

# Minio 凭据
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=your_minio_password_here

# JWT 密钥(使用随机字符串)
ACCESS_TOKEN_SECRET=$(openssl rand -hex 32)
REFRESH_TOKEN_SECRET=$(openssl rand -hex 32)

# Chrome 访问 token
CHROME_TOKEN=$(openssl rand -hex 16)

生成真实的随机密钥:

echo "ACCESS_TOKEN_SECRET=$(openssl rand -hex 32)"
echo "REFRESH_TOKEN_SECRET=$(openssl rand -hex 32)"
echo "CHROME_TOKEN=$(openssl rand -hex 16)"

将生成的值填入 .env 文件。

配置 Caddy 反向代理

sudo nano /etc/caddy/Caddyfile
resume.yourdomain.com {
    # 前端
    handle / {
        reverse_proxy localhost:3001
    }

    # 后端 API
    handle /api/* {
        uri strip_prefix /api
        reverse_proxy localhost:3000
    }

    # Minio 对象存储(公开读取)
    handle /storage/* {
        uri strip_prefix /storage
        reverse_proxy localhost:9000
    }

    # 安全头
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
    }

    # 日志
    log {
        output file /var/log/caddy/resume.log
    }
}

启动服务

cd ~/reactive-resume

# 启动所有容器
docker compose up -d

# 查看启动日志
docker compose logs -f

# 重载 Caddy 配置
sudo systemctl reload caddy

等待约 1-2 分钟,所有容器初始化完成后,访问 https://resume.yourdomain.com 即可看到注册界面。


核心功能

注册首个管理员账户

首次访问时点击"注册",填写邮箱和密码完成注册。默认情况下,任何人都可以注册账户。如需禁用公开注册(仅限管理员邀请):

# 在 docker-compose.yml 的 backend 环境变量中添加:
DISABLE_SIGNUPS: "true"

创建和编辑简历

  1. 登录后点击"新建简历"
  2. 选择模板(提供 12+ 种设计模板)
  3. 在左侧面板填写个人信息、工作经历、教育背景、技能等
  4. 右侧实时预览最终效果
  5. 调整字体、颜色、间距等排版参数

导出 PDF

# PDF 导出依赖 Chrome 容器,确保其正常运行
docker compose ps chrome

# 在简历编辑页面右上角点击"下载 PDF"
# PDF 由无头 Chrome 渲染,保持与网页预览完全一致的排版

公开分享链接

在简历设置中开启"公开访问",即可获得一个永久分享链接,格式为:

https://resume.yourdomain.com/r/your-unique-slug

实战示例

备份数据库

# 备份 PostgreSQL
docker compose exec postgres pg_dump -U rxresume reactive_resume \
    > ~/backups/rxresume_$(date +%Y%m%d).sql

# 备份 Minio 数据
docker run --rm -v reactive-resume_minio_data:/data \
    -v ~/backups:/backup alpine \
    tar czf /backup/minio_$(date +%Y%m%d).tar.gz /data

更新到最新版本

cd ~/reactive-resume
docker compose pull
docker compose up -d
docker image prune -f

常见问题

Q:PDF 导出失败或超时

A:检查 Chrome 容器是否正常运行(docker compose ps chrome)。内存不足时 Chrome 可能崩溃,建议服务器内存至少 2GB,并确认 CHROME_TOKEN 环境变量与配置一致。

Q:上传头像或附件失败

A:检查 Minio 容器状态,确认 reactive-resume bucket 已被 minio-init 服务创建,并设置了匿名读取权限。可手动执行初始化:docker compose run --rm minio-init

Q:注册邮箱收不到验证邮件

A:默认不需要邮件验证即可登录。若配置了 SMTP 但邮件未收到,检查 SMTP_URL 格式是否正确,以及邮件服务商是否需要应用专用密码。

Q:Caddy 无法获取 SSL 证书

A:确认域名已正确解析到服务器 IP,服务器 80 和 443 端口已开放(sudo ufw allow 80 && sudo ufw allow 443)。查看 Caddy 日志:journalctl -u caddy -f

Q:如何重置管理员密码

A:

docker compose exec postgres psql -U rxresume reactive_resume -c \
    "UPDATE users SET password='\$argon2id\$...' WHERE email='admin@example.com';"
# 或通过"忘记密码"功能发送重置邮件(需配置 SMTP)

Reactive Resume 是目前功能最完善的开源简历构建工具,借助 Docker Compose 部署方式,即使没有深厚的运维经验也可以在半小时内搭建完成。如果你正在寻找一台性价比高的服务器来托管个人工具集,推荐选用雨云服务器 rainyun-com1 核 2GB 机型,注册时填入优惠码 2026off 即可领取 5 折优惠券,以极低的月费运行属于自己的私有简历系统,告别数据隐患。

更多推荐