本地部署Ollama+Dify

Dify是一个可以自定义AI应用的工具。与普通的AI聊天工具相比,它可以自定义特定功能的聊天机器人,以快速执行特定的任务;可以创建复杂的Chatflow和工作流,过程中调用各种工具,以实现复杂的功能;还支持上传文件和爬取网络页面,轻松实现RAG。它是一个开源程序,因此我们可以自己部署它,配合开源免费的ollama,打造适合自己的AI应用。

1、准备工作

1台性能较为强大的本地电脑A,拥有ipv6公网。它将用来安装ollama和Dify服务器虚拟机B。本文假设电脑A安装了Windows 11系统。电脑A应至少具备8G显存、32G内存。

1台ipv4/ipv6双栈云服务器C,用于反向代理B。

1份科学上网的配置文件yml。

1个非国内运营商托管的域名(可用的比如cloudflare)。

1个dns.he.net帐号。

2、安装和配置ollama

这一步较为简单。访问https://ollama.com/,下载Windows客户端(安装文件较大,建议带科学上网下载),直接安装即可。

安装完之后,需要配置ollama的环境变量。开始菜单-“编辑系统环境变量”,在系统变量中新建三个变量:

OLLAMA_MODELS,默认是在C盘,由于将要下载大量本地大模型,建议选择一个速度快且空间足的分区路径,例如D:\AI\OLLAMA\models

OLLAMA_HOST,值为0.0.0.0,令OLLAMA服务可以被其他机器访问。

OLLAMA_ORIGINS,值为*,允许OLLAMA跨域使用。

配置好环境变量后,右键点击托盘内的白色小绵羊(ollama),Quit Ollama,然后开始菜单-“ollama”重启它,使变量生效。

此时,ollama的服务已经运行在本机了,服务地址是0.0.0.0:11434。

假设你的本机地址是192.168.1.65,那么局域网中其他机器就可以通过http://192.168.1.65:11434来使用ollama的API(注意它可不是一个网页)。

3、下载本地大模型

访问https://ollama.com/library。这里列出了ollama直接支持的本地大模型列表。比较著名的有:

deepseek-r1,这个不用过多介绍了。671b是满血版,其余为蒸馏版。由于机器性能有限,通常我们只能选择本地部署蒸馏版。
llama3.3,Meta公司(Facebook)的开源大模型。
qwq,阿里的推理模型,32b的性能可以比肩deepseek-r1的70b。
nomic-embed-text,Text-embedding(文本嵌入)模型。注意,由于将要部署Dify,该模型为必须。

安装这些大模型非常简单。网页进入任意一个大模型的主页,选择合适的模型大小,ollama在网页上就直接给出了执行命令行,例如:

ollama run deepseek-r1:14b

开始菜单-“cmd”,打开命令行工具。复制上述命令,到cmd窗口中粘贴(右键即为粘贴),回车执行,即可启动该模型的下载,下载完会自动在命令行窗口中运行。

大模型运行时,会有提示:

>>> Send a message (/? for help)

此时直接打字即可与大模型开始聊天了。输入/exit退出运行。

在磁盘空间允许的情况下,可以下载各种你喜欢的大模型。不要忘记下载Text-embedding模型,由于它不是聊天模型,所以用pull而不是run:

ollama pull nomic-embed-text

好了,现在ollama已经拥有了多个可用的模型。可以在命令行窗口中执行ollama list查看已经安装的全部模型。ollama -h可以查看ollama命令的全部用法。

4、安装VMware workstation pro

下载VMware workstation pro 17.5.2(百度网盘)。注意其中有一个“解决DeviceGuard和Hyper-V兼容问题”文件夹,其中的dgreadiness_v3.6.zip一并下载,待会儿要用到。

近年来,微软大力推广“基于虚拟化的安全性”(Virtualization-Based Security,VBS),尤其是在较新的系统和较新的设备上,一般VBS会默认开启。VBS一旦开启,会独占Intel VT-x或AMD-V,导致VMware无法正常运行。可以通过开始菜单-“系统信息”,查看“基于虚拟化的安全性”是否处于“启用”状态。若为“启用”,则需要按以下步骤手动关闭。

