Featured image of post 如何部署并运行kun-touchgal-next项目

如何部署并运行kun-touchgal-next项目

这篇文章详细地描述了如何部署并运行kun-touchgal-next项目

先来介绍一下项目的基本情况

  1. 项目遵循 AGPL 3.0 开源协议
  2. 项目为 Node.js 技术栈,使用的框架为 Next.js,建议使用的 Node.js 版本为 Node 22
  3. 建议在服务器安装 NVM 以管理 Node.js 的版本,必须使用 pnpm
  4. 项目使用 PostgreSQL 作为数据库,需要安装 PostgreSQL
  5. 项目使用 PM2 作为部署手段,需要安装 PM2
  6. 项目使用 Redis 作为缓存,需要安装 Redis
  7. 项目的文档/博客内容(/doc)在项目的 /posts 文件夹中,你需要用 MDX 格式来编写文章

接下来就是安装的具体步骤,演示中的服务器安装的是 Debian12 系统,如果你使用的是其他的发行版请自行替换部分安装命令

安装 Node.js 环境

  1. 首先先更新一下软件包列表,更新一下软件

    1
    
    sudo apt update && sudo apt upgrade -y
    
  2. 然后安装一下必要依赖

    1
    
    sudo apt install curl wget git -y
    
  3. 用官方脚本安装 nvm

    1
    
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
    
  4. 安装完之后重载一下 shell 配置

    1
    
    source ~/.bashrc
    
  5. 验证一下安装,如果有输出版本号就说明安装完成

    1
    
    nvm --version
    

image-20250421013357837

  1. 用 nvm 安装 Node.js 22 版本,安装完成后会自动使用 Node.js 22,安装完成之后你可以用 node -v 查看版本号验证一下安装。注意本项目一定要使用 Node.js 22及以上版本,使用低于22版本的 Node.js 可能会有不可预见的问题

    1
    
    nvm install 22
    

    image-20250421013626085

  2. 执行 npm i -g pnpm 来安装 pnpm,然后使用 pnpm self-update 来将 pnpm 更新到最新版,然后可以使用 pnpm --version 来查看 pnpm 的版本,只要是大版本 9 以上都可以

image-20250421014145466

安装 Redis 环境

  1. 使用包管理器安装 redis

    1
    
    sudo apt install redis-server
    
  2. 启动 redis 并设置开机自启

    1
    2
    
    sudo systemctl start redis-server
    sudo systemctl enable redis-server
    
  3. 执行 redis-cli ping 来验证安装,如果返回 PONG 则说明安装正确

    image-20250421014645299

安装 PM2 环境

  1. 由于服务器上已经安装了 Node.js+pnpm 环境,所以可以直接用pnpm安装 pm2

    1
    
    pnpm i -g pm2
    

image-20250421014829920

  1. 执行 pm2 -v 来验证安装

image-20250421014856909

安装 PostgreSQL 环境

  1. 使用包管理器安装 PostgreSQL,安装完成后 PostgreSQL 会自动启动

    1
    
    sudo apt install postgresql postgresql-client
    
  2. 切换到 postgres 用户

    1
    
    sudo -i -u postgres
    
  3. 启动 PostgreSQL 命令行客户端

    1
    
    psql
    
  4. 修改管理密码,改好之后执行 quit 再按 Ctrl+D 退出

    1
    2
    
    # 这里的 your_password 要改成你自己的密码
    ALTER USER postgres WITH PASSWORD 'your_password';
    
  5. PostgreSQL 安装完成之后默认使用的是 peer 验证,也就是需要切换到 postgres 用户才能登录 PostgreSQL,这对我这种用惯了 MySQL 的有点不习惯。如果你也不习惯这种操作方式,你可以到 /etc/postgresql/15/main/pg_hba.conf 中将验证方式改为 scram-sha-256,当然这并不会影响程序的运行,所以这一步是可选的。改完之后执行 sudo systemctl restart postgresql 重启 PostgreSQL 应用修改

image-20250421015731668

  1. 执行 psql -U postgres 输入密码启动 PostgreSQL 命令行客户端

  2. 创建数据库,这里的数据库的名称 touchgal 可以随便改

    1
    
    CREATE DATABASE touchgal;
    
  3. 执行 \l 命令来查看当前服务器中所有的数据库,以确认 touchgal 数据库存在(\l 命令使用后按下 q 键退出)。 也可以执行 \c touchgal 切换到 touchgal 数据库,因为项目使用的数据库名为 touchgal,以确认 touchgal 数据库被创建成功

