diff --git a/.env b/.env
index 2f80455..033e090 100644
--- a/.env
+++ b/.env
@@ -1,5 +1,5 @@
-IMAGE_NAME=vitepressbook
+IMAGE_NAME=wandoubabadocs
IMAGE_TAG=latest
-CONTAINER_NAME=vitepressbook
-CONTAINER_PORT=7001
-HOST_PORT=7001
\ No newline at end of file
+CONTAINER_NAME=wandoubabadocs
+CONTAINER_PORT=80
+HOST_PORT=7007
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index b5ccb18..2016399 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
docs/.vitepress/dist
+docs/.vitepress/cache
node_modules
!.gitignore
\ No newline at end of file
diff --git a/README.md b/README.md
index 53b7643..5f36fd6 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,6 @@
-# 可以用docker一键启动的 VitePress 文档工程
+# wandoubaba的技术文档
-本项目提供了一种简单的方式来容器化 VitePress 文档网站。通过使用 Docker 和一些辅助脚本,您可以方便地构建、管理和部署您的文档项目。
-
-## 介绍
-
-本工程可以自动将VitePress生成的静态站点打包到docker镜像内,包括自定义的nginx配置文件,当镜像构建成功后可以直接分发到目标主机,不需要携带任何额外的主机文件。
+wandoubaba是一位很老的PHP程序员,他不是大牛却很喜欢研究程序,随着时间一点一点的积累了一些些技术资料,包括PHP、Docker、Worker(Webman)、RabbitMQ、FreeSWITCH、GoLang、Kubernete(k8s)等等。
## 系统依赖
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index 3bfeca1..3161edd 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -2,27 +2,69 @@ import { defineConfig } from 'vitepress'
// https://vitepress.dev/reference/site-config
export default defineConfig({
- title: "VitePress Book",
- description: "A VitePress Site",
+ title: "wandoubaba的技术收藏",
+ description: "wandoubaba是一位很老的PHP程序员,他不是大牛却很喜欢研究程序,随着时间一点一点的积累了一些些技术资料,包括PHP、Docker、Worker(Webman)、RabbitMQ、FreeSWITCH、GoLang、Kubernete(k8s)等等。",
+ srcDir: 'src',
+ ignoreDeadLinks: true,
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
+ logo: '/wandoubaba.svg',
+ footer: {
+ message: 'Released under the MIT License.',
+ copyright: 'Copyright © 2019-present wandoubaba'
+ },
nav: [
- { text: 'Home', link: '/' },
- { text: 'Examples', link: '/markdown-examples' }
+ { text: '首页', link: '/' },
+ { text: 'PHP', link: '/php/' },
+ { text: 'Docker', link: '/docker/' },
+ { text: 'Go', link: '/go/' },
+ { text: '前端', link: '/frontend/' },
+ { text: 'FreeSWITCH', link: '/freeswitch/' }
],
-
sidebar: [
+ { text: '前言', link: '/start' },
{
- text: 'Examples',
+ text: 'Docker',
items: [
- { text: 'Markdown Examples', link: '/markdown-examples' },
- { text: 'Runtime API Examples', link: '/api-examples' }
+ { text: '不常用命令备忘', link: '/docker/command' },
+ { text: '安装Docker(debian包管理器)', link: '/docker/install-apt' },
+ { text: '安装Docker(二进制文件)', link: '/docker/install-binary' },
+ { text: '配置国内镜像源', link: '/docker/mirrors' },
+ { text: '制作Vue开发环境镜像', link: '/docker/vue' },
+ { text: '制作集成ik中文分词器的elasticsearch镜像', link: '/docker/elasticsearch-ik' },
+ { text: '制作支持stomp和延时队列的rabbitmq镜像', link: '/docker/rabbitmq-stomp' },
+ { text: '部署单节点MinIO服务', link: '/docker/minio' },
+ { text: '部署Posrgres服务', link: '/docker/postgres' },
+ { text: '部署一个私有Gitea服务', link: '/docker/gitea' }
+ ]
+ },
+ {
+ text: 'PHP',
+ items: [
+ // 'docker-phpfpm74',
+ // 'docker81',
+ // 'nginx',
+ // 'openresty',
+ // 'php82'
+ { text: 'monolog保存日志到mongodb', link: '/php/monolog-mongo' },
+ { text: '制作7.4的FPM环境镜像', link: '/php/docker-phpfpm74' },
+ { text: '基于PHP8.x制作workman环境镜像', link: '/php/docker-php8' },
+ { text: '源码编译安装PHP8.2环境', link: '/php/php82' }
+ ]
+ },
+ {
+ text: '运维',
+ items: [
+ { text: '用acme.sh自动部署和续签SSL证书', link: '/ops/acme' },
+ { text: '源码编译安装Nginx', link: '/ops/nginx' },
+ { text: '源码编译安装OpenResty', link: '/ops/openresty' },
+ { text: 'Linux以二进制方式安装node环境', link: '/ops/node' }
]
}
],
socialLinks: [
- { icon: 'github', link: 'https://github.com/vuejs/vitepress' }
+ { icon: 'github', link: 'https://git.wandoubaba.com/wandoubaba/docs.git' }
]
}
})
diff --git a/docs/api-examples.md b/docs/api-examples.md
deleted file mode 100644
index 6bd8bb5..0000000
--- a/docs/api-examples.md
+++ /dev/null
@@ -1,49 +0,0 @@
----
-outline: deep
----
-
-# Runtime API Examples
-
-This page demonstrates usage of some of the runtime APIs provided by VitePress.
-
-The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files:
-
-```md
-
-
-## Results
-
-### Theme Data
-
{{ theme }}
-
-### Page Data
-{{ page }}
-
-### Page Frontmatter
-{{ frontmatter }}
-```
-
-
-
-## Results
-
-### Theme Data
-{{ theme }}
-
-### Page Data
-{{ page }}
-
-### Page Frontmatter
-{{ frontmatter }}
-
-## More
-
-Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).
diff --git a/docs/index.md b/docs/index.md
deleted file mode 100644
index d5c6851..0000000
--- a/docs/index.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-# https://vitepress.dev/reference/default-theme-home-page
-layout: home
-
-hero:
- name: "VitePress Book"
- text: "A VitePress Site"
- tagline: My great project tagline
- actions:
- - theme: brand
- text: Markdown Examples
- link: /markdown-examples
- - theme: alt
- text: API Examples
- link: /api-examples
-
-features:
- - title: Feature A
- details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
- - title: Feature B
- details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
- - title: Feature C
- details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
----
-
diff --git a/docs/markdown-examples.md b/docs/markdown-examples.md
deleted file mode 100644
index f9258a5..0000000
--- a/docs/markdown-examples.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Markdown Extension Examples
-
-This page demonstrates some of the built-in markdown extensions provided by VitePress.
-
-## Syntax Highlighting
-
-VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting:
-
-**Input**
-
-````md
-```js{4}
-export default {
- data () {
- return {
- msg: 'Highlighted!'
- }
- }
-}
-```
-````
-
-**Output**
-
-```js{4}
-export default {
- data () {
- return {
- msg: 'Highlighted!'
- }
- }
-}
-```
-
-## Custom Containers
-
-**Input**
-
-```md
-::: info
-This is an info box.
-:::
-
-::: tip
-This is a tip.
-:::
-
-::: warning
-This is a warning.
-:::
-
-::: danger
-This is a dangerous warning.
-:::
-
-::: details
-This is a details block.
-:::
-```
-
-**Output**
-
-::: info
-This is an info box.
-:::
-
-::: tip
-This is a tip.
-:::
-
-::: warning
-This is a warning.
-:::
-
-::: danger
-This is a dangerous warning.
-:::
-
-::: details
-This is a details block.
-:::
-
-## More
-
-Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown).
diff --git a/docs/src/docker/command.md b/docs/src/docker/command.md
new file mode 100644
index 0000000..f5f0cb7
--- /dev/null
+++ b/docs/src/docker/command.md
@@ -0,0 +1,40 @@
+# docker不常用命令备忘
+
+> wandoubaba / 2024-10-29
+
+## 基础操作
+
+### 查看磁盘占用
+
+```sh
+# 查看镜像、容器、卷的总磁盘占用情况
+docker system df
+# 查看每个image、container的详细空间占用情况
+docker system df -v
+```
+
+## 清理操作
+
+### 删除关闭的容器和未使用的镜像
+
+```sh
+docker system prune -a
+```
+
+## 镜像操作
+
+### 把容器导出为镜像
+
+```sh
+docker commit <容器ID或容器名> <镜像名>:<镜像tag>
+```
+
+### 镜像导入导出(save & load)
+
+```sh
+docker save -o <要保存的文件名>.tar <本地镜像名>:<本地镜像tag>
+```
+
+```sh
+docker load < <镜像文件名>
+```
diff --git a/docs/src/docker/elasticsearch-ik.md b/docs/src/docker/elasticsearch-ik.md
new file mode 100644
index 0000000..9a66819
--- /dev/null
+++ b/docs/src/docker/elasticsearch-ik.md
@@ -0,0 +1,55 @@
+# 制作集成ik中文分词器的elasticsearch镜像
+
+> wandoubaba / 2024-10-29
+
+## 说明
+
+按照本文过程制作后的镜像不是跨平台的,在arm64平台制作的镜像只能用于arm64平台,在amd64平台制作的镜像只能用于amd64平台。
+
+## 制作过程
+
+本文要制作一个整合了`analysis-ik`分词器的`elasticsearch`服务镜像。
+
+注意`analysis-ik`和`elasticsearch`的版本要保持一致,本文选择版本`7.17.18`。
+
+拉取基础镜像:
+
+```sh
+docker pull docker.elastic.co/elasticsearch/elasticsearch:7.17.18
+```
+
+启动容器:
+
+```sh
+docker run -p 127.0.0.1:9200:9200 -p 127.0.0.1:9300:9300 -e "discovery.type=single-node" --name=es docker.elastic.co/elasticsearch/elasticsearch:7.17.18
+```
+
+进入容器安装`analysis-ik`插件:
+
+```sh
+docker exec -it es bash
+```
+
+```sh
+./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.18/elasticsearch-analysis-ik-7.17.18.zip
+```
+
+在容器内执行上面的命令后会自动下载并安装`elasticsearch-analysis-ik`插件(如果由于网络原因导致下载制作,请重试几次),下载后的问答请回答`y`。
+
+安装成功后退出容器:
+
+```sh
+exit
+```
+
+导出镜像:
+
+```sh
+docker commit es <镜像名称>:<镜像tag>
+```
+
+## 一键启动
+
+这个仓库已经利用本文制作的镜像实现了一个一键启动的服务。
+
+
\ No newline at end of file
diff --git a/docs/src/docker/gitea.md b/docs/src/docker/gitea.md
new file mode 100644
index 0000000..b0a21e7
--- /dev/null
+++ b/docs/src/docker/gitea.md
@@ -0,0 +1,292 @@
+# Docker部署Gitea服务器完整过程
+
+> wandoubaba / 2024-10-29
+
+## 介绍
+
+下面引用 [gitea官方文档](https://docs.gitea.cn/) 中的一段描述:
+
+```
+Gitea 是一个轻量级的 DevOps 平台软件。从开发计划到产品成型的整个软件生命周期,他都能够高效而轻松的帮助团队和开发者。包括 Git 托管、代码审查、团队协作、软件包注册和 CI/CD。它与 GitHub、Bitbucket 和 GitLab 等比较类似。 Gitea 最初是从 Gogs 分支而来,几乎所有代码都已更改。
+```
+
+## 本文目标
+
+- 仓库、数据库等用户产生数据保存在数据盘中
+- 使用postgresql数据库
+- 数据库和gitea服务以docker方式启动
+- 主机和容器使用22端口实现SSH直通
+- 使用域名访问,通过nginx反向代理实现通过80端口访问web UI
+
+> 为了方便,文档中的操作都是在root用户下执行,建议在生产环境中使用普通用户执行操作,在命令前加`sudo`。
+
+## 准备域名
+
+提前准备一个公网域名,指向到下面即将要操作的服务器IP上,后面的操作完成了,域名解析也差不多该生效了。
+
+> 假设我们用的是`gitea.wukezhenzhu.com`,后面配置是用以它为例。
+
+## 准备服务器
+
+本文中我使用了Debian 11,既然是用docker方式部署的,所以几乎不受操作系统限制。
+
+> 接下来的操作是本人一步一步边操作加记录的。
+
+### 挂载数据盘
+
+通过`df -h`、`lsblk`、`fdisk -l`等命令确认当前磁盘和分区状态,下面是结果示例:
+
+```sh
+root@debian:~# df -h
+Filesystem Size Used Avail Use% Mounted on
+udev 2.0G 0 2.0G 0% /dev
+tmpfs 394M 560K 393M 1% /run
+/dev/sda1 491G 1.4G 464G 1% /
+tmpfs 2.0G 0 2.0G 0% /dev/shm
+tmpfs 5.0M 0 5.0M 0% /run/lock
+tmpfs 394M 0 394M 0% /run/user/0
+root@debian:~# lsblk
+NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
+sda 8:0 0 500G 0 disk
+├─sda1 8:1 0 499G 0 part /
+├─sda2 8:2 0 1K 0 part
+└─sda5 8:5 0 975M 0 part [SWAP]
+sdb 8:16 0 4T 0 disk
+sr0 11:0 1 1024M 0 rom
+root@debian:~# fdisk -l
+Disk /dev/sdb: 4 TiB, 4398046511104 bytes, 8589934592 sectors
+Disk model: Virtual disk
+Units: sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+
+
+Disk /dev/sda: 500 GiB, 536870912000 bytes, 1048576000 sectors
+Disk model: Virtual disk
+Units: sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+Disklabel type: dos
+Disk identifier: 0xac8bf5c9
+
+Device Boot Start End Sectors Size Id Type
+/dev/sda1 * 2048 1046575103 1046573056 499G 83 Linux
+/dev/sda2 1046577150 1048573951 1996802 975M 5 Extended
+/dev/sda5 1046577152 1048573951 1996800 975M 82 Linux swa
+```
+
+从上面的结果可以看到,系统中有一个名为`/dev/sdb`的4TB硬盘是空闲的,下面我们要把它整个挂载到`/data`目录下:
+
+```sh
+root@debian:~# mkfs.ext4 /dev/sdb
+mke2fs 1.46.2 (28-Feb-2021)
+Creating filesystem with 1073741824 4k blocks and 134217728 inodes
+Filesystem UUID: f081b706-f637-4b84-b70b-5521b7ad5b6b
+Superblock backups stored on blocks:
+ 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
+ 4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
+ 102400000, 214990848, 512000000, 550731776, 644972544
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (262144 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+root@debian:~# mkdir /data
+root@debian:~# mount -t ext4 /dev/sdb /data
+root@debian:~# df -h
+Filesystem Size Used Avail Use% Mounted on
+udev 2.0G 0 2.0G 0% /dev
+tmpfs 394M 560K 393M 1% /run
+/dev/sda1 491G 1.4G 464G 1% /
+tmpfs 2.0G 0 2.0G 0% /dev/shm
+tmpfs 5.0M 0 5.0M 0% /run/lock
+tmpfs 394M 0 394M 0% /run/user/0
+/dev/sdb 4.0T 28K 3.8T 1% /data
+```
+
+经过上面的操作,已经把磁盘`/dev/sdb`格式化为ext4文件系统,并成功挂载下`/data`目录下,但是如果现在重启系统后,数据盘还不能自动完成挂载,需要执行下面的操作:
+
+```sh
+root@debian:~# ll /dev/disk/by-uuid/
+total 0
+lrwxrwxrwx 1 root root 10 Apr 21 14:22 0bc1a76e-3457-4e2c-b708-a201e510f343 -> ../../sda1
+lrwxrwxrwx 1 root root 9 Apr 21 14:30 f081b706-f637-4b84-b70b-5521b7ad5b6b -> ../../sdb
+lrwxrwxrwx 1 root root 10 Apr 21 14:22 ff162b2a-5e9e-4661-854a-64ad11f22fa5 -> ../../sda5
+
+root@debian:~# echo "UUID=f081b706-f637-4b84-b70b-5521b7ad5b6b /data ext4 defaults 0 0" >> /etc/fstab
+```
+
+> 上面写入`/etc/fstab`文件中的UUID是在`/dev/disk/by-uuid/`中查到的`sdb`对应的UUID。
+
+可以试着`reboot`一下,重启后数据盘会自动完成挂载。
+
+> 操作系统的准备工作已经完成,但是我们建议中国大陆用户要为系统配置一组高速的软件源,配置文件位置`/etc/apt/sources.list`,本文不对展开讲解。
+
+### 准备docker环境
+
+> 按照docker官方文档安装[Docker Engine](https://docs.docker.com/engine/install/debian/)和[Docker Compose](https://docs.docker.com/compose/install/other/)。
+
+```sh
+# 卸载原有旧版本的docker(新系统可以跳过)
+for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
+# 安装ca支持
+sudo apt-get update && sudo apt-get install ca-certificates curl gnupg
+# 配置docker官方GPG密钥
+sudo install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+sudo chmod a+r /etc/apt/keyrings/docker.gpg
+# 配置docker官方软件源
+echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
+# 安装docker engine
+sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
+# 单独安装docker-compose(不执行后面这步,使用docker compose [command]也是可以的)
+curl -SL https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
+ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
+chmod +x /usr/local/bin/docker-compose
+# 查看docker版本
+docker version
+# 查看docker-compose版本
+docker-compose version
+```
+
+对于国内服务器,给docker hub配置几个加速源是必要的操作,[阿里云容器镜像服务-镜像加速器](https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors)。
+
+除了阿里云,也可以试试下面的加速源:
+
+- https://registry.docker-cn.com
+- https://hub-mirror.c.163.com
+
+### 部署gitea和postgresql服务
+
+#### 配置nginx实现反向代理
+
+我们希望实现的是通过网址http://gitea.wukezhenzhu.com直接访问gitea的web UI,而gitea服务默认使用的http端口是3000,为了不过多更改服务配置,我们只要用nginx做一层指向127.0.0.1:3000端口的反向代理即可,具体如何操作本文不展开。
+
+#### 创建git专用的系统账号和分组
+
+```sh
+# 创建git分组和git用户
+adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git
+
+# 记录下返回结果中的UID和GID,如:
+Adding system user `git' (UID 112) ...
+Adding new group `git' (GID 117) ...
+Adding new user `git' (UID 112) with group `git' ...
+
+# 为git用户生成ssh-key
+sudo -u git ssh-keygen -t rsa -b 4096 -C "Gitea Host Key"
+```
+
+#### 为主机和容器建立SSH直通
+
+创建名为`/usr/local/bin/gitea`的可执行文件,文件内容:
+
+```shell
+ssh -p 2222 -o StrictHostKeyChecking=no git@127.0.0.1 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
+```
+
+为`/usr/local/bin/gitea`文件添加可执行权限:
+
+```sh
+chmod +x /usr/local/bin/gitea
+```
+
+把git用户的ssh公钥添加到`/home/git/.ssh/authorized_keys`中(因为主机的`/home/git/.ssh/`会映射到容器中)
+
+```sh
+echo "$(cat /home/git/.ssh/id_rsa.pub)" >> /home/git/.ssh/authorized_keys
+```
+
+#### 准备docker-compose.yml文件
+
+创建`/data/docker-compose.yml`文件,内容如下(随着时间推移,可以试着改变镜像的版本),注意修改`USER_UID`和`USER_GID`为实际值:
+
+```yml
+version: "3"
+
+networks:
+ gitea:
+ external: false
+
+services:
+ gitea:
+ image: gitea/gitea:1.19
+ container_name: gitea
+ environment:
+ - USER_UID=112
+ - USER_GID=117
+ - GITEA__database__DB_TYPE=postgres
+ - GITEA__database__HOST=gitea_db:5432
+ - GITEA__database__NAME=gitea
+ - GITEA__database__USER=gitea
+ - GITEA__database__PASSWD=gitea
+ restart: always
+ networks:
+ - gitea
+ volumes:
+ - ./gitea:/data
+ - /etc/timezone:/etc/timezone:ro
+ - /etc/localtime:/etc/localtime:ro
+ - /home/git/.ssh/:/data/git/.ssh
+ ports:
+ - "3000:3000"
+ - "127.0.0.1:2222:22"
+ depends_on:
+ - gitea_db
+ gitea_db:
+ image: postgres:14
+ container_name: gitea_db
+ restart: always
+ environment:
+ - POSTGRES_USER=gitea
+ - POSTGRES_PASSWORD=gitea
+ - POSTGRES_DB=gitea
+ networks:
+ - gitea
+ volumes:
+ - ./postgres:/var/lib/postgresql/data
+```
+
+在/data目录下执行:
+
+```sh
+docker compose up
+```
+
+如果在编排期间没有提示错误的话,说明我们在服务器端的部署工作基本完成了,下面进入web安装与配置阶段。
+
+#### 通过Web UI完成服务安装与配置
+
+假设最开始做的域名解析已经生效了,接下来打开浏览器访问gitea.wukezhenzhu.com(如果打不开页面,检查检查域名解析、服务器防火墙、nginx代理):
+
+```
+http://gitea.wukezhenzhu.com
+```
+
+- 数据库设置:都使用默认值就行(因为我们没有把pg的5432端口映射给主机,所以基本也不需要给数据库设置强口令)。
+- 站点名称:会显示在Web首页和浏览器标题栏
+- 仓库根目录:默认
+- LFS根目录:默认
+- 以用户名运行:默认(git)
+- 服务器域名:就是刚才解析的域名,文本中是gitea.wukezhenzhu.com
+- SSH服务端口:22
+- HTTP服务端口:3000
+- 基础URL:如果这里是带:3000端口号的url,我们就把端口号去掉,就是http://gitea.wukezhenzhu.com/。
+- 日志路径:默认
+- 启用更新检查:不勾选,因为我们用的是docker,即使在线更新了,容器重启后也会把程序重置。
+- 电子邮箱设置:建议配置并开启邮件确认注册和邮件通知提醒
+- 第三方服务设置:根据情况
+- 管理账号设置:根据情况
+
+完成以上配置后,直接点“立即安装”,然后等待一小会,页面会自动以管理员登录(如果创建了管理员),或者进入到gitea的登录页。
+
+#### 以daemon方式重新启动服务
+
+在服务器上按ctrl+c停止docker服务,再重启执行一遍docker-compose命令,这次后面加上-d。
+
+```sh
+docker compose up -d
+```
+
+好了,大功告成!
diff --git a/docs/src/docker/index.md b/docs/src/docker/index.md
new file mode 100644
index 0000000..a81f52b
--- /dev/null
+++ b/docs/src/docker/index.md
@@ -0,0 +1,3 @@
+# Docker
+
+记录了一些与docker相关的内容。
diff --git a/docs/src/docker/install-apt.md b/docs/src/docker/install-apt.md
new file mode 100644
index 0000000..b68d083
--- /dev/null
+++ b/docs/src/docker/install-apt.md
@@ -0,0 +1,41 @@
+# Debian11中安装Docker
+
+> wandoubaba / 2024-10-29
+
+本文参考docker官方文档:
+
+-
+
+## 联网环境安装
+
+依次执行下面的命令就可以。
+
+> 如果root账号下提示没有`sudo`命令的话,使用`apt-get install sudo -y`安装一下就可以了。
+
+```sh
+# 卸载旧版本(可省略)
+for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
+# 安装新版本
+sudo apt-get update
+sudo apt-get install -y ca-certificates curl gnupg
+sudo install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+sudo chmod a+r /etc/apt/keyrings/docker.gpg
+echo \
+ "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
+ "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
+ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
+sudo apt-get update
+sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
+```
+
+> 可以把上面的过程制作一个`docker.sh`脚本里,直接执行脚本就能完成安装了。
+
+## 验证安装
+
+```sh
+# 查看docker版本
+docker version
+# 查看docker compose版本
+docker compose version
+```
diff --git a/docs/src/docker/install-binary.md b/docs/src/docker/install-binary.md
new file mode 100644
index 0000000..5981a07
--- /dev/null
+++ b/docs/src/docker/install-binary.md
@@ -0,0 +1,319 @@
+# 用二进制文件安装Docker
+
+> wandoubaba / 2024-11-04
+
+## 说明
+
+本文在Debian12系统上直接通过二进制包安装docker服务,适用于离线场景。
+
+## 系统依赖
+
+- 64位环境
+- Linux kernel版本3.10以上
+- iptables版本1.4以上
+- git版本1.7以上
+- ps
+- xz-utils版本4.9以上
+- 正确的cgroupfs层次结构
+
+## 准备二进制文件
+
+先在可以连接互联网的环境下载安装包(截至文本发布时,docker的最新版本是27.3.1)
+
+```sh
+# docker、containerd等
+curl -L -O https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz
+# docker compose
+curl -L -O https://github.com/docker/compose/releases/download/v2.30.1/docker-compose-linux-x86_64
+# docker buildx
+curl -L -O https://github.com/docker/buildx/releases/download/v0.18.0/buildx-v0.18.0.linux-amd64
+```
+
+然后以各种各样的方式把二进制安装包复制到目标环境中。
+
+## 安装过程
+
+### 复制docker文件
+
+```sh
+tar zxvf docker-27.3.1.tgz
+sudo cp docker/* /usr/bin/
+```
+
+### 创建用户组
+
+```sh
+sudo groupadd docker
+sudo usermod -aG docker $USER
+newgrp docker
+```
+
+### 注册系统服务
+
+#### containerd.service
+
+```sh
+vim /usr/lib/systemd/system/containerd.service
+```
+
+内容如下:
+
+```sh
+# Copyright The containerd Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[Unit]
+Description=containerd container runtime
+Documentation=https://containerd.io
+After=network.target local-fs.target
+
+[Service]
+ExecStartPre=-/sbin/modprobe overlay
+ExecStart=/usr/bin/containerd
+
+Type=notify
+Delegate=yes
+KillMode=process
+Restart=always
+RestartSec=5
+# Having non-zero Limit*s causes performance problems due to accounting overhead
+# in the kernel. We recommend using cgroups to do container-local accounting.
+LimitNPROC=infinity
+LimitCORE=infinity
+LimitNOFILE=infinity
+# Comment TasksMax if your systemd version does not supports it.
+# Only systemd 226 and above support this version.
+TasksMax=infinity
+OOMScoreAdjust=-999
+
+[Install]
+WantedBy=multi-user.target
+```
+
+#### docker.socket
+
+```sh
+vim /usr/lib/systemd/system/docker.socket
+```
+
+内容
+
+```sh
+[Unit]
+Description=Docker Socket for the API
+
+[Socket]
+# If /var/run is not implemented as a symlink to /run, you may need to
+# specify ListenStream=/var/run/docker.sock instead.
+ListenStream=/run/docker.sock
+SocketMode=0660
+SocketUser=root
+SocketGroup=docker
+
+[Install]
+WantedBy=sockets.target
+```
+
+#### docker.service
+
+```sh
+vim /usr/lib/systemd/system/docker.service
+```
+
+内容
+
+```sh
+[Unit]
+Description=Docker Application Container Engine
+Documentation=https://docs.docker.com
+After=network-online.target docker.socket firewalld.service containerd.service time-set.target
+Wants=network-online.target containerd.service
+Requires=docker.socket
+
+[Service]
+Type=notify
+# the default is not to use systemd for cgroups because the delegate issues still
+# exists and systemd currently does not support the cgroup feature set required
+# for containers run by docker
+ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
+ExecReload=/bin/kill -s HUP $MAINPID
+TimeoutStartSec=0
+RestartSec=2
+Restart=always
+
+# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
+# Both the old, and new location are accepted by systemd 229 and up, so using the old location
+# to make them work for either version of systemd.
+StartLimitBurst=3
+
+# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
+# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
+# this option work for either version of systemd.
+StartLimitInterval=60s
+
+# Having non-zero Limit*s causes performance problems due to accounting overhead
+# in the kernel. We recommend using cgroups to do container-local accounting.
+LimitNOFILE=infinity
+LimitNPROC=infinity
+LimitCORE=infinity
+
+# Comment TasksMax if your systemd version does not support it.
+# Only systemd 226 and above support this option.
+TasksMax=infinity
+
+# set delegate yes so that systemd does not reset the cgroups of docker containers
+Delegate=yes
+
+# kill only the docker process, not all processes in the cgroup
+KillMode=process
+OOMScoreAdjust=-500
+
+[Install]
+WantedBy=multi-user.target
+```
+
+#### 启动服务并设置开机自启
+
+```sh
+systemctl enable --now containerd
+systemctl enable --now docker
+```
+
+### 安装docker compose
+
+截至本文发布时,docker compose的最新版本是2.30.1,以下命令适用于amd64平台,其他平台请到去找对应的二进制包。
+
+```sh
+cp docker-compose-linux-x86_64 /usr/local/lib/docker/cli-plugins/docker-compose
+chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
+```
+
+### 安装docker buildx
+
+截至本文发布时,docker buildx的最新版本是0.18.0,以下命令适用于amd64平台,其他平台请到对找对应的二进制包。
+
+```sh
+cp buildx-v0.18.0.linux-amd64 /usr/local/lib/docker/cli-plugins/docker-buildx
+chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
+docker buildx install
+```
+
+### 配置网络
+
+```sh
+modprobe br_netfilter
+sudo bash -c 'echo -e "net.bridge.bridge-nf-call-iptables = 1\nnet.bridge.bridge-nf-call-ip6tables = 1" > /etc/sysctl.d/bridge.conf && modprobe br_netfilter'
+sudo sysctl -p /etc/sysctl.d/bridge.conf
+systemctl restart docker
+```
+
+### 配置镜像仓库地址
+
+> 纯离线环境又没有私有仓库的话,这一步做不做没什么区别。
+
+```sh
+mkdir /etc/docker
+vim /etc/docker/daemon.json
+```
+
+文件内容:
+
+```json
+{
+ "registry-mirrors": [
+ "https://registry.docker-cn.com",
+ "https://docker.mirrors.ustc.edu.cn",
+ "https://dockerhub.azk8s.cn",
+ "http://hub-mirror.c.163.com"
+ ]
+}
+```
+
+生效
+
+```sh
+systemctl daemon-reload
+systemctl restart docker
+```
+
+## 结果确认
+
+执行`docker info`后应该可以看到下面的结果:
+
+```sh
+Client:
+ Version: 27.3.1
+ Context: default
+ Debug Mode: false
+ Plugins:
+ buildx: Docker Buildx (Docker Inc.)
+ Version: v0.18.0
+ Path: /usr/local/lib/docker/cli-plugins/docker-buildx
+ compose: Docker Compose (Docker Inc.)
+ Version: v2.30.1
+ Path: /usr/local/lib/docker/cli-plugins/docker-compose
+
+Server:
+ Containers: 0
+ Running: 0
+ Paused: 0
+ Stopped: 0
+ Images: 0
+ Server Version: 27.3.1
+ Storage Driver: overlay2
+ Backing Filesystem: extfs
+ Supports d_type: true
+ Using metacopy: false
+ Native Overlay Diff: true
+ userxattr: false
+ Logging Driver: json-file
+ Cgroup Driver: systemd
+ Cgroup Version: 2
+ Plugins:
+ Volume: local
+ Network: bridge host ipvlan macvlan null overlay
+ Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
+ Swarm: inactive
+ Runtimes: io.containerd.runc.v2 runc
+ Default Runtime: runc
+ Init Binary: docker-init
+ containerd version: 7f7fdf5fed64eb6a7caf99b3e12efcf9d60e311c
+ runc version: v1.1.14-0-g2c9f560
+ init version: de40ad0
+ Security Options:
+ apparmor
+ seccomp
+ Profile: builtin
+ cgroupns
+ Kernel Version: 6.1.0-23-amd64
+ Operating System: Debian GNU/Linux 12 (bookworm)
+ OSType: linux
+ Architecture: x86_64
+ CPUs: 4
+ Total Memory: 3.698GiB
+ Name: ten01
+ ID: f3c00e60-7eee-4b53-97a6-b1937701c3b1
+ Docker Root Dir: /var/lib/docker
+ Debug Mode: false
+ Experimental: false
+ Insecure Registries:
+ 127.0.0.0/8
+ Registry Mirrors:
+ https://registry.docker-cn.com/
+ https://docker.mirrors.ustc.edu.cn/
+ https://dockerhub.azk8s.cn/
+ http://hub-mirror.c.163.com/
+ Live Restore Enabled: false
+ Product License: Community Engine
+```
\ No newline at end of file
diff --git a/docs/src/docker/minio.md b/docs/src/docker/minio.md
new file mode 100644
index 0000000..7131dca
--- /dev/null
+++ b/docs/src/docker/minio.md
@@ -0,0 +1,62 @@
+# Docker部署MinIO服务
+
+> wandoubaba / 2024-10-29
+
+## 介绍
+
+下面是[MinIO官网](https://www.minio.org.cn/)的一段介绍:
+
+```
+MinIO 是一种高性能、S3 兼容的对象存储。
+它专为大规模 AI/ML、数据湖和数据库工作负载而构建,并且它是由软件定义的存储。
+不需要购买任何专有硬件,就可以在云上和普通硬件上拥有分布式对象存储。
+MinIO拥有开源 GNU AGPL v3 和商业企业许可证的双重许可。
+```
+
+简单来说,MinIO 是一个被广泛用使用的开源对象存储服务组件,可以用它轻松搭建私有的对象存储服务。
+
+## 操作过程
+
+本文只是简单启动一个单节点单硬盘服务,更复杂的场景可以参考[MinIO对象存储Container官方文档](https://www.minio.org.cn/docs/minio/container/index.html)。
+
+### 创建存储目录
+
+比如创建`/app/minio/`目录,准备用其中的`/app/minio/data`保存所有存储桶(bucket)和其中的对象。
+
+```sh
+mkdir /app/minio/data -p
+```
+
+### 创建docker-compose.yml文件
+
+创建文件`/app/minio/docker-compose.yml`,内容如下(注意自己改管理员账号密码):
+
+```yml
+services:
+ minio:
+ image: quay.io/minio/minio:latest
+ hostname: "minio"
+ restart: always
+ environment:
+ MINIO_ROOT_USER: ROOTNAME
+ MINIO_ROOT_PASSWORD: CHANGEME123
+ MINIO_VOLUMES: /data
+ ports:
+ - 9001:9001
+ - 9000:9000
+ volumes:
+ - ./data:/data
+ command: server --console-address ':9001'
+```
+
+### 启动容器
+
+在`/app/minio`目录下执行下面的命令:
+
+```sh
+docker compose up -d
+```
+
+### 验证安装
+
+服务器防火墙要放行 9000 和 9001端口,假设我的服务器的IP是 192.168.0.8 ,那么在web浏览器上打开 `http://192.168.0.8:9001` ,应该可以看到登录页,填入`MINIO_ROOT_USER`和`MINIO_ROOT_PASSWORD`对应的值,应该可以登录minio的web控制台。
diff --git a/docs/src/docker/mirrors.md b/docs/src/docker/mirrors.md
new file mode 100644
index 0000000..fb320cf
--- /dev/null
+++ b/docs/src/docker/mirrors.md
@@ -0,0 +1,27 @@
+# 配置Docker Hub国内镜像加速
+
+本文以以下操作系统适用:Ubuntu 16.04+, Debian 8+, CentOS 7+
+
+创建或者修改`/etc/docker/daemon.json`文件:
+
+```json
+{
+ "registry-mirrors": [
+ "https://registry.docker-cn.com",
+ "https://docker.mirrors.ustc.edu.cn",
+ "https://dockerhub.azk8s.cn",
+ "http://hub-mirror.c.163.com"
+ ]
+}
+```
+
+> 也可以去阿里云镜像加速服务中获取账号专用的阿里云加速链接,添加到`registry-mirrors`数组中。
+
+重启服务:
+
+```sh
+sudo systemctl daemon-reload
+sudo systemctl restart docker
+```
+
+用命令`docker info`可以查看配置是否生效。
diff --git a/docs/src/docker/postgres.md b/docs/src/docker/postgres.md
new file mode 100644
index 0000000..4022930
--- /dev/null
+++ b/docs/src/docker/postgres.md
@@ -0,0 +1,86 @@
+# Docker部署Postgres数据库服务
+
+> wandoubaba / 2024-10-29
+
+## 创建存储目录
+
+比如创建`/app/postgres/`目录。
+
+```sh
+mkdir /app/postgres -p
+```
+
+## 创建docker-compose.yml文件
+
+创建文件`/app/postgres/docker-compose.yml`,内容如下(注意自己改postgres用户的密码):
+
+以host网络启动:
+
+```yml
+services:
+ db:
+ image: postgres:14
+ container_name: postgres
+ restart: always
+ environment:
+ POSTGRES_PASSWORD: PASSWORD
+ PGDATA: /var/lib/postgresql/data/pgdata
+ volumes:
+ - ./data:/var/lib/postgresql/data
+ network_mode:
+ host
+```
+
+以bridge网络启动(推荐):
+
+```yml
+services:
+ db:
+ image: postgres:14
+ container_name: postgres
+ restart: always
+ environment:
+ POSTGRES_PASSWORD: PASSWORD
+ PGDATA: /var/lib/postgresql/data/pgdata
+ volumes:
+ - ./data:/var/lib/postgresql/data
+ ports:
+ - 5432:5432
+```
+
+## 启动容器
+
+在`/app/postgres`目录下执行下面的命令:
+
+```sh
+docker compose up -d
+```
+
+## 查看当前postgres版本
+
+### 方法一 - 进入容器使用命令
+
+```sh
+docker exec -it postgres /bin/bash
+# 进入容器后执行下面命令
+psql --version
+# psql (PostgreSQL) 14.1 (Debian 14.1-1.pgdg110+1)
+postgres --version
+# postgres (PostgreSQL) 14.1 (Debian 14.1-1.pgdg110+1)
+pg_config | grep VERSION
+# VERSION = PostgreSQL 14.1 (Debian 14.1-1.pgdg110+1)
+```
+
+### 方法二 - 连接数据库使用查询命令
+
+```sql
+show server_version;
+```
+
+结果如下:
+
+```txt
+server_version |
+------------------------------+
+14.1 (Debian 14.1-1.pgdg110+1)|
+```
diff --git a/docs/src/docker/rabbitmq-stomp.md b/docs/src/docker/rabbitmq-stomp.md
new file mode 100644
index 0000000..2b5f37e
--- /dev/null
+++ b/docs/src/docker/rabbitmq-stomp.md
@@ -0,0 +1,104 @@
+# rabbitmq启用stomp和延时队列(rabbitmq_delayed_message_exchange插件)构建多平台镜像
+
+> wandoubaba / 2024-10-29
+
+## 下载对应版本的插件安装包
+
+本文使用的rabbitmq版本是3.13.4,用下面的命令可以下载对应的延时队列插件安装包
+
+```sh
+curl -L -O https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.13.0/rabbitmq_delayed_message_exchange-3.13.0.ez
+```
+
+> 如果要使用其他版本的rabbitmq,可以到 去找对应的安装包。
+
+## Dockerfile文件
+
+```dockerfile
+# 使用 RabbitMQ 3.13.4 管理镜像作为基础镜像
+FROM rabbitmq:3.13.4-management
+
+# 设置工作目录
+WORKDIR /
+
+# 将本地的插件文件复制到容器内
+COPY rabbitmq_delayed_message_exchange-3.13.0.ez .
+
+# 启用插件
+RUN rabbitmq-plugins enable rabbitmq_delayed_message_exchange rabbitmq_stomp rabbitmq_web_stomp rabbitmq_web_stomp_examples
+
+# 持久化数据目录
+VOLUME ["/var/lib/rabbitmq/mnesia"]
+
+# 将容器的启动命令更改为默认命令
+CMD ["rabbitmq-server"]
+```
+
+> `Dockerfile`文件应该与`rabbitmq_delayed_message_exchange-3.13.0.ez`文件在同一个目录下。
+
+## 构建多平台镜像
+
+### 确认`docker buildx`环境
+
+```sh
+docker info
+```
+
+执行以上命令可以看到类似下面的信息:
+
+```txt
+Client: Docker Engine - Community
+ Version: 27.0.3
+ Context: default
+ Debug Mode: false
+ Plugins:
+ buildx: Docker Buildx (Docker Inc.)
+ Version: v0.15.1
+ Path: /usr/libexec/docker/cli-plugins/docker-buildx
+ compose: Docker Compose (Docker Inc.)
+ Version: v2.28.1
+ Path: /usr/libexec/docker/cli-plugins/docker-compose
+...
+```
+
+一般情况下,如果是通过包管理器安装的docker engine或者docker desktop的话,默认就已经安装好了buildx和compose插件了。
+
+### 跨平台构建并发布
+
+接下来,我们的目标是用上面的Dockerfile构建多平台的`rabbitmq:3.13.4`镜像并直接推送到`quay.io`平台上:
+
+> 为什么是`quay.io`?因为有一段时间全国封锁docker-hub时,`quay.io`是可以推拉镜像的,仅此而已。
+
+```sh
+docker login quay.io
+docker buildx create --use
+docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64 --push -t quay.io/wandoubaba517/rabbitmq:3.13.4 .
+```
+
+执行上面的命令,执行过程中会自动从docker hub上拉取名为`moby/buildkit:buildx-stable-1`的镜像并启动容器开始自动构建和推送,整个过程在我的2核4G服务器上执行了好几个小时,所以建议使用`tmux`等工具,任务执行起来就可以关闭终端了。
+
+## 使用镜像
+
+```sh
+docker run -d \
+ -p 5672:5672 \
+ -p 15672:15672 \
+ -p 61613:61613 \
+ -v ./data:/var/lib/rabbitmq/mnesia \
+ -v ./conf/conf.d:/etc/rabbitmq/conf.d \
+ --hostname rabbitmq \
+ --name rabbitmq \
+ quay.io/wandoubaba517/rabbitmq:3.13.4
+```
+
+## 工程示例
+
+
+
+```sh
+git clone git@git.wandoubaba.com:wandoubaba/docker-rabbitmq.git
+cd docker-rabbitmq
+# 先在conf/conf.d/10-defaults.conf文件中设置首次启动创建的默认用户名和密码
+# 然后再执行启动脚本
+./start
+```
diff --git a/docs/src/docker/vue.md b/docs/src/docker/vue.md
new file mode 100644
index 0000000..156d25d
--- /dev/null
+++ b/docs/src/docker/vue.md
@@ -0,0 +1,126 @@
+# 制作vue开发环境镜像(node18.18.2+openresty1.21.4.2)
+
+> wandoubaba / 2024-10-29
+
+## 说明
+
+按照本文过程制作后的镜像不是跨平台的,在arm64平台制作的镜像只能用于arm64平台,在amd64平台制作的镜像只能用于amd64平台。
+
+## 系统环境
+
+- docker engine
+- docker compose
+
+## 制作过程
+
+### 拉取node18.18.2镜像
+
+```sh
+docker pull node:18-bullseye
+```
+
+### 准备openresty源码
+
+```sh
+curl -O https://openresty.org/download/openresty-1.21.4.2.tar.gz
+tar zxvf openresty-1.21.4.2.tar.gz
+```
+
+### 启动node容器
+
+```sh
+docker run -itd --name=node-resty node:18-bullseye
+```
+
+### 容器内环境
+
+如果宿主系统是deiban11就直接把sources.list复制到容器内,如果不是,就单独制作一个deiban11的sources.list文件复制到容器内
+
+```sh
+docker cp /etc/apt/sources.list node-resty:/etc/apt/
+docker cp openresty-1.21.4.2 node-resty:/
+docker exec -it node-resty bash
+```
+
+在容器内进行下面的操作
+
+```sh
+apt update
+cd openresty-1.21.4.2
+./configure -j2
+gmake
+gmake install
+ln -sf /usr/local/openresty/bin/openresty /usr/local/bin/nginx
+cd /
+mkdir /app/web -p
+exit
+```
+
+### 宿主机操作
+
+```sh
+# 创建一个开发目录
+mkdir web
+# 把nginx.conf文件复制到宿主
+docker cp node-resty:/usr/local/openresty/nginx/conf/nginx.conf ./
+# 把docker-entrypoint.sh复制到宿主
+docker cp node-resty:/usr/local/bin/docker-entrypoint.sh ./
+```
+
+修改docker-entrypoint.sh文件,在`exec "$@"`一句之前加上`nginx`一行。
+
+```sh
+docker cp ./docker-entrypoint.sh node-resty:/usr/local/bin/
+```
+
+### 生成镜像
+
+```sh
+docker commit node-resty node-resty:18.18.2
+```
+
+### 提交到docker hub
+
+```sh
+docker login --username=
+docker tag node-resty:18.18.2 /node-resty:18.18.2
+docker push /node-resty:18.18.2
+```
+
+### 使用方法
+
+假设在某一个vue项目目录下。
+
+```sh
+docker pull /node-resty:18.18.2
+# npm install
+docker run -it --rm --name=node-resty -w /app/web -v ./:/app/web /node-resty:18.18.2 npm install
+# npm run build
+docker run -it --name=node-resty -w /app/web -v ./:/app/web -v ./dist:/usr/local/openresty/nginx/html -p 80:80 /node-resty:18.18.2 npm run build
+```
+
+可以看到,上面的操作明显太麻烦了。我们可以试着写一个docker-compose.yml文件:
+
+```yml
+version: "3.1"
+
+services:
+ node-resty:
+ image: /node-resty:18.18.2
+ container_name: node-resty
+ ports:
+ - 80:80
+ restart: always
+ volumes:
+ - ./docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh
+ - ./:/app/web
+ - ./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf
+ - ./dist:/usr/local/openresty/nginx/html
+ working_dir: /app/web
+ stdin_open: true
+ command: ["npm", "run", "build"]
+```
+
+还可以通过编写shell脚本的方式解锁更多开发和发布姿势。
+
+参照可以把镜像用于实际开发和生产。
diff --git a/docs/src/freeswitch/CentOS7.9(2009)安装freeswitch1.10.md b/docs/src/freeswitch/CentOS7.9(2009)安装freeswitch1.10.md
new file mode 100644
index 0000000..b25df6e
--- /dev/null
+++ b/docs/src/freeswitch/CentOS7.9(2009)安装freeswitch1.10.md
@@ -0,0 +1,387 @@
+## CentOS7.9(2009)安装freeswitch1.10
+
+---
+
+> 2022年6月,这个文档已经失效,按照这个文档操作将不会成功,转至Debian11编译安装FreeSWITCH1.10,亲测成功。
+
+### 安装centos7.9(2009)操作系统
+
+略
+
+### 系统更新和安装依赖
+
+```bash
+yum update -y
+# 安装fs依赖
+yum install -y http://files.freeswitch.org/freeswitch-release-1-6.noarch.rpm epel-release
+# 安装ffmpeg需要
+rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
+rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-1.el7.nux.noarch.rpm
+
+yum install -y yum-utils git gcc gcc-c++ automake autoconf libtool libtiff-devel libjpeg-devel openssl-devel vim
+
+yum install -y alsa-lib-devel bison broadvoice-devel bzip2 curl-devel libdb4-devel e2fsprogs-devel erlang flite-devel g722_1-devel gdbm-devel gnutls-devel ilbc2-devel ldns-devel libcodec2-devel libcurl-devel libedit-devel libidn-devel libmemcached-devel libogg-devel libsilk-devel libsndfile-devel libtheora-devel libuuid-devel libvorbis-devel libxml2-devel lua-devel lzo-devel ncurses-devel net-snmp-devel opus-devel pcre-devel perl perl-ExtUtils-Embed pkgconfig portaudio-devel postgresql-devel python-devel python-devel soundtouch-devel speex-devel sqlite-devel unbound-devel unixODBC-devel which yasm zlib-devel libshout-devel libmpg123-devel lame-devel rpm-build libX11-devel libyuv-devel swig wget ffmpeg ffmpeg-devel
+
+# 单独下载spandsp源码
+cd /usr/local/src
+git clone https://github.com/freeswitch/spandsp.git
+cd spandsp
+./bootstrap.sh
+./configure
+make
+make install
+ldconfig
+
+# 单独下载sofia-sip(SIP协议栈)源码
+cd /usr/local/src
+git clone https://github.com/freeswitch/sofia-sip.git
+cd sofia-sip
+./bootstrap.sh
+./configure
+make
+make install
+ldconfig
+cd ..
+
+# 编译安装cmake 3.7.2
+cd /usr/local/src
+wget https://cmake.org/files/v3.7/cmake-3.7.2.tar.gz
+tar zxvf cmake-3.7.2.tar.gz
+cd cmake-3.7.2
+./bootstrap
+gmake
+gmake install
+
+# 安装libatomic
+yum install -y libatomic uuid-devel libuuid-devel
+
+# 单独下载libks源码(需要cmake 3.7.2以上版本)
+cd /usr/local/src
+git clone https://github.com/signalwire/libks.git
+cd libks
+cmake .
+make
+make install
+
+# 单独安装opus-dev(否则在freeswitch里make时可能会报You must install libopus-dev to build mod_opus)
+cd /usr/local/src
+wget https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz
+tar zxvf opus-1.3.1.tar.gz
+cd opus-1.3.1
+./configure
+make
+make install
+
+export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
+
+# 安装python组件
+curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip-2.7.py
+python get-pip-2.7.py -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
+#这两个命令用完之后使用pip install 后面要加上
+-i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
+# 验证pip是否安装成功可以用 `pip --version`
+# pip安装python组件
+pip install pydub -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
+pip install python-ESL -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
+pip install pika -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
+pip install DBUtils==2.0.3 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
+# pip install dbutils (python 2.7 is not support dbutils炸裂)
+```
+
+### 开始安装
+
+```bash
+cd /usr/local/src
+git clone -b v1.10 https://github.com/signalwire/freeswitch.git freeswitch
+# 如果github连接不顺畅的话,可以试试码云镜像仓库(更新慢1天)
+# git clone -b v1.10 https://gitee.com/mirrors/FreeSWITCH.git freeswitch
+cd freeswitch
+./bootstrap.sh -j
+```
+
+- 编辑modules.conf文件
+
+```bash
+vim modules
+```
+
+根据需要打开或关闭注释
+
+```
+formats/mod_shout
+languages/mod_python
+#event_handlers/mod_cdr_pg_csv
+asr_tts/mod_unimrcp
+#开启freeswitch自带的http状态界面
+xml_int/mod_xml_rpc
+```
+
+如果需要使用mod_xml_curl的话
+
+```
+xml_int/mod_xml_curl
+```
+
+给不需要的模块加上注释
+
+```
+#applications/mod_av
+#applications/mod_signalwire
+```
+
+然后保存退出
+
+- 开始编译安装
+
+```bash
+export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
+./configure --with-python=/usr/bin/python2.7 --with-lua=/usr/bin/lua --enable-core-pgsql-support
+# 如果在spandsp位置报错,可能是忘export那一句
+make
+#make mod_cdr_pg_csv-install
+make mod_unimrcp-install
+# 如果需要xml_curl模块的话
+make mod_xml_curl-install
+make mod_xml_rpc-install
+make install
+```
+
+- 安装音频文件(英文)
+
+```bash
+make cd-sounds-install
+make cd-moh-install
+make uhd-sounds-install
+make uhd-moh-install
+make hd-sounds-install
+make hd-moh-install
+make sounds-install
+make moh-install
+
+# make moh-install && make sounds-install && make hd-moh-install && make hd-sounds-install && make uhd-moh-install && make uhd-sounds-install && make cd-moh-install && make cd-sounds-install
+```
+
+- 建立软连接
+
+```bash
+sudo ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/
+sudo ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
+```
+
+- 配置mod
+
+```bash
+sudo vim /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml
+```
+
+在前3行开启
+
+```xml
+
+
+
+```
+
+打开注释
+
+```xml
+
+
+
+```
+
+添加配置
+
+```xml
+
+
+
+```
+
+注释掉其他不需要的模块
+
+```xml
+
+
+```
+
+- 配置acl白名单
+
+```bash
+vim /usr/local/freeswitch/conf/autoload_configs/acl.conf.xml
+```
+
+根据自己网络的实际情况进行配置(照抄大概率无效)
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+- 配置ESL
+
+```bash
+vim /usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml
+```
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+- 适配WebRTC(JSSIP/SIPJS)
+
+在`/usr/local/freeswitch/conf/sip_profiles/internal.xml`中添加或修改下面这些配置
+
+```xml
+
+
+
+```
+
+```xml
+
+
+```
+
+- 适配特定终端(以云翌通安卓SDK为例)
+
+在`/usr/local/freeswitch/conf/sip_profiles/internal.xml`中添加下面这些配置
+
+```xml
+
+```
+
+- 拨号计划规则
+
+在`/usr/local/freeswitch/conf/sip_profiles/internal.xml`中修改下面这些配置
+
+```xml
+
+
+```
+
+### 安全配置
+
+- 配置端口
+
+在`/usr/local/freeswitch/conf/vars.xml`文件中:
+
+```xml
+
+
+
+
+```
+
+```xml
+
+
+
+```
+
+在`/usr/local/freeswitch/conf/sip_profiles/internal.xml`文件中:
+
+```xml
+
+
+
+
+```
+
+- 默认密码
+
+在`/usr/local/freeswitch/conf/vars.xml`文件中:
+
+```xml
+
+
+```
+
+- 配置防火墙
+
+```bash
+# 开放sip端口tcp协议
+sudo firewall-cmd --permanent --add-port=5060/tcp
+# 开放sip端口udp协议
+sudo firewall-cmd --permanent --add-port=5060/udp
+# 开放ws端口
+sudo firewall-cmd --permanent --add-port=5066/tcp
+# 开放wss端口
+sudo firewall-cmd --permanent --add-port=7443/tcp
+# 开放rtp端口(范围)
+sudo firewall-cmd --permanent --add-port=16384-32768/udp
+# 让防火墙配置生效
+sudo firewall-cmd --reload
+```
+
+- 参考资料
+
+|FireWall Ports|Network Protocol|Application Protocol|Description|
+|---|---|---|---|
+|1719|UDP|H.323|Gatekeeper RAS port|
+|1720|TCP|H.323|Call Signaling|
+|3478|UDP|STUN service|Used for NAT traversal|
+|3479|UDP|STUN service|Used for NAT traversal|
+|5002|TCP|MLP|protocol server|
+|5003|UDP| |Neighborhood service|
+|5060|UDP & TCP|SIP UAS|Used for SIP signaling (Standard SIP Port, for default Internal Profile)|
+|5070|UDP & TCP|SIP UAS|Used for SIP signaling (For default "NAT" Profile)|
+|5080|UDP & TCP|SIP UAS|Used for SIP signaling (For default "External" Profile)|
+|8021|TCP|ESL|Used for mod_event_socket *|
+|16384-32768|UDP|RTP/ RTCP multimedia streaming|Used for audio/video data in SIP and other protocols|
+|5066|TCP|Websocket|Used for WebRTC|
+|7443|TCP|Websocket|Used for WebRTC|
+
+### 效率
+
+- 关闭ipv6
+
+在`/usr/local/freeswitch/conf/sip_profiles/`目录下
+
+```bash
+cd /usr/local/freeswitch/conf/sip_profiles
+mv internal-ipv6.xml internal-ipv6.xml.removed
+mv external-ipv6.xml external-ipv6.xml.removed
+```
+
+### 启动
+
+- 后台快速启动
+
+```bash
+freeswitch -nc -nonat
+```
+
+- 控制台启动(退出即关闭服务)
+
+```bash
+freeswitch
+```
diff --git a/docs/src/freeswitch/Debian11安装FreeSWITCH1.10-参照ClueCon官方文档.md b/docs/src/freeswitch/Debian11安装FreeSWITCH1.10-参照ClueCon官方文档.md
new file mode 100644
index 0000000..c8e4501
--- /dev/null
+++ b/docs/src/freeswitch/Debian11安装FreeSWITCH1.10-参照ClueCon官方文档.md
@@ -0,0 +1,551 @@
+# Debian11安装FreeSWITCH1.10_参照ClueCon官方文档
+
+[[toc]]
+
+## 安装操作系统
+
+### 更换软件源
+
+> 在有些地方可能Debian10/11使用网易源速度较好
+
+```shell
+vi /etc/apt/sources.list
+```
+
+```text
+deb http://mirrors.163.com/debian/ buster main non-free contrib
+deb http://mirrors.163.com/debian/ buster-updates main non-free contrib
+deb http://mirrors.163.com/debian/ buster-backports main non-free contrib
+deb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib
+
+deb-src http://mirrors.163.com/debian/ buster main non-free contrib
+deb-src http://mirrors.163.com/debian/ buster-updates main non-free contrib
+deb-src http://mirrors.163.com/debian/ buster-backports main non-free contrib
+deb-src http://mirrors.163.com/debian-security/ buster/updates main non-free contrib
+```
+
+### 系统安装完成后可以进行系统升级并安装一些基础软件
+
+```shell
+apt update && apt upgrade -y
+apt install -y wget git vim lrzsz net-tools
+```
+
+### 在Debian系统里想要SSH登录root账号
+
+```shell
+vim /etc/ssh/sshd_conf
+```
+
+修改内容如下:
+
+```ini
+#PermitRootLogin prohibit-password
+PermitRootLogin yes
+
+#PasswordAuthentication yes
+PasswordAuthentication yes
+```
+
+修改后重启一下ssh服务
+
+```shell
+/etc/init.d/ssh restart
+```
+
+### 在Debian系统里启用ll命令
+
+```shell
+vim ~/.bashrc
+```
+
+解除alias ll行的注释或者添加一行:
+
+```ini
+alias ll='ls $LS_OPTIONS -l --color=auto'
+```
+
+退出终端重新进入或者使用下面命令生效:
+
+```shell
+source ~/.bashrc
+```
+
+> 命令`echo "alias ll='ls $LS_OPTIONS -l --color=auto'" >> ~/.bashrc && source ~/.bashrc && ll`
+
+## 安装lua和luarocks环境
+
+### 安装lua
+
+> lua安装包的下载地址:
+
+```shell
+apt install -y build-essential libreadline-dev unzip
+cd /usr/src
+wget http://www.lua.org/ftp/lua-5.2.4.tar.gz
+tar zxvf lua-5.2.4.tar.gz
+cd lua-5.2.4
+make linux test
+make install
+```
+
+> 合并命令:`cd /usr/src && wget http://www.lua.org/ftp/lua-5.2.4.tar.gz`,下载成功后再执行`tar zxvf lua-5.2.4.tar.gz && cd lua-5.2.4 && make linux test && make install && cd ..`
+
+### 安装luarocks3.9.0
+
+> luarocks安装包的下载地址
+
+```shell
+cd /usr/src
+wget https://luarocks.github.io/luarocks/releases/luarocks-3.9.0.tar.gz
+tar zxfv luarocks-3.9.0.tar.gz
+cd luarocks-3.9.0
+./configure
+make
+make install
+```
+
+> 合并命令:`cd /usr/src && wget https://luarocks.github.io/luarocks/releases/luarocks-3.9.0.tar.gz`,下载成功后再执行`tar zxfv luarocks-3.9.0.tar.gz && cd luarocks-3.9.0 && ./configure && make && make install && cd ..`
+
+## 安装python2.7和对应的pip(非必要)
+
+```shell
+apt install python
+cd /usr/src
+wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
+python get-pip.py
+# 下面的命令可以查看各种版本
+python --version # 查看python2的版本
+python3 --version # 查看python3的版本
+pip --version # 查看pip2的版本
+```
+
+## 编译安装FreeSWITCH
+
+### 安装FreeSWITCH
+
+> 不知道后来从什么时间点开始,通过signalwire的源去安装FreeSWITCH所需依赖包时,需要使用向Signalwire平台申请的Access Token,临时提供一个`pat_jMxihv2uTh3ivpPdSqUMffB3`
+
+```shell
+# 这个token不要照抄,要替换成自己的
+TOKEN=pat_jMxihv2uTh3ivpPdSqUMffB3
+
+apt update && apt install -yq gnupg2 wget lsb-release
+wget --http-user=signalwire --http-password=$TOKEN -O /usr/share/keyrings/signalwire-freeswitch-repo.gpg https://freeswitch.signalwire.com/repo/deb/debian-release/signalwire-freeswitch-repo.gpg
+
+echo "machine freeswitch.signalwire.com login signalwire password $TOKEN" > /etc/apt/auth.conf
+echo "deb [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" > /etc/apt/sources.list.d/freeswitch.list
+echo "deb-src [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" >> /etc/apt/sources.list.d/freeswitch.list
+
+apt update && apt upgrade -y
+
+# Install dependencies required for the build
+apt build-dep freeswitch -y
+
+```
+
+> 命令```TOKEN=pat_jMxihv2uTh3ivpPdSqUMffB3 && apt update && apt install -yq gnupg2 wget lsb-release &&wget --http-user=signalwire --http-password=$TOKEN -O /usr/share/keyrings/signalwire-freeswitch-repo.gpg https://freeswitch.signalwire.com/repo/deb/debian-release/signalwire-freeswitch-repo.gpg && echo "machine freeswitch.signalwire.com login signalwire password $TOKEN" > /etc/apt/auth.conf && echo "deb [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" > /etc/apt/sources.list.d/freeswitch.list && echo "deb-src [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" >> /etc/apt/sources.list.d/freeswitch.list && apt update && apt upgrade -y && apt build-dep freeswitch -y```
+
+```shell
+
+# then let's get the source. Use the -b flag to get a specific branch
+cd /usr/src/
+git clone https://github.com/signalwire/freeswitch.git -b v1.10 freeswitch
+cd freeswitch
+
+# Because we're in a branch that will go through many rebases, it's
+# better to set this one, or you'll get CONFLICTS when pulling (update).
+git config pull.rebase true
+
+# ... and do the build
+./bootstrap.sh -j
+./configure
+make
+make install
+```
+
+### 安装音频文件(英文)
+
+```shell
+cd /usr/src/freeswitch
+make cd-sounds-install
+make cd-moh-install
+make uhd-sounds-install
+make uhd-moh-install
+make hd-sounds-install
+make hd-moh-install
+make sounds-install
+make moh-install
+```
+
+> 合并成一条命令`cd /usr/src/freeswitch && make moh-install && make sounds-install && make hd-moh-install && make hd-sounds-install && make uhd-moh-install && make uhd-sounds-install && make cd-moh-install && make cd-sounds-install && cd ..`
+
+## 配置FreeSWITCH
+
+### conf/vars.xml中的配置项
+
+> 主要是sip用户默认密码、stun地址、sip端口号等配置
+
+```shell
+vim /usr/local/freeswitch/conf/vars.xml
+```
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### conf/sip_profiles/internal.xml中的配置项
+
+> 主要是与内部sip账号相关的配置
+
+```shell
+vim /usr/local/freeswitch/conf/sip_profiles/internal.xml
+```
+
+```xml
+
+
+
+
+
+
+
+
+```
+
+### conf/autoload_configs/acl.conf.xml中的配置项
+
+> 主要用来制定可(通过ESL)连接FreeSWITCH的IP规则
+
+```shell
+vim /usr/local/freeswitch/conf/autoload_configs/acl.conf.xml
+```
+
+下面的文件内容要根据实际情况配置,不能照抄。
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### conf/autoload_configs/switch.conf.xml中的配置项
+
+> 主要配置并发数
+
+```shell
+vim /usr/local/freeswitch/conf/autoload_configs/switch.conf.xml
+```
+
+```xml
+
+
+
+```
+
+### conf/autoload_configs/event_socket.conf.xml中的配置项
+
+> 用于配置ESL相关参数
+
+```shell
+vim /usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml
+```
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### conf/autoload_configs/modules.conf.xml中的配置
+
+> 负责开启或关闭一些模块,开启模块时需要确定模块已经被正确安装
+
+```shell
+vim /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml
+```
+
+```xml
+
+
+
+
+
+
+```
+
+### 关闭ipv6配置
+
+> 为了提高一点启动效率而已,如果需要IPV6就跳过这一步
+
+```shell
+cd /usr/local/freeswitch/conf/sip_profiles/
+mv external-ipv6.xml external-ipv6.xml.removed
+mv internal-ipv6.xml internal-ipv6.xml.removed
+```
+
+### 做freeswitch和fs_cli的软连接
+
+```shell
+ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/
+ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
+```
+
+## 配置ufw防火墙
+
+```shell
+apt install -y ufw
+# 基础规则
+ufw default allow outgoing && ufw default deny incoming && ufw allow ssh
+# FS-SIP
+ufw allow 5060
+# FS-SIP-EXTERNAL
+ufw allow 5080
+# FS-WS
+ufw allow 5066/tcp
+# FS-WSS
+ufw allow 7443/tcp
+# Event Socket
+ufw allow 8021/tcp
+# FS-RTP
+ufw allow 16384:32768/udp
+# FS-MRCP-RTP
+ufw allow 4000:5000/udp
+# ufw开机自启
+systemctl enable ufw
+# 启动ufw
+ufw enable
+# 检查ufw开机项
+systemctl list-unit-files | grep ufw
+```
+
+## 启动FreeSWITCH
+
+```shell
+# 控制台启动,退出即关闭服务
+freeswitch -nonat
+# 也可以后台启动,启动后需要使用fs_cli查看控制台,需要用shutdown命令关闭服务
+freeswitch -nc -nonat
+```
+
+## fs_cli连接
+
+```shell
+vim ~/.fs_cli_conf
+```
+
+```ini
+[default]
+host => 127.0.0.1
+port => 8021
+password => ClueConAAAA
+debug => 6
+```
+
+做了以上配置后,直接`fs_cli`就能查看控制台,`...`退出控制台
+
+## SIP终端注册测试
+
+> 假设这个FreeSWITCH服务器和SIP终端的网络是互通的
+
+**注册信息:**
+
+|项|值|
+|---|---|
+|服务器IP|FreeSWITCH服务器的IP或域名|
+|SIP端口号|5060,或是在vars.xml中配置的其他端口号|
+|用户名|1001~1019中的任意一个分机号都行|
+|密码|654654321,或是在vars.xml中配置的其他默认密码|
+|网络协议|TCP或UDP都可以|
+
+> 如果终端分机注册成功,用分机呼叫`9664`可以听到通话保持音乐,呼叫`9196`可以听到`echo`效果(你说什么他回什么),如果以上结果正常,说明本次FreeSWITCH服务器安装成功,可以开始后面的具体的开发和配置了。
+
+## 向已安装的FreeSWITCH添加模块
+
+### 添加mod_shout模块
+
+> mod_shout模块可以将通话录音保存为mp3文件
+
+先进入FreeSWITCH的源码目录
+
+```shell
+cd /usr/src/freeswitch
+vim modules.conf
+```
+
+修改如下内容
+
+```ini
+# 找到mod_shout一行,解除行首的注释
+formats/mod_shout
+```
+
+保存退出后,再执行下面的命令
+
+```shell
+make mod_shout-install
+```
+
+待编译安装完成后,在FreeSWITCH的安装目录`/usr/local/freeswitch`中的`mod`目录下就已经存在`mod_shout.so`这个文件了。
+
+接下来要回到FreeSWITCH的安装目录
+
+```shell
+cd /usr/local/freeswitch
+vim conf/autoload_configs/modules.conf.xml
+```
+
+编辑文件内容
+
+```xml
+
+
+```
+
+最后进入FreeSWITCH控制台`fs_cli`,在控制台中执行命令`load mod_shout`,到此mod_shout模块已经安装完成并在FreeSWITCH服务器生效。
+
+### 添加mod_unimrcp模块
+
+> mod_unimrcp模块可以通过mrcp协议实现实时语音识别和语音合成能力
+
+先进入FreeSWITCH的源码目录
+
+```shell
+cd /usr/src/freeswitch
+vim modules.conf
+```
+
+修改如下内容
+
+```ini
+# 找到mod_unimrcp一行,解除行首的注释
+asr_tts/mod_unimrcp
+```
+
+保存退出后,再执行下面的命令
+
+```shell
+make mod_unimrcp-install
+```
+
+待编译安装完成后,在FreeSWITCH的安装目录`/usr/local/freeswitch`中的`mod`目录下就已经存在`mod_unimrcp.so`这个文件了。
+
+接下来要回到FreeSWITCH的安装目录
+
+```shell
+cd /usr/local/freeswitch
+vim conf/autoload_configs/modules.conf.xml
+```
+
+编辑文件内容
+
+```xml
+
+
+```
+
+最后进入FreeSWITCH控制台`fs_cli`,在控制台中执行命令`load mod_unimrcp`,到此mod_unimrcp模块已经安装完成并在FreeSWITCH服务器生效。
+
+> 以上方法只适用于FreeSWITCH1.10.7及之前的版本,1.10.8开始,mod_unimrcp被从核心代码中移除,转移为独立项目,详见另外一份文档
+
+### 添加mod_python模块
+
+> mod_python模块可以支持用python脚本制作ivr,支持的python版本为2.7,如果需要python3的支持,需要安装mod_python3
+
+先进入FreeSWITCH的源码目录
+
+```shell
+cd /usr/src/freeswitch
+vim modules.conf
+```
+
+修改如下内容
+
+```ini
+# 找到mod_python一行,解除行首的注释
+languages/mod_python
+```
+
+保存退出后,再执行下面的命令
+
+```shell
+make mod_python-install
+```
+
+待编译安装完成后,在FreeSWITCH的安装目录`/usr/local/freeswitch`中的`mod`目录下就已经存在`mod_python.so`这个文件了。
+
+接下来要回到FreeSWITCH的安装目录
+
+```shell
+cd /usr/local/freeswitch
+vim conf/autoload_configs/modules.conf.xml
+```
+
+编辑文件内容
+
+```xml
+
+
+```
+
+最后进入FreeSWITCH控制台`fs_cli`,在控制台中执行命令`load mod_python`,到此mod_unimrcp模块已经安装完成并在FreeSWITCH服务器生效。
+
+### 添加mod_g729模块
+
+> FreeSWITCH源码中的G729模块只能用在透传模式下,如果想要在非透传模式下使用G729编码,就需要手动安装第三方模块
+
+通过git克隆源码,编译安装
+
+```bash
+cd /usr/src
+git clone https://github.com/abaci64/mod_g729.git
+cd mod_g729
+make
+make install
+```
+
+进入FreeSWITCH配置文件修改modules.conf.xml配置
+
+```xml
+
+
+```
+
+然后重新启动FreeSWITCH服务,即可以使用g729编码。
+
+```shell
+bgapi originate {ignore_early_media=true,absolute_codec_string=g729\,PCMA}sofia/gateway/[YOUR_GATEWAY]/[TARGET_PHONE] &echo
+```
diff --git a/docs/src/freeswitch/Debian11安装lua和luarocks.md b/docs/src/freeswitch/Debian11安装lua和luarocks.md
new file mode 100644
index 0000000..ca7c603
--- /dev/null
+++ b/docs/src/freeswitch/Debian11安装lua和luarocks.md
@@ -0,0 +1,34 @@
+## Debian11安装lua和luarocks
+
+> wandoubaba / 2023-01-18
+
+严格来说,这个内容并不只针对FreeSWITCH,不过打造一个合适的lua的编写和运行环境也是玩转FreeSWITCH的一个前提,而且笔者是通过FreeSWITCH才认识lua的,所以把搭建lua环境也当作是FreeSWITCH的一个案例看待。
+
+### 安装lua
+
+> 后面的操作过程中如果使用root账号的话就不需要加`sudo`了
+
+```sh
+sudo apt-get install -y lua5.1
+```
+
+### 安装luarocks
+
+```sh
+sudo apt-get install -y unzip
+cd /opt
+wget https://luarocks.org/releases/luarocks-3.9.2.tar.gz
+tar zxpf luarocks-3.9.2.tar.gz
+cd luarocks-3.9.2
+./configure && make
+sudo make install
+```
+
+### 验证
+
+```sh
+# 查看lua版本号
+lua -v
+# 查看luarocks版本号
+luarocks --version
+```
diff --git a/docs/src/freeswitch/Docker部署阿里云的MRCP服务.md b/docs/src/freeswitch/Docker部署阿里云的MRCP服务.md
new file mode 100644
index 0000000..da0191a
--- /dev/null
+++ b/docs/src/freeswitch/Docker部署阿里云的MRCP服务.md
@@ -0,0 +1,124 @@
+## Docker部署阿里云的MRCP服务(版权)
+
+> wandoubaba / 2023-02-21
+
+在阿里云的的智能语音服务中,除了提供常规的ASR、TTS等能力外,也有完整的MRCP服务(阿里名称:SDM),不但可以对接私有化的智能语音能力,同时还可以对接公有云的ASR和TTS。
+
+引用阿里云《SDM(MRCP-SERVER)公共镜像使用》文档中的一段话:
+
+> SDM(MRCP-SERVER)目前在公共云上有对应的镜像仓库,用户可以直接拉取公共云镜像到本地,然后部署使用,一定程度上简化了部署和接入的成本。
+
+### 环境依赖
+
+机器需求:4C8G
+
+操作系统:CentOS7.2及以上(其他支持Docker环境的较新版本的Linux发行版)
+
+软件环境要求:Docker环境
+
+### 安装过程
+
+安装部署主要包括两个过程:到阿里云开通公共云语音服务、部署SDM镜像。
+
+#### 开通阿里云智能语音服务
+
+> 下面这些操作都是在阿里云的控制台里完成的。
+
+- 注册阿里云账号,这里省略具体步骤。
+
+- 登录阿里云控制台,到“智能语音交互服务”页面开通ASR、TTS相关服务
+
+- 阿里云的语音服务都支持试用版免费使用,只不过并发路数有限,开发测试可以用。
+
+- 到阿里云的“Access Key管理页面”创建并获取一组供SDM使用的具有调用智能语音服务能力的“Access Key ID”和“Access Key Secret”(注意妥善保存)。
+
+- 到阿里云“智能语音交互”控制台->“全部项目”,如果没有项目创建一个项目,项目类型选择“语音识别+语音合成+语音分析“,主要是要拿到项目的“AppKey”。
+
+- 注意“AppKey”对应项目的“项目功能配置”中,要选择8K模型。
+
+经过以上操作,在云端的基础能力就已经配置好了,一共得到了3个变量:“Access Key ID”、“Access Key Secret”、“AppKey”,后面部署SDM时会用到这几个变量。
+
+#### 部署SDM镜像
+
+> 下面的操作是在要部署SDM的服务器上进行的,如果是以root登录的话,就自行忽略`sudo`,假设Linux系统上已经安装好了docker服务。
+
+开始操作之前,最好事先在主机上为SDM规划一个目录,用于保存配置文件和日志等运行时文件,本文假设这个目录是`/data/sdm`,下面的操作都默认在`/data/sdm`目录下进行。
+
+##### 初始化配置
+
+```sh
+# 进入主机准备的sdm文件目录
+cd /data/sdm
+# 拉取镜像
+sudo docker pull registry.cn-shanghai.aliyuncs.com/nls-cloud/sdm:latest
+# 确认本地已拉取的镜像
+sudo docker images | grep sdm
+# 初始化本地环境
+sudo docker run -d --privileged --net=host --name nls-cloud-sdm -v `pwd`/logs:/home/admin/logs -v `pwd`/data:/home/admin/disk registry.cn-shanghai.aliyuncs.com/nls-cloud/sdm:latest standalone
+```
+
+到这里只是用到初始化环境,将容器中的SDM目录映射到宿主机上,由于相关配置参数还没有修改,所以容器最终不会运行起来(如果真运行起来了,也请用`docker stop`命令将它停了吧),下面需要进行相关配置操作。
+
+##### 配置
+
+首次启动后,容器内的配置文件在宿主机`/data/sdm/data/nls-cloud-sdm/conf`目录下,一般来说只需要修改其中的3个配置文件:nlstoken.json、service-asr.json、service-tts.json。
+
+- nlstoken.json(配置AccessKeyId和AccessKeySecret):
+
+```json
+{
+ "AccessKeyId": "前面得到的AccessKeyId",
+ "AccessKeySecret": "前面得到的AccessKeySecret",
+ "DefaultToken": ""
+}
+```
+
+说明:对接公有云时,DefaultToken的值要是空白。
+
+- service-asr.json(主要配置url和AppKey):
+
+```json
+{
+ "url": "wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1",
+ "appkey": "前面得到的项目AppKey",
+}
+```
+
+- service-tts.json(主要配置url和AppKey):
+
+```json
+{
+ "url": "wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1",
+ "appkey": "前面得到的项目AppKey",
+}
+```
+
+其他asr和tts的配置一般不用修改,如果有特殊需求的话就按需配置好了。
+
+##### 启动
+
+```sh
+sudo docker start nls-cloud-sdm
+# 查看是否启动成功
+sudo docker ps
+# 查看服务进程是否已拉起
+ps -ef | grep alimrcp-server
+# 查看端口是否监听
+sudo lsof -i:7010
+# 查看日志中有没有ERROR信息
+cat logs/nls-cloud-sdm/alimrcp-server.log | grep ERROR
+# 设置容器自启动
+sudo docker update --restart=always nls-cloud-sdm
+```
+
+##### 端口
+
+默认情况下,SDM使用以下端口与客户端(如FreeSWITCH)通信,与服务端(阿里云)不需要开放端口,只需要能连接阿里云公有云服务即可。
+
+- 7010(TCP&UDP):SIP端口。
+- 1544、1554(TCP):MRCP协议端口。
+- 10000-20000(UDP):RTP协议端口,用来传输语音流。
+
+##### 并发
+
+SDM单机资源默认支持100路ASR+100路TTS,这个并发指的是SDM与客户端(如FreeSWITCH)的资源处理能力,与公有云的ASR、TTS并发能力无关。
diff --git a/docs/src/freeswitch/FreeSWITCH命令.md b/docs/src/freeswitch/FreeSWITCH命令.md
new file mode 100644
index 0000000..c510646
--- /dev/null
+++ b/docs/src/freeswitch/FreeSWITCH命令.md
@@ -0,0 +1,117 @@
+# FreeSWITCH常用的命令
+
+---
+
+## 启动freeswitch
+
+```bash
+freeswitch -nc # 后台启动
+freeswitch -nc -nonat # 后台启动且关闭自动nat(有独立公网IP时不需要开启nat功能,能明显提高启动速度)
+```
+
+## fs_cli中使用的命令
+
+- **shutdown**
+
+> 关闭freeswitch服务
+
+- **reloadxml**
+
+> 重载配置(如拨号计划)
+
+- **reloadacl**
+
+> 重载acl
+
+- **sofia profile internal restart**
+
+> 重启internal服务
+
+- **sofia profile external restart**
+
+> 重启external服务
+
+- **sofia status profile internal**
+
+> 查看服务端口等信息
+
+结果示例:
+
+```text
+=================================================================================================
+Name internal
+Domain Name N/A
+Auto-NAT false
+DBName sofia_reg_internal
+Pres Hosts 183.211.245.46,183.211.245.46
+Dialplan XML
+Context public
+Challenge Realm auto_from
+RTP-IP 183.211.245.46
+SIP-IP 183.211.245.46
+URL sip:mod_sofia@183.211.245.46:5060
+BIND-URL sip:mod_sofia@183.211.245.46:5060;transport=udp,tcp
+WS-BIND-URL sip:mod_sofia@183.211.245.46:5066;transport=ws
+WSS-BIND-URL sips:mod_sofia@183.211.245.46:7443;transport=wss
+HOLD-MUSIC local_stream://moh
+OUTBOUND-PROXY N/A
+CODECS IN OPUS,G722,PCMU,PCMA,VP8
+CODECS OUT OPUS,G722,PCMU,PCMA,VP8
+TEL-EVENT 101
+DTMF-MODE rfc2833
+CNG 13
+SESSION-TO 0
+MAX-DIALOG 0
+NOMEDIA false
+LATE-NEG true
+PROXY-MEDIA false
+ZRTP-PASSTHRU true
+AGGRESSIVENAT false
+CALLS-IN 8
+FAILED-CALLS-IN 0
+CALLS-OUT 2
+FAILED-CALLS-OUT 0
+REGISTRATIONS 2
+```
+
+- **sofia status profile internal reg**
+
+> 查看注册用户
+
+结果示例:
+
+```text
+Registrations:
+=================================================================================================
+Call-ID: G7ZfP264pLJawfNLKuFg1A..
+User: 1002@183.211.245.46
+Contact: ""
+Agent: Zoiper rv2.10.6.2
+Status: Registered(TCP)(unknown) EXP(2021-09-14 13:42:51) EXPSECS(359)
+Ping-Status: Reachable
+Ping-Time: 0.00
+Host: fstesting
+IP: 39.152.207.190
+Port: 43502
+Auth-User: 1002
+Auth-Realm: 183.211.245.46
+MWI-Account: 1002@183.211.245.46
+
+Call-ID: JRlQZx3SoV0ElHunKRrQNg..
+User: 1001@183.211.245.46
+Contact: ""
+Agent: Zoiper rv2.10.6.2
+Status: Registered(UDP)(unknown) EXP(2021-09-14 13:38:15) EXPSECS(83)
+Ping-Status: Reachable
+Ping-Time: 0.00
+Host: fstesting
+IP: 39.152.207.190
+Port: 41043
+Auth-User: 1001
+Auth-Realm: 183.211.245.46
+MWI-Account: 1001@183.211.245.46
+
+Total items returned: 2
+=================================================================================================
+
+```
diff --git a/docs/src/freeswitch/FreeSWITCH对接百度MRCP.md b/docs/src/freeswitch/FreeSWITCH对接百度MRCP.md
new file mode 100644
index 0000000..36dcf20
--- /dev/null
+++ b/docs/src/freeswitch/FreeSWITCH对接百度MRCP.md
@@ -0,0 +1,170 @@
+# Freeswitch通过mod_unimrcp与百度mrcp-server对接(lua版)
+
+---
+
+## 参考链接
+
+[https://freeswitch.org/confluence/display/FREESWITCH/mod_unimrcp]
+[https://ptorch.com/news/206.html]
+[https://ptorch.com/news/207.html]
+
+## 安装并加载mod_unimrcp模块
+
+```bash
+# 在freeswitch源码目录(不是安装目录)
+make mod_unimrcp-install
+# 在freeswitch安装目录中编译modules.conf.xml文件
+cd /usr/local/freeswitch
+vim conf/autoload_configs/modules.conf.xml
+```
+
+```xml
+
+
+```
+
+## 设置profile文件和conf文件
+
+```bash
+vim /usr/local/freeswitch/conf/mrcp_profiles/unimrcpserver-mrcp-v2.xml
+```
+
+输入以下内容:
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+编辑`unimrcp.conf.xml`文件改`default-tts-profile`和`default-asr-profile`
+
+```bash
+vim /usr/local/freeswitch/conf/autoload_configs/unimrcp.conf.xml
+```
+
+```xml
+
+
+
+
+```
+
+## 设置dialplan
+
+```bash
+vim /usr/local/freeswitch/conf/dialplan/default.xml
+```
+
+添加一个extension:
+
+```xml
+
+
+
+
+
+
+
+```
+
+在`/usr/local/freeswitch/scripts`目录下创建`baidu.lua`文件:
+
+```bash
+touch /usr/local/freeswitch/scripts/baidu.lua
+vim /usr/local/freeswitch/scripts/baidu.lua
+```
+
+文件内容如下:
+
+```lua
+session:answer()
+
+--freeswitch.consoleLog("INFO", "Called extension is '".. argv[1]"'\n")
+welcome = "/usr/local/freeswitch/sounds/en/us/callie/ivr/8000/ivr-welcome_to_freeswitch.wav"
+--
+grammar = "baidu"
+no_input_timeout = 80000
+recognition_timeout = 80000
+--
+
+tryagain = 1
+while (tryagain == 1) do
+--
+ session:execute("play_and_detect_speech", welcome .. " detect:unimrcp {start-input-timers=false,no-input-timeout=" .. no_input_timeout .. ",recognition-timeout=" .. recognition_timeout .. "} " .. grammar)
+ xml = session:getVariable('detect_speech_result')
+ --
+ if (xml == nil) then
+ freeswitch.consoleLog("CRIT","Result is 'nil'\n")
+ tryagain = 0
+ else
+ freeswitch.consoleLog("CRIT","Result is '" .. xml .. "'\n")
+ tryagain = 0
+ end
+end
+--
+-- put logic to forward call here
+--
+session:sleep(250)
+session:hangup()
+```
+
+> 以上脚本实现当分机用户拨打5001时,freeswitch会自动播放一段录音,并接收用户发出的声音,同时把声音传给mrcp服务器并接收返回结果
+
+在`/usr/local/freeswitch/grammar`目录新增`hello.gram`语法文件,内容为百度mrcp程序句中的语法文件内容:
+
+```xml
+
+
+
+
+ - one
+ - two
+ - three
+
+
+
+```
+
+## 让配置生效并测试
+
+```bash
+fs_cli
+reloadxml
+```
+
+## 防火墙
+
+在freeswitch服务器和mrcp服务器都不需要额外开放端口。
diff --git a/docs/src/freeswitch/FreeSWITCH对接阿里云MRCP.md b/docs/src/freeswitch/FreeSWITCH对接阿里云MRCP.md
new file mode 100644
index 0000000..cc19d64
--- /dev/null
+++ b/docs/src/freeswitch/FreeSWITCH对接阿里云MRCP.md
@@ -0,0 +1,142 @@
+## FreeSWITCH对接阿里云MRCP服务(SDM)
+
+> wandoubaba / 2023-02-21
+
+在阿里云的的智能语音服务中,除了提供常规的ASR、TTS等能力外,也有完整的MRCP服务(阿里名称:SDM),不但可以对接私有化的智能语音能力,同时还可以对接公有云的ASR和TTS。
+
+### 网络规划
+
+- MRCP服务器
+
+|配置项|配置值|
+|---|---|
+|IP| 192.168.0.10|
+|SIP端口|7010(TCP&UDP)|
+|MRCP端口|1544、1554(TCP)|
+|RTP端口|10000-20000(UDP)|
+
+- FreeSWITCH服务器
+
+|配置项|配置值|
+|---|---|
+|IP|192.168.0.60|
+|SIP端口|5060(TCP&UDP)|
+|RTP端口(与MRCP通信)|40000-50000(UDP)|
+
+### 部署SDM
+
+目前阿里云并没有开放SDM服务,通过阿里云智能语音服务的客户经理可以得以《SDM(MRCP-SERVER)公共镜像使用》文档,按照文档部署,比较容易。
+
+摘抄阿里云《SDM(MRCP-SERVER)公共镜像使用》文档中的一段话:
+
+> SDM(MRCP-SERVER)目前在公共云上有对应的镜像仓库,用户可以直接拉取公共云镜像到本地,然后部署使用,一定程度上简化了部署和接入的成本。
+
+### 安装mod_unimrcp模块
+
+详见《为FreeSWITCH安装mod_unimrcp模块》。
+
+### 配置mod_unimrcp
+
+在FreeSWITCH的安装目录修改`conf/autoload_configs/modules.conf.xml`文件:
+
+```xml
+
+
+```
+
+在FreeSWITCH的安装目录下创建`conf/mrcp_profiles/aliyun-mrcpserver.xml`文件:
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+创建或修改`conf/autoload_configs/unimrcp.conf.xml`文件:
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+在`grammar`目录下创建`alimrcp.gram`文件:
+
+```js
+#JSGF V1.0;
+/** JSGF Grammar for example */
+grammar example;
+public = [];
+```
+
+修改unimrcp配置后需要重启FreeSWITCH服务。
+
+### 通过dialplan测试
+
+在FreeSWITCH安装目录里创建`conf/dialplan/default/mrcp.xml`文件:
+
+```xml
+
+
+
+
+
+
+
+
+
+```
+
+在fs_cli中执行`reloadxml`,然后盯着控制台,用分机呼叫001,接通后说一句话,应该会在控制台看到识别结果,类似:
+
+```xml
+
+
+
+
+ 中午吃什么?
+ 730
+ 2220
+ 511ba061b8a54d7b93e0f5675534febd
+ 5d27104393eb4dbe-1.wav
+
+ 中午吃什么?
+
+
+```
+
+恭喜,到这里,你的FreeSWITCH已经可以“听”和“说”了。
diff --git a/docs/src/freeswitch/FreeSWITCH配置SSL.md b/docs/src/freeswitch/FreeSWITCH配置SSL.md
new file mode 100644
index 0000000..ba3116b
--- /dev/null
+++ b/docs/src/freeswitch/FreeSWITCH配置SSL.md
@@ -0,0 +1,40 @@
+# FreeSWITCH配置SSL证书
+
+---
+
+## 申请证书
+
+向域名提供商申请SSL证书,然后下载证书文件,应该会得到2个文件,分别是`xxx.key`和`xxx.pem`。
+
+## 上传证书(至freeswitch目录)
+
+把`xxx.key`文件和`xxx.pem`文件上传到freeswitch安装目录的`certs`目录下,如`/usr/local/freeswitch/certs`。
+
+## 合成wss.pem文件
+
+> 先备份原有的wss.pem文件
+
+```bash
+cat xxx.pem xxx.key > wss.pem
+```
+
+## 配置wss端口
+
+```bash
+vim /usr/local/freeswitch/conf/sip_profiles/internal.xml
+```
+
+```xml
+
+```
+
+## 重启freeswitch服务
+
+```bash
+freeswitch -stop
+freeswitch -nc -nonat
+```
+
+## 客户端配置
+
+在sip.js或jssip或其他webrtc客户端配置服务器访问地址为`wss://域名:7443`
diff --git a/docs/src/freeswitch/FreeSWITCH问题.md b/docs/src/freeswitch/FreeSWITCH问题.md
new file mode 100644
index 0000000..72e3ab7
--- /dev/null
+++ b/docs/src/freeswitch/FreeSWITCH问题.md
@@ -0,0 +1,11 @@
+# FreeSWITCH问题(和解决)
+
+[[toc]]
+
+## 网内通话,在conf/dialplan/default.xml中设置的拨号计划不生效,只走public.xml
+
+在`conf/sip_profiles/internal.xml`文件中:
+
+把``改成``
+
+> 它默认是public
diff --git a/docs/src/freeswitch/debian-service.md b/docs/src/freeswitch/debian-service.md
new file mode 100644
index 0000000..236ac6f
--- /dev/null
+++ b/docs/src/freeswitch/debian-service.md
@@ -0,0 +1,70 @@
+# Debian11中注册FreeSWITCH为系统服务
+
+Debian 11使用了systemd作为启动管理器,而不再使用sysvinit,所以我们不去`/etc/init.d/`目录中去搞,而是在`/etc/systemd/system/`里面搞。
+
+假设FreeSWITCH的安装目录是`/usr/local/freeswitch`。
+
+## 创建freeswitch.service文件
+
+```sh
+touch /etc/systemd/system/freeswitch.service
+vim /etc/systemd/system/freeswitch.service
+```
+
+文件内容参考如下:
+
+```ini
+[Unit]
+Description=FreeSWITCH
+After=network.target network-online.target
+Wants=network-online.target
+
+[Service]
+User=freeswitch
+Group=freeswitch
+WorkingDirectory=/usr/local/freeswitch
+ExecStart=/usr/local/freeswitch/bin/freeswitch
+ExecStop=/usr/local/freeswitch/bin/freeswitch -stop
+ExecStartPre=/bin/sleep 3
+Restart=always
+
+[Install]
+WantedBy=default.target
+```
+
+其中`[Service]`段的`ExecStartPre=/bin/sleep 3`表示在启动FreeSWITCH前,先等待3秒,这一句可根据实际环境酌情使用。
+
+保存`freeswitch.service`文件并退出。
+
+## 创建freeswitch启动用户和组
+
+```sh
+## 创建freeswith用户组
+groupadd -r freeswitch
+## 创建freeswitch用户
+useradd -r -g freeswitch -s /bin/false -d /usr/local/freeswitch -c "FreeSWITCH" freeswitch
+## 更改freeswitch程序目录的权限
+sudo chown -R freeswitch:freeswitch /usr/local/freeswitch
+```
+
+## 注册系统服务并实现开机自启
+
+```sh
+## 注册freeswitch服务
+sudo systemctl daemon-reload
+## 让freeswitch随系统自动启动
+sudo systemctl enable freeswitch
+```
+
+现在名为freeswitch的系统服务已经注册完成,可以使用下面的系统命令管理freeswitch的启动与停止了:
+
+```sh
+## 启动服务
+sudo systemctl start freeswitch
+## 重新启动服务(停止再启动)
+sudo systemctl restart freeswitch
+## 停止服务
+sudo systemctl stop freeswitch
+## 查看服务状态
+sudo systemctl status freeswitch
+```
diff --git a/docs/src/freeswitch/debian12.md b/docs/src/freeswitch/debian12.md
new file mode 100644
index 0000000..5ac60b5
--- /dev/null
+++ b/docs/src/freeswitch/debian12.md
@@ -0,0 +1,137 @@
+# Debian12编译安装FreeSWITCH1.10
+
+> wandoubaba / 2024-08-19
+
+本文以Debian12和FreeSWITCH1.10.12为例,介绍一步一步编译安装FreeSWITCH的方法。
+
+## 先下载/克隆各种资源
+
+```shell
+# 假设所有资源都下载到/opt/目录下
+cd /opt
+# 下载FreeSWITCH源码
+git clone -b v1.10 https://github.com/signalwire/freeswitch freeswitch
+# 下载libks源码
+git clone https://github.com/signalwire/libks
+# 下载sofia-sip源码
+git clone https://github.com/freeswitch/sofia-sip
+# 下载spandsp源码
+git clone -b fs https://github.com/freeswitch/spandsp
+# 下载signalwire-c源码
+git clone https://github.com/signalwire/signalwire-c
+```
+
+> 国内连接github很累,另外不保证各资源仓库以后更新后对应的操作方法是否会变,建议资源下载成功后自己留一份备份
+
+## 一步一步安装
+
+> 如果后面的操作是在root账号下,就不需要再用sudo了
+
+先安装必要的依赖程序。
+
+```shell
+# 安装FreeSWITCH需要的依赖
+sudo apt-get install -y \
+ build-essential cmake automake autoconf 'libtool-bin|libtool' pkg-config \
+ libssl-dev zlib1g-dev libdb-dev unixodbc-dev libncurses5-dev \
+ libexpat1-dev libgdbm-dev bison erlang-dev libtpl-dev libtiff5-dev uuid-dev \
+ libpcre3-dev libedit-dev libsqlite3-dev libcurl4-openssl-dev nasm \
+ libogg-dev libspeex-dev libspeexdsp-dev \
+ libldns-dev \
+ python3-dev \
+ libavformat-dev libswscale-dev 'libswresample-dev|libavresample-dev' \
+ liblua5.3-dev \
+ libopus-dev \
+ libpq-dev \
+ libsndfile1-dev libflac-dev libogg-dev libvorbis-dev \
+ libshout3-dev libmpg123-dev libmp3lame-dev \
+ lsb-release
+
+# 安装libks
+cd libks
+cmake . -DCMAKE_INSTALL_PREFIX=/usr -DWITH_LIBBACKTRACE=1
+sudo make install
+cd ..
+# 安装sofia-sip
+cd sofia-sip
+./bootstrap.sh
+./configure CFLAGS="-g -ggdb" --with-pic --with-glib=no --without-doxygen --disable-stun --prefix=/usr
+make -j`nproc --all`
+sudo make install
+cd ..
+# 安装spandsp
+cd spandsp
+./bootstrap.sh
+./configure CFLAGS="-g -ggdb" --with-pic --prefix=/usr
+make -j`nproc --all`
+sudo make install
+cd ..
+# 安装signalwire-c
+cd signalwire-c
+PKG_CONFIG_PATH=/usr/lib/pkgconfig cmake . -DCMAKE_INSTALL_PREFIX=/usr
+sudo make install
+cd ..
+```
+
+可以开始安装FreeSWITCH了
+
+```shell
+# 编译安装FreeSWITCH
+cd freeswitch
+sed -i 's|#formats/mod_shout|formats/mod_shout|' build/modules.conf.in
+./bootstrap.sh -j
+./configure
+make -j`nproc`
+sudo make install
+# 安装英文声音资源(可选)
+make cd-sounds-install && \
+make cd-moh-install && \
+make uhd-sounds-install && \
+make uhd-moh-install && \
+make hd-sounds-install && \
+make hd-moh-install && \
+make sounds-install && \
+make moh-install
+cd ..
+```
+
+## 启动FreeSWITCH服务
+
+执行以上步骤后,FreeSWITCH已经被安装到/usr/local/freeswitch目录下了。
+
+```shell
+cd /usr/local/freeswitch
+# 前台启动服务
+bin/freeswitch
+```
+
+等待一段时间后,FreeSWITCH服务就已经成功启动了,在当前控制台输入命令`sofia status`可以看到一点配置信息。前台启动方式非常简单,但是一旦执行`...`命令退出控制台后,对应的FreeSWITCH服务也就退出了。如果想在后台启动服务,在执行`bin/freeswitch`时后面加上`-nc`命令参数就可以了。
+
+## 做freeswitch和fs_cli的软连接
+
+```shell
+ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/
+ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
+```
+
+做完这一步操作后,就可以在任意目录下执行freeswitch地fs_cli命令了(但是要注意freeswitch的运行目录的相对路径问题)。
+
+## 配置.fs_cli_conf文件
+
+fs_cli的本质也是通过esl连接去控制FreeSWITCH,所以如果对FreeSWITCH做配置时更改了event_socket的端口号、密码等内容时,再使用fs_cli工具时就需要在后面加上各种复杂的参数,为了简化操作,我们可以配置一个名为.fs_cli_conf的文件,在里面写好FreeSWITCH的esl相关参数,以后就可以直接执行fs_cli命令进入到FreeSWITCH控制台了。
+
+```shell
+vim ~/.fs_cli_conf
+```
+
+文件内容参数:
+
+```ini
+[default]
+host => 127.0.0.1
+port => 8021
+password => ClueConAAAA
+debug => 6
+```
+
+做了以上配置后,直接`fs_cli`就能查看控制台,`...`退出控制台。
diff --git a/docs/src/freeswitch/docker.md b/docs/src/freeswitch/docker.md
new file mode 100644
index 0000000..5d2ccf3
--- /dev/null
+++ b/docs/src/freeswitch/docker.md
@@ -0,0 +1,95 @@
+# 制作FreeSWITCH镜像的Dockerfile
+
+> wandoubaba / 2024-08-19
+
+下面是基于`debian:bookworm`镜像制作FreeSWITCH1.10.12版服务镜像,同时安装`mod_unimrcp`模块并开启`mod_shout`模块。
+
+```dockerfile
+FROM debian:bookworm
+
+RUN apt-get update && apt-get upgrade -y && \
+ apt-get install -y wget tar git \
+ build-essential cmake automake autoconf 'libtool-bin|libtool' pkg-config \
+ libssl-dev zlib1g-dev libdb-dev \
+ unixodbc-dev libncurses5-dev \
+ libexpat1-dev libgdbm-dev bison erlang-dev \
+ libtpl-dev libtiff5-dev uuid-dev \
+ libpcre3-dev libedit-dev libsqlite3-dev \
+ libcurl4-openssl-dev nasm \
+ libogg-dev libspeex-dev libspeexdsp-dev \
+ libldns-dev \
+ python3-dev \
+ libavformat-dev libswscale-dev 'libswresample-dev|libavresample-dev' \
+ liblua5.3-dev \
+ libopus-dev \
+ libpq-dev \
+ libsndfile1-dev libflac-dev libogg-dev libvorbis-dev \
+ libshout3-dev libmpg123-dev libmp3lame-dev \
+ lsb-release
+
+RUN mkdir /install && cd /install && \
+ git clone -b v1.10 https://github.com/signalwire/freeswitch freeswitch && \
+ git clone https://github.com/signalwire/libks && \
+ git clone https://github.com/freeswitch/sofia-sip && \
+ git clone -b fs https://github.com/freeswitch/spandsp && \
+ git clone https://github.com/signalwire/signalwire-c && \
+ git clone https://github.com/unispeech/unimrcp.git && \
+ git clone https://github.com/freeswitch/mod_unimrcp.git && \
+ wget https://www.unimrcp.org/project/component-view/unimrcp-deps-1-6-0-tar-gz/download -O unimrcp-deps-1.6.0.tar.gz && \
+ tar xvzf unimrcp-deps-1.6.0.tar.gz
+
+RUN cd /install/libks && \
+ cmake . -DCMAKE_INSTALL_PREFIX=/usr -DWITH_LIBBACKTRACE=1 && \
+ make install
+
+RUN cd /install/sofia-sip && \
+ ./bootstrap.sh && \
+ ./configure CFLAGS="-g -ggdb" --with-pic --with-glib=no --without-doxygen --disable-stun --prefix=/usr && \
+ make -j`nproc --all` && \
+ make install
+
+RUN cd /install/spandsp && \
+ ./bootstrap.sh && \
+ ./configure CFLAGS="-g -ggdb" --with-pic --prefix=/usr && \
+ make -j`nproc --all` && \
+ make install
+
+RUN cd /install/signalwire-c && \
+ PKG_CONFIG_PATH=/usr/lib/pkgconfig cmake . -DCMAKE_INSTALL_PREFIX=/usr && \
+ make install
+
+RUN cd /install/freeswitch && \
+ sed -i 's|#formats/mod_shout|formats/mod_shout|' build/modules.conf.in && \
+ ./bootstrap.sh -j && \
+ ./configure && \
+ make -j`nproc` && \
+ make install && \
+ make cd-sounds-install && \
+ make cd-moh-install && \
+ make uhd-sounds-install && \
+ make uhd-moh-install && \
+ make hd-sounds-install && \
+ make hd-moh-install && \
+ make sounds-install && \
+ make moh-install && \
+ ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/ && \
+ ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
+
+RUN cd /install/unimrcp-deps-1.6.0/libs/apr && \
+ ./configure --prefix=/usr/local/apr && \
+ make && make install && \
+ cd ../apr-util && \
+ ./configure --prefix=/usr/local/apr --with-apr=/usr/local/apr && \
+ make && make install && \
+ cd ../../../unimrcp && \
+ ./bootstrap && \
+ ./configure --with-sofia-sip=/usr && \
+ make && make install && \
+ cd ../mod_unimrcp && \
+ export PKG_CONFIG_PATH=/usr/local/freeswitch/lib/pkgconfig:/usr/local/unimrcp/lib/pkgconfig && \
+ ./bootstrap.sh && \
+ ./configure && \
+ make && make install
+
+RUN apt-get clean
+```
diff --git a/docs/src/freeswitch/fail2ban.md b/docs/src/freeswitch/fail2ban.md
new file mode 100644
index 0000000..e56c763
--- /dev/null
+++ b/docs/src/freeswitch/fail2ban.md
@@ -0,0 +1,240 @@
+# 使用fail2ban自动拦截恶意注册
+
+> wandoubaba / 2023-07-10
+
+通常情况下,如果我们的FreeSWITCH应用是面向互联网开放的话,就要对互联网开放SIP端口,那么就避免不了来自一些“不友善”的IP发来的尝试SIP注册的请求,我们往往会在FreeSWITCH的日志中看到类似这下面这样的信息:
+
+```log
+2023-07-10 19:12:35.902557 98.23% [WARNING] sofia_reg.c:3211 Can't find user [8001@192.168.0.112] from 194.61.28.102
+You must define a domain called '192.168.0.112' in your directory and add a user with the id="8001" attribute
+and you must configure your device to use the proper domain in its authentication credentials.
+2023-07-10 19:13:38.522558 98.27% [WARNING] sofia_reg.c:3211 Can't find user [80018001@192.168.0.112] from 194.61.28.102
+You must define a domain called '192.168.0.112' in your directory and add a user with the id="80018001" attribute
+and you must configure your device to use the proper domain in its authentication credentials.
+2023-07-10 19:14:42.342569 98.10% [WARNING] sofia_reg.c:3211 Can't find user [80018001@192.168.0.112] from 194.61.28.102
+You must define a domain called '192.168.0.112' in your directory and add a user with the id="80018001" attribute
+and you must configure your device to use the proper domain in its authentication credentials.
+```
+
+> 自从1.10.7开始,FreeSWITCH的日志中都会在时间戳的后面加上空闲CPU百分比,这里的FreeSWITCH版本是1.10.8。
+
+从上面这些内容我们不难看出,有个主机一直从`194.61.28.102`这个IP在向我们的FreeSWITCH发直SIP注册请求,想要注册分机号`8001`或者`80018001`,去网上查询一下,可以看到这个IP的地理位置位于美国的加里福尼亚洲,笔者可以肯定两点:
+
+1. 我们的业务没有美国的客户。
+2. 我们的SIP账号中没有8001或者80018001这样的账号。
+
+因此我们可以非常肯定,这种注册行为完全是我们所不欢迎的。
+
+通常情况下,我们可以通过将这个IP添加到系统防火墙的黑名单来拒绝来自这种恶意IP的请求,但是完全靠这种手动操作是治标不治本的,因为过不了多久就会有来自其他IP的恶意注册请求出现,靠手动处理完全是禁不绝的。
+
+那么,能不能有一种自动化的工具能够代替人工来做这种自动捕捉和禁止的动作呢?
+
+答案就是:**fail2ban**
+
+## fail2ban简介
+
+fail2ban是一款入侵防御软件,通过监控指定日志文件中的文本行,可以自动捕获到尝试操作失败的事件,进而得到入侵来源地址并自动将地址加入系统防火墙黑名单中,从而实现对系统自动入侵防御的目的。
+
+## 用fail2ban防止FreeSWITCH被恶意注册
+
+本文假设系统中已经正确安装、配置并运行了FreeSWITCH。
+
+### 针对Debian上的FreeSWITCH1.10.8
+
+版本信息
+
+|软件/组件|版本|
+|---|---|
+|操作系统|Debian10.2.1-6(bullseye)|
+|FreeSWITCH|1.10.8|
+|fail2ban|0.11.2|
+
+#### 安装fail2ban
+
+```sh
+sudo apt-get install fail2ban
+```
+
+#### 配置fail2ban
+
+fail2ban默认已经内置了针对多种常见服务的入侵防御配置,但是默认都不是开启的状态,默认情况下fail2ban只是开启了针对`sshd`服务的防御,下面我们就一步一步开始打开针对FreeSWITCH的恶意注册防御。
+
+##### 目录结构
+
+|目录或文件|作用|说明|
+|---|---|---|
+|/etc/fail2ban/fail2ban.conf|fail2ban的主配置文件|一般情况下不需要修改这里|
+|/etc/fail2ban/jail.conf|fail2ban的默认拦截配置文件|官方建议不要修改这个文件|
+|/etc/fail2ban/filter.d/|fail2ban的默认捕获规则目录|这里包含各种服务的规则文件,如果需要修改,建议在这里基于.conf文件创建.local文件|
+|/etc/fail2ban/jail.d/|fail2ban的具体拦截规则目录|在这里创建.local文件来配置拦截规则,如freeswitch.local|
+|/etc/fail2ban/action.d/|fail2ban执行拦截的执行动作配置|一般情况下不需要修改这里的文件|
+
+##### 创建拦截规则
+
+在`/etc/fail2ban/jail.d/`目录下创建名为`freeswitch.local`的文件:
+
+```sh
+touch /etc/fail2ban/jail.d/freeswitch.local
+```
+
+编辑`/etc/fail2ban/jail.d/freeswitch.local`文件
+
+```ini
+[freeswitch]
+enabled = true
+filter = %(known/filter)s[_pref_line='(?: [\d\.]+%%%%)?']
+banaction = ufw
+maxretry = 5
+findtime = 3600
+bantime = 259200
+ignoreip = 127.0.0.1/32
+port = 5060,5061
+logpath = /usr/local/freeswitch/log/freeswitch.log
+```
+
+规则说明:
+
+- `enabled = true` 表示开启这个规则。
+- `filter = %(known/filter)s[_pref_line='(?: [\d\.]+%%%%)?']` 是针对FS版本1.10.7之后版本的日志文件中,在每行时间戳后面会加下空间CPU百分比,加上这行就可以正常识别到事件,如果不加上这行就无法正确识别到事件(参考)。
+- `banaction = ufw` 表示拦截时使用ufw命令,如果不加这句,则默认在拦截时会使用iptables命令(如果系统中使用了ufw来管理防火墙,建议加上这句,否则有可能拦截无效)。
+- `maxretry = 5` 表示相同事件连续发生的次数,这里设置为5表示连续尝试5次就被视为恶意行为
+- `findtime = 3600` 表示监控的周期,配合maxretry使用,这里的配置表示“3600秒内发生5次尝试即被视为恶意行为”。
+- `bantime = 259200` 表示拦截时间,这里设置为259200秒就是72小时,也就是3天
+- `ignoreip = 127.0.0.1/32` 表示不拦截的IP地址。
+- `port = 5060,5061` 是SIP服务的端口号(包括TLS)。
+- `logpath = /usr/local/freeswitch/log/freeswitch.log` 是FreeSWITCH是实时日志文件的绝对路径。
+
+上面这个拦截规则实现的效果就是,在1小时之内,如果来自同一个IP的SIP注册失败次数达到5次,就认为这个IP发起了恶意注册请求,3天内自动拒绝来自这个IP的所有请求。
+
+##### 检查事件匹配规则
+
+```sh
+cat /etc/fail2ban/filter.d/freeswitch.conf
+```
+
+可以看到类似下面的内容
+
+```ini
+# Fail2Ban configuration file
+#
+# Enable "log-auth-failures" on each Sofia profile to monitor
+#
+# -- this requires a high enough loglevel on your logs to save these messages.
+#
+# In the fail2ban jail.local file for this filter set ignoreip to the internal
+# IP addresses on your LAN.
+#
+
+[INCLUDES]
+
+# Read common prefixes. If any customizations available -- read them from
+# common.local
+before = common.conf
+
+[Definition]
+
+_daemon = freeswitch
+
+# Parameter "mode": normal, ddos or extra (default, combines all)
+# Usage example (for jail.local):
+# [freeswitch]
+# mode = normal
+# # or with rewrite filter parameters of jail:
+# [freeswitch-ddos]
+# filter = freeswitch[mode=ddos]
+#
+mode = extra
+
+# Prefix contains common prefix line (server, daemon, etc.) and 2 datetimes if used systemd backend
+_pref_line = ^%(__prefix_line)s(?:(?:\d+-)?\d+-\d+ \d+:\d+:\d+\.\d+)?
+
+prefregex = ^%(_pref_line)s \[WARN(?:ING)?\](?: \[SOFIA\])? \[?sofia_reg\.c:\d+\]? .+$
+
+cmnfailre = ^Can't find user \[[^@]+@[^\]]+\] from $
+
+mdre-normal = %(cmnfailre)s
+ ^SIP auth failure \((REGISTER|INVITE)\) on sofia profile \'[^']+\' for \[[^\]]*\] from ip $
+
+mdre-ddos = ^SIP auth (?:failure|challenge) \((REGISTER|INVITE)\) on sofia profile \'[^']+\' for \[[^\]]*\] from ip $
+
+mdre-extra = %(cmnfailre)s
+
+
+failregex = >
+
+ignoreregex =
+
+datepattern = ^(?:%%Y-)?%%m-%%d[ T]%%H:%%M:%%S(?:\.%%f)?
+ {^LN-BEG}
+
+# Author: Rupa SChomaker, soapee01, Daniel Black, Sergey Brester aka sebres
+# https://freeswitch.org/confluence/display/FREESWITCH/Fail2Ban
+# Thanks to Jim on mailing list of samples and guidance
+#
+# No need to match the following. Its a duplicate of the SIP auth regex.
+# ^\.\d+ \[DEBUG\] sofia\.c:\d+ IP Rejected by acl "\S+"\. Falling back to Digest auth\.$
+```
+
+这是fail2ban官方内容的事件匹配规则,针对本文档所使用各组件版本,这里的规则不需要修改。
+
+##### fail2ban命令
+
+```sh
+## 启动系统服务
+systemctl start fail2ban
+## 重启系统服务(修改配置生效)
+systemctl restart fail2ban
+## 停止系统服务
+systemctl stop fail2ban
+## 用fail2ban-client命令启动服务
+fail2ban-client start
+## 用fail2ban-client命令重载全部配置(修改配置生效)
+fail2ban-client reload
+## 用fail2ban-client命令重载指定监禁配置(把换成具体的名称)
+fail2ban-client reload
+## 用fail2ban-client命令停止服务
+fail2ban-client stop
+## 查看当前保护状态
+fail2ban-client status
+## 查看当前保护的具体服务状态(把换成具体的名称)
+fail2ban-client status
+## 查看版本
+fail2ban-client version
+## 手动监禁一个IP(把换成具体名称,把换成具体IP)
+fail2ban-client set banip
+## 手动将一个IP解除监禁(把换成具体名称,把换成具体IP)
+fail2ban-client set unbanip
+```
+
+##### fail2ban日志
+
+位置 `/var/log/fail2ban.log`
+
+##### 查看拦截是否生效
+
+在本文的示例环境中,使用了`ufw`做为系统防火墙管理工具,所以我们使用ufw命令可以看到拦截是否生效:
+
+```sh
+ufw status
+```
+
+结果可能类似下面:
+
+```sh
+Status: active
+
+To Action From
+-- ------ ----
+Anywhere REJECT 194.61.28.102
+Anywhere REJECT 193.107.216.55
+Anywhere REJECT 193.107.216.29
+Anywhere REJECT 193.107.216.143
+22/tcp ALLOW Anywhere
+80/tcp ALLOW Anywhere
+443/tcp ALLOW Anywhere
+....
+```
+
+上面被REJECT的这几个IP就是被fail2ban监禁的IP。
+
+关于fail2ban的更多玩法可以到fail2ban的官方github上去了解:
\ No newline at end of file
diff --git a/docs/src/freeswitch/index.md b/docs/src/freeswitch/index.md
new file mode 100644
index 0000000..8f1ea78
--- /dev/null
+++ b/docs/src/freeswitch/index.md
@@ -0,0 +1 @@
+# FreeSWITCH相关
diff --git a/docs/src/freeswitch/mod_unimrcp.md b/docs/src/freeswitch/mod_unimrcp.md
new file mode 100644
index 0000000..239b2c4
--- /dev/null
+++ b/docs/src/freeswitch/mod_unimrcp.md
@@ -0,0 +1,74 @@
+# FreeSWITCH安装mod_unimrcp模块
+
+> wandoubaba / 2023-01-18
+
+本文操作过程基于Debian11操作系统。自FreeSWITCH1.10.8开始,mod_unimrcp已经从FreeSWITCH主库分离,成为独立项目,因此不能再用`make mod_unimrcp-install`命令安装模块了。
+
+## 确保FreeSWITCH已经安装成功
+
+安装过程请参见[Debian编译安装FreeSWITCH](debian.html)。
+
+## 安装unimrcp和依赖
+
+下面的操作如果在root账号下,请省略`sudo`前缀。
+
+```sh
+sudo apt-get install wget tar
+wget https://www.unimrcp.org/project/component-view/unimrcp-deps-1-6-0-tar-gz/download -O unimrcp-deps-1.6.0.tar.gz
+tar xvzf unimrcp-deps-1.6.0.tar.gz
+cd unimrcp-deps-1.6.0
+# 安装apr
+cd libs/apr
+./configure --prefix=/usr/local/apr
+make
+sudo make install
+cd ..
+# 安装apr-util
+cd apr-util
+./configure --prefix=/usr/local/apr --with-apr=/usr/local/apr
+make
+sudo make install
+cd ../../..
+# 安装unimrcp
+git clone https://github.com/unispeech/unimrcp.git
+cd unimrcp
+./bootstrap
+./configure --with-sofia-sip=/usr
+make
+sudo make install
+cd ..
+```
+
+## 安装mod_unimrcp
+
+按照下面的程序清单执行完毕后,在FreeSWITCH的安装目录下的mod目录中会出现`mod_unimrcp.so`文件,如`/usr/local/freeswitch/mod/mod_unimrcp.so`。
+
+```sh
+cd /opt
+git clone https://github.com/freeswitch/mod_unimrcp.git
+cd mod_unimrcp
+export PKG_CONFIG_PATH=/usr/local/freeswitch/lib/pkgconfig:/usr/local/unimrcp/lib/pkgconfig
+./bootstrap.sh
+./configure
+make
+sudo make install
+```
+
+如果在执行./bootstrap.sh后遇到`required file './ltmain.sh' not found`错误的话,通过以下方法或许可以解决:
+
+```sh
+libtoolize --version
+libtoolize --automake --copy --debug --force
+```
+
+## 在FreeSWITCH配置中启用mod_unimrcp
+
+编辑配置文件`/usr/local/freeswitch/conf/autoload_configs/modules.conf.xml`,在`configuration->modules`节点下,追加下面一行配置:
+
+```xml
+
+```
+
+如果FreeSWITCH是已启动状态,在fs控制台执行load mod_unimrcp即可加载模块。
+
+此时执行`load mod_unimrcp`后,有可能会看到`mod_unimrcp.c:3893 Could not open unimrcp.conf`之类的报错,那是因为我们还没有对unimrcp模块做具体配置,后面会有专门的文档介绍unimrcp模块的具体使用。
diff --git a/docs/src/freeswitch/ubuntu1604.md b/docs/src/freeswitch/ubuntu1604.md
new file mode 100644
index 0000000..59744af
--- /dev/null
+++ b/docs/src/freeswitch/ubuntu1604.md
@@ -0,0 +1,213 @@
+# Ubuntu16.04安装freeswitch1.6
+
+## 操作系统和软件版本
+
+ubuntu16.04
+
+freeswitch v1.6
+
+python2.7
+
+lua5.1
+
+## 准备工作
+
+### 安装系统
+
+最小安装ubuntu16.04系统,安装ssh server
+
+### 安装依赖
+
+```sh
+sudo apt-get install -y \
+ python-dev swig ffmpeg \
+ yasm unixodbc-dev \
+ libshout3-dev libmpg123-dev \
+ libmp3lame-dev libsndfile-dev \
+ autoconf automake devscripts \
+ libopus-dev libvorbis0a \
+ libogg0 libogg-dev \
+ libvorbis-dev gawk \
+ g++ git-core libjpeg-dev \
+ libncurses5-dev libtool-bin \
+ pkg-config libtiff5-dev \
+ libperl-dev libgdbm-dev \
+ libdb-dev gettext libssl-dev \
+ libcurl4-openssl-dev \
+ libpcre3-dev libspeex-dev \
+ libspeexdsp-dev libsqlite3-dev \
+ libedit-dev libldns-dev \
+ libpq-dev
+```
+
+如果需要开启mod_lua模块,还需要安装lua
+
+```sh
+sudo apt-get install -y lua5.1 liblua5.1-dev
+```
+
+- 安装一些python依赖
+
+安装dbutils可能会失败,是因为python和pip的版本太老了。
+
+这一步不是必须的,只有在你需要用python2为FreeSWITCH写脚本时才会用到。
+
+```sh
+wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
+python get-pip.py
+pip install pydub
+pip install python-ESL
+pip install pika
+pip install dbutils
+```
+
+### 下载源码
+
+```sh
+git clone https://github.com/signalwire/freeswitch.git
+cd freeswitch
+git checkout v1.6
+git remote rm origin
+```
+
+> 最后一句是断开本地目录和远程代码库的关联
+
+## 安装freeswitch
+
+- 配置lua
+
+```bash
+cp /usr/include/lua5.1/*.h src/mod/languages/mod_lua/
+```
+
+```bash
+sudo ln -s /usr/lib/x86_64-linux-gnu/liblua5.1.so /usr/lib/x86_64-linux-gnu/liblua.so
+```
+
+- 预处理
+
+```bash
+sudo ./bootstrap.sh -j
+```
+
+- 预配置模块
+
+```bash
+vim modules.conf
+```
+
+打开注释
+
+```
+formats/mod_shout
+languages/mod_python
+event_handlers/mod_cdr_pg_csv
+asr_tts/mod_unimrcp
+```
+
+如果不需要使用lua语言模块,则将下面内容加注释
+
+```
+#languages/mod_lua
+```
+
+- 编译安装
+
+```bash
+./configure --with-python=/usr/bin/python2.7 --with-lua=/usr/bin/lua5.1 --enable-core-pgsql-support
+sudo make
+sudo make mod_cdr_pg_csv-install
+sudo make mod_unimrcp-install
+sudo make install
+```
+
+- 安装声音包
+
+```bash
+sudo make sounds-install
+sudo make moh-install
+sudo make cd-sounds-install
+sudo make cd-moh-install
+sudo make uhd-sounds-install
+sudo make uhd-moh-install
+```
+
+- 全局命令
+
+```bash
+sudo ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/
+sudo ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
+```
+
+- 配置模块
+
+```bash
+vim /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml
+```
+
+打开注释
+
+```xml
+
+
+```
+
+添加配置
+
+```xml
+
+
+```
+
+- 配置acl白名单
+
+```bash
+vim /usr/local/freeswitch/conf/autoload_configs/acl.conf.xml
+```
+
+根据自己网络的实际情况进行配置(照抄大概率无效)
+
+```xml
+
+
+
+
+
+
+```
+
+- 配置ESL
+
+```bash
+vim /usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml
+```
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## 4. 启动freeswitch
+
+```bash
+freeswitch -nc
+```
+
+通过fs_cli可以进入freeswitch控制台(freeswitch服务启动需要等一段时间,而且可能会很长)
+
+```bash
+fs_cli --password=ClueCon
+```
diff --git a/docs/src/freeswitch/恶意SIP行为IP黑名单.md b/docs/src/freeswitch/恶意SIP行为IP黑名单.md
new file mode 100644
index 0000000..e3dc77c
--- /dev/null
+++ b/docs/src/freeswitch/恶意SIP行为IP黑名单.md
@@ -0,0 +1,90 @@
+# 恶意SIP行为IP黑名单(持续更新)
+
+> 更新时间: 2023年7月4日
+
+```text
+103.145.13.152
+103.145.13.249
+13.64.199.47
+13.71.209.198
+134.119.178.63
+134.119.223.166
+141.94.119.172
+141.98.10.20
+141.98.11.91
+143.244.57.69
+143.244.57.86
+146.0.32.162
+151.106.27.151
+151.106.34.153
+162.244.32.51
+162.244.33.16
+172.107.196.242
+178.239.21.117
+178.239.21.140
+178.239.21.66
+178.239.21.79
+185.159.82.22
+185.167.96.138
+185.209.162.207
+185.209.162.21
+185.246.211.81
+185.53.90.125
+185.53.90.166
+192.99.232.191
+193.107.216.135
+193.107.216.141
+193.107.216.147
+193.107.216.232
+193.107.216.62
+193.46.255.163
+193.46.255.253
+20.106.123.29
+20.106.171.142
+20.206.66.152
+20.213.250.164
+20.216.2.135
+20.227.142.53
+212.83.145.185
+222.79.56.89
+23.148.145.240
+23.148.145.54
+23.148.145.83
+23.148.145.94
+23.254.36.131
+37.19.217.75
+37.221.123.90
+45.134.144.10
+45.134.144.169
+45.134.144.254
+45.134.144.47
+45.134.144.57
+45.134.144.86
+45.159.188.57
+45.93.16.61
+45.95.147.9
+51.103.210.57
+51.12.91.47
+51.132.241.252
+51.142.145.184
+51.142.145.87
+77.247.108.35
+80.94.93.88
+84.247.51.246
+85.114.130.103
+87.119.220.202
+87.119.220.250
+92.118.39.12
+92.118.39.59
+92.204.134.78
+103.145.13.47
+77.247.108.248
+77.247.108.56
+77.247.108.31
+149.7.16.224
+103.145.13.74
+103.145.13.47
+77.247.108.248
+77.247.108.56
+77.247.108.31
+```
diff --git a/docs/src/freeswitch/搭建STUN服务.md b/docs/src/freeswitch/搭建STUN服务.md
new file mode 100644
index 0000000..ee74f3f
--- /dev/null
+++ b/docs/src/freeswitch/搭建STUN服务.md
@@ -0,0 +1,100 @@
+# 搭建STUN服务
+
+---
+
+> 以centos7为例
+
+* github地址:
+
+```
+https://github.com/jselbie/stunserver
+```
+
+* STUNServer官网:
+
+```
+http://www.stunprotocol.org/
+```
+
+## 部署过程(推荐Docker)
+
+> 确保已有docke环境
+
+```bash
+# 下载安装包
+wget http://www.stunprotocol.org/stunserver-1.2.16.tgz
+# 解压
+tar xvf stunserver-1.2.16.tgz
+# 转移目录
+mv stunserver /usr/local/
+cd /usr/local/stunserver
+docker image build -t=stun-server-image .
+docker run -d -p 3478:3478/tcp -p 3478:3478/udp --name=stun-server stun-server-image
+```
+
+## 部署过程(编译安装)
+
+* 如果是centos系统:
+
+```bash
+# 安装依赖
+yum install -y gcc gcc-c++ make boost-devel openssl-devel
+cd /usr/local/src
+```
+
+* 如果是debian系统:
+
+```bash
+apt install -y libboost1.74-all-dev
+cd /usr/src
+```
+
+```bash
+# 下载安装包
+wget http://www.stunprotocol.org/stunserver-1.2.16.tgz
+# 解压
+tar xvf stunserver-1.2.16.tgz
+# 转移目录
+mv stunserver /usr/local/
+cd /usr/local/stunserver
+# 安装
+make
+# 校验
+./stuntestcode
+# 启动服务
+./stunserver &
+```
+
+## 防火墙
+
+```bash
+firewall-cmd --permanent --add-port=3478/udp
+firewall-cmd --reload
+```
+
+## 开机启动stun服务
+
+```bash
+vim /etc/rc.local
+```
+
+在最后添加一行
+
+```bash
+/usr/local/stunserver/stunserver &
+```
+
+对rc.local添加执行权限
+
+```bash
+chmod +x /etc/rc.d/rc.local
+```
+
+## 配置freeswitch
+
+```bash
+cd /usr/local/freeswitch/conf
+vim vars.xml
+```
+
+把stun-set中的服务地址换成刚配置好的stun服务器地址
diff --git a/docs/src/freeswitch/部署百度智能呼叫中心的MRCPServer.md b/docs/src/freeswitch/部署百度智能呼叫中心的MRCPServer.md
new file mode 100644
index 0000000..58142ec
--- /dev/null
+++ b/docs/src/freeswitch/部署百度智能呼叫中心的MRCPServer.md
@@ -0,0 +1,265 @@
+# 部署百度智能呼叫中心的MRCPServer
+
+---
+
+## 官方链接
+
+
+
+## 系统要求
+
+centos7+
+
+## 操作系统 & 必要配置
+
+- 最小安装centos7+系统(比如7.9)
+- 网卡名称配置为eth0
+- 配置服务器IP
+- 安装必要软件
+
+```bash
+yum install -y net-tools telnet git vim wget
+```
+
+## 部署MRCPServer
+
+### 下载sdk
+
+```bash
+curl https://ai.baidu.com/download?sdkId=111 -L -o mrcpserver.tar.gz
+```
+
+### 解压
+
+```bash
+tar zxvf mrcpserver.tar.gz
+```
+
+### 部署配置
+
+- 预处理
+
+```bash
+cd MRCPServer
+./bootstrap.sh
+```
+
+- 配置IP和端口
+
+```bash
+cd mrcp-server
+vim conf/unimrcpserver.xml
+```
+
+定位到`unimrcpserver->properties->ip`节点对绑定IP进行配置,可以有多种配置方式
+
+```xml
+
+183.211.245.48
+
+
+
+eth0
+
+0.0.0.0
+```
+
+定位到`unimrcpserver->components->sip-uas->sip-port`节点,可以配置SIP端口
+
+```xml
+
+5060
+```
+
+定位到`unimrcpserver->components->rtsp-uas->rtsp-port`节点,可以配置RTSP端口
+
+```xml
+
+1554
+```
+
+定位到`unimrcpserver->components->mrcpv2-uas->mrcp-port`节点,可以配置mrcp端口
+
+```xml
+
+1544
+```
+
+定位到`unimrcpserver->components->rtp-factory`节点,可以配置rtp端口范围
+
+```xml
+
+5000
+6000
+```
+
+- 配置asr
+
+```
+vim conf/mrcp-asr.conf
+```
+
+定位到`AUTH_APPID`和`AUTH_APPKEY`,这两个值分别对应百度控制台语音技术应用的AppID和API Key,网址
+
+```
+# AppID(照抄无效)
+AUTH_APPID : 2400000
+# API Key(照抄无效)
+AUTH_APPKEY : "FfMfDOdAdjBqCaLKAmNfqquW"
+```
+
+- 配置tts
+
+```bash
+vim conf/mrcp-proxy.conf
+```
+
+定位到`AUTH_APPID`和`AUTH_APPKEY`,这两个值分别对应百度控制台语音技术应用的AppID和API Key,网址
+
+```
+# AppID(照抄无效)
+AUTH_APPID : 2400000
+# API Key(照抄无效)
+AUTH_APPKEY : "FfMfDOdAdjBqCaLKAmNfqquW"
+```
+
+- 配置启动控制文件
+
+```bash
+vim conf/unimrcpserver_control.conf
+```
+
+定位到`_check_cmd_pro="./bin/check 127.0.0.1 1544"`,把127.0.0.1替换成unimrcpserver.xml配置的ip(如果auto这里就不用换了),把1544替换成在unimrcpserver.xml配置的mrcp-port
+
+## 启动服务
+
+### 以调试模式启动系统
+
+做好配置后,首次启动服务建议以调试模式启动,以便可以在console里看到启动过程。
+
+```bash
+# 根据sdk保存位置不同,你的具体路径不一定跟这里一样
+cd /root/MRCPServer/mrcp-server
+./bin/unimrcpserver -r . &
+```
+
+正常情况下,应该会看到类似下面的输出
+
+```console
+Version: mrcp-asr | v2.0.0 | 20200609-175030 | 0e285e16 | mrcp-asr-ctrip-1.5
+Version: mrcp-tts | v2.0.0 | 20200601-212708 | 24a1c9b1 | dev-liantong.mrcp1.5.0
+```
+
+> 调试模式启动后,如果想要关闭服务,需要用`ps -aux | grep mrcp`查看相关进程的PID,然后用`kill -9 PID`杀掉进程
+
+### 以启护进程方式启动服务
+
+在生产环境时,建使用启动脚本,以守护进程方式启动服务。
+
+执行`${SERVER_ROOT}/mrcp-server/bin/`下的`unimrcpserver_control`并带上控制参数:
+
+```bash
+cd /root/MRCPServer/mrcp-server/bin
+#启动
+./unimrcpserver_control start
+#停止
+./unimrcpserver_control stop
+#重启
+./unimrcpserver_control restart
+```
+
+> restart指令必须在start状态下才可以使用,修改配置文件后需要restart才能生效,但是如果修改的是ip或者端口,restart会出错,这时就只能`ps -aux | grep mrcp`然后再`kill -9 PID`杀掉相关进程后,再发重新start
+
+### 安全设置
+
+MRCPServer对于客户端没有安全校验机制,如果不启用防火墙或者中是单纯的开放端口,结果可能会被任意freeswitch接入,为了避免这种情况发生,应该对MRCPServer开启防火墙并采用指定IP机制,具体操作如下:
+
+```txt
+MRCPServer服务器
+IP:183.211.245.48
+SIP-PORT:8060/udp, 8060/tcp
+RTSP-PORT:1554/tcp
+MRCP-PORT:1544/tcp
+RTP:5000-6000/udp
+
+freeswitch服务器
+IP:112.4.97.6
+```
+
+在MRCP服务端配置防火墙规则如下:
+
+```bash
+# 向112.4.97.6开放sip端口8060/tcp
+firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="112.4.97.6" port protocol="tcp" port="8060" accept'
+# 向112.4.97.6开放sip端口8060/udp
+firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="112.4.97.6" port protocol="udp" port="8060" accept'
+# 向112.4.97.6开放rtsp端口1554/tcp
+firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="112.4.97.6" port protocol="tcp" port="1554" accept'
+# 向112.4.97.6开放mrcp端口1544/tcp
+firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="112.4.97.6" port protocol="tcp" port="1544" accept'
+# 向112.4.97.6开放rtp范围5000-6000/udp
+firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="112.4.97.6" port protocol="udp" port="5000-6000" accept'
+```
+
+### 用sdk中的客户端进行asr测试
+
+#### 在本机测试
+
+- 保证${SERVER_ROOT}/mrcp-server/conf/mrcp-asr.conf文件中的相关配置填写正确
+
+```text
+* AUDIO_CONTROLLER_ADDR,百度上游服务地址(默认值当前有效)
+* AUTH_APPID和AUTH_APPKEY,从百度官网中获取的APPID和API Key的值。
+* NEED_SAVE_AUDIO,是否保存语音识别时用户语音,默认1为保存
+* AUDIO_SPLIT_TIME,是VAD判断的间隔时间(单位毫秒)
+```
+
+- 配置LD_LIBRARY_PATH变量
+
+```bash
+# 注意把${SERVER_ROOT}替换成真实路径
+export LD_LIBRARY_PATH=${SERVER_ROOT}/mrcp-server/lib:$LD_LIBRARY_PATH
+```
+
+- 修改测试程序配置文件
+
+conf/client-profiles/unimrcp.xml 是测试工具的配置文件,需要将其中的unimrcpclient->settings->sip-settings->server-ip的值修改为本机IP,端口设置为主程序端口,如5060。
+
+- 执行测试程序
+
+ - 切换到 ${SERVER_ROOT}/mrcp-server/bin 目录下
+ - 执行 ./asrclient
+ - 待测试程序启动后,在控制台输入 run grammar.xml xeq.pcm
+ - 在控制台会显示识别结果,在log目录下的mrcp_debug.log中也可以看到整个识别过程
+
+> 更多信息可参考
+
+### 用sdk中的客户端进行tts测试
+
+待完善
+
+### 服务开机自启动
+
+待完善
+
+### 配置文件说明
+
+#### vad配置文件conf/vad.conf
+
+```
+sp_threshold : 0.2 # 有效声音的音量阈值(多少以上有效)
+sil_threshold : 0.1 # 被认为无效声音的音量阈值(多少以下无效)
+max_wait_duration : 150 # 最大等待时长
+max_sp_duration : 24000 # 最长说话时间
+max_sp_pause : 150 # 最大说话暂停时长
+head_sil_duration : 18000 # 开头允许的最大静音时长
+start_back_frame : 40
+end_back_frame : 40
+debug_log : 0
+sample_rate : 8000
+cmvnfile : global.cmvn
+dnnfile : vad.dnn
+package_len : 1600
+
+vad_num : 10
+```
diff --git a/docs/src/frontend/index.md b/docs/src/frontend/index.md
new file mode 100644
index 0000000..4484968
--- /dev/null
+++ b/docs/src/frontend/index.md
@@ -0,0 +1 @@
+# 前端相关
diff --git a/docs/src/frontend/npm切换源.md b/docs/src/frontend/npm切换源.md
new file mode 100644
index 0000000..a164739
--- /dev/null
+++ b/docs/src/frontend/npm切换源.md
@@ -0,0 +1,33 @@
+# npm切换源
+
+---
+
+## 查看源来的镜像地址
+
+```bash
+npm get registry
+```
+
+## 设置成淘宝源
+
+```bash
+npm config set registry http://registry.npm.taobao.org
+```
+
+## 设置成初始的源
+
+```bash
+npm config set registry https://registry.npmjs.org/
+```
+
+## 将npm替换成cnpm
+
+```bash
+npm install -g cnpm --registry=https://registry.npm.taobao.org
+```
+
+## 全局安装yarn
+
+```bash
+cnpm install yarn -g
+```
diff --git a/docs/src/frontend/在VuePress项目中添加百度统计代码.md b/docs/src/frontend/在VuePress项目中添加百度统计代码.md
new file mode 100644
index 0000000..57cc90d
--- /dev/null
+++ b/docs/src/frontend/在VuePress项目中添加百度统计代码.md
@@ -0,0 +1,88 @@
+# 在VuePress项目中添加百度统计代码
+
+## 背景
+
+VuePress是Vue驱动的静态网站生成器,如果想知道VuePress生成的网站每天的访问情况而又不想为它开发后台,最好就是引用外部统计脚本,本文选择百度统计平台。
+
+## 获取统计代码
+
+百度统计平台地址:
+
+登录后先创建站点,然后就可以获取统计代码,得到的统计代码示例:
+
+```html
+
+```
+
+同时,在百度统计的代码获取页中还有一段说明,原文如下:
+
+```text
+代码安装说明
+
+1. 请将代码添加到网站全部页面的标签前。
+2. 建议在header.htm类似的页头模板页面中安装,以达到一处安装,全站皆有的效果。
+3. 如需在JS文件中调用统计分析代码,请直接去掉以下代码首尾的,后,放入JS文件中即可。
+
+如果代码安装正确,一般20分钟后,可以查看网站分析数据。
+```
+
+可我们的VuePress项目中生成的html文件都是由Vue编译出来的,实际源代码中都是Markdown文档和js文件,所以我们无法按照百度统计平台中的方法去安装代码。
+
+## 安装代码
+
+具体只需要处理2个文件,分别是`.vuepress/config.js`和`.vuepress/enhanceApp.js`(如果不存在就自己创建)。
+
+### 编辑config.js
+
+```js
+module.exports = {
+ /// ...其他配置项
+ head: [
+ /// ...其他head项
+ // 百度统计代码
+ [
+ "script",
+ {},
+ `var _hmt = _hmt || [];
+ (function() {
+ var hm = document.createElement("script");
+ hm.src = "https://hm.baidu.com/hm.js?1eb7f71a234c2320xxxxxxxxxxxxxxxx";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(hm, s);
+ })();`,
+ ],
+ ],
+ /// ...其他配置项
+};
+```
+
+### 编辑enhanceApp.js
+
+主要是用来让统计代码可以捕捉到Vue的路由变化。
+
+```js
+export default ({ router }) => {
+ // 路由切换事件处理
+ router.beforeEach((to, from, next) => {
+ //触发百度的pv统计
+ if (typeof _hmt != "undefined") {
+ if (to.path) {
+ _hmt.push(["_trackPageview", to.fullPath]);
+ }
+ }
+ next();
+ });
+};
+```
+
+## 安装检查
+
+完成上面操作后,将项目重新编辑打包并发布到服务器上,试着浏览网站,打开`F12`,在`Network`中查看有没有`hm.js`,如果有,就说明统计代码安装成功了,按照百度统计的说法,多等些时候就能看到统计结果了。
diff --git a/docs/src/frontend/在linux中安装node二进制文件.md b/docs/src/frontend/在linux中安装node二进制文件.md
new file mode 100644
index 0000000..89a14a5
--- /dev/null
+++ b/docs/src/frontend/在linux中安装node二进制文件.md
@@ -0,0 +1,42 @@
+## 在linux中安装node二进制文件
+
+### 下载二进制文件
+
+下载网址
+备用中文网址
+
+以18.16.1版本为例
+
+```sh
+wget https://npmmirror.com/mirrors/node/v18.16.1/node-v18.16.1-linux-x64.tar.xz
+```
+
+### 安装
+
+先创建安装目录并解压文件
+
+```sh
+sudo mkdir -p /usr/local/lib/nodejs
+tar xJvf node-v18.16.1-linux-x64.tar.xz -C /usr/local/lib/nodejs
+```
+
+再将node执行目录写入/etc/profile,在`export PATH`的上一行添加:
+
+```
+PATH=/usr/local/lib/nodejs/node-v18.16.1-linux-x64/bin:$PATH
+```
+
+重新加载profile
+
+```sh
+source /etc/profile
+```
+
+安装完成!
+
+查看版本
+
+```sh
+node -v
+npm -v
+```
diff --git a/docs/src/frontend/在vscode里配置vetur符合eslint.md b/docs/src/frontend/在vscode里配置vetur符合eslint.md
new file mode 100644
index 0000000..d16dfec
--- /dev/null
+++ b/docs/src/frontend/在vscode里配置vetur符合eslint.md
@@ -0,0 +1,59 @@
+# 在vscode里配置vetur符合eslint
+
+## 默认格式化程序
+
+| 配置项 | 值 |
+|---|---|
+|vetur.format.defaultFormatter.html|prettier|
+|vetur.format.defaultFormatter.js|vscode-typescript|
+|vetur.format.defaultFormatter.css|prettier|
+|vetur.format.defaultFormatter.less|prettier|
+|vetur.format.defaultFormatter.scss|prettier|
+|vetur.format.defaultFormatter.postcss|prettier|
+|vetur.format.defaultFormatter.sass|sass-formatter|
+
+## js函数名与括号之间添加一个空格
+
+| 配置项 | 值 |
+|---|---|
+|javascript.format.insertSpaceBeforeFunctionParenthesis|true|
+
+> 这个选项只在`vetur.format.defaultFormatter.js`值为`vscode-typescript`时有效。
+
+## 配置缩进
+
+| 配置项 | 值 | 说明 |
+|---|---|---|
+|vetur.format.scriptInitialIndent|false|<script>内代码初始缩进为0|
+|vetur.format.styleInitialIndent|false|<style>内代码初始缩进为0|
+|vetur.format.options.tabSize|2|代码缩进单位为2个空格|
+|vetur.format.options.useTabs|false|使用空格代替tab|
+
+## js中的字符串使用单引号而不是双引号
+
+只要`vetur.format.defaultFormatter.js`值为`vscode-typescript`就已经可以了。
+
+| 配置项 | 值 |
+|---|---|
+|vetur.format.defaultFormatter.js|vscode-typescript|
+
+## 取消行尾分号(如果有分号会在格式时自动删除)
+
+| 配置项 | 值 |
+|---|---|
+|javascript.format.semicolons|remove|
+
+> 这个不是只针对vue的,而是对所有js生效。
+
+## 避免脚本中因使用别名被报错
+
+| 配置项 | 值 |
+|---|---|
+|vetur.validation.script|false|
+
+## 避免其他过于严格的报错(可选)
+
+| 配置项 | 值 |
+|---|---|
+|vetur.validation.style|false|
+|vetur.validation.template|false|
diff --git a/docs/src/frontend/解决create-vue创建的项目运行后提示Network: use --host to expose的问题.md b/docs/src/frontend/解决create-vue创建的项目运行后提示Network: use --host to expose的问题.md
new file mode 100644
index 0000000..6fe8226
--- /dev/null
+++ b/docs/src/frontend/解决create-vue创建的项目运行后提示Network: use --host to expose的问题.md
@@ -0,0 +1,18 @@
+## 解决create-vue创建的项目运行后提示Network: use --host to expose的问题
+
+### 修改vite.config.js文件
+
+```js
+import vue from '@vitejs/plugin-vue'
+
+/**
+ * https://vitejs.dev/config/
+ * @type {import('vite').UserConfig}
+ */
+export default {
+ plugins: [vue()],
+ server: {
+ host: '0.0.0.0' // 新增内容
+ }
+}
+```
diff --git a/docs/src/git/常用git命令.md b/docs/src/git/常用git命令.md
new file mode 100644
index 0000000..e000d49
--- /dev/null
+++ b/docs/src/git/常用git命令.md
@@ -0,0 +1,98 @@
+# 常用git命令
+
+> git官方中文文档 中包含更多的信息
+
+---
+
+## 从远程克隆一个仓库
+
+```bash
+# 通过SSH连接克隆一个仓库(可能需要事先配置SSH公钥)
+# 执行成功后会在当前路径创建一个名为fsdoc的目录,进入目录后即可以用git命令操作仓库了
+git clone git@gitee.com:wandoubaba517/fsdoc.git
+# 通过HTTP连接克隆一个仓库(有时可能会需要用户名和密码)
+# 执行成功后会在当前路径创建一个名为callapp_mrcp的目录
+git clone https://gitee.com/polaris-arvin_admin/callapp_mrcp.git
+```
+
+> 除了`git clone`命令外,其他git命令都需要在仓库目录下进行操作
+
+## 分支操作
+
+> 别忘了在仓库目录下操作
+
+```bash
+# 查看所有分支(本地和远程)
+git branch -a
+# 切换分支
+git checkout develop
+# 创建一个名为iss053的分支同时切换到这个新分支
+git checkout -b iss053
+# 在iss053分支提交修改
+git commit -a -m "添加一些git分支操作"
+# 将iss053分支的变更合并到master分支
+git checkout master
+git merge iss053
+# 合并后可以删iss053分支
+git branch -d iss053
+# 如果合并时发现冲突,需要手动处理一下
+# 刷新远端分支列表
+git remote update origin -p
+# 在没有使用git add之前放弃当前全部操作
+git checkout .
+# 在使用了git add后但还没有git commit之前放弃当前全部操作
+git reset HEAD .
+git checkout .
+# 在使用了git commit后回滚操作
+git reset --hard HEAD^ # 回滚到上一次commit状态
+git reset --hard # 回滚到指定的任意一次提交
+# 查看commitid
+git log # 退出请按q键
+```
+
+## 代码推拉
+
+> 别忘了在仓库目录下操作
+
+```bash
+# 从远程分支拉取代码到本地
+git pull # 会提取默认关联的远程分支
+
+# 添加本次要跟踪的代码(全部)
+git add .
+# 提交变更(在本地)
+git commit -m "本次提交说明内容"
+
+# 把变更推送到远程服务器
+git push # 推送到默认关联的远程分支
+git push origin # 有些时候当关联有问题时,可能需要手写origin
+git push origin bob # 可以指定目标远程分支
+```
+
+## 给本地的一个文件夹添加git管理并关联远程仓库
+
+```bash
+# 在这个文件夹内执行
+git init
+# 给本地的一个git文件夹关联一个远程服务器
+git remote add origin git@gitee.com:wandoubaba517/ps.git
+# 对目录内所有文件建立跟踪
+git add .
+# 提交本次跟踪
+git commit -m "这次提交的说明"
+# 推送当前分支并建立与远程上游的跟踪
+git push --set-upstream origin master
+# 把本地当前分支与远端指定分支关联(关联后在本地这个分支下直接git pull和git push就行了,不需要再加origin)
+git branch --set-upstream-to=origin/
+```
+
+## 在一个本地目录上添加多个远程仓库
+
+```bash
+# 关联另一个远程仓库
+git remote set-url --add origin git@gitee.com:wandoubaba517/personal.git
+# 推送当前分支并建立与远程上游的跟踪
+git push --set-upstream origin master
+# 以后再推送时直接push就行了
+git push
+```
diff --git a/docs/src/git/生成sshkey.md b/docs/src/git/生成sshkey.md
new file mode 100644
index 0000000..aa96af3
--- /dev/null
+++ b/docs/src/git/生成sshkey.md
@@ -0,0 +1,90 @@
+# 各操作系统生成sshkey的方法
+
+---
+
+---
+
+## Windows 10
+
+> 其他版本系统类似
+
+### 1. 先得安装git
+
+> 如果电脑里已经有git bash就跳过这一步
+
+- 上git官网 `https://git-scm.com/` 去下载最新版,注意对应操作系统。
+- 安装git,按照向导操作,明白选项意思的就根据自己实际情况配置,不明白的就留下默认值。
+
+### 2. 检查系统内是否已经有sshkey文件
+
+```cmd
+cd ~/.ssh
+dir
+```
+
+> 如果~/.ssh目录下已经存有id_rsa和id_rsa.pub文件的话,那就不需要执行 `3` 了
+
+### 3. (在git bash中)创建sshkey
+
+先打开git bash(是git带的命令行工具)
+
+```bash
+ssh-keygen -t rsa -C "yourname@yourpc"
+```
+
+> 一路回车(如果希望以后操作git每次push时都输入密码的话,那这里可以设置一个密码)
+
+以上操作完成后,默认会在~/.ssh/目录下生成名为id_rsa和id_rsa.pub的文件。
+
+### 4. 给自己的公钥文件起一个个性化的名字
+
+> 还是在git bash中操作
+
+```bash
+cd ~/.ssh
+cp id_rsa.pub yourname_yourpc.pub
+```
+
+### 5. 完成
+
+在需要用到sshkey的地方(比如git服务器)把你的pub文件部署上去就可以了。
+
+---
+
+## MAC
+
+### 1. 先检查系统内是否已经有sshkey文件
+
+```bash
+cd ~/.ssh
+ls
+```
+
+> 如果~/.ssh目录下已经存有id_rsa和id_rsa.pub文件的话,那就不需要执行 `2` 了
+
+### 2. 创建sshkey
+
+```bash
+ssh-keygen -t rsa -C "yourname@yourpc"
+```
+
+> 一路回车(如果希望以后操作git每次push时都输入密码的话,那这里可以设置一个密码)
+
+以上操作完成后,默认会在~/.ssh/目录下生成名为id_rsa和id_rsa.pub的文件。
+
+### 3. 给自己的公钥文件起一个个性化的名字
+
+```bash
+cd ~/.ssh
+cp id_rsa.pub yourname_yourpc.pub
+```
+
+### 4. 完成
+
+在需要用到sshkey的地方(比如git服务器)把你的pub文件部署上去就可以了。
+
+---
+
+## linux
+
+> linux下的操作方式与mac非常非常类似。
diff --git a/docs/src/go/index.md b/docs/src/go/index.md
new file mode 100644
index 0000000..81f0371
--- /dev/null
+++ b/docs/src/go/index.md
@@ -0,0 +1 @@
+# go相关
diff --git a/docs/src/go/install.md b/docs/src/go/install.md
new file mode 100644
index 0000000..7952c41
--- /dev/null
+++ b/docs/src/go/install.md
@@ -0,0 +1,92 @@
+# 安装Go环境
+
+> wandoubaba / 2024-08-29
+
+截止本文发布时,go的最新版本是`1.23.0`。
+
+## linux
+
+### 下载
+
+```sh
+wget https://go.dev/dl/go1.23.0.linux-amd64.tar.gz
+```
+
+### 删除旧版本
+
+```sh
+ rm -rf /usr/local/go && tar -C /usr/local -xzf go1.23.0.linux-amd64.tar.gz
+```
+
+### 解压安装
+
+```sh
+tar zxvf go1.23.0.linux-amd64.tar.gz -C /usr/local/
+```
+
+修改环境变量
+
+```sh
+touch /etc/profile.d/go.sh
+vim /etc/profile.d/go.sh
+```
+
+文件内容如下,然后保存退出
+
+```sh
+export PATH=$PATH:/usr/local/go/bin
+```
+
+使环境变量立即生效
+
+```sh
+source /etc/profile.d/go.sh
+```
+
+### 验证安装
+
+```sh
+go version
+```
+
+结果应该是
+
+```txt
+go version go1.23.0 linux/amd64
+```
+
+## mac
+
+### 下载
+
+Intel平台
+
+```sh
+wget https://go.dev/dl/go1.23.0.darwin-amd64.pkg
+```
+
+Arm平台
+
+```sh
+wget https://go.dev/dl/go1.23.0.darwin-arm64.pkg
+```
+
+### 安装
+
+直接在Finder中执行pkg文件,或者在终端中用命令
+
+```sh
+sudo installer -pkg go1.23.0.darwin-amd64.pkg -target /usr/local/
+```
+
+### 验证安装
+
+```sh
+go version
+```
+
+结果应该是
+
+```txt
+go version go1.23.0 linux/amd64
+```
\ No newline at end of file
diff --git a/docs/src/go/proxy.md b/docs/src/go/proxy.md
new file mode 100644
index 0000000..7cb3db1
--- /dev/null
+++ b/docs/src/go/proxy.md
@@ -0,0 +1,13 @@
+# 解决`go mod tidy`加载模块超时的问题
+
+## 查看go环境相关信息
+
+```sh
+go env
+```
+
+## 修改`GOPROXY`配置
+
+```sh
+go env -w GOPROXY=https://goproxy.cn
+```
diff --git a/docs/src/index.md b/docs/src/index.md
new file mode 100644
index 0000000..5be8a8f
--- /dev/null
+++ b/docs/src/index.md
@@ -0,0 +1,28 @@
+---
+# https://vitepress.dev/reference/default-theme-home-page
+layout: home
+
+hero:
+ name: "个人技术收藏"
+ text: "wandoubaba的经验"
+ tagline: 关于PHP、GoLang、Vue、Git、Docker、MQ、FreeSWITCH……
+ image:
+ src: /wandoubaba.png
+ alt: cover pic
+ actions:
+ - theme: brand
+ text: 打开资料
+ link: /start
+
+features:
+ - title: PHP
+ details: 号称“世界上最好的语言”,又有人说它“已经没落”,不管怎样,用它确实能做很多事情。
+ - title: Docker
+ details: 真是一种很有用的技术,至少它打破了“环境死一半”的魔咒。
+ - title: GoLang
+ details: 被认为是“Google版的C++”,也被认为是“PHP的完美补充”,用它可以实现一些PHP做不到的特性。
+ - title: FreeSWITCH
+ details: 与PHP没什么关系,是一个电话的软交换解决方案,做音视频实时通信项目时大概率会用到它。
+
+---
+
diff --git a/docs/src/kubernetes/index.md b/docs/src/kubernetes/index.md
new file mode 100644
index 0000000..b53b992
--- /dev/null
+++ b/docs/src/kubernetes/index.md
@@ -0,0 +1 @@
+# kubernetes(k8s)相关内容
\ No newline at end of file
diff --git a/docs/src/kubernetes/install.md b/docs/src/kubernetes/install.md
new file mode 100644
index 0000000..04f09a6
--- /dev/null
+++ b/docs/src/kubernetes/install.md
@@ -0,0 +1,605 @@
+# K8s安装过程(Debian12+Kubernetes1.28+Containerd+Calico用apt-get在线搭建1master+2node的K8s集群)
+
+> wandoubaba / 2024-10-21
+
+截止本文发布时,kubernetes最新版本是`v1.31`,而补丁已经全部打完的最新稳定版本是`v1.28`,本文基于后者。
+
+## 安装准备
+
+### 资源准备
+
+|准备项|内容|
+|---|---|
+|操作系统|Debian 12(bookworm)|
+|系统内核|6.1.0-23-amd64|
+|容器运行时|containerd CRI|
+
+### 主机清单
+
+|IP(假设)|主机名|CPU|内存|
+|---|---|---|---|
+|172.31.0.11|k8s-master01|8c|8G|
+|172.31.0.14|k8s-master04|8c|16G|
+|172.31.0.15|k8s-master05|8c|16G|
+
+## 过程
+
+### 确认主机基本信息(每台主机)
+
+```sh
+# 查看IP地址,确认设置为静态地址
+ip addr | awk '/inet /{split($2, ip, "/"); print ip[1]}'
+# 查看MAC地址,确保每台主机的MAC唯一
+ip link | awk '/state UP/ {getline; print $2}'
+# 查看主机的UUID,确保product_uuid的唯一性
+sudo cat /sys/class/dmi/id/product_uuid
+# 查看内核版本
+uname -r
+# 查看操作系统发行版本信息
+cat /etc/os-release
+# 确认cpu核心数量
+lscpu -p | grep -v "^#" | wc -l
+# 确认内存容量
+free -h | awk '/Mem/{print $2}'
+# 确认磁盘空间
+lsblk
+```
+
+### 设置主机名并更新/etc/hosts文件(每台主机)
+
+#### 设置主机名
+
+```sh
+# 在主控制节点(k8s-master01)上执行
+sudo hostnamectl set-hostname k8s-master01
+# 在工作节点(k8s-node01、k8s-node02)上执行
+sudo hostnamectl set-hostname k8s-node01
+sudo hostnamectl set-hostname k8s-node02
+```
+
+主机名设置成功后可以`exit`退出终端再重新连接,或者直接执行`bash`,都可以看到修改后的效果
+
+#### 修改/etc/hosts文件
+
+要根据自己的真实IP进行修改
+
+```sh
+sudo bash -c 'cat <> /etc/hosts
+172.31.0.11 k8s-master01
+172.31.0.14 k8s-node01
+172.31.0.15 k8s-node02
+EOF'
+```
+
+### 设置时区并安装时间服务(每台主机)
+
+```sh
+sudo timedatectl set-timezone Asia/Shanghai
+sudo apt-get update && sudo apt-get install -y chrony
+```
+
+#### 配置阿里云时间服务器(可选)
+
+```
+pool ntp1.aliyun.com iburst maxsources 4
+```
+
+提示:在/etc/chrony/chrony.conf中加入上述配置,将其他pool开头的配置注释掉;
+
+重启chrony,并验证
+
+```sh
+sudo systemctl restart chrony
+sudo systemctl status chrony
+sudo chronyc sources
+```
+
+### 禁用swap(每台主机)
+
+```sh
+sudo swapoff -a
+```
+
+还要在`/etc/fstab`文件中注释关于swapr挂载的行。
+
+### 禁用防火墙(每台主机)
+
+```sh
+sudo ufw disable
+sudo apt-get remove ufw
+```
+
+### 优化内核参数
+
+```sh
+sudo bash -c 'cat > /etc/sysctl.d/kubernetes.conf < /etc/modules-load.d/kubernetes.conf << EOF
+# /etc/modules-load.d/kubernetes.conf
+
+# Linux 网桥支持
+br_netfilter
+
+# IPVS 加载均衡器
+ip_vs
+ip_vs_rr
+ip_vs_wrr
+ip_vs_sh
+
+# IPv4 连接跟踪
+nf_conntrack_ipv4
+
+# IP 表规则
+ip_tables
+EOF'
+
+# 添加可执行权限
+sudo chmod a+x /etc/modules-load.d/kubernetes.conf
+```
+
+### 关闭安全策略服务(每台主机)
+
+```sh
+# 停止 AppArmor 服务
+sudo systemctl stop apparmor.service
+
+# 禁用 AppArmor 服务
+sudo systemctl disable apparmor.service
+```
+
+### 关闭防火墙(每台主机)
+
+```sh
+# 禁用ufw
+sudo ufw disable
+sudo systemctl stop ufw.service
+sudo systemctl disable ufw.service
+```
+
+### 安装容器运行时(每台主机)
+
+#### 下载
+
+在查看最新版本,然后选择对应的`cri-containerd-x.x.x-linux-platform`文件下载:
+
+```sh
+curl -L -O https://github.com/containerd/containerd/releases/download/v1.7.23/cri-containerd-1.7.23-linux-amd64.tar.gz
+```
+
+#### 安装
+
+```sh
+sudo tar xf cri-containerd-1.7.23-linux-amd64.tar.gz -C /
+```
+
+#### 配置
+
+```sh
+sudo mkdir /etc/containerd
+sudo bash -c 'containerd config default > /etc/containerd/config.toml'
+sudo sed -i '/sandbox_image/s/3.8/3.9/' /etc/containerd/config.toml
+sudo sed -i '/SystemdCgroup/s/false/true/' /etc/containerd/config.toml
+```
+
+#### 启动
+
+```sh
+# 启用并立即启动containerd服务
+sudo systemctl enable --now containerd.service
+# 检查containerd服务的当前状态
+sudo systemctl status containerd.service
+```
+
+#### 验证
+
+```sh
+# 检查containerd的版本
+containerd --version
+# 与CRI(Container Runtime Interface)兼容的容器运行时交互的命令行工具
+crictl --version
+# 运行符合 OCI(Open Container Initiative)标准的容器
+sudo runc --version
+```
+
+### 安装docker(每个主机,在k8s中可选,仅用于构建镜像)
+
+```sh
+# Add Docker's official GPG key:
+sudo apt-get update
+sudo apt-get install -y ca-certificates curl
+sudo install -m 0755 -d /etc/apt/keyrings
+sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
+sudo chmod a+r /etc/apt/keyrings/docker.asc
+
+# Add the repository to Apt sources:
+echo \
+ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
+ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
+ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
+sudo apt-get update
+sudo apt-get install -y docker-ce docker-ce-cli docker-buildx-plugin docker-compose-plugin
+```
+
+### 安装k8s组件(每个主机)
+
+指的是安装`kubelet`、`kubeadm`、`kubectl`
+
+```sh
+sudo apt-get update
+# apt-transport-https may be a dummy package; if so, you can skip that package
+
+sudo apt-get install -y apt-transport-https ca-certificates curl gpg
+# If the directory `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below.
+
+# sudo mkdir -p -m 755 /etc/apt/keyrings
+curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
+
+# This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list
+echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
+
+sudo apt-get update
+sudo apt-get install -y kubelet kubeadm kubectl
+sudo apt-mark hold kubelet kubeadm kubectl
+sudo systemctl enable --now kubelet
+```
+
+#### 配置kubelet
+
+```sh
+sudo bash -c 'cat > /etc/default/kubelet << EOF
+# 该参数指定了 kubelet 使用 systemd 作为容器运行时的 cgroup 驱动程序
+KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
+EOF'
+# 这里先设置kubelet为开机自启
+sudo systemctl enable kubelet
+```
+
+### 初始化master01主机
+
+#### 查看k82镜像(可选)
+
+```sh
+sudo kubeadm config images list
+```
+
+应该能列出以下信息:
+
+```sh
+registry.k8s.io/kube-apiserver:v1.31.1
+registry.k8s.io/kube-controller-manager:v1.31.1
+registry.k8s.io/kube-scheduler:v1.31.1
+registry.k8s.io/kube-proxy:v1.31.1
+registry.k8s.io/coredns/coredns:v1.11.3
+registry.k8s.io/pause:3.10
+registry.k8s.io/etcd:3.5.15-0
+```
+
+> 如果看到类似`remote version is much newer: v1.31.1; falling back to: stable-1.28`的提示说版本低,忽略它就行了。
+
+> k8s的镜像默认是谷歌仓库地址,需要代理才可以正常访问;如果你没有代理,请使用阿里云仓库也是可以的;用--image-repository="registry.aliyuncs.com/google_containers"来指定使用阿里云镜像仓库中的镜像部署k8s集群。
+
+#### 下载镜像(可选)
+
+```sh
+sudo kubeadm config images pull
+```
+
+#### 创建k8s集群
+
+##### 初始化master01节点
+
+- 要把下面的`--apiserver-advertise-address`参数换成实际的`k8s-master01`主机IP地址.
+- `--pod-network-cidr`参数指的是本k8s集群中要让pod使用的网段。
+
+```sh
+sudo kubeadm init --control-plane-endpoint=k8s-master01 --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=172.31.0.11 --cri-socket unix:///run/containerd/containerd.sock
+```
+
+如果执行顺利的话,应该会看到下面的信息(每次的具体参数应该不同)
+
+```sh
+Your Kubernetes control-plane has initialized successfully!
+
+To start using your cluster, you need to run the following as a regular user:
+
+ mkdir -p $HOME/.kube
+ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
+ sudo chown $(id -u):$(id -g) $HOME/.kube/config
+
+Alternatively, if you are the root user, you can run:
+
+ export KUBECONFIG=/etc/kubernetes/admin.conf
+
+You should now deploy a pod network to the cluster.
+Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
+ https://kubernetes.io/docs/concepts/cluster-administration/addons/
+
+You can now join any number of control-plane nodes by copying certificate authorities
+and service account keys on each node and then running the following as root:
+
+ kubeadm join k8s-master01:6443 --token 1ahq7i.sv3pqgcss8v5oecj \
+ --discovery-token-ca-cert-hash sha256:8bea18bff8c86d0bc23214974d6b2045c90760448cd4731c94546a9ae836e9ca \
+ --control-plane
+
+Then you can join any number of worker nodes by running the following on each as root:
+
+kubeadm join k8s-master01:6443 --token 1ahq7i.sv3pqgcss8v5oecj \
+ --discovery-token-ca-cert-hash sha256:8bea18bff8c86d0bc23214974d6b2045c90760448cd4731c94546a9ae836e9ca
+```
+
+接下来我们就先配置一下kubectl的配置文件
+
+```sh
+mkdir -p $HOME/.kube
+sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
+sudo chown $(id -u):$(id -g) $HOME/.kube/config
+```
+
+接下来可以查看节点状态:
+
+```sh
+kubectl get nodes -o wide
+```
+
+应该能看到类似下面的结果:
+
+```sh
+# 查看节点状态
+kubectl get nodes -o wide
+# 结果类似
+NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
+k8s-master01 NotReady control-plane 25m v1.28.14 172.31.0.11 Debian GNU/Linux 12 (bookworm) 6.1.0-23-cloud-amd64 containerd://1.7.23
+# 查看集群信息
+kubectl cluster-info
+# 结果类似
+Kubernetes control plane is running at https://k8s-master01:6443
+CoreDNS is running at https://k8s-master01:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
+
+To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
+# 列出所有CRI容器列表
+sudo crictl ps -a
+# 结果类似(其中STATE一列应该都是Running)
+CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
+6177ae20a68e6 6a89d0ef825cb 29 minutes ago Running kube-proxy 0 e8d15cb2bcd1a kube-proxy-jlndc
+a1a43a29df5c2 6cbf215f8d44e 30 minutes ago Running kube-scheduler 1 3163922b00a0e kube-scheduler-k8s-master01
+19dfb26520340 7abec2d806048 30 minutes ago Running kube-controller-manager 1 f6df8f333fcf0 kube-controller-manager-k8s-master01
+b4c7a5f9c967f 3438637c2f3ae 30 minutes ago Running kube-apiserver 0 b05316fac4cad kube-apiserver-k8s-master01
+8a4c587d9b8d9 2e96e5913fc06 30 minutes ago Running etcd 0 9a8c10ea30b80 etcd-k8s-master01
+```
+
+### 添加worker节点(把k8s-node01和k8s-node02添加到集群)
+
+先在`k8s-master01`上得到添加节点命令(添加`k8s-node01`和`k8s-node02`之前分别是在`k8s-master01`上执行一次)
+
+```sh
+sudo kubeadm token create --print-join-command
+# 结果与下面的类似(每一次的token应该都是不一样的),把下面的结果复制下来,准备到worker节点上去执行
+kubeadm join k8s-master01:6443 --token epvxya.fh4qmay5uwc8628a --discovery-token-ca-cert-hash sha256:8bea18bff8c86d0bc23214974d6b2045c90760448cd4731c94546a9ae836e9ca
+```
+
+下面的操作主要在`k8s-node01`和`k8s-node02`上分别执行
+
+```sh
+# 安装nmap用于在worker节点上验证master节点上的api-server服务端口的连通性
+sudo apt-get install nmap -y
+# 把下面的ip地址换成实际master节点主机ip
+nmap -p 6443 -Pn 10.31.0.11
+# 结果
+Starting Nmap 7.93 ( https://nmap.org ) at 2024-10-21 18:50 CST
+Nmap scan report for k8s-master01 (172.31.0.11)
+Host is up (0.00081s latency).
+
+PORT STATE SERVICE
+6443/tcp open sun-sr-https
+
+Nmap done: 1 IP address (1 host up) scanned in 0.03 seconds
+# 把刚才在master节得得到的join命令粘贴过来执行(建议用非root用户,在前面加上sudo)
+sudo kubeadm join k8s-master01:6443 --token epvxya.fh4qmay5uwc8628a --discovery-token-ca-cert-hash sha256:8bea18bff8c86d0bc23214974d6b2045c90760448cd4731c94546a9ae836e9ca
+# 结果类似下面
+This node has joined the cluster:
+* Certificate signing request was sent to apiserver and a response was received.
+* The Kubelet was informed of the new secure connection details.
+
+Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
+```
+
+再到`k8s-master01`上验证一下
+
+```sh
+kubectl get nodes
+# 结果类似
+NAME STATUS ROLES AGE VERSION
+k8s-master01 NotReady control-plane 41m v1.28.14
+k8s-node01 NotReady 2m6s v1.28.14
+```
+
+然后在master节点上再执行一次`sudo kubeadm token create --print-join-command`,在`k8s-node02`上重复上面的过程。
+
+最后在`k8s-master01`上查看节点信息
+
+```sh
+kubectl get nodes
+# 结果类似下面
+NAME STATUS ROLES AGE VERSION
+k8s-master01 NotReady control-plane 43m v1.28.14
+k8s-node01 NotReady 4m26s v1.28.14
+k8s-node02 NotReady 40s v1.28.14
+# 查看k8s的pod信息
+kubectl get pods -n kube-system
+# 结果类似
+NAME READY STATUS RESTARTS AGE
+coredns-5dd5756b68-4btx5 0/1 Pending 0 45m
+coredns-5dd5756b68-8v2z8 0/1 Pending 0 45m
+etcd-k8s-master01 1/1 Running 0 45m
+kube-apiserver-k8s-master01 1/1 Running 0 45m
+kube-controller-manager-k8s-master01 1/1 Running 1 45m
+kube-proxy-5tqw2 1/1 Running 0 6m33s
+kube-proxy-864zg 1/1 Running 0 2m47s
+kube-proxy-jlndc 1/1 Running 0 45m
+kube-scheduler-k8s-master01 1/1 Running 1 45m
+```
+
+注意到每一个node的`STATUS`列都是`NotReady`,这是因为还没有安装配置网络插件,pod间的通信有问题。
+
+### 安装calico网络插件(master节点)
+
+参考文档
+
+#### 安装Tigera Calico operator
+
+```sh
+kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.2/manifests/tigera-operator.yaml
+# 结果类似下面
+serviceaccount/tigera-operator created
+clusterrole.rbac.authorization.k8s.io/tigera-operator created
+clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
+deployment.apps/tigera-operator created
+# 查看集群命名空间
+kubectl get ns
+# 结果类似下面
+NAME STATUS AGE
+default Active 63m
+kube-node-lease Active 63m
+kube-public Active 63m
+kube-system Active 63m
+tigera-operator Active 13s
+# 查看tigera-operator下的pod
+kubectl get pods -n tigera-operator
+# 结果
+NAME READY STATUS RESTARTS AGE
+tigera-operator-5cfff76b77-tdswm 1/1 Running 0 3m46s
+```
+
+#### 安装Calico
+
+```sh
+curl -L -O https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/custom-resources.yaml
+# 修改ip池,需与初始化时一致
+sed -i 's/192.168.0.0/10.244.0.0/' custom-resources.yaml
+# 安装calico
+kubectl create -f custom-resources.yaml
+# 结果
+installation.operator.tigera.io/default created
+apiserver.operator.tigera.io/default created
+```
+
+再执行`watch`命令等到所有pod的`STATUS`都变成`Running`
+
+```sh
+watch kubectl get pods -n calico-system
+# 结果
+Every 2.0s: kubectl get pods -n calico-system k8s-master01: Mon Oct 21 19:22:54 2024
+
+NAME READY STATUS RESTARTS AGE
+calico-kube-controllers-5846f6d55d-87n88 1/1 Running 0 85s
+calico-node-4mhxj 1/1 Running 0 85s
+calico-node-6c64k 1/1 Running 0 85s
+calico-node-sbzwz 1/1 Running 0 85s
+calico-typha-6c76968df6-lcjm6 1/1 Running 0 84s
+calico-typha-6c76968df6-xbnk5 1/1 Running 0 85s
+csi-node-driver-2vrg7 2/2 Running 0 85s
+csi-node-driver-gmb7m 2/2 Running 0 85s
+csi-node-driver-mnqvx 2/2 Running 0 85s
+```
+
+确认pod运行状态直到所有的pod状态都是`Running`
+
+```sh
+watch kubectl get pods -n calico-system
+# 结果类似
+Every 2.0s: kubectl get pods -n calico-system k8s-master01: Mon Oct 21 19:23:47 2024
+
+NAME READY STATUS RESTARTS AGE
+calico-kube-controllers-5846f6d55d-87n88 1/1 Running 0 2m18s
+calico-node-4mhxj 1/1 Running 0 2m18s
+calico-node-6c64k 1/1 Running 0 2m18s
+calico-node-sbzwz 1/1 Running 0 2m18s
+calico-typha-6c76968df6-lcjm6 1/1 Running 0 2m17s
+calico-typha-6c76968df6-xbnk5 1/1 Running 0 2m18s
+csi-node-driver-2vrg7 2/2 Running 0 2m18s
+csi-node-driver-gmb7m 2/2 Running 0 2m18s
+csi-node-driver-mnqvx 2/2 Running 0 2m18s
+```
+
+用`ctrl+c`退出`watch`状态,再查看k8s系统的pod状态
+
+```sh
+kubectl get pods -n kube-system -o wide
+# 结果类似
+NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
+coredns-5dd5756b68-4btx5 1/1 Running 0 72m 10.244.58.196 k8s-node02
+coredns-5dd5756b68-8v2z8 1/1 Running 0 72m 10.244.58.193 k8s-node02
+etcd-k8s-master01 1/1 Running 0 72m 172.31.0.11 k8s-master01
+kube-apiserver-k8s-master01 1/1 Running 0 72m 172.31.0.11 k8s-master01
+kube-controller-manager-k8s-master01 1/1 Running 1 72m 172.31.0.11 k8s-master01
+kube-proxy-5tqw2 1/1 Running 0 33m 172.31.0.14 k8s-node01
+kube-proxy-864zg 1/1 Running 0 29m 172.31.0.15 k8s-node02
+kube-proxy-jlndc 1/1 Running 0 72m 172.31.0.11 k8s-master01
+kube-scheduler-k8s-master01 1/1 Running 1 72m 172.31.0.11 k8s-master01
+```
+
+清理taints(污点)
+
+```sh
+kubectl taint nodes --all node-role.kubernetes.io/control-plane-
+```
+
+再次确认集群节点
+
+```sh
+kubectl get nodes -o wide
+# 结果类似
+NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
+k8s-master01 Ready control-plane 75m v1.28.14 172.31.0.11 Debian GNU/Linux 12 (bookworm) 6.1.0-23-cloud-amd64 containerd://1.7.23
+k8s-node01 Ready 35m v1.28.14 172.31.0.14 Debian GNU/Linux 12 (bookworm) 6.1.0-23-cloud-amd64 containerd://1.7.23
+k8s-node02 Ready 32m v1.28.14 172.31.0.15 Debian GNU/Linux 12 (bookworm) 6.1.0-23-cloud-amd64 containerd://1.7.23
+```
diff --git a/docs/src/linux/centos7防火墙.md b/docs/src/linux/centos7防火墙.md
new file mode 100644
index 0000000..e50793c
--- /dev/null
+++ b/docs/src/linux/centos7防火墙.md
@@ -0,0 +1,84 @@
+# centos7防火墙操作
+
+---
+
+centos7默认使用firewall作为防火墙(iptables仍然有效)。
+
+## 查看防火墙服务状态
+
+```bash
+firewall-cmd --state
+```
+
+## 启动、关闭、状态
+
+```bash
+# 查看状态
+systemctl status firewalld
+# 启动
+systemctl start firewalld
+# 停止
+systemctl stop firewalld
+# 重启
+systemctl restart firewalld
+# 禁卡开机启动
+systemctl disable firewalld
+# 开机启动
+systemctl enable firewalld
+```
+
+## 端口操作
+
+```bash
+# 查看已经打开的端口
+firewall-cmd --list-ports
+# 查看当前所有配置(包括端口、服务等所有)
+firewall-cmd --list-all
+# 查看firewall所有可识别的服务
+firewall-cmd --get-service
+# 查看端口是否开通(如果开的是服务,直接查端口有可能会是no)
+firewall-cmd --query-port=22/tcp
+# 查看服务是否开通
+firewall-cmd --query-service=ssh
+# 开放某个端口(permanent是永久生效)
+firewall-cmd --permanent --add-port=80/tcp
+# 开放某段端口范围
+firewall-cmd --permanent --add-port=5000-6000/tcp
+# 关闭某个端口
+firewall-cmd --permanent --remove-port=80/tcp
+# 开放某个服务(的默认端口)
+firewall-cmd --permanent --add-service=http
+# 关闭某个服务(的默认端口)
+firewall-cmd --permanent --remove-service=http
+# 对指定IP开放(相当于白名单)
+firewall-cmd --permanent --add-source=192.168.1.100
+# 对指定IP段开放(相当于白名单)
+firewall-cmd --permanent --add-source=192.168.1.0/24
+# 移除某IP
+firewall-cmd --permanent --remove-source=192.168.1.100
+```
+
+## 复杂操作
+
+```bash
+# 允许指定IP访问本机指定端口
+firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="80" accept'
+# 允许指定IP段访问本机端口范围
+firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="8080-8090" accept'
+# 禁止指定IP访问本机指定端口
+firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="80" reject'
+# 屏蔽某个IP的所有请求
+firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=103.145.13.92 reject'
+```
+
+## 配置生效
+
+任何操作执行完成后,都需要重新装载或重启服务以使其生效:
+
+```bash
+firewall-cmd --reload
+# 或
+service firewalld restart
+# 或
+systemctl restart firewalld
+```
diff --git a/docs/src/linux/docker操作.md b/docs/src/linux/docker操作.md
new file mode 100644
index 0000000..5a6c261
--- /dev/null
+++ b/docs/src/linux/docker操作.md
@@ -0,0 +1,31 @@
+# docker操作
+
+---
+
+## docker容器设置开机自启动
+
+> 前提是docker服务先被设置成开机自启
+
+- 新建容器时配置自启参数
+
+```bash
+docker run --restart=always <容器id> 或 <容器名称>
+```
+
+- 已经存在的容器配置自启
+
+```bash
+docker update --restart=always <容器id> 或 <容器名称>
+```
+
+- 取消容器自启
+
+```bash
+docker update --restart=no <容器id> 或 <容器名称>
+```
+
+- 批量设置所有容器自启
+
+```bash
+docker update --restart=always $(docker ps -aq)
+```
diff --git a/docs/src/linux/linux常用命令.md b/docs/src/linux/linux常用命令.md
new file mode 100644
index 0000000..a2309c7
--- /dev/null
+++ b/docs/src/linux/linux常用命令.md
@@ -0,0 +1,60 @@
+# linux常用命令和操作技巧
+
+---
+
+## 查看linux发行版本
+
+- centos
+
+```bash
+rpm -q centos-release
+```
+
+结果大概如下:
+
+centos-release-7-9.2009.1.el7.centos.x86_64
+
+- ubuntu
+
+```bash
+lsb_release -a
+```
+
+## 查看本机的公网IP
+
+```bash
+curl cip.cc
+```
+
+## 用curl下载文件(不需要单独安装wget)
+
+```bash
+curl http://domain/path -L -O
+```
+
+将会在path的最后一段作为文件名来保存文件
+
+```bash
+curl http://domain/path -L -o filename
+```
+
+将会以filename为文件名保存文件
+
+## centos系统临时切换成英文/中文
+
+```bash
+export LANG=en_US.UTF-8
+```
+
+```bash
+export LANG=zh_CN.UTF-8
+```
+
+## ll按时间或大小排序
+
+```bash
+# 按时间降序(最新的在最后)
+ll -rt
+# 按大小降序(最小的在最后)
+ll -Sh
+```
diff --git a/docs/src/linux/linux改网卡名.md b/docs/src/linux/linux改网卡名.md
new file mode 100644
index 0000000..59076f8
--- /dev/null
+++ b/docs/src/linux/linux改网卡名.md
@@ -0,0 +1,138 @@
+# 在ubuntu系统里把网卡名称改为eth0
+
+---
+
+## 在ubuntu16.04系统
+
+> 非root用户需要在命令前加sudo
+
+### 1. 修改grub文件
+
+```bash
+vim /etc/default/grub
+```
+
+原文
+
+```
+GRUB_CMDLINE_LINUX=""
+```
+
+改为
+
+```
+GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
+```
+
+保存退出
+
+### 2. grub生效
+
+```bash
+grub-mkconfig -o /boot/grub/grub.cfg
+```
+
+### 3. 改网络配置
+
+> 适用于ubuntu16.04,其他版本不一定有效
+
+```bash
+vim /etc/network/interfaces
+```
+
+原文(类似)
+
+```txt
+auto ens160
+
+iface ens160 inet static
+```
+
+改为
+
+```txt
+auto eth0
+
+iface eth0 inet static
+```
+
+### 4. 网卡开机自启(大部分情况可省略)
+
+```bash
+systemctl enable networking.service
+```
+
+### 5. 重启
+
+```bash
+reboot
+```
+
+或
+
+```bash
+init 6
+```
+
+### 6. 查看网络信息
+
+```bash
+ip addr
+```
+
+---
+
+## 在centos7系统
+
+### 1. 先确定当前网卡名
+
+```bash
+ip addr
+```
+
+### 2. 改网卡配置文件
+
+> 原网卡名称有可能不一样
+
+```bash
+vim /etc/sysconfig/network-scripts/ifcfg-ens192
+```
+
+把`DEVICE=ens192`改为`DEVICE=eth0`
+
+把`NAME=ens192`改为`NAME=eth0`
+
+保存退出
+
+再把网卡配置文件的文件名改了
+
+```bash
+cd /etc/sysconfig/network-scripts
+mv ifcfg-ens192 ifcfg-eth0
+```
+
+### 3. 修改grub
+
+```bash
+vim /etc/default/grub
+```
+
+往`GRUB_COMLINE_LINUX`里面加上`net.ifnames=0 biosdevname=0`
+
+保存退出
+
+执行命令
+
+```bash
+grub2-mkconfig -o /boot/grub2/grub.cfg
+```
+
+### 4. 重启系统并校验效果
+
+```bash
+init 6
+```
+
+```bash
+ip a
+```
diff --git a/docs/src/linux/ssh免密码连接服务器.md b/docs/src/linux/ssh免密码连接服务器.md
new file mode 100644
index 0000000..8d67265
--- /dev/null
+++ b/docs/src/linux/ssh免密码连接服务器.md
@@ -0,0 +1,40 @@
+# SSH免密码连接服务器
+
+> 前提:服务器已经部署了你的私钥对应的公钥文件
+---
+
+## 使用默认密钥文件连接服务器
+
+```bash
+ssh username@server
+```
+
+例:
+
+```bash
+ssh root@192.168.0.8
+```
+
+> 使用`~/.ssh/id_rsa`文件以root身份登录192.168.0.8主机
+
+## 使用指定密钥文件连接服务
+
+```bash
+ssh -i keyfile username@server
+```
+
+例:
+
+```bash
+ssh -i ~/.ssh/bob root@192.168.0.8
+```
+
+> 使用`~/.ssh/bob`私钥文件以root身份登录192.168.0.8主机
+
+## 指定密钥文件并且服务器ssh端口不是默认的22
+
+```bash
+ssh -i ~/.ssh/bob root@192.168.0.8 -p 22222
+```
+
+> 服务器把ssh端口设置成22222,需要凭`~/.ssh/bob`文件登录
diff --git a/docs/src/linux/ssh客户端保持连接.md b/docs/src/linux/ssh客户端保持连接.md
new file mode 100644
index 0000000..abe836c
--- /dev/null
+++ b/docs/src/linux/ssh客户端保持连接.md
@@ -0,0 +1,12 @@
+# SSH客户端保持连接的方法
+
+---
+
+在客户端电脑的`~/.ssh/config`文件开头做如下配置:
+
+```
+Host *
+ ServerAliveInterval 30
+```
+
+> 表示每隔30秒自动向服务端发送一个no-op包
diff --git a/docs/src/linux/tmux操作.md b/docs/src/linux/tmux操作.md
new file mode 100644
index 0000000..5f82236
--- /dev/null
+++ b/docs/src/linux/tmux操作.md
@@ -0,0 +1,33 @@
+# tmux操作
+
+```bash
+ctrl+b s 退出 tmux 到列表
+```
+
+```bash
+ctrl+b d 退出到root
+```
+
+```bash
+tmux ls 查看所有窗口
+```
+
+```bash
+tmux kill-window -t 2 杀掉编号为2的窗口
+```
+
+```bash
+tumx a 上一次进入的窗口
+```
+
+```bash
+tmux new -s py 新建窗口
+```
+
+```bash
+cd /usr/local/freeswitch/scripts/call_outivr python listen_event_process.py 启动esl监听程序
+```
+
+```bash
+cd /usr/local/freeswitch ./freeswitch 启动freeswitch 如果发现已经启动 则退出到root界面杀掉进程pid
+```
diff --git a/docs/src/linux/ubuntu配置nfs服务.md b/docs/src/linux/ubuntu配置nfs服务.md
new file mode 100644
index 0000000..242b84b
--- /dev/null
+++ b/docs/src/linux/ubuntu配置nfs服务.md
@@ -0,0 +1,114 @@
+# ubuntu系统配置NFS服务端及客户端
+
+## 配置nfs服务端与客户端
+
+> nfs的作用是实现各主机间的共享存储空间,`切记不要在公网环境中使用nfs!!!`
+
+### 1. NFS服务端安装与配置
+
+- 安装nfs服务,需要先安装:
+
+```shell
+ sudo apt install nfs-kernel-server nfs-common
+```
+
+- 配置nfs共享目录:
+
+```bash
+ vim /etc/exports
+```
+
+- 添加如下两行:
+
+```ini
+/storage 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash,fsid=0)
+/storage 127.0.0.1/24(rw,sync,no_subtree_check,no_root_squash,fsid=0)
+```
+
+> 其中`/storage`为需要共享的路径,`Tab`键后的ip地址是允许访问的网段(根据实际情况修改),括号内则是一些权限(不建议改动)。
+
+- 重启nfs服务并刷新共享配置:
+
+```bash
+ /etc/init.d/nfs-kernel-server restart
+ exportfs -rv
+```
+
+### 2. NFS服务端的端口处理
+
+> NFS服务是基于RPC协议的服务,通过`rpcinfo -p`命令会发现除了`111`和`2049`端口外,其`mountd`和`nlockmgr`以及`status`对应的端口是随机分配的,这样几乎无法搞防火墙和端口映射了,为了不让服务器裸奔,需要对nfs-kernel-server主机做一些配置以固定其端口。
+
+- 修改`/etc/default/nfs-common`文件,配置`status`服务端口为`40001`:
+
+```ini
+ STATDOPTS="--port 40001"
+```
+
+- 修改`/etc/default/nfs-kernel-server`文件,配置`mountd`服务端口为`40002`:
+
+```ini
+ RPCMOUNTDOPTS="--manage-gids -p 40002"
+```
+
+- 创建`/etc/modprobe.d/options.conf`文件,添加如下内容,配置`nlockmgr`端口为`40003`:
+
+```ini
+ options lockd nlm_udpport=40003 nlm_tcpport=40003
+```
+
+- 在`/etc/modules`文件中添加`lockd`:
+
+```ini
+# /etc/modules: kernel modules to load at boot time.
+#
+# This file contains the names of kernel modules that should be loaded
+# at boot time, one per line. Lines beginning with "#" are ignored.
+lockd
+```
+
+- 重启服务器(`reboot`),然后再运行`rpcinfo -p localhost`,就会看到,各种端口都已经被固定了。
+
+### 3. NFS客户端安装与配置
+
+- 安装nfs客户端(以ubuntu为例):
+
+```shell
+ sudo apt install nfs-common -y
+```
+
+- 确保客户端与服务端的网络连接正常,在客户端主机上执行以下操作:
+
+```shell
+ showmount -e 192.168.1.68
+```
+
+> 正常情况下会命令执行后会返回服务器开放出来的共享目录路径,包含类似`/storage 192.168.1.0/24`的信息。
+
+- 打开`/etc/fstab`文件:
+
+```shell
+ vim /etc/fstab
+```
+
+- 在文件末尾所加行(`tab`键间隔)后保存并退出编辑器:
+
+```ini
+192.168.1.68:/storage /storage nfs defaults 0 0
+```
+
+> 其中第1段IP为本机IP地址,第2段为要挂载到`/storage`目录,后面几段原样照抄。
+> 如果在nfs服务端本机内配置,可将ip地址改为127.0.0.1。
+
+- 创建挂载点目录:
+
+```shell
+ mkdir /storage
+```
+
+> 完成以上操作后,就会在系统启动时自动将服务器的/storage目录挂载到本机的/storage目录。
+
+- 以下命令可实现一次性的手动挂载(如果未在fstab中配置的话,重启服务器将失效):
+
+```shell
+ sudo mount -t nfs -o nolock 192.168.1.68:/storage /storage
+```
diff --git a/docs/src/linux/ubuntu配静态IP.md b/docs/src/linux/ubuntu配静态IP.md
new file mode 100644
index 0000000..2a23115
--- /dev/null
+++ b/docs/src/linux/ubuntu配静态IP.md
@@ -0,0 +1,30 @@
+# 为ubuntu系统配置静态ip地址
+
+---
+
+> 如果使用非root用户,需要在命令前加sudo
+
+## ubuntu 16.04
+
+```bash
+vim /etc/network/interfaces
+```
+
+只修改eth0部分(或者是别的网卡名)
+
+```
+auto eth0
+iface eth0 inet static
+ address 183.211.245.49
+ netmask 255.255.255.128
+ broadcast 183.211.245.127
+ gateway 183.211.245.1
+ dns-nameservers 221.131.143.69
+```
+
+如果想用dhcp自动获取ip的话,照下面改
+
+```
+auto eth0
+iface eth0 inet dhcp
+```
diff --git a/docs/src/linux/vim操作.md b/docs/src/linux/vim操作.md
new file mode 100644
index 0000000..cdf2fdb
--- /dev/null
+++ b/docs/src/linux/vim操作.md
@@ -0,0 +1,40 @@
+# vim快捷操作
+
+---
+
+## 定义tab键为4个空格
+
+```bash
+# ubuntu
+vim /etc/vim/vimrc
+# centos
+vim /etc/vimrc
+```
+
+在最后添加如下配置
+
+```text
+set ts=4
+set sw=4
+set expandtab
+```
+
+## 查找替换
+
+把每一行中的所有fromstring替换为tostring
+
+```txt
+:%s/fromstring/tostring/g
+```
+
+把每一行中的第一个fromstring替换为tostring
+
+```txt
+:%s/fromstring/tostring
+```
+
+## 粘贴时缩进错乱
+
+```txt
+:set paste
+```
diff --git a/docs/src/linux/删除.user.ini文件.md b/docs/src/linux/删除.user.ini文件.md
new file mode 100644
index 0000000..6657680
--- /dev/null
+++ b/docs/src/linux/删除.user.ini文件.md
@@ -0,0 +1,12 @@
+# 删除.user.ini文件
+
+用宝塔创建站点后在站点根目录会有.user.ini文件等一系列的默认文件,其他文件都可以正常被删除,只有这个.user.ini文件无法用`rm -rf .user.ini`命令删除,原因是它被锁定了,需要先解锁再删除。
+
+```sh
+# 解除 user.ini 文件锁定
+chattr -i .user.ini
+# 删除 .user.ini 文件
+rm -rf .user.ini
+```
+
+可以了。
diff --git a/docs/src/linux/删除某时间前的文件或文件夹.md b/docs/src/linux/删除某时间前的文件或文件夹.md
new file mode 100644
index 0000000..c1d2f13
--- /dev/null
+++ b/docs/src/linux/删除某时间前的文件或文件夹.md
@@ -0,0 +1,19 @@
+# 删除某时间前的文件或文件夹(比如录音文件)
+
+## 命令示例
+
+```bash
+find /usr/local/freeswitch/log/freeswitch.log.*.1 -mtime +5 -exec rm -rf {} \;
+```
+
+解读:
+
+删除5天前的freeswitch日志
+
+```bash
+find /usr/local/freeswitch/recordings/ -type d -mtime +10 -exec rm -rf {} \;
+```
+
+解读:
+
+删除10天前的freeswitch录音
diff --git a/docs/src/linux/阿里云centos磁盘扩容.md b/docs/src/linux/阿里云centos磁盘扩容.md
new file mode 100644
index 0000000..6ef6bb6
--- /dev/null
+++ b/docs/src/linux/阿里云centos磁盘扩容.md
@@ -0,0 +1,47 @@
+# 阿里云CentOS7磁盘扩容
+
+## 场景
+
+在阿里云控制台对主机云盘成功完成磁盘扩容操作。
+
+## centos系统内操作
+
+查看磁盘和分区
+
+```bash
+fdisk -l
+```
+
+结果有可能会看到有一个名为/dev/vda的磁盘,同时有一个名为/dev/vda1的分区,而且/dev/vda的磁盘容量已经是扩容后的容量了。
+
+查看分区大小
+
+```bash
+df -h
+```
+
+结果可以看到分区大小还是扩容前的大小。
+
+为分区扩容
+
+```bash
+growpart /dev/vda 1
+```
+
+语法
+
+```sh
+growpart [DeviceName] [PartionNumber]
+```
+
+扩容文件系统
+
+```bash
+resize2fs /dev/vda1
+```
+
+语法
+
+```sh
+resize2fs [PartitionName]
+```
diff --git a/docs/src/lua/luasocket示例.md b/docs/src/lua/luasocket示例.md
new file mode 100644
index 0000000..4152272
--- /dev/null
+++ b/docs/src/lua/luasocket示例.md
@@ -0,0 +1 @@
+## luasocket示例
diff --git a/docs/src/ops/acme.md b/docs/src/ops/acme.md
new file mode 100644
index 0000000..9d469df
--- /dev/null
+++ b/docs/src/ops/acme.md
@@ -0,0 +1,209 @@
+# 用acme.sh实现ssl证书部署及自动续签
+
+> wandoubaba / 2024-11-04
+
+## 介绍
+
+`acme.sh`是一个实现了 `acme` 协议的客户端工作,使用它可以申请`Let's Encrpypt`、`TrustAsia`等机构的免费SSL证书并可以实现自动部署与自动续签。
+
+项目地址:
+
+本文主要介绍如何使用 `acme.sh` 为域名申请免费的90天证书,并实现Nginx自动部署和自动续签。
+
+> 本文的操作环境是 Debian 11/12 系统,域名从腾讯云注册(DNSPod提供解析)。
+
+## 安装acme.sh客户端
+
+使用发下命令安装,email可以换成自己的:
+
+```sh
+curl https://get.acme.sh | sh -s email=my@example.com
+```
+
+如果上面的命令安装失败,可以换下面这种方式:
+
+```sh
+git clone https://gitee.com/neilpang/acme.sh.git
+cd acme.sh
+./acme.sh --install -m my@example.com
+. ~/.bashrc
+```
+
+整个安装过程只会把工具安装到`~/.acme.sh/`目录下,只是在`~/.bashrc`中添加了一句`. "/root/.acme.sh/acme.sh.env"`,看一眼`acme.sh.env`内容,是这样的:
+
+```sh
+cat /root/.acme.sh/acme.sh.env
+# 结果
+export LE_WORKING_DIR="/root/.acme.sh"
+alias acme.sh="/root/.acme.sh/acme.sh"
+```
+
+建议再安装个`socat`(它本身功能也十分强大,是linux网络运维的瑞士军刀),可以用于以`standalone mode`申请证书时临时“伪装”一个服务器出来。
+
+```sh
+apt-get install socat
+```
+
+## 确认证书申请方式
+
+在`acme.sh`的官方文档中可以看到分发证书的方式有很多种,比如文件验证、独立模式、手动DNS、自动DNS等等,我们为了实现全自动化和未来的自动续签,所以我们选择“自动DNS解析方式”。
+
+我的域名注册商是腾讯云,解析服务由DNSPod提供,幸运的是`acme.sh`支持DNSPod平台的API密钥,所以我先到DNSPod平台上去创建一组密钥:
+
+- 登录网址:
+- 登录控制台
+- 我的账号 - API密钥
+- 切换到`DNSPod Token`(不要用腾讯云API密钥)
+- 记录`ID`和`Token`(页面关闭后就再也看不见了)
+
+执行下面命令:
+
+```sh
+export DP_Id=
+export DP_Key=
+```
+
+## 申请证书
+
+```sh
+acme.sh --issue --dns dns_dp -d example.com
+```
+
+如果执行成功,最后可以看到类似下面的结果,说明已经将证书文件安装到了本地:
+
+```sh
+[Mon Nov 4 01:12:52 PM CST 2024] Your cert is in: /root/.acme.sh/example.com/example.com.cer
+[Mon Nov 4 01:12:52 PM CST 2024] Your cert key is in: /root/.acme.sh/example.com/example.com.key
+[Mon Nov 4 01:12:52 PM CST 2024] The intermediate CA cert is in: /root/.acme.sh/example.com/ca.cer
+[Mon Nov 4 01:12:52 PM CST 2024] And the full chain certs is there: /root/.acme.sh/example.com/fullchain.cer
+[Mon Nov 4 01:12:52 PM CST 2024] _on_issue_success
+```
+
+## 部署证书
+
+下面分别是在apache上和在nginx上部署证书的示例,需要替换的内容是`example.com`和相`关文件的绝对路径`,以及服务`重新加载配置的命令`。
+
+### Apache示例:
+
+```sh
+acme.sh --install-cert -d example.com \
+--cert-file /path/to/certfile/in/apache/cert.pem \
+--key-file /path/to/keyfile/in/apache/key.pem \
+--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
+--reloadcmd "service apache2 force-reload"
+```
+
+### Nginx示例:
+
+```sh
+acme.sh --install-cert -d example.com \
+--key-file /path/to/keyfile/in/nginx/key.pem \
+--fullchain-file /path/to/fullchain/nginx/cert.pem \
+--reloadcmd "service nginx force-reload"
+```
+
+### 修改配置文件
+
+acme.sh只会重新部署证书文件,不会去更改任何其他配置文件(为了安全考虑),所以,要让web服务器应用证书,还需要手动去修改相关的配置文件。
+
+我们以nginx为例,提供一个web站点加载ssl证书并提供https服务(开443端口)的示例:
+
+```nginx
+server {
+ listen 80;
+ listen [::]:80;
+ server_name localhost;
+
+ # ssl
+ listen 443 ssl;
+ server_name localhost;
+
+ ssl_certificate /etc/nginx/certs/cert.pem; # 证书文件路径
+ ssl_certificate_key /etc/nginx/certs/key.pem; # 私钥文件路径
+
+ ssl_session_cache shared:SSL:1m;
+ ssl_session_timeout 10m;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+ ssl_prefer_server_ciphers on;
+
+
+
+ #access_log /var/log/nginx/host.access.log main;
+
+ location / {
+ root /usr/share/nginx/html;
+ index index.html index.htm;
+ }
+
+ error_page 404 /404.html;
+ location = /404.html {
+ root /usr/share/nginx/html;
+ }
+
+ # redirect server error pages to the static page /50x.html
+ #
+ error_page 500 502 503 504 /50x.html;
+ location = /50x.html {
+ root /usr/share/nginx/html;
+ }
+}
+```
+
+如果我们希望所有的http请求(80)都可以自动转到https(443)上,可以对上面的配置文件做一些修改:
+
+```nginx
+server {
+ listen 80;
+ listen [::]:80;
+ server_name localhost;
+
+ # 重定向所有 HTTP 请求到 HTTPS
+ return 301 https://$host$request_uri;
+}
+
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name localhost;
+
+ ssl_certificate /etc/nginx/certs/cert.pem; # 证书文件路径
+ ssl_certificate_key /etc/nginx/certs/key.pem; # 私钥文件路径
+
+ ssl_session_cache shared:SSL:1m;
+ ssl_session_timeout 10m;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+ ssl_prefer_server_ciphers on;
+
+ #access_log /var/log/nginx/host.access.log main;
+
+ location / {
+ root /usr/share/nginx/html;
+ index index.html index.htm;
+ }
+
+ error_page 404 /404.html;
+ location = /404.html {
+ root /usr/share/nginx/html;
+ }
+
+ # redirect server error pages to the static page /50x.html
+ error_page 500 502 503 504 /50x.html;
+ location = /50x.html {
+ root /usr/share/nginx/html;
+ }
+}
+```
+
+修改完配置文件后,再要重新启动服务或者重新加载一下配置,才会生效。
+
+## 验证自动续签机制
+
+```sh
+crontab -l
+```
+
+如果看到有下面这样的定时任务,说明acme.sh的自动续签机制是生效的
+
+```sh
+43 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
+```
diff --git a/docs/src/ops/index.md b/docs/src/ops/index.md
new file mode 100644
index 0000000..6277452
--- /dev/null
+++ b/docs/src/ops/index.md
@@ -0,0 +1,3 @@
+# 其他技术资料
+
+一些不便分类又有必要记录的内容
\ No newline at end of file
diff --git a/docs/src/ops/nginx.md b/docs/src/ops/nginx.md
new file mode 100644
index 0000000..e06482f
--- /dev/null
+++ b/docs/src/ops/nginx.md
@@ -0,0 +1,154 @@
+# 编译安装nginx
+
+> wandoubaba / 2023-07-21
+
+## 系统环境
+
+以Debian11为例
+
+## 下载源码
+
+以1.24.0版本为例,下载nginx:
+
+```sh
+wget https://nginx.org/download/nginx-1.24.0.tar.gz
+```
+
+如果提示`wget: command not found`就先安装wget,执行`sudo apt-get install wget`就行。
+
+解压:
+
+```sh
+tar zxvf nginx-1.24.0.tar.gz
+```
+
+## 安装依赖
+
+```sh
+sudo apt-get install libgd-dev build-essential zlib1g-dev libpcre3-dev libssl-dev lsb-release
+```
+
+## 创建www用户和组
+
+查看www用户是否存在
+
+```sh
+id www
+```
+
+创建www分组和www用户,并且不允许登录系统
+
+```sh
+groupadd www
+useradd -g www -s /sbin/nologin www
+```
+
+再查看www用户
+
+```sh
+id www
+```
+
+## 编译安装
+
+```sh
+cd nginx-1.24.0
+```
+
+带参数执行编译
+
+```sh
+./configure --user=www --group=www \
+ --with-http_ssl_module \
+ --with-http_v2_module \
+ --with-http_realip_module \
+ --with-http_image_filter_module \
+ --with-http_addition_module \
+ --with-http_stub_status_module \
+ --with-stream \
+ --with-stream_ssl_module \
+ --with-stream_ssl_preread_module \
+ --with-http_gzip_static_module \
+ --with-http_gunzip_module \
+ --with-http_sub_module \
+ --with-http_flv_module \
+ --with-http_mp4_module \
+ --with-http_dav_module \
+ --with-openssl-opt=-g \
+ --with-pcre-opt=-g \
+ --with-pcre
+```
+
+安装:
+
+```sh
+make
+sudo make install
+```
+
+经过以上步骤,nginx已经被安装到`/usr/local/nginx`目录下,程序文件位于`/usr/local/nginx/sbin/nginx`。
+
+## 启动服务
+
+可以先把nginx程序路径写到系统环境中(可以把这条命令加到`~/.bashrc`文件中)
+
+```sh
+export PATH=/usr/local/nginx/sbin/:$PATH
+```
+
+执行直接执行`nginx`即可启动服务。
+
+在浏览器访问`http://ip`(把IP换成你的nginx主机地址),如果防火墙和安全组都放行了80端口,我们现在应该能看到`Welcome to nginx`页面了。
+
+用下面的命令可以控制服务的启停:
+
+```sh
+## 重启服务
+nginx -s reopen
+## 停止服务
+nginx -s stop
+nginx -s quit
+## 重载配置
+nginx -s reload
+```
+
+## 注册系统服务
+
+注意:操作系统不同,下面的方法可能不一样。
+
+创建`/etc/systemd/system/nginx.service`文件:
+
+```ini
+[Unit]
+Description=Nginx Service
+After=syslog.target network.target
+
+[Service]
+Type=forking
+PIDFile=/usr/local/nginx/logs/nginx.pid
+ExecStartPre=/usr/local/nginx/sbin/nginx -t
+ExecStart=/usr/local/nginx/sbin/nginx
+ExecReload=/usr/local/nginx/sbin/nginx -s reload
+ExecStop=/usr/local/nginx/sbin/nginx -s stop
+PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
+```
+
+执行下面的命令使服务生效并实现随系统启动:
+
+```sh
+sudo systemctl daemon-reload
+sudo systemctl enable nginx
+```
+
+用下面的命令控制服务:
+
+```sh
+sudo systemctl start nginx
+sudo systemctl restart nginx
+sudo systemctl stop nginx
+sudo systemctl reload nginx
+sudo systemctl status nginx
+```
diff --git a/docs/src/ops/node.md b/docs/src/ops/node.md
new file mode 100644
index 0000000..565d86a
--- /dev/null
+++ b/docs/src/ops/node.md
@@ -0,0 +1,101 @@
+# Linux安装node二进制
+
+> wandoubaba / 2024-08-29
+
+## 下载
+
+在 中可以下载到需要的版本和对应平台的安装包。本文写作时的最新版本是`v22.7.0`。
+
+```sh
+wget https://nodejs.org/download/release/v22.7.0/node-v22.7.0-linux-x64.tar.xz
+```
+
+## 解压安装
+
+```sh
+tar xvf node-v22.7.0-linux-x64.tar.xz
+mv node-v22.7.0-linux-x64 /usr/local/node
+ln -s /usr/local/node/bin/node /usr/local/bin/node
+ln -s /usr/local/node/bin/npm /usr/local/bin/npm
+```
+
+验证安装
+
+```sh
+node --version
+npm --version
+```
+
+## 配置npm源
+
+淘宝镜像
+
+```sh
+ npm config set registry https://registry.npmmirror.com
+```
+
+阿里云
+
+```sh
+npm config set registry https://npm.aliyun.com
+```
+
+腾讯云
+
+```sh
+npm config set registry http://mirrors.cloud.tencent.com/npm/
+```
+
+华为云
+
+```sh
+npm config set registry https://mirrors.huaweicloud.com/repository/npm/
+```
+
+官方
+
+```sh
+npm config set registry https://registry.npmjs.org/
+```
+
+## 安装yarn
+
+Yarn 是一个由 Facebook 贡献的 Javascript 包管理器
+
+```sh
+npm install -g yarn
+ln -s /usr/local/node/bin/yarn /usr/local/bin/yarn
+```
+
+验证安装
+
+```sh
+yarn --version
+```
+## 安装nrm
+
+nrm 是一个 npm 源管理器,允许你快速地在 npm 源间切换。
+
+```sh
+npm install -g nrm
+ln -s /usr/local/node/bin/nrm /usr/local/bin/nrm
+```
+
+查看可选的源
+
+```sh
+nrm ls
+```
+
+使用taobao源
+
+```sh
+nrm use taobao
+```
+
+测试速度
+
+```sh
+nrm test
+```
+
diff --git a/docs/src/ops/openresty.md b/docs/src/ops/openresty.md
new file mode 100644
index 0000000..992e14f
--- /dev/null
+++ b/docs/src/ops/openresty.md
@@ -0,0 +1,140 @@
+# 编译安装OpenResty
+
+> wandoubaba / 2023-07-21
+
+## 系统环境
+
+以Debian11为例
+
+## 安装依赖
+
+```sh
+apt-get install wget libpcre3-dev libssl-dev perl make build-essential curl libgd-dev lsb-release
+```
+
+## 安装postgres模块依赖
+
+我们这要安装驱动,而不是安装一个pg数据库服务,所以只需要安装一个`libpq-dev`就够了。
+
+```sh
+sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
+wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
+sudo apt-get update
+sudo apt-get -y install libpq-dev
+```
+
+## 创建www用户和组
+
+查看www用户是否存在
+
+```sh
+id www
+```
+
+创建www分组和www用户,并且不允许登录系统
+
+```sh
+groupadd www
+useradd -g www -s /sbin/nologin www
+```
+
+再查看www用户
+
+```sh
+id www
+```
+
+## 下载源码包
+
+```sh
+wget https://openresty.org/download/openresty-1.21.4.2.tar.gz
+```
+
+## 解压&编译&安装
+
+```sh
+tar zxvf openresty-1.21.4.2.tar.gz
+cd openresty-1.21.4.2
+./configure \
+ --prefix=/www/server/openresty \
+ --with-pcre-jit \
+ --with-http_iconv_module \
+ --with-http_postgres_module \
+ --user=www --group=www \
+ --with-http_ssl_module \
+ --with-http_v2_module \
+ --with-http_realip_module \
+ --with-http_image_filter_module \
+ --with-http_addition_module \
+ --with-http_stub_status_module \
+ --with-stream \
+ --with-stream_ssl_module \
+ --with-stream_ssl_preread_module \
+ --with-http_gzip_static_module \
+ --with-http_gunzip_module \
+ --with-http_sub_module \
+ --with-http_flv_module \
+ --with-http_mp4_module \
+ --with-http_dav_module \
+ --with-openssl-opt=-g \
+ --with-pcre-opt=-g \
+ --with-pcre
+gmake
+gmake install
+```
+
+## 注册系统服务和开机自启
+
+在`/etc/systemd/system/`目录下创建`nginx.service`文件,内容如下:
+
+```ini
+[Unit]
+Description=Nginx HTTP Server
+After=network.target
+
+[Service]
+Type=forking
+PIDFile=/www/server/openresty/nginx/logs/nginx.pid
+ExecStartPre=/www/server/openresty/nginx/sbin/nginx -t -q -g 'daemon on; master_process on;'
+ExecStart=/www/server/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;'
+ExecReload=/www/server/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;' -s reload
+ExecStop=/www/server/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;' -s quit
+PrivateTmp=true
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
+```
+
+保存文件并退出后,执行下面命令:
+
+```sh
+systemctl daemon-reload
+systemctl enable nginx
+```
+
+现在已完成系统服务注册和开机自启,下面是服务控制命令:
+
+```sh
+systemctl start nginx # 启动nginx服务
+systemctl stop nginx # 停止nginx服务
+systemctl restart nginx # 重启nginx服务
+systemctl reload nginx # 重新加载nginx配置文件
+systemctl status nginx # 检查nginx服务状态
+```
+
+## 测试
+
+正确启动服务后,使用`ps`命令可以查看nginx服务进程
+
+```sh
+ps aux | grep nginx
+```
+
+使用`ss`命令可以查看端口监听情况
+
+```sh
+ss -tnlp | grep 80
+```
+
+在浏览器中访问`http://ip`应该可以看到OpenResty的默认欢迎页`Welcom to OpenResty`。
diff --git a/docs/src/php/docker-php8.md b/docs/src/php/docker-php8.md
new file mode 100644
index 0000000..8fd127c
--- /dev/null
+++ b/docs/src/php/docker-php8.md
@@ -0,0 +1,259 @@
+# 基于php8.x制作跨平台的workerman环境Docker镜像
+
+> wandoubaba / 2024-10-29
+
+## 说明
+
+本方法基于PHP官方`8.1.30-cli`版本的镜像制作,安装好workerman开发常用的依赖和扩展,并通过`docker buildx`构建多平台的Docker镜像。
+
+## Dockerfile文件
+
+```dockerfile
+# 拉基础镜像
+FROM php:8.1.30-cli
+
+# 替换源(本文操作时使用的是aws主机所以用的是国外源,国内操作可以换成阿里、中科大等国内源)
+RUN rm /etc/apt/sources.list.d/debian.sources && \
+ echo 'deb http://mirror.us.oneandone.net/debian bookworm main' > /etc/apt/sources.list && \
+ echo 'deb-src http://mirror.us.oneandone.net/debian bookworm main' >> /etc/apt/sources.list && \
+ echo 'deb http://mirror.us.oneandone.net/debian-security bookworm-security main' >> /etc/apt/sources.list && \
+ echo 'deb-src http://mirror.us.oneandone.net/debian-security bookworm-security main' >> /etc/apt/sources.list && \
+ echo 'deb http://mirror.us.oneandone.net/debian bookworm-updates main' >> /etc/apt/sources.list && \
+ echo 'deb-src http://mirror.us.oneandone.net/debian bookworm-updates main' >> /etc/apt/sources.list && \
+ echo 'deb http://mirror.us.oneandone.net/debian bookworm-backports main' >> /etc/apt/sources.list && \
+ echo 'deb-src http://mirror.us.oneandone.net/debian bookworm-backports main' >> /etc/apt/sources.list
+
+# 安装一些依赖
+RUN apt-get update && apt-get install -y \
+ libfreetype6-dev libjpeg62-turbo-dev \
+ libpng-dev libwebp-dev zlib1g-dev \
+ libzip-dev zip \
+ libevent-dev libssl-dev \
+ lsb-release libpq-dev \
+ libgmp-dev \
+ libmagickwand-dev \
+ libzookeeper-mt-dev \
+ librdkafka-dev
+
+# 安装扩展
+RUN docker-php-ext-configure gd --enable-gd --with-freetype --with-jpeg --with-webp \
+ && docker-php-ext-install -j$(nproc) gd \
+ && docker-php-ext-install exif \
+ && docker-php-ext-install opcache \
+ && docker-php-ext-install pdo_mysql \
+ && docker-php-ext-install mysqli \
+ && docker-php-ext-install zip \
+ && docker-php-ext-install pcntl \
+ && docker-php-ext-install fileinfo \
+ && pecl install https://pecl.php.net/get/redis-6.1.0.tgz \
+ && docker-php-ext-enable redis \
+ && docker-php-ext-install sockets \
+ && pecl install https://pecl.php.net/get/event-3.1.4.tgz \
+ && docker-php-ext-enable event \
+ && cat /usr/local/etc/php/conf.d/docker-php-ext-event.ini >> /usr/local/etc/php/conf.d/docker-php-ext-sockets.ini \
+ && mv /usr/local/etc/php/conf.d/docker-php-ext-sockets.ini /usr/local/etc/php/conf.d/docker-php-ext-event.ini \
+ && docker-php-ext-install -j$(nproc) pgsql pdo_pgsql \
+ && pecl install https://pecl.php.net/get/mongodb-1.19.3.tgz \
+ && docker-php-ext-enable mongodb \
+ && docker-php-ext-install -j$(nproc) gmp \
+ && pecl install https://pecl.php.net/get/imagick-3.7.0.tgz \
+ && docker-php-ext-enable imagick \
+ && docker-php-ext-install bcmath \
+ && docker-php-ext-enable bcmath \
+ && pecl install https://pecl.php.net/get/xlswriter-1.5.5.tgz \
+ && docker-php-ext-enable xlswriter \
+ && pecl install https://pecl.php.net/get/zookeeper-1.2.1.tgz \
+ && docker-php-ext-enable zookeeper \
+ && pecl install https://pecl.php.net/get/rdkafka-6.0.3.tgz \
+ && docker-php-ext-enable rdkafka
+
+# 安装Composer
+RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
+ && php composer-setup.php \
+ && php -r "unlink('composer-setup.php');" \
+ && mv composer.phar /usr/local/bin/composer \
+ && composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
+
+# 安装swow扩展
+# RUN composer require swow/swow && ./vendor/bin/swow-builder --install
+
+# 创建应用目录
+RUN mkdir -p /app
+
+# 设置工作目录
+WORKDIR /app
+```
+
+> 在`替换源`那一段中,应该把其中的源地址替换成你的主机可以快速访问的源地址,不建议直接使用本文的源。
+
+## 用`docker buildx`构建
+
+将上面的Dockerfile脚本直接保存为`Dockerfile`文件。
+
+### 检查`docker buildx`环境
+
+```sh
+docker info
+```
+
+执行以上命令可以看到类似下面的信息:
+
+```txt
+Client: Docker Engine - Community
+ Version: 27.0.3
+ Context: default
+ Debug Mode: false
+ Plugins:
+ buildx: Docker Buildx (Docker Inc.)
+ Version: v0.15.1
+ Path: /usr/libexec/docker/cli-plugins/docker-buildx
+ compose: Docker Compose (Docker Inc.)
+ Version: v2.28.1
+ Path: /usr/libexec/docker/cli-plugins/docker-compose
+...
+```
+
+一般情况下,如果是通过包管理器安装的docker engine或者docker desktop的话,默认就已经安装好了buildx和compose插件了。
+
+### 跨平台构建并发布
+
+接下来,我们的目标是用上面的Dockerfile构建跨平台的`php:8.1-workerman`镜像并直接推送到`quay.io`平台上:
+
+(本文中我的quay.io账号是wandoubaba517,你要替换成你自己的账号。)
+
+```sh
+docker login quay.io
+docker buildx create --use
+docker buildx build --platform linux/386,linux/s390x,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8 --push -t quay.io/wandoubaba517/php:8.1-workerman .
+```
+
+执行上面的命令,执行过程中会自动从docker hub上拉取名为`moby/buildkit:buildx-stable-1`的镜像并启动容器开始自动构建和推送,整个过程在我的2核4G服务器上会执行数小时,可以使用`tmux`等终端工具异步执行。
+
+## 使用镜像
+
+```sh
+docker pull quay.io/wandoubaba517/php:8.1-workerman
+docker run -itd -p 8787:8787 -v ./:/app -w /app quay.io/wandoubaba517/php:8.1-workerman
+```
+
+### docker-compose.yml
+
+```yml
+services:
+ workerman:
+ image: quay.io/wandoubaba517/php:8.1-workerman
+ container_name: workerman
+ restart: always
+ volumes:
+ - ./:/app
+ working_dir: /app
+ stdin_open: true
+ ports:
+ - 8787:8787
+ ommand: ['php', 'start.php', 'start']
+ healthcheck:
+ test: ["CMD", "curl", "-f", "http://localhost:8787/"]
+ interval: 5s
+ retries: 3
+ start_period: 5s
+ timeout: 10s
+```
+
+### composer命令脚本
+
+> 仅适用于linux系统
+
+```sh
+#!/bin/bash
+
+# 使用heredoc构建docker run命令
+read -r -d '' DOCKER_COMMAND <<'EOF'
+docker run --rm \
+-v "$(pwd)":/app \
+-w /app \
+quay.io/wandoubaba517/php:8.1-workerman \
+composer
+EOF
+
+# 检查是否有传递参数,并将它们附加到命令的末尾
+if [ $# -gt 0 ]; then
+ DOCKER_COMMAND+=" $@"
+fi
+
+# 执行docker run命令
+eval "$DOCKER_COMMAND"
+```
+
+把上面的脚本保存为`compose`文件,设置可执行权限:
+
+```sh
+chmod +x ./composer
+```
+
+然后就可以用`./composer`代替composer命令了。
+
+也可以直接把这个composer脚本复制到/usr/bin/目录下以供全局使用(不建议这样,失去了多版本共存的意义)。
+
+### php命令脚本
+
+```sh
+#!/bin/bash
+
+# 获取脚本所在目录的绝对路径
+SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
+
+# 切换工作目录到脚本所在目录
+cd "$SCRIPT_DIR" || exit 1
+
+# 使用heredoc构建docker run命令
+read -r -d '' DOCKER_COMMAND <<'EOF'
+docker run --rm \
+--network host \
+-v "$(pwd)":/app \
+-v "$(pwd)/php.ini":/usr/local/etc/php/php.ini \
+-w /app \
+quay.io/wandoubaba517/php:8.1-workerman \
+php
+EOF
+
+# 检查是否有传递参数,并将它们附加到命令的末尾
+if [ $# -gt 0 ]; then
+ DOCKER_COMMAND+=" $@"
+fi
+
+# 执行docker run命令
+eval "$DOCKER_COMMAND"
+```
+
+同样要为`php`脚本赋予可执行权限
+
+```sh
+chmod +x ./php
+```
+
+然后就可以执行`./php`代替php命令了。
+
+### 最佳实践
+
+建议把composer脚本和php脚本都保存在项目工程目录下,另外再把容器内`/usr/local/etc/php/php-production.ini`文件也复制到工程目录下并命名为`php.ini`,在`docker-compose.yml`文件中配置卷映射
+
+```yml
+ volumes:
+ - ./:/app
+ - ./php.ini:/usr/local/etc/php/php.ini
+```
+
+## 其他版本
+
+用本文中的方法可以同样制作`8.0`和`8.2`版本做镜像,但是`8.3`不行,因为`zookeeper`扩展只支持php版本`不高于8.2.999`,一般项目可能也用不上这个扩展,在`Dockerfile`中把这个扩展和相关的依赖删掉,也可以制作出`8.3`版本的镜像。
+
+### 工程示例
+
+
+
+```sh
+git clone git@git.wandoubaba.com:wandoubaba/docker-webman.git
+cd docker-webman
+./composer install
+./php start.php start
+```
diff --git a/docs/src/php/docker-phpfpm74.md b/docs/src/php/docker-phpfpm74.md
new file mode 100644
index 0000000..ee6aa44
--- /dev/null
+++ b/docs/src/php/docker-phpfpm74.md
@@ -0,0 +1,376 @@
+# 基于docker的phpfpm+nginx环境
+
+## 简介
+
+本文以php7.4为例,介绍在具有docker环境的系统上,不安装任何php相关服务,完全利用docker容器来实现运行环境的搭建,最后还会以ThinkPHP6.0为例演示真实项目的运行,本文中的环境可在生产环境使用。
+
+## 准备工作
+
+在本地创建一个工作目录,笔者的宿主机上它的位置就是`/app/dev/phpfpm-demo`。
+
+```sh
+mkdir -p /app/dev/phpfpm-demo
+cd /app/dev/phpfpm-demo
+```
+
+## 制作过程
+
+### 基础镜像
+
+```sh
+docker pull nginx:1.24
+docker pull php:7.4.33-fpm-bullseye
+```
+
+其中,nginx镜像不需要做更改可以直接使用,而php镜像则要在基础镜像的基础上安装一些必要的依赖和扩展。
+
+### 制作PHP镜像
+
+#### 为PHP安装扩展
+
+```sh
+docker run --rm --name php-fpm -it -d php:7.4.33-fpm-bullseye
+docker exec -it php-fpm
+```
+
+在容器内安装依赖前最好先更换一下软件源,否则可能会很慢。
+
+```sh
+cp /etc/apt/sources.list /etc/apt/sources.list.bak && echo "deb http://mirrors.aliyun.com/debian/ bullseye main non-free contrib
+deb-src http://mirrors.aliyun.com/debian/ bullseye main non-free contrib
+deb http://mirrors.aliyun.com/debian-security/ bullseye-security main
+deb-src http://mirrors.aliyun.com/debian-security/ bullseye-security main
+deb http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
+deb-src http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
+deb http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib
+deb-src http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib" | tee /etc/apt/sources.list >/dev/null
+```
+
+基础php镜像中没有`redis`、`mysql`等扩展,我们要自己安装一下。在容器内可以随时用`php -m`命令查看当前已经生效的扩展
+
+```sh
+apt update && apt install -y \
+# gd扩展依赖
+libzip-dev libpng-dev \
+ibwebp-dev libjpeg-dev \
+libfreetype6-dev \
+# pgsql扩展依赖
+libpq-dev \
+# gmp扩展依赖
+libgmp-dev \
+# composer需要
+git
+
+# redis扩展
+pecl install redis && docker-php-ext-enable redis
+# mysql扩展
+docker-php-ext-install pdo_mysql && docker-php-ext-enable pdo_mysql
+# opcache扩展
+docker-php-ext-install opcache && docker-php-ext-enable opcache
+# zip扩展
+docker-php-ext-install zip && docker-php-ext-enable zip
+# xlswriter扩展(超高速读写excel文件)
+pecl install xlswriter && docker-php-ext-enable xlswriter
+# pgsql扩展(连接postgres数据库)
+docker-php-ext-install pdo_pgsql && docker-php-ext-enable pdo_pgsql
+# gmp扩展
+docker-php-ext-install gmp && docker-php-ext-enable gmp
+# gd扩展(直接使用docker-php-ext-install gd虽然也能安装成功,但是不支持freetype的话tp的验证码会出错)
+docker-php-source extract
+cd /usr/src/php/ext/gd
+docker-php-ext-configure gd --with-webp=/usr/include/webp --with-jpeg=/usr/include --with-freetype=/usr/include/freetype2
+make && make install
+docker-php-ext-install gd && docker-php-ext-enable gd
+# 安装composer
+php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" && php composer-setup.php && php -r "unlink('composer-setup.php');" && mv composer.phar /usr/local/bin/composer
+```
+
+以上是笔者经历过的项目中比较常用的扩展,如果还有其他需要,可以按照类似的方式安装。
+
+最后一切完毕后就可以离开容器了:
+
+```sh
+exit
+```
+
+另外,我们需要知道几个关键路径:
+
+- php.ini文件所有路径:`/usr/local/etc/php/php.ini`
+- 应用路径:`/var/www/html`
+
+这两个路径我们未来要采用映射的方式从项目目录映射到容器内,因此不需要在容器内做什么动作了。
+
+如果在自己的宿主机中没有现成的`php.ini`文件,可以从容器内复制出来一份:
+
+```sh
+# 开发环境建议
+docker cp php-fpm:/usr/local/etc/php/php.ini-development ./php.ini
+# 生产环境建议
+docker cp php-fpm:/usr/local/etc/php/php.ini-production ./php.ini
+```
+
+#### 保存PHP镜像
+
+```sh
+docker commit php-fpm php-fpm:7.4
+```
+
+以后我们要使用的就是这个新创建的镜像,如果有`hub.docker.com`网站的账号,可以使用`docker push`命令把这个镜像上传到自己的docker hub上,方便以后在其他地方使用。
+
+现在我们刚才启动的镜像已经不再需要了,直接删除就行。
+
+```sh
+# 启动时已经使用了--rm参数,所以容器被关闭就会自动删除
+docker stop php-fpm
+```
+
+### 准备nginx配置文件
+
+我们直接启动nginx容器,然后从容器是把配置文件复制到宿主机上。
+
+```sh
+# 当前目录是宿主机上的工作目录
+mkdir nginx
+docker run --rm --name php-fpm-nginx -it -d nginx:1.24
+docker cp php-fpm-nginx:/etc/nginx/nginx.conf ./nginx/
+docker cp php-fpm-nginx:/etc/nginx/conf.d ./nginx/
+dorker stop php-fpm-nginx
+```
+
+现在我们已经准备好了`nginx:1.24`镜像和`php-fpm:7.4`镜像,已经具备工作条件,下面就开始使用。
+
+## 环境与配置
+
+到目前为止,我们已经有两个镜像:`nginx:1.24`和`php-fpm:7.4`,同时工作目录`/app/dev/phpfpm-demo`中的目录结构如下:
+
+|目录或文件|说明|
+|---|---|
+|php.ini|PHP环境的配置文件|
+|nginx|Nginx的配置文件目录|
+|nginx/nginx.conf|nginx的主配置文件|
+|nginx/conf.d|nginx下的站点配置目录|
+
+现在我们已经把环境准备好了,接下来准备一个可以一键启动的`docker-compose.yml`文件,再修改一些nginx的配置,就可以了。
+
+`docker-compose.yml`文件:
+
+```yml
+version: "3.1"
+
+services:
+ php:
+ image: php-fpm:7.4
+ container_name: php74
+ restart: always
+ volumes:
+ - ./php.ini:/usr/local/etc/php/php.ini
+ - ./:/var/www/html
+ stdin_open: true
+ nginx:
+ image: nginx:1.24
+ container_name: phpnginx
+ restart: always
+ volumes:
+ - ./nginx/nginx.conf:/etc/nginx/nginx.conf
+ - ./nginx/conf.d:/etc/nginx/conf.d
+ - ./:/usr/share/nginx/html
+ stdin_open: true
+ ports:
+ - 8008:80
+ depends_on:
+ - php
+```
+
+简单解读一下:
+
+- 把当前工作目录中的`php.ini`文件映射到php容器对应的路径上。
+- 把当前上作目录映射到php容器中的默认站点根目录上。
+- 把当前工作目录中的nginx配置文件映射到nginx容器对应的路径上。
+- 把当前工作目录映射到nginx容器中的默认站点根目录上。
+- 把nginx容器的80端口映射到宿主机上的8008端口上(可以自己改)。
+- nginx容器和php容器都不使用host网络而是自己组成一个私有网络。
+
+接下来我们去修改nginx的配置文件,只需要修改`nginx/conf.d/default.conf`这一个文件即可,在里面加入下面这一段:
+
+在`location /`段中添加`index.php`:
+
+```
+ location / {
+ root /usr/share/nginx/html;
+ index index.html index.htm index.php;
+ }
+```
+
+然后再添加下面一段:
+
+```
+ location ~ \.php$ {
+ fastcgi_pass phpfpm74:9000;
+ fastcgi_index index.php;
+ fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
+ include fastcgi_params;
+ }
+```
+
+接下来,我们在站点根目录上创建一个`index.html`文件:
+
+```html
+
+
+
+
+
+ 欢迎
+
+
+ Hello, web
+
+
+```
+
+再创建一个`phpinfo.php`文件:
+
+```php
+ 下面的操作只适用于linux系统,如果是windows系统的话可以按照这个思路做`composer.bat`批处理文件。
+
+```sh
+touch composer
+```
+
+编辑`composer`脚本内容如下:
+
+```shell
+#!/bin/bash
+
+docker compose run --rm webman-jsonrpc composer $@
+```
+
+给文件添加执行权限:
+
+```sh
+chmod +x composer
+```
+
+现在就可以使用这个`composer`脚本了:
+
+```sh
+./composer create-project topthink/think:6.0.* think
+```
+
+网络正常的情况下,我们应该会看到工作目录下已经出现的`tp`文件夹,打开就会看到完整的thinkphp项目目录。
+
+### 开发ThinkPHP项目
+
+下面我们整理一下工作目录结构:
+
+```sh
+mv tp/* .
+mv tp/.* .
+rm -rf tp
+```
+
+接下来,我们再修改一下nginx配置文件来支持thinkphp的伪静态,再把nginx站点目录和php站点目录指向到工作路径的pulic目录下。
+
+编辑`nginx/conf.d/default.conf`文件如下:
+
+```
+ location / {
+ root /usr/share/nginx/html/public/;
+ index index.html index.htm index.php;
+ try_files $uri $uri/ /index.html last;
+ if (!-e $request_filename){
+ rewrite ^(.*)$ /index.php?s=$1 last; break;
+ }
+ }
+
+ location ~* (runtime|app)/{
+ return 403;
+ }
+
+ location ~ \.php$ {
+ fastcgi_pass phpfpm74:9000;
+ fastcgi_index index.php;
+ fastcgi_param SCRIPT_FILENAME /var/www/html/public/$fastcgi_script_name;
+ include fastcgi_params;
+ }
+```
+
+现在,再次在工作目录中用docker compose启动容器就可以启动这个tp项目了:
+
+```sh
+docker compose up -d
+```
+
+再次在浏览器中打开`http://ip:8008`,可以看到tp的欢迎页面了。
+
+最后别忘了给`runtime`目录修改一个所有者,否则项目运行还是会出问题:
+
+```sh
+chown www-data:www-data -R runtime
+```
+
+### 在宿主机使用php命令
+
+和制作`composer`脚本一样,我们同样可以通过制作名为`php`的脚本来实现在工作目录中使用`./php`命令来代替`php`命令:
+
+```sh
+touch php
+```
+
+编辑`php`脚本内容:
+
+```shell
+#!/bin/bash
+
+docker compose run --rm php php "$@"
+```
+
+给脚本执行权限:
+
+```sh
+chmod +x php
+```
+
+使用脚本:
+
+```sh
+./php think make:controller Test
+```
+
+看到`Controller:app\controller\Test created successfully.`结果后,就可以看到工作目录下的`app\controller`目录中已经出现`Test.php`文件了。
+
+## 一键完成
+
+以上是搭建这样一套环境的整个过程,按照以上过程,已经做好了现成的一套代码库,可以直接使用:
+
+```sh
+git clone https://git.wandoubaba.com/wandoubaba/docker-tp6-php74.git tp-project
+cd tp-project
+git remote remove origin
+./composer install
+chown www-data:www-data -R runtime
+docker compose up -d
+```
diff --git a/docs/src/php/index.md b/docs/src/php/index.md
new file mode 100644
index 0000000..3024ec6
--- /dev/null
+++ b/docs/src/php/index.md
@@ -0,0 +1 @@
+# PHP相关
diff --git a/docs/src/php/monolog-mongo.md b/docs/src/php/monolog-mongo.md
new file mode 100644
index 0000000..d81e5e0
--- /dev/null
+++ b/docs/src/php/monolog-mongo.md
@@ -0,0 +1,165 @@
+# PHP实现把日志保存到mongodb中
+
+`monolog`可以说是PHP中应用最为广泛的日志组件,使用它可以方便的实现多种日志记录需求,本文主要利用`monolog`的`MongoDBHandler`类,将日志保存至`mongodb`中。
+
+## 环境
+
+本文使用`webman`框架,用法基本与`laravel`大同小异。
+
+## 准备工作
+
+### 需要为php安装mongodb扩展
+
+```sh
+pecl install mongodb
+```
+
+> 也可以使用已经做好环境的docker镜像:`docker pull wandoubaba517/workerman:8.1`
+
+### monolog版本要在3.0以上
+
+先创建一个全新的`webman`项目:
+
+```sh
+composer create-project workerman/webman
+cd webman
+```
+
+`webman`中默认已经内置了`monolog`,不过我们要确保`monolog`的版本要在3.0以上:
+
+```sh
+compose require monolog/monolog:^3.0
+```
+
+### 用docker快速启动一下mongodb服务
+
+```sh
+mkdir -p log/db
+touch mongod.conf
+```
+
+`mongod.conf`文件中的内容类似下面的样子:
+
+```yml
+storage:
+ dbPath: /data/db
+net:
+ port: 27017
+ bindIp: 0.0.0.0
+```
+
+`docker-compose.yml`文件中添加`log`服务,类似下面的样子(把root和password换成你自己想要设置的):
+
+```yml
+version: "3.1"
+
+services:
+ log:
+ image: mongo:7.0
+ container_name: mongodb-log
+ restart: always
+ environment:
+ MONGO_INITDB_ROOT_USERNAME: root
+ MONGO_INITDB_ROOT_PASSWORD: password
+ MONGO_INITDB_DATABASE: log
+ volumes:
+ - ./log/db:/data/db
+ - ./log/mongod.conf:/etc/mongod.conf
+ network_mode: host
+ command: ['mongod', '--config', '/etc/mongod.conf']
+```
+
+执行`docker compose up -d`就可以启动mongodb服务了。
+
+### 引入`mongodb/laravel-mongodb`组件
+
+```sh
+composer require mongodb/laravel-mongodb
+```
+
+## 实现代码
+
+### `config/database.php`文件中配置mongodb连接
+
+```php
+return [
+ 'default' => 'pgsql',
+ 'connections' => [
+ 'pgsql' => [
+ /// ...
+ ],
+ 'mongo' => [
+ 'driver' => 'mongodb',
+ 'host' => '127.0.0.1',
+ 'port' => 27017,
+ 'database' => 'log',
+ 'username' => 'root',
+ 'password' => 'password',
+ 'options' => [
+ 'appname' => 'homestead'
+ ],
+ ],
+ /// ...
+ ]
+];
+```
+
+### `config/log.php`文件中配置日志通道
+
+```php
+return [
+ 'mongo' => [
+ 'handlers' => [
+ [
+ 'class' => Monolog\Handler\MongoDBHandler::class,
+ 'constructor' => [
+ new Mongodb\Client('mongodb://root:password@localhost:27017'),
+ 'log', // 数据库名
+ 'default', // 集合名(相当于表名)
+ Monolog\Level::Debug, // 最低日志等级(默认就是Debug)
+ ],
+ ],
+ ],
+ ],
+ /// ...
+];
+```
+
+### 业务代码中应用
+
+以`app/controller/IndexController.php`中的`log`方法为例:
+
+```php
+info(__CLASS__ . DIRECTORY_SEPARATOR . __FUNCTION__, $request->all());
+ $logs = Db::connection('mongo')->collection('default')->get();
+ return json($logs);
+ }
+}
+```
+
+### 运行测试
+
+启动服务,然后用浏览器或者接口调试工具访问`http://IP:port/index/log`,控制器方法会先记录一条日志,然后再把整所有已经保存的日志全部都输出回来。
+
+## 与文本日志对比
+
+主要优势:方便查询(文本日志文件的最小粒度是一天一个文件,当日志量具大时,在几百M或者几个G甚至更大的一个文本文件中定位某行记录,简直就是灾难)。
+
+主要劣势:需要自行处理过期记录(文本日志可以自动删除过期的文件)。
+
+## 推荐
+
+本文作者建好了一个开箱即用的webman+mongodb代码仓库:
diff --git a/docs/src/php/php74安装pgsql扩展.md b/docs/src/php/php74安装pgsql扩展.md
new file mode 100644
index 0000000..3e3481b
--- /dev/null
+++ b/docs/src/php/php74安装pgsql扩展.md
@@ -0,0 +1,53 @@
+# 为PHP7.4安装pgsql和pdo_pgsql扩展
+
+## 环境与版本
+
+操作系统:CentOS7.9 / Debian11
+
+> 在Debian上操作相对简单,所以本文以Centos7.9为例
+
+软件版本:PHP7.4, postgresql15
+
+## 操作过程
+
+假设基本的LNMP环境都已经安装好了,但是没有安装pgsql扩展。
+
+首先要先安装postgresql才可以安装pgsql扩展,其实不需要安装数据库的服务端,安装devel包就行了。
+
+> postgresql官方下载安装网址:
+
+```sh
+# Install the repository RPM:
+sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
+
+# Install PostgreSQL:
+# 这句和官网的不一样,官网让安装postgresql15-server,而我们只需要支持扩展,所以只安装postgresql15-devel
+sudo yum install -y postgresql15-devel
+```
+
+以上任务执行完毕后,postgresql15的开发包被安装到了`/usr/pgsql-15/`中,后面我们会用到`/usr/pgsql-15/bin`这个路径。
+
+下面需要找到我们PHP7.4的源码目录(没有的话就临时下载一份),进入源码目录`src/ext/pgsql`,执行以下操作:
+
+```sh
+phpize
+# 注意替换下面的PATH/TO/php-config为真实的php-config路径,用find / -name "php-config"可以找到
+./configure --with-pgsql=/usr/pgsql-15/bin/ --with-php-config=PATH/TO/php-config
+make
+make install
+```
+
+正常情况下,名为pgsql.so的文件将会出现在`PATH/TO/PHP/lib/php/extensions/no-debug-non-zts-20190902/`目录中,记住这个路径。
+
+用php --ini命令找到php.ini和php-cli.ini文件,分别编辑这两个文件,在最后面添加以下内容:
+
+```ini
+[pgsql]
+extension=PATH/TO/PHP/lib/php/extensions/no-debug-non-zts-20190902/pgsql.so
+```
+
+> 再次提醒,别忘了把`PATH/TO/PHP`替换成你的环境中的实际路径。
+
+执行`php -m | grep pgsql`应该可以看到pgsql扩展已经安装好了。
+
+PHP7.4源码目录中的`src/ext/pdo_pgsql`是pdo_pgsql扩展的源码,安装过程与pgsql扩展是相同的,这里就不说了。
diff --git a/docs/src/php/php82.md b/docs/src/php/php82.md
new file mode 100644
index 0000000..41170aa
--- /dev/null
+++ b/docs/src/php/php82.md
@@ -0,0 +1,394 @@
+# 编译安装PHP8.2
+
+> wandoubaba / 2023-07-21
+
+以Debian11操作系统为例。
+
+本文目标:在纯净的操作系统上安装PHP8.2环境,同时安装composer和pecl,并通过pecl安装一些常用的扩展,最终实现在环境中运行基于Workerman的项目。
+
+## 安装依赖
+
+```sh
+sudo apt-get install -y \
+ wget make gcc curl \
+ libxml2 libxml2-dev \
+ libsqlite3-dev \
+ libwebp-dev libonig-dev \
+ libsodium-dev pkg-config \
+ libssl-dev openssl \
+ libgd-dev build-essential \
+ zlib1g-dev libpcre3-dev \
+ lsb-release autoconf \
+ libzip-dev unzip
+```
+
+安装`libcurl`
+
+```sh
+wget https://curl.se/download/curl-8.2.0.tar.gz
+tar zxvf curl-8.2.0.tar.gz
+cd curl-8.2.0
+./configure --with-openssl
+make
+make install
+```
+
+## 创建安装目录
+
+为了让多个版本的PHP可以共存,我们不准备把PHP安装到默认目录内,而是为每个版本设置一个目录。
+
+```sh
+mkdir -p /www/server/php/82/etc
+```
+
+## 创建www用户和组
+
+查看www用户是否存在
+
+```sh
+id www
+```
+
+创建www分组和www用户,并且不允许登录系统
+
+```sh
+groupadd www
+useradd -g www -s /sbin/nologin www
+```
+
+再查看www用户
+
+```sh
+id www
+```
+
+为www用户创建home目录,composer会用到。
+
+```sh
+mkdir /home/www
+chown www:www -R /home/www
+usermod -d /home/www www
+```
+
+## 下载PHP
+
+```sh
+wget https://www.php.net/distributions/php-8.2.8.tar.gz
+```
+
+## 解压&编译&安装
+
+```sh
+tar zxvf php-8.2.8.tar.gz
+cd php-8.2.8
+./configure \
+ --prefix=/www/server/php/82 \
+ --with-config-file-path=/www/server/php/82/etc \
+ --enable-fpm \
+ --with-fpm-user=www \
+ --with-fpm-group=www \
+ --enable-mysqlnd \
+ --with-mysqli=mysqlnd \
+ --with-pdo-mysql=mysqlnd \
+ --with-freetype \
+ --with-jpeg \
+ --with-zlib \
+ --enable-xml \
+ --disable-rpath \
+ --enable-bcmath \
+ --enable-shmop \
+ --enable-sysvsem \
+ --with-curl \
+ --enable-mbregex \
+ --enable-mbstring \
+ --enable-intl \
+ --enable-ftp \
+ --enable-gd \
+ --with-openssl \
+ --with-mhash \
+ --enable-pcntl \
+ --enable-sockets \
+ --enable-soap \
+ --with-gettext \
+ --disable-fileinfo \
+ --enable-opcache \
+ --with-sodium=/usr/local/libsodium \
+ --with-webp
+make
+sudo make install
+```
+
+## 创建全局命令
+
+```sh
+ln -s /www/server/php/82/bin/php /usr/local/bin/php
+ln -s /www/server/php/82/bin/phpize /usr/local/bin/phpize
+```
+
+## 创建php.ini
+
+在PHP的源码目录下有`php.ini-development`和`php.ini-production`两个文件,分别表示“开发环境配置”和“生产环境配置”,这里我们直接使用生产环境的。
+
+```sh
+cp php.ini-production /www/server/php/82/etc/php.ini
+```
+
+## 安装composer
+
+```sh
+cd /www/server/php/82/bin
+php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
+php composer-setup.php
+ln -s /www/server/php/82/bin/composer.phar /usr/local/bin/composer
+composer selfupdate
+composer --version
+```
+
+把composer源改成国内镜像
+
+```sh
+composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
+```
+
+## 安装pecl
+
+pecl是可以方便为PHP安装扩展的工具。
+
+```sh
+cd /www/server/php/82/bin
+wget http://pear.php.net/go-pear.phar
+php go-pear.phar
+ln -s /www/server/php/82/bin/pecl /usr/local/bin/pecl
+```
+
+## 安装扩展
+
+- event扩展
+
+event扩展可以使基于Workerman的项目发挥更高的性能。
+
+注意提示:Include libevent OpenSSL support [yes] : 时输入no回车,其它直接敲回车就行。
+
+```sh
+apt-get install libevent-dev -y
+pecl install event
+```
+
+安装成功后,命令行会提示编译后的库文件所在的位置,如`/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/event.so`。
+
+在`php.ini`文件的最后添加下面的内容:
+
+```ini
+[event]
+extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/event.so"
+```
+
+再执行`php -m`命令后会看到`event`扩展出现在了已安装的扩展列表中,说明扩展安装成功。
+
+- zip扩展
+
+```sh
+pecl install zip
+```
+
+在`php.ini`文件的最后添加:
+
+```ini
+[zip]
+extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/zip.so"
+```
+
+- redis扩展
+
+```sh
+pecl install redis
+```
+
+在`php.ini`文件的最后添加:
+
+```ini
+[redis]
+extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/redis.so"
+```
+
+- swoole扩展
+
+```sh
+pecl install swoole
+```
+
+在`php.ini`文件的最后添加:
+
+```ini
+[swoole]
+extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/swoole.so"
+```
+
+- protobuf扩展
+
+如果项目中需要使用到gRPC服务端或客户端,就要安装protobuf扩展
+
+```sh
+pecl install protobuf
+```
+
+在`php.ini`文件的最后添加:
+
+```ini
+[protobuf]
+extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/protobuf.so"
+```
+
+- xlswriter扩展
+
+如果项目中需要读或写excel文件,可以尝试一下这个扩展,它的最大特点的就解析速度,无论读还是写(但是并不具备phpoffice/phpspreadsheet的所有功能)。
+
+```sh
+pecl install xlswriter
+```
+
+在`php.ini`文件的最后添加:
+
+```ini
+[xlswriter]
+extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/xlswriter.so"
+```
+
+- pdo_pgsql扩展
+
+如果项目中需要使用postgresql数据库,就需要安装这个扩展。
+
+先安装pg数据库的驱动库libpg:
+
+```sh
+sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
+wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
+sudo apt-get update
+sudo apt-get -y install libpq-dev
+```
+
+然后进入PHP源代码目录中的`ext/pdo_pgsql`目录下
+
+```sh
+## 注意要把下面的path/to换成实际路径
+cd path/to/php-8.2.8/ext/pdo_pgsql
+phpize
+./configure --with-php-config=/www/server/php/82/bin/php-config
+make
+make install
+```
+
+在`php.ini`文件的最后添加:
+
+```ini
+[pdo_pgsql]
+extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/pdo_pgsql.so"
+```
+
+- fileinfo扩展
+
+fileinfo通过在文件的给定位置查找特定的魔术字节序列,来获取文件的MIME信息。laravel框架依赖这个扩展。
+
+进入PHP源代码目录中的`ext/fileinfo`目录下
+
+```sh
+## 注意要把下面的path/to换成实际路径
+cd path/to/php-8.2.8/ext/fileinfo
+phpize
+./configure --with-php-config=/www/server/php/82/bin/php-config
+make
+make install
+```
+
+在`php.ini`文件的最后添加:
+
+```ini
+[fileinfo]
+extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/fileinfo.so"
+```
+
+## 测试
+
+独立的php-cli环境已经安装完成了,下面我们可以用简单的HTTP服务框架`webman`测试一下。
+
+```sh
+mkdir /www/wwwroot
+cd /www/wwwroot
+composer create-project workerman/webman
+cd webman
+php start.php start
+```
+
+一切顺利的话,应该可以在命令行中看到已经启动了名为`webman`的服务进程,默认监听端口`8787`
+
+```sh
+Workerman[start.php] start in DEBUG mode
+------------------------------------------- WORKERMAN -------------------------------------------
+Workerman version:4.1.11 PHP version:8.2.8 Event-Loop:\Workerman\Events\Event
+-------------------------------------------- WORKERS --------------------------------------------
+proto user worker listen processes status
+tcp root webman http://0.0.0.0:8787 16 [OK]
+tcp root monitor none 1 [OK]
+-------------------------------------------------------------------------------------------------
+Press Ctrl+C to stop. Start success.
+```
+
+这个时候使用浏览器访问`http://ip:8787`就可以看到webman框架的欢迎页了。
+
+## 启用php-fpm
+
+为了与nginx整合以支持类似laravel或tp这样的fpm框架,我们还需要启动php-fpm服务。
+
+```sh
+ln -s /www/server/php/82/sbin/php-fpm /usr/local/bin/php-fpm
+cd /www/server/php/82/etc/php-fpm.d
+cp www.conf.default www.conf
+php-fpm
+```
+
+要实现多版本PHP环境共存,主要是解决不同版本的php-fpm服务监听端口冲突的问题,我们可以做个约定规则,就是让各个版本的php-fpm都监听`90xx`端口,比如我们现在安装的是8.2版本,那就让它的php-fpm监听`9082`端口。
+
+修改`www.conf`文件,找到`listen = 127.0.0.1:9000`一行,把它改为`listen = 127.0.0.1:9082`,保存退出即可。
+
+下面要把php-fpm注册为系统服务。
+
+```sh
+touch /etc/systemd/system/php-fpm.service
+vim /etc/systemd/system/php-fpm.service
+```
+
+文件内容:
+
+```ini
+[Unit]
+Description=The PHP 8.2 FastCGI Process Manager
+After=network.target
+
+[Service]
+Type=simple
+PIDFile=/run/php-fpm.pid
+ExecStart=/www/server/php/82/sbin/php-fpm --nodaemonize --fpm-config /www/server/php/82/etc/php-fpm.conf
+ExecReload=/bin/kill -USR2 MAINPID
+ExecStop=/bin/kill −SIGINT MAINPID
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
+```
+
+保存退出后执行下面的命令:
+
+```sh
+sudo systemctl daemon-reload
+sudo systemctl enable php-fpm
+```
+
+服务控制命令:
+
+```sh
+sudo systemctl start php-fpm
+sudo systemctl restart php-fpm
+sudo systemctl stop php-fpm
+sudo systemctl reload php-fpm
+sudo systemctl status php-fpm
+```
\ No newline at end of file
diff --git a/docs/src/public/favicon.ico b/docs/src/public/favicon.ico
new file mode 100644
index 0000000..c99affd
Binary files /dev/null and b/docs/src/public/favicon.ico differ
diff --git a/docs/src/public/wandoubaba.png b/docs/src/public/wandoubaba.png
new file mode 100644
index 0000000..53594d3
Binary files /dev/null and b/docs/src/public/wandoubaba.png differ
diff --git a/docs/src/public/wandoubaba.svg b/docs/src/public/wandoubaba.svg
new file mode 100644
index 0000000..9eb0d90
--- /dev/null
+++ b/docs/src/public/wandoubaba.svg
@@ -0,0 +1,3 @@
+
diff --git a/docs/src/start.md b/docs/src/start.md
new file mode 100644
index 0000000..edf9be6
--- /dev/null
+++ b/docs/src/start.md
@@ -0,0 +1,11 @@
+# 前言
+
+这里包含了由 PHP 程序员创建的技术文档,主要记录在做与 FreeSWITCH 相关的开发过程中所遇到的问题、技能、知识、方法等内容,也包括学习Go、Docker相关的技术。
+
+如果这里的内容能帮到您,作者感到很荣幸。
+
+如果你发现这里的内容有问题,欢迎你来指正。
+
+源代码地址:
+
+作者邮箱:
diff --git a/nginx/conf.d/default.conf b/nginx/conf.d/default.conf
index d408225..2ec29ca 100644
--- a/nginx/conf.d/default.conf
+++ b/nginx/conf.d/default.conf
@@ -2,8 +2,8 @@ server {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
- listen 7001;
- listen [::]:7001;
+ listen 80;
+ listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
diff --git a/package-lock.json b/package-lock.json
index c5099cc..340aa69 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5 +1,5 @@
{
- "name": "book",
+ "name": "docs.wandoubaba.com",
"lockfileVersion": 3,
"requires": true,
"packages": {