1)开始菜单-“启用或关闭 windows 功能”,确保取消勾选Hyper-V。

2)管理员权限打开cmd,执行:

bcdedit /set hypervisorlaunchtype off

然后重启电脑。

3)管理员权限打开powershell,定位到dgreadiness_v3.6目录,执行:

set-ExecutionPolicy RemoteSigned

输入Y同意,然后执行:

.\DG_Readiness_Tool_v3.6.ps1 -Disable

重启后在进入操作系统之前,根据屏幕提示,关闭相关功能。

4)进入系统后,开始菜单-“服务”,确认Hyper-V的相关服务是否禁用。

5)开始菜单-“系统信息”,确认“基于虚拟化的安全性”已经处于“未启用”状态。

那么可以正常安装VMware workstaion pro。17.5.2并不是最新版本,但切勿使用更新的版本。博通收购VMware之后,先是免费了VMware的个人用户使用,但之后“大刀阔斧”地对VMware进行了“升级”,把VMware搞得支离破碎,口碑一塌糊涂。17.5.2是硕果仅存的功能完备的稳定版本。

注意,VMware与电源计划存在潜在的冲突。开始菜单-“选择电源计划”,确保其处于默认的“平衡”计划。当选择“高性能”计划时,VMware虚拟机的性能将显著下降。

5、安装Ubuntu Server虚拟机

下载Ubuntu Server的最新LTS(Long-Term Support)版本:https://ubuntu.com/download/server。

打开VMware workstaion pro,文件-“新建虚拟机”,选择“典型”、“安装程序光盘映像文件”,选择下载的Ubuntu Server ISO文件。随后根据提示一步一步安装。注意将网络设置改为“桥接”。当处于桥接状态时,虚拟机的网络就如同与宿主机处于同一个局域网了。

磁盘建议不要太小,因为未来可能要用它干很多事情。以不低于200G为佳。对于固态硬盘来说,建议单文件即可。内存建议不小于8G,推荐16G。CPU可以2x4核。

安装过程中设置的用户名密码需要做好记录。

安装过程中,询问是否需要安装Ubuntu Pro?选择否。询问是否需要安装OpenSSH Server?选择是。询问还需要安装哪些组件?建议选择snap即可,docker不建议在此时安装。

全部安装完成后,Ubuntu Server第一次启动可能需要较长时间,主要卡在cloud-init这一步。可以多等一会儿。以后就不需要这么久了。

启动成功后,它的界面就是一个命令行的登录窗口。用刚刚安装时设置的用户名密码登录。

首先要做两件事:启用root帐户并允许root通过ssh登录;查看并固定它的ipv4地址。

在当前用户名下,输入:

sudo passwd root

回车后,首先需要输入当前用户的密码,然后连续两次输入同样的密码,即可为root设置密码。注意该密码一定要做好记录。

然后,输入以下命令用nano编辑ssh的配置文件:

sudo nano /etc/ssh/sshd_config

添加以下内容:

PermitRootLogin yes
PasswordAuthentication yes

注意,PermitRootLogin可能有了,但默认情况下被注释掉了。删除前面的#注释符即可。编辑完成后,Ctrl+O,回车,Ctrl+X,保存并退出nano编辑器。

重启ssh服务:

sudo systemctl restart ssh

此时,root帐户已被激活并可以通过ssh连接服务器了。

接下来固定ipv4地址。输入命令:

ip a

可以看到当前的网络配置和网络地址。如果你的网络环境和我一样(局域网ipv4+公网ipv6,并且VMware虚拟机设置中的网络处于“桥接”模式),那么应该可以看到当前分配了一个ipv4地址和一个ipv6地址,它们隶属于一个网卡名称,通常是“ens33”。记住这个网卡名称。

输入以下命令编辑netplan配置文件:

sudo nano /etc/netplan/00-installer-config.yaml

内容如下(注意缩进,每一层是2个空格,冒号后有一个空格):

network:
  version: 2
  ethernets:
    ens33:
      dhcp4: no
      dhcp6: yes
      addresses:
        - 192.168.1.66/24
      routes:
        - to: 0.0.0.0/0
          via: 192.168.1.1
      nameservers:
        addresses: [8.8.8.8, 1.1.1.1]

dhcp6: yes表示ipv6保持动态获取,这符合一般家宽的情况。ipv4则直接写死,这里假设ipv4地址是192.168.1.66,网关是192.168.1.1。DNS用的是Google和Cloudflare。

同样地Ctrl+O、回车、Ctrl+X保存并退出nano编辑器。

6、用SSH连接Ubuntu Server

在你日常使用的机器(本文假设就是安装了VMware的宿主机服务器A)上安装Xshell(百度网盘)和Winscp(百度网盘)。注意Xshell破解之后就不要升级了否则破解会失效。Winscp为免费软件,可以升级到最新版本。

用Xshell来连接Ubuntu Server。点击菜单中“文件”-“新建”,在“连接”页填入Ubuntu Server信息。名称随意,例如“UT”;协议就按默认的SSH;主机填入192.168.1.66,端口号是默认的22。切换到“用户身份验证”页,用户名填“root”,密码是你刚刚为root帐户设置的密码。方法用默认的Password。点击“确认”,此时Ubuntu Server就已经保存在Xshell的服务器列表中了。“文件”-“打开”,选择刚刚添加的“UT”,不出意外的话,可以顺利登录,并进入SSH命令行提示符模式,当前用户是root,因此提示符会形如“root@[ubuntu机器名]:~#”。

运行WinSCP后,点击“新标签页”,再单击“新建站点”。文件协议按默认的SFTP,主机名填入192.168.1.66,填入端口号22,然后是用户名(root)和密码。全部填完之后,单击下方的“保存”,输入一个好记的站点名称,例如“UT”。之后双击“UT”,尝试连接服务器。

通常来说,WinSCP左侧是一个树状目录,类似Windows的资源管理器,上方有一个地址栏。注意ubuntu(所有Linux)的地址是类似“/etc/nginx/dir1/dir2”这样的形式,和Windows有所不同。打开到某个路径后,双击路径下面的文件可以直接打开并编辑。也可以用ctrl+c、ctrl+v或者拖动的方式来管理文件。这比在SSH命令行下操作方便多了。

由于将来要将Ubuntu Server通过反向代理暴露到公网,所以建议打开防火墙ufw,首先允许22端口。输入命令:

ufw allow 22

然后启用它:

ufw enable

查看当前防火墙的规则列表:

ufw status

如果要删除某个规则,首先用序号方式列出所有规则,然后用delete:

ufw status numbered
ufw delete 3    #删除序号为3的规则

注意,每删除一次规则,规则的序号会变,所以每次删除一个规则之前都要先ufw status numbered一下,否则很容易出错。

顺便整理Ubuntu Server磁盘分区。默认情况下,你为虚拟机分配的所有磁盘空间,并不会被虚拟机默认全部用掉。将它扩展为使用全部可用空间,避免将来麻烦。依次执行:

lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
sudo resize2fs /dev/ubuntu-vg/ubuntu-lv

用以下命令查看空间情况:

df -h

7、安装docker

用Xshell登录Ubuntu  Server。假设当前是以root登录,所以命令均省略了sudo。依次执行以下命令:

apt update
apt install -y ca-certificates curl gnupg lsb-release    #安装依赖
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor | sudo tee /etc/apt/keyrings/docker.gpg > /dev/null      #添加GPG密钥
chmod a+r /etc/apt/keyrings/docker.gpg      #设置GPG权限
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
    https://download.docker.com/linux/ubuntu jammy stable" | \
    sudo tee /etc/apt/sources.list.d/docker.list > /dev/null                 #添加docker官方源,注意这四行是同一个命令, \ 是多行命令的换行符