image-20250421020738958

  1. 使用 \q 命令退出 PostgreSQL

安装 Nginx 环境

  1. 使用包管理器安装 nginx

    1
    
    sudo apt install nginx
    
  2. 执行 sudo nano /etc/nginx/sites-available/touchgal.conf 编写nginx配置文件,这里的文件名可以随便修改。在配置文件里写一个简单的反向代理即可,因为项目默认监听 127.0.0.1:3000,所以我们将反代目标地址设置为 127.0.0.1:3000。这里默认你会在设置好后使用 cloudflare 反代,否则的话你需要在nginx中设置好 SSL

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    server
    {
        listen 80;
        server_name www.touchgal.io;
    
        location ^~ /
        {
            proxy_pass http://127.0.0.1:3000;
            proxy_set_header Host www.touchgal.io;
        }
    
    }
    
  3. 创建软链接来启用网站

    1
    
    sudo ln -s /etc/nginx/sites-available/touchgal.conf /etc/nginx/sites-enabled/
    
  4. 测试并应用配置

    1
    2
    
    nginx -t
    nginx -s reload
    

从 GitHub clone 项目并初始化项目

  1. 将 GitHub 仓库 clone 到服务器的当前文件夹,进入项目根目录并安装项目依赖

    1
    2
    3
    
    git clone https://github.com/KUN1007/kun-touchgal-next
    cd kun-touchgal-next
    pnpm i
    

image-20250421021034993

  1. 复制一份环境参数设置文件

    1
    
    cp .env.example .env
    
  2. 用nano或者其他编辑器修改 .env 的内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 前面我们已经创建了数据库,这里填写你的数据库密码
KUN_DATABASE_URL = "postgresql://postgres:<你的数据库密码>@localhost:5432/<你的数据库名称>?schema=public"

// 你的网站带 https 的域名
KUN_VISUAL_NOVEL_SITE_URL = "https://www.touchgal.io"

// 这里两个都填你的网站带 https 的域名
NEXT_PUBLIC_KUN_PATCH_ADDRESS_DEV = "https://www.touchgal.io"
NEXT_PUBLIC_KUN_PATCH_ADDRESS_PROD = "https://www.touchgal.io"


// redis 的默认地址和端口, 一般不用改动
REDIS_HOST = '127.0.0.1'
REDIS_PORT = '6379'


// JWT 的签发和 JWT 的私钥(JWT_SECRET),签发不用管,私钥应该尽可能复杂,私钥别直接用默认的,自己生成个
JWT_ISS = 'touchgal'
JWT_AUD = 'touchgal_admin'
JWT_SECRET = 'moemoekungalgamekunisthecutest!chinorensukiazkhx'


// Node.js 环境,在生产环境中应该改为 NODE_ENV = "production"
NODE_ENV = "development"


// 邮箱功能配置
KUN_VISUAL_NOVEL_EMAIL_FROM = "<发件人名称>"
KUN_VISUAL_NOVEL_EMAIL_HOST = "<SMTP服务器地址>"
KUN_VISUAL_NOVEL_EMAIL_PORT = '<SMTP服务器端口>'
KUN_VISUAL_NOVEL_EMAIL_ACCOUNT = "<发件的地址>"
KUN_VISUAL_NOVEL_EMAIL_PASSWORD = "<SMTP服务器密码>"


// S3 相关配置,需要改为你自己的,很重要
KUN_VISUAL_NOVEL_S3_STORAGE_ACCESS_KEY_ID = "<AccessKeyID>"
KUN_VISUAL_NOVEL_S3_STORAGE_SECRET_ACCESS_KEY = "<SecretKey>"
KUN_VISUAL_NOVEL_S3_STORAGE_BUCKET_NAME = "<桶名称>"
KUN_VISUAL_NOVEL_S3_STORAGE_ENDPOINT = "<存储桶 Endpoint>"
KUN_VISUAL_NOVEL_S3_STORAGE_REGION = "<存储桶地区>"
NEXT_PUBLIC_KUN_VISUAL_NOVEL_S3_STORAGE_URL = "<CDN链接,如https://img.touchgalstatic.org,结尾不带斜杠>"


// 图床域名,不带 https
KUN_VISUAL_NOVEL_IMAGE_BED_HOST = "img.touchgalstatic.org"
// 图床域名,带 url
KUN_VISUAL_NOVEL_IMAGE_BED_URL = "https://img.touchgalstatic.org"