apt update             #不能省略,添加了源之后更新源索引
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin     #安装官方docker以及build、compose两个插件
exec bash     #刷新环境变量,让docker命令生效

8、为Ubuntu Server打造科学上网环境

众所周知,GFW把github、docker hub都给屏蔽了。为了愉快地在“内网”使用Ubuntu,安装各种服务,需要为Ubuntu Server准备科学上网环境。

这里假设作为日常使用的宿主机A已经具备了科学上网条件。

首先下载clash.meta的二进制文件:https://github.com/MetaCubeX/mihomo/releases。这里下载mihomo-linux-amd64-vxxx.gz这个文件,其中xxx为版本。解压缩gz文件,得到一个名为mihomo-linux-amd64的二进制文件(没有后缀名),建议重命名为mihomo,并用Winscp将它放到Ubuntu Server的/root/mihomo目录(先创建这个目录)。

下载GeoData:https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb。将它放到这个目录:/root/.config/mihomo

接着下载yacd:https://github.com/haishanh/yacd/releases,下载yacd.tar.xz文件,解压缩后是一个public文件夹,将它放到/root/mihomo/yacd。这是一个可以用网页方式对代理节点进行设置的工具。有了它就可以方便地切换mihomo不同的分组下使用的节点。

将宿主机上已经存在的clash配置文件复制一份。假设配置文件为config.yml。用UltraEdit(百度网盘)对它进行编辑。注意,如果使用windows自带的记事本,或winscp自带的编辑器对它进行编辑,可能会遭遇代码页问题,出现随机乱码。用UltraEdit将它另存为“UTF-8 无BOM”格式以确保万无一失。

用UltraEdit对它进行编辑,确保以下设置:

port: 7890
external-controller: 0.0.0.0:9090
external-ui: /root/mihomo/yacd/public
secret: ""  # 如果你不想设置 API 密码,可以留空
allow-lan: true  #为了让docker内的应用直接使用局域网IP使用代理

默认情况下,yml使用7890端口进行代理服务。同时指定yacd使用9090端口,并可以通过任意IP访问yacd(监听端口0.0.0.0)。修改好后,将config.yml与mihomo放在一起,也就是这个目录:/root/mihomo/。

接下来通过winscp进入/etc/systemd/system/目录,新建文件mihomo.service,输入以下内容:

[Unit]
Description=Mihomo Service
After=network.target

[Service]
Type=simple
WorkingDirectory=/root/mihomo
ExecStart=/root/mihomo/mihomo -f /root/mihomo/config.yml
Environment="HOME=/root"
Restart=on-failure
RestartSec=3
StandardOutput=journal
StandardError=journal
Environment="LOG_LEVEL=debug"

[Install]
WantedBy=multi-user.target

使用Xshell连上Ubuntu Server,为mihomo赋予执行权限:

chmod +x /root/mihomo/mihomo

在系统防火墙中添加7890、9090例外:

ufw allow 7890
ufw allow 9090

然后加载systemd配置,设置mihomo开启启动,并运行mihomo:

sudo systemctl daemon-relaod
sudo systemctl enable mihomo
sudo systemctl start mihomo

如果一切顺利,mihomo应该已经成功运行,并在7890开始监听。用这个命令查看mihomo的运行状态:

systemctl status mihomo

如果我们在使用代理时,想查看mihomo的代理记录,那么新开一个Xshell连接,并执行:

journalctl -u mihomo -f

这将实时显示当前mihomo的连接状态,便于分析网络问题。

注意,与Windows下的Clash不同,mihomo运行时,Ubuntu Server的所有程序并不会自动进入科学上网状态。mihomo只是运行在那里,监听7890端口,只有当某个程序被指定使用该端口联网时,才会使用到mihomo的代理功能。

可以用http://192.168.1.66:9090访问yacd界面,轻松设置分流规则。注意,默认情况下,yacd只添加了http://127.0.0.1:9090,可以手动将http://192.168.1.66:9090添加到管理地址。