// 禁止搜索引擎爬取测试网站,生产环境中应该删除或者注释掉该行
// KUN_VISUAL_NOVEL_TEST_SITE_LABEL = "noindex"
  1. 保存好 .env 后运行项目初始化脚本

    1
    
    pnpm deploy:install
    

image-20250421022611223

  1. 运行完成后执行 ls -lh 命令查看当前的文件夹,理论上应该有一个完全公开权限的文件夹 uploads,这个文件夹会缓存用户的上传文件

  2. 执行 psql -U postgres,然后输入密码,可以进入 PostgreSQL。输入 \c touchgal 切换到 touchgal 数据库。使用 \dt 查看数据库 touchgal 中有哪些表,确认刚才运行项目初始化脚本的时候已经将表创建成功了。使用 \q 命令退出 PostgreSQL

  3. 运行生产环境的构建脚本,构建完成后项目会运行在服务器本地的 127.0.0.1:3000 端口,因为之前我们已经设置好了 Nginx 反向代理,所以现在你应该已经可以打开网站了

    1
    
    pnpm deploy:build
    
  4. 到网站的注册页面注册一个用户,第一个注册的用户的UID为1,建议给 UID 为 1 的用户超级管理员

  5. 回到到服务器中,执行 psql -U postgres 启动 PostgreSQL 命令行客户端,然后输入密码进入 PostgreSQL。输入 \c touchgal 切换到 touchgal 数据库。执行 UPDATE "user" SET role = 4 WHERE id = 1; 这个 SQL 语句的作用是将 ID 为 1 的用户设置为超级管理员。

    系统规定,role 字段为 1 的用户是普通用户,2 为创作者,3 为管理员,4 超级管理员

    注意,这里的 UID 为 1 的用户就是上面注册的那个用户

  6. 重新进入网站刷新页面,应该已经可以在用户 1 的主页看到用户 1 变为了超级管理员

到这里整个项目已经部署完毕,接下来是一些模块的使用教程和注意事项

如何编写项目 /doc 目录的 MDX 文件

  1. 本项目使用 MDX 作为网站 Blog 编写格式,区别于 Markdown 的地方就是可以在 MDX 文件里面写 tsx / jsx,如果用不到这些高级功能可以不用管

  2. 本项目的 matter 属性如下

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    ---
    title: 鲲 Galgame 补丁开发文档
    banner: '/posts/dev/documentation/banner.avif'
    description: '鲲 Galgame 补丁的开发技术栈为 Next.js 15 + Prisma + PostgreSQL + PM2 + Cloudflare Tunnel + S3 Object Storage'
    date: 2024-12-08
    authorUid: 2
    authorName: '鲲'
    authorAvatar: 'https://image.moyu.moe/user/avatar/user_2/avatar-mini.avif'
    authorHomepage: 'https://github.com/KUN1007'
    pin: false
    ---
    

    banner 属性的文章的头图,可以使用 https url 的链接,也可以使用相对路径静态文件资源的链接,将图片文件托管在项目的目录中。我这里,会将项目的 public 目录解析为文章中静态资源的根目录,这里的 ‘/posts/dev/documentation/banner.avif’ 的位置就在项目的 public 文件夹下对应的位置

    description 属性严重设计到 /doc 目录的 SEO,建议填写 170 字左右

    date 是文字发布的日期,authorUid 就是文章发布者的 UID,就是用户主页路径里的数字,一般填写你自己的就可以,下面两个也是一样的

    pin 属性指明了这个文章是否会被在主页的走马灯(轮播图)组件中置顶

  3. 项目的 posts 目录存放了当前所有的文章,posts 目录的结构就对应着 /doc 页面的目录结构

    然后页面的路径就是这样的

    页面中的目录映射了 posts 文件夹的目录结构

  4. 目录的名称映射文件在项目的 contants/doc.ts 文件中,当你新建目录的时候应该同步更新这个文件的目录名称映射

如何添加友情链接

在项目的 config/friend.json 文件中编写对应的信息即可

如何配置网站的信息

网站的信息目前已经配置好,如果需要更改,则必须更改 config/moyu-moe.ts 文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
const KUN_SITE_NAME = 'TouchGal'
const KUN_SITE_MENTION = '@touchgal'
const KUN_SITE_TITLE = 'TouchGal - 一站式Galgame文化社区!'
const KUN_SITE_IMAGE =
  'https://img.touchgalstatic.org/uploads/20241217174250074.avif'