9、为各类程序配置代理

首先当然是docker。

在/etc/systemd/system/目录中,创建子目录docker.service.d。然后在其中新建文件http-proxy.conf,编辑内容为:

[Service]
Environment="HTTP_PROXY=http://192.168.1.66:7890"
Environment="HTTPS_PROXY=http://192.168.1.66:7890"
Environment="NO_PROXY=localhost,127.0.0.1"

注意,这里的192.168.1.66是Ubuntu Server的局域网地址。还记得吗,前面我们将它设置为了固定ipv4。并在config.yml中设置了allow-lan: true。所以,docker可以通过http://192.168.1.66:7890使用本机的代理。

然后重启docker:

systemctl daemon-reexec
systemclt daemon-reload
systemctl restart docker

接下来是git。在/root/目录创建文件.gitconfig,内容如下:

[http]
    proxy = http://192.168.1.66:7890
[https]
    proxy = http://192.168.1.66:7890

保存后即刻生效。

最后,系统中还有一系列常用的程序:curl、wget、pip、conda、docker build、npm/yarn、python requests等,这些都遵守系统环境变量。编辑/root/.bashrc文件,加入以下内容:

export http_proxy=http://192.168.1.66:7890
export https_proxy=http://192.168.1.66:7890
export no_proxy=localhost,127.0.0.1

然后刷新环境变量:

exec bash

好了,现在科学上网已经设置完毕,常用的程序都已经解决了使用代理的问题。

10、部署Dify

在/root根目录下,下载仓库:

cd / 
git clone https://github.com/langgenius/dify.git

这会创建/root/dify目录,并将整个Dify的Github库克隆到本地。

修改/root/dify/docker/.env.example文件:

#最前面加上这4行
HTTP_PROXY=http://192.168.1.66:7890
HTTPS_PROXY=http://192.168.1.66:7890
http_proxy=http://192.168.1.66:7890
https_proxy=http://192.168.1.66:7890
#修改以下password为你自己的password
DB_PASSWORD=difyai123456
REDIS_PASSWORD=difyai123456
CELERY_BROKER_URL=redis://:difyai123456@redis:6379/1      #注意密码与REDIS_PASSWORD一致
#建议设置一个自己的SECRET_KEY
SECRET_KEY=
EXPOSE_NGINX_PORT=81          #默认为80,为了避免与机器上其他nginx服务冲突,建议改掉,记得用ufw放行
EXPOSE_NGINX_SSL_PORT=1443     #默认为443,为了避免与机器上其他nginx服务冲突,建议改掉

修改/root/dify/docker/docker-compose.yaml文件:

x-shared-env: &shared-api-worker-env
  #在x-shared-env: &shared-api-worker-env段里首先加上以下四行,注意缩进为两个空格
  HTTP_PROXY: ${HTTP_PROXY:-http://192.168.2.66:7890}
  HTTPS_PROXY: ${HTTPS_PROXY:-http://192.168.2.66:7890}
  http_proxy: ${http_proxy:-http://192.168.2.66:7890}
  https_proxy: ${https_proxy:-http://192.168.2.66:7890}

分别找到services段中的api段和worker段,在environment段中添加NO_PROXY例外,注意每层缩进两个空格。

services:
  api:
    environment:
      NO_PROXY: plugin_daemon,weaviate,db,redis,sandbox,nginx,frontend,localhost,127.0.0.1,172.18.0.0/16 

  worker:
    environment:
      NO_PROXY: plugin_daemon,weaviate,db,redis,sandbox,nginx,frontend,localhost,127.0.0.1,172.18.0.0/16

这些配置确保了docker服务之间的通讯不经过代理。

同样地,ufw放行81端口。由于本地用不到1443(将通过云服务器反向代理),所以只需要放行81即可。

ufw allow 81

将.env.example文件复制为.env文件。然后,切换到/root/dify/docker目录,并执行compose up:

cd /root/dify/docker
docker compose up -d

第一次compose up需要一点时间。由于已经具有可科学上网环境,安装过程应该也不会太久。如果一切正常,最终将会看到若干个Container Started的提示。

此时,从局域网中另一台电脑(例如宿主机电脑A)访问:http://192.168.1.66:81,将可以看到Dify的首页。第一次访问会让你设置管理员帐号。完成设置,妥善保存密码。

11、部署Firecrawl

Dify安装好了,已经可以愉快地玩耍。但还有一点小遗憾:Dify的知识库支持从网页抓取,但抓取的服务需要第三方支持。Firecrawl相对好一些,但只提供有效的免费额度,用完就没了。好在它也是一个开源项目,所以也可以自行部署。

返回根目录,下载仓库:

cd /
git clone https://github.com/mendableai/firecrawl.git

然后编辑/root/firecrawl/apps/api/.env.example,设置一下API KEY:

TEST_API_KEY=fc-my-dify-key-xxxxxx

然后将.env.example复制为.env。

编辑docker-compose.yaml,为services显式指定代理:

x-common-service: &common-service
    ulimits:
    nofile:
      soft: 65535
      hard: 65535
#  networks:                 #将它注释掉
#    - backend              #将它注释掉

services:
  playwright-service:
    restart: always                 #让系统启动时自动启动
    build: apps/playwright-service-ts
    environment:
      HTTP_PROXY: http://127.0.0.1:7890        #显式指定代理
      HTTPS_PROXY: http://127.0.0.1:7890      #显式指定代理
      NO_PROXY: localhost,127.0.0.1               #绕过本地地址
      PORT: 3000
      PROXY_SERVER: ${PROXY_SERVER}
      PROXY_USERNAME: ${PROXY_USERNAME}
      PROXY_PASSWORD: ${PROXY_PASSWORD}
      BLOCK_MEDIA: ${BLOCK_MEDIA}
    network_mode: host                 #改成host模式
    #networks:                                #注释掉
    #  - backend                             #注释掉

  api:
    restart: always              #让系统启动时自动启动
    <<: *common-service
    environment:
      HTTP_PROXY: http://127.0.0.1:7890            #同上
      HTTPS_PROXY: http://127.0.0.1:7890          #同上
      NO_PROXY: localhost,127.0.0.1                   #同上
      <<: *common-env
      REDIS_URL: redis://127.0.0.1:6379
      REDIS_RATE_LIMIT_URL: redis://127.0.0.1:6379
      HOST: "0.0.0.0"
      PORT: ${INTERNAL_PORT:-3002}
      FLY_PROCESS_GROUP: app
    network_mode: host                             #同上
    depends_on:
      - redis
      - playwright-service
    #ports:
    #  - "${PORT:-3002}:${INTERNAL_PORT:-3002}"
    command: [ "pnpm", "run", "start:production" ]
    networks: []
    security_opt:
      - apparmor:unconfined
      - seccomp:unconfined

worker和redis,也全部改成network_mode:host,同时注释掉networks: - backend两行。但是worker和redis不用显示指定代理。worker和redis也全部加上restart: always。

接下来还需要编辑/root/firecrawl/apps/api/Dockerfile,找到相应段落,统统加上显式代理:

FROM base AS prod-deps
ENV HTTP_PROXY=http://192.168.1.66:7890
ENV HTTPS_PROXY=http://192.168.1.66:7890
ENV NO_PROXY=localhost,127.0.0.1
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile

FROM base AS build
ENV HTTP_PROXY=http://192.168.1.66:7890
ENV HTTPS_PROXY=http://192.168.1.66:7890
ENV NO_PROXY=localhost,127.0.0.1
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install && pnpm run build


ENV HTTP_PROXY=http://192.168.1.66:7890
ENV HTTPS_PROXY=http://192.168.1.66:7890
ENV NO_PROXY=localhost,127.0.0.1
RUN cd /app/sharedLibs/go-html-to-md && \
    go mod tidy && \
    go build -o html-to-markdown.so -buildmode=c-shared html-to-markdown.go && \
    chmod +x html-to-markdown.so

# Install Rust
FROM rust:1-slim AS rust-base
ENV HTTP_PROXY=http://192.168.1.66:7890
ENV HTTPS_PROXY=http://192.168.1.66:7890
ENV NO_PROXY=localhost,127.0.0.1
COPY sharedLibs/html-transformer /app/sharedLibs/html-transformer

防火墙放行3002端口:

ufw allow 3002

最后返回到firecawl目录,执行build:

cd /root/firecrawl
docker compose up -d --build

这个过程会比较漫长。第一次build成功之后,以后运行它,就只需要:

docker compose up -d

即可。同样地,应该会看到若干个Container Started。这时候,firecrawl已经运行,它的API KEY即为在.env中设置的TEST_API_KEY,而BASE URL即为http://192.168.1.66:3000。将它们填入Dify的Firecrawl配置即可。

12、设置Dify服务器的动态域名

现在Dify服务器已经安装好,但在外网环境下还是不能直接访问到它。家宽虽然拥有公网ipv6,但它是动态的,需要为它配备一套基于ipv6动态域名方案,才能之后用一台公网ipv4的云服务器提供稳定的反向代理服务。

假设你已经拥有域名mysite.com(不能是国内网站托管的域名,cloudflare可以)。为虚拟机Dify服务器起个二级域名,注意这个域名并不直接在公网使用,只是作为dify.mysite.com的后端连接的域名。比如可以叫myut.mysite.com。

推荐使用免费的dns.he.net动态域名解析服务。首先登录你的域名托管商,在mysite.com域名的DNS解析管理页面,为myut.mysite.com添加5个NS:ns1.he.net、ns2.he.net……ns5.he.net。

NS(NameServer)解析的意思是,对这个域名具体解析到哪里,你别管了,交给我设置的这些(nsx.he.net)来负责吧。添加5个原因是为了DNS解析的健壮性,确保全球不同地区均可以稳定地解析domain.sample.com的NS设置。注意,5个NS无法写到同一行中,这是由DNS规范确定的。

接着到dns.he.net免费注册一个账号。这个页面既包括手动的静态DNS,也包括动态DNS,每个免费用户可以设置50个域名。

第一步,添加域名,点击左侧“Add a new domain”。属于myut.mysite.com。它会对这个域名进行一番检查,确保它已经正确设置了NS,除了NS之外的其他设置已经清空。

添加成功后,myut.mysite.com就出现在了Active domains for this account表格中。点击域名前面编辑图标(Edit zone),进入Managing zone页面,可以看到,之前添加过的5个NS已经罗列在其中。除此之外,还有一个SOA,它标记了5个NS中具体哪一个是主域名解析器。这些都不用管它。

点击表格顶部的“New AAAA”(添加的是ipv6解析,如果是ipv4则为New A),在弹出的窗口中,Name可以再次输入域名,IPv6 Address留空(因为我们想要的是动态域名),TTL默认,然后勾选最下方的“Enable entry for dynamic dns”,这时候IPv6中可能会自动填上::1,或者上一个设置的ipv6地址,不用在意(因为它会被动态域名机制自动更新)。点击Submit提交。

之后可以看到DNS解析表格的最后一行是刚刚添加的AAAA记录。蓝色的四个AAAA表示这是一个动态域名。注意,后面有一个DDNS列,其中有一个类似“刷新”的图标,它不是刷新!它的功能鼠标移上去可以发现:“Generate a DDNS key.”

这个KEY对于DDNS来说至关重要,DDNS的原理就是任意一台设备,只要能报出域名和对应的KEY,就可以更新域名对应的IP为当前设备的IP。点击这个“Generate a DDNS key”,单击“Generate”,它会生成一个密码(DDNS key),妥善保存它,然后务必记得,再次点击Submit,让这个刚刚生成的key生效。

好了,dns.he.net这边的设置已经完成,下面就是如何让Dify服务器向dns.he.net报告自己的IP了。

Xshell进入Dify服务器(Ubuntu Server虚拟机)。输入以下命令:

crontab  -e

它会用nano打开当前系统的任务计划配置。添加一行(注意改成自己的域名,并把DDNS_KEY换成刚刚从dns.he.net上得到的字符串):

*/5 * * * * curl -6 https://myut.mysite.com:DNS_KEY@dyn.dns.he.net/nic/update?hostname=myut.mysite.com

Ctrl+O、回车、Ctrl+X保存退出。任务计划即刻生效,你的Dify服务器将每隔5分钟向dns.he.net报告一次自己的ipv6地址,以确保myut.mysite.com始终指向正确的ipv6。

13、利用云服务器反向代理Dify

接下来就需要有一台ipv4/ipv6双栈云服务器,让它作为前端接受来自Internet的访问。可以选择dmit的云服务,线路稳定,支持ipv4/ipv6双栈,就是价格略贵。云服务器也安装ubuntu server系统。假设云服务器的公网ipv4地址为123.123.123.123。注意,如果使用国内的云服务器,你的域名需要经过备案。

首先登录你的域名托管商,增加一条二级域名的DNS解析,例如dify.mysite.com,指向云服务器地址123.123.123.123。

然后用Xsehll登录云服务器(Ubuntu Server)。安装nginx和certbot:

sudo apt update
sudo apt -y install nginx
sudo snap install --classic certbot

用Winscp连接上云服务器,在/etc/nginx/site-enabled/新建一个文件dify.mysite.com,编辑其内容如下:

server {
    server_name dify.mysite.com;
    client_max_body_size 500M;
    location / {
	resolver [2001:4860:4860::8888] [2001:4860:4860::8844] [2606:4700:4700::1111] [2606:4700:4700::1001] valid=60s; 
	set $target "myut.mysite.com:81";
	proxy_pass http://$target;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";

        proxy_connect_timeout 600s;
        proxy_send_timeout 600s;
        proxy_read_timeout 600s;

        proxy_buffering on;

    }
    listen 80; 
}

记得在云服务器上开放80和443端口:

ufw allow 80
ufw allow 443

然后重新加载nginx:

nginx -s reload

这时候,反向代理已经成功了,通过http://dify.mysite.com已经可以访问到你家里的Dify虚拟机服务器。当然,为了安全着想,肯定要申请SSL证书,升级成https访问:

certbot --nginx -d dify.mysite.com

这将为dify.mysite.com申请证书,自动修改Nginx配置文件,并配置好证书自动续期。

之后,就可以用https://dify.mysite.com来访问你的Dify网站了。

14、为Dify添加ollama大模型

这一步其实已经非常简单了。自部署的Dify肯定要添加大模型才能使用。Dify支持名目繁多的大模型API,当然也支持ollama。

登录Dify网站。在右上角账户名称下方点击“设置”。点击左侧模型供应商,在安装模型供应商列表中找到ollama并安装之。安装成功后,ollama就会出现在页面顶部,点击“添加模型”。

模型名称填写ollama list显示出来的大模型名称,例如:gemma3:27b。

基础URL填写:http://192.168.1.65:11434,因为你的Dify虚拟机和你安装了ollama的服务器本质上是在同一个局域网。

其余选项根据大模型的特点填写。具体大模型支持的上下文长度,可以上网查一下。

最后,别忘了添加text-embedding模型,在做知识库嵌入的时候是必须的。

添加了若干个大模型之后,就可以在Dify的工作室里,创建自己喜欢的聊天机器人或AI Agent,或研究各种Chatflow和工作流了。知识库里也可以上传各种文件,再也不用受到Dify官方云服务的各种收费限制啦。

实际上,这样配置的Dify整体上是运行在科学上网的环境。只要mihomo使用的config.yml中添加的节点过硬,完全可以在Dify中添加包括OpenAI在内的各种API。

Enjoy!