const KUN_SITE_DESCRIPTION =
  'TouchGal 是一个一站式 Galgame 文化社区。提供Galgame 论坛、Galgame 下载等服务。承诺永久免费, 高质量。为Galgame 爱好者提供一片净土!'
const KUN_SITE_URL = 'https://www.touchgal.io'
const KUN_SITE_ARCHIVE = 'https://archive.touchgal.co/'
const KUN_SITE_FORUM = 'https://bbs.touchgal.co/'
const KUN_SITE_NAV = 'https://gal.red'
const KUN_SITE_TELEGRAM_GROUP = 'https://t.me/+yPQQaPhgLbc5MGIx'
const KUN_SITE_LIST = [
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.net' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.moe' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.one' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.com' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.org' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.me' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.co' }
]
const KUN_SITE_KEYWORDS = [
  'TouchGAL',
  'Gal',
  'Galgame',
  '论坛',
  '网站',
  'Galgame 下载',
  'Galgame 资源',
  'Galgame wiki',
  'Galgame 评测',
  'Galgame 数据分析',
  'Galgame 新作动态',
  'Galgame 汉化 / 国际化',
  'Galgame 制作',
  'Galgame 讨论',
  '游戏交流',
  '其他交流',
  ...Object.values(SUPPORTED_TYPE_MAP)
]

暂时仅建议更改这里的信息,如非必要不要更改这个文件,这涉及到网站全部的名称、链接配置与 SEO 优化

关于项目的构建

  1. 每次当你对项目做了任何更改,必须重新在服务器的项目根目录运行一遍 pnpm deploy:build 命令,这会将你的更改应用到项目中,并重新构建项目
  2. 构建过程一般在 1 ~ 2 分钟,这个期间网站会有部分功能不可用,正在访问网站的用户不会受到影响
  3. 构建完毕之后服务器需要将新生成的文件读取到到内存,CDN 和用户浏览器的缓存也需要刷新,网站速度会短暂变慢直到 CDN 和用户浏览器的缓存与服务器同步

严重警告

如果你在运行 pnpm deploy:build 或者运行任何其它命令的时候,看到下面的提示消息

1
2
3
⚠️ We found changes that cannot be executed:
× To apply this change we need to reset the database, do you want to continue? All data will be lost. ... 
no

这时,必须连按两下 Ctrl + c 中断操作,或者输入 n 以取消操作

千万不要按 y 或者回车,否则,数据库中的所有数据会被全部重置,不可能还原,如果没有备份将会倾家荡产,非常严重

这个是使用 prisma 造成了对数据库不可逆的更改造成的,一般不会有这种情况,如果有会明确告知

几个重要的地方说明

  1. 自行修改项目代码造成的任何不良后果需要自行承担

  2. 网站的 NSFW 文章,用户主页等已经彻底阻止搜索引擎索引,这些文章将会 0 SEO 甚至反 SEO,不会对其它页面产生影响

  3. 项目的 uploads 文件夹是用户上传的临时文件,因为怕有的用户上传一半不传了或者传了不发布产生死文件。项目没过 1h 会自动扫描一遍项目中的 uploads 文件夹,删除超过 1 天的死文件

  4. 项目占用服务器的内存取决于网站的访问量以及项目的实例数,理论上 300k ~ 400k 月独立 ip 数的网站,使用 pm2 部署,按照目前的配置可以流畅运行,内存占用在 700MB 左右

  5. 如果觉得网站速度还是不够,可以多开几个实例,实例数取决于服务器的核数,pm2 会利用服务器的核数自动负载均衡,目前只开了一个实例。例如 16 核服务器可建议开 16 个实例,项目会自动进行负载均衡,但是同时项目对服务器的内存占用也会变成 700MB * 16

    开多实例的方法就是更改项目根目录的 ecosystem.config.js 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    module.exports = {
      apps: [
        {
          name: 'kun-touchgal-next',
          port: 3000,
          cwd: '.',
          instances: 1,
          autorestart: true,
          watch: false,
          max_memory_restart: '1G',
          script: './.next/standalone/server.js'
        }
      ]
    }
    

    你可以把这里的 instances 数量改为对应你服务器核数的数字,比如你划出了一个 4c8g 的小鸡,可以把 instances 改为 4,6c12g 则可以把 instances 改为 6

Licensed under CC BY-NC-SA 4.0