写给小白的从零搭建ChatGPT拼车服务教程

不知道写什么,干脆水一发小白向的 ChatGPT Web Share 搭建拼车服务教程吧,本文建立在已拥有一个 ChatGPT Plus 账号的基础上,购买方式可在论坛搜素。

  1. 选购主机

要部署拼车站点,首先需要一台属于合适的服务器(VPS),主要需注意三点:

  • 性能
  • 网络
  • 价格
    性能方面,我们以一张 IDC 价目表( VPS 商家)为例。

    IDC一般会提供的信息包括:
  • CPU 核心数
  • RAM(内存)
  • DISK(硬盘容量)
  • 流量和带宽
  • 价格
  • 线路
  • ……
    这里我们主要关注 CPU 和内存两项资源即可。CWS 文档的推荐配置为 2 核 2 G RAM以上,最低配置为 1 核 1 G ,我们根据该标准选取合适款式的 VPS 即可。
    快速上手 | ChatGPT Web Share 文档)
    另外,针对于我们想要搭建的 CWS 服务,新手在选购中还需注意的点可能有:
  • 支付方式
  • 网络线路
  • 主机位置
    支付方式:IDC 商家并不一定提供微信和支付宝这两项国内最常用的支付渠道,尤其是外国商家,所以在选购时需要挑选支持自己意向支付渠道的商家;
    网络线路:为了拥有良好的连接体验,需要在购买前了解所选 VPS 的网络线路,很多 IDC 都会提供 Looking Glass 测速服务,可以让自己和拼车小伙伴提前测试,关于线路的详细信息可参考下面主题(若不差钱则选购三网 CN2 GIA 即可);
    https://linux.do/t/topic/36472?u=ginkgo
    主机位置:中国大陆地区的主机提供 Web 服务需要进行 ICP 备案。
    另外,购买服务器时可以将其安装为 Debian 12 或 Ubuntu 22 系统,前者相对精简,后者会带更多默认软件,笔者推荐前者。
  1. 部署服务
    硬件都已置办完毕,接下来就是软件的搭建了。

连接服务器
作为从未接触过 Linux VPS 的小白,首先需要一个 SSH 软件来连接上我们的 VPS 。这里以开源免费的 WindTerm 来演示(其实我喜欢 Termius ),关于 SSH 工具的选取可参考下列主题:

到下面的网站下载最新发行版(根据自身系统选择):

这里为方便读者,贴出 2.6.1版本(截至 2024 年 4 月 14 日的最新版)下载链接(发行说明太长了):

解压缩之后打开软件,点击左上角“会话“——”新建会话“,得到下方对话框


“主机”处填写你从 IDC 那里获取的服务器 IP 地址;
“端口”处一般保持默认的 22 端口,除非你买的是 NAT 服务器,但是不建议新手尝试。
输入完毕之后,点击“连接”,会弹出验证对话框,点击“账户”,输入“root“,再输入 IDC 提供的密码,就成功连接上你的服务器啦!

如果不能成功连接,可能是由于众所周知的原因,你需要检查服务器是否在黑名单内,通过下面的网站进行多地 Ping :
https://www.itdog.cn/ping/
如果你的服务器在中国大陆一片红,海外却一片绿,说明不幸被墙,则需要更换 IP ,可以发工单联系客服或自主更换 IP 。

Docker 安装
Docker 是一个开源的应用容器引擎,大佬们会使用 Docker 技术封装软件,我们便可以通过简单的配置开箱即用。
我们参考 Docker 官方文档进行安装

首先将 Docker 添加到 apt 源,apt 是一个包管理器,可以看作一个软件商城,通过它来进行软件的下载和更新。
将下面的代码复制到你的 SSH 工具中并回车:

添加 Docker 的官方 GPG 密钥:

sudo apt-get update
sudo apt-get install 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

添加仓库到apt源:

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

上面的代码已经将 Docker 作为软件提供商添加到了我们的 apt 仓库,接下来我们键入命令安装 Docker 软件:
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

验证安装成功:
sudo docker run hello-world
当你看到”Hello from Docker!“字样的文本,说明安装成功了!

ChatGPT Web Share 部署
安装了 Docker 软件之后,我们便可以部署拼车服务了,首先创建一个单独的文件夹用于数据存放:

cd ~
mkdir cws && cd cws
mkdir -p data/config

再将代码写入环境变量:

export MONGODB_PASSWORD=password  # MongoDB 密码
export INITIAL_ADMIN_PASSWORD=password  # 初始管理员密码

MongoDB 是 CWS 所使用的数据库密码,管理员密码是拼车面板的管理员密码,都需要进行修改,不要使用默认密码。

再执行下面的命令生成配置文件:

docker run -it --rm \
  -v $PWD/data/config:/tmp/config \
 ghcr.io/chatpire/chatgpt-web-share:latest \
  python /app/backend/manage.py create_config -O /tmp/config --generate-secrets --mongodb-url "mongodb://cws:${MONGODB_PASSWORD}@mongo:27017" --initial-admin-password "${INITIAL_ADMIN_PASSWORD}" --chatgpt-base-url http://ninja:7999/backend-api/

接着创建 .env 文件:

echo "TZ=Asia/Shanghai" > .env
echo "MONGO_INITDB_DATABASE=cws" >> .env
echo "MONGO_INITDB_ROOT_USERNAME=cws" >> .env
echo "MONGO_INITDB_ROOT_PASSWORD=$MONGODB_PASSWORD" >> .env

再创建 Docker Compose 配置文件:
vi docker-compose.yml
通过 vi 编辑器创建文件后,按下“Ins Scrlk”键进入插入模式,粘贴下列内容:

services:
  chatgpt-web-share:
    image: ghcr.io/chatpire/chatgpt-web-share:latest
    container_name: cws
    restart: unless-stopped
    ports:
      - 5000:80
    volumes:
      - ./data:/app/backend/data
    environment:
      - TZ=${TZ}
      - CWS_CONFIG_DIR=/app/backend/data/config
    depends_on:
      - mongo
    networks:
      - cwsnetwork

  mongo:
    container_name: mongo
    image: mongo:6.0
    restart: always
    # ports:
    #   - 27017:27017
    volumes:
      - ./mongo_data:/data/db
    environment:
      MONGO_INITDB_DATABASE: ${MONGO_INITDB_DATABASE}
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
    networks:
      - cwsnetwork

networks:
  cwsnetwork:
    name: cwsnetwork
    external: true

最后按下键盘的”ESC“键盘退出编辑,按下“:"(冒号键),输入“wq"再“回车”保存。( Vim 编辑器的用法可参考下面的文章)

接着启动服务,执行:
docker compose up -d
如果不起作用,则执行:
docker-compose up -d

访问”http://服务器IP:5000/",如果正常看到网页,说明服务部署成功了,接下来我们需要进行 CWS 服务的配置。

  1. 服务配置

输入你的管理员账号密码登录(默认账号admin),点击右上角的小人标识进入管理后台,点击左栏的小齿轮进入系统配置,将项目下的 Enabled 和 Is Plus Account 都打开,在“Chatgpt Base Url”项下输入始皇的接口“there is no wall - 搞七捻三 - LINUX DO

接着在上面切换到“credentials”项目,这里需要输入 Access Token,在 ChatGPT 官网登录账号后访问:
https://chat.openai.com/api/auth/session
"accessToken"冒号后,所有引号内的字符均是 Access Token (不含引号),复制过去保存即可。现在,再启用各类模型,并在左侧“用户管理”界面中设置各账号的模型权限,就可以开始与 ChatGPT 对话啦!

如果你不想配置域名、https 和 CDN,便可以止步于此,如果你想要给它加上 https 安全锁,而且也不想要地址中端口号的累赘,想要直接通过域名访问服务,并添加 CDN 加速,请继续阅读。

  1. 采购域名(可选)

为了方便访问,并部署 SSL 支持(给你的网站加上https的小锁,可以保护内容不被中间人获悉和篡改)和隐藏源服务器 IP(有好事之徒可能会通过 DDos 等方式打你的服务器),我们需要购买一个域名。
自从 Freenom 停止 tk 等免费一级域名注册后,已很难找到免费域名了,如果你实在不愿意花这笔钱可以参考下面的主题:

一般推荐采购一个一级域名,可以使用下面的域名比价网站
https://tld-list.com/


左边输入你想要的域名,例如“linux”,右边会显示目前各顶级域下“linux”的注册情况,右侧显示了该域名是否被注册、最便宜的注册价(首年)、最便宜的续费家、最便宜的转移价以及最便宜的三年总价。
目前来说,较为实惠的域名是6-9位纯数字 xyz 域名,例如“123456789.xyz”,比较便宜的注册商有如下两家
https://www.spaceship.com/
https://www.namesilo.com/
在前者注册,十年仅需 6.99 美元( 50.59 人民币),可谓是相当经济实惠了。

  1. 设置域名(可选)

为了使用大善人 Cloudflare 提供的 CDN 等各类服务,我们需要将域名的 DNS 服务商从默认的 Spaceship 转移到 Cloudflare ,首先你需要注册一个 Cloudflare 账号,在控制台主页点击“添加站点”,输入你的域名,选择最下面的免费套餐,DNS 记录可以先点击”继续“跳过,复制分配给你的两个“Cloudflare名称服务器”。
https://dash.cloudflare.com/

登录你的 Spaceship 账号,访问高级 DNS 设置界面:
https://www.spaceship.com/application/advanced-dns-application/
点击想要配置的域名,在“Custom DNS”一栏中点击“change",输入你刚刚复制的两个 Cloudflare 名称服务器地址,并保存。

这样就成功地把你的域名托管到了 Cloudflare,点击“立刻检查名称服务器”并等待其生效即可,DNS 记录的传递需要时间。

  1. 内网穿透(可选 / 推荐)
    推荐使用大善人 Cloudflare 推出的 Zero Trust 服务中的 Tunnel 来进行内网穿透,安全地将内网Web服务映射至公网。使用方法可参考该主题:

记得把反代端口,即 Service 项下的 URL 修改为localhost:5000,如果是通过容器方法部署,将 cloudflared 并入 CWS 的 Docker Compose 配置,也可反代 cws:80 。成功启动之后访问你设置的域名即可打开服务。

  1. 反向代理(可选)
    我们也可以通过 Nginx、Caddy 等软件进行反向代理,这里以Nginx为例。
    首先安装Nginx,这里推荐烧饼博客打包的 Nginx 镜像源,已整合了 QUIC / HTTP3 和 Brotli 等实用插件,执行下方命令即可安装。
apt install -y lsb-release ca-certificates apt-transport-https curl gnupg dpkg
curl -sS https://n.wtf/public.key | gpg --dearmor > /usr/share/keyrings/n.wtf.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/n.wtf.gpg] https://mirror-cdn.xtom.com/sb/nginx/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/n.wtf.list
apt update
apt install -y nginx-extras

然后修改 Nginx 配置,我这里提供一份范本,参照修改即可,先删除默认的配置,再进行编辑。

rm /etc/nginx/nginx.conf
vim /etc/nginx/nginx.conf

下方的范本已添加 HTTP2 和 HTTP 3 协议的支持,开启了 0 - RTT ,启用了 Gzip 和 Brotli 压缩,为静态资源添加了缓存标头,为 HTTP 添加跳转并禁止 IP 访问。仅需要将各处的 server_name 修改为自己域名(配置中均以 cws.linux.do 为例)便可把服务跑起来,当然你也可以使用 Nginx 配置生成器 来生成配置。另外,根据服务器 CPU 性能不同,也可调整 gzip_comp_levelbrotli_comp_level 的值,前者介于【 1,9 】,后者介于【 0,11 】,数值越大压缩等级越高,所需 CPU 性能也越大。可以通过 top 命令观察 Nginx 的 CPU 占用,与此同时访问网站以确定此值。

user                 www-data;
pid                  /run/nginx.pid;
worker_processes     auto;
worker_rlimit_nofile 65535;

# Load Modules
include              /etc/nginx/modules-enabled/*.conf;

events {
    multi_accept       on;
    worker_connections 65535;
}

http {
    charset                utf-8;
    sendfile               on;
    tcp_nopush             on;
    tcp_nodelay            on;
    server_tokens          off;
    log_not_found          off;
    types_hash_max_size    2048;
    types_hash_bucket_size 64;
    client_max_body_size   16M;
    autoindex off;

    # MIME
    include                mime.types;
    default_type           application/octet-stream;

    # Logging
    access_log             off;
    error_log              /dev/null;

    # SSL
    ssl_session_timeout    1d;
    ssl_session_cache      shared:SSL:10m;
    ssl_session_tickets    off;

    # Mozilla Modern Configuration
    ssl_protocols          TLSv1.3;

    # OCSP Stapling
    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver               1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 9.9.9.9 149.112.112.112 64.6.64.6 64.6.65.6 valid=60s;
    resolver_timeout       2s;

    # Connection Header for WebSocket Reverse Proxy
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ""      close;
    }

    map $remote_addr $proxy_forwarded_elem {

        # IPv4 addresses can be sent as-is
        ~^[0-9.]+$        "for=$remote_addr";

        # IPv6 addresses need to be bracketed and quoted
        ~^[0-9A-Fa-f:.]+$ "for=\"[$remote_addr]\"";

        # Unix domain socket names cannot be represented in RFC 7239 syntax
        default           "for=unknown";
    }

    map $http_forwarded $proxy_add_forwarded {

        # If the incoming Forwarded header is syntactically valid, append to it
        "~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";

        # Otherwise, replace it
        default "$proxy_forwarded_elem";
    }

    # Load Configs
    include /etc/nginx/conf.d/*.conf;

    # ChatGPT Web Share
    server {
        listen                               443 quic reuseport;
        listen                               443 ssl;
        listen                               [::]:443 quic reuseport;
        listen                               [::]:443 ssl;
        http2                                on;
        http3                                on;
        http3_hq                             on;
        server_name                          cws.linux.do;

        # SSL
        ssl_ecdh_curve                       X25519;
        ssl_dhparam                          /etc/nginx/ssl/dhparam.pem;
        ssl_prefer_server_ciphers            on;
    	ssl_ciphers                          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
        ssl_early_data                       on;
        quic_retry                           on;
        ssl_certificate                      /etc/nginx/ssl/cws.crt;
        ssl_certificate_key                  /etc/nginx/ssl/cws.key;

        # Security Headers
        add_header Alt-Svc                   'h3=":443"; ma=86400';
        add_header X-XSS-Protection          "1; mode=block" always;
        add_header X-Content-Type-Options    "nosniff" always;
        add_header Referrer-Policy           "no-referrer-when-downgrade" always;
        add_header Content-Security-Policy   "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
        add_header Permissions-Policy        "interest-cohort=()" always;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

        # . Files
        location ~ /\.(?!well-known) {
            deny all;
        }

        # Logging
        access_log /var/log/nginx/access.log combined buffer=512k flush=1m;
        error_log  /var/log/nginx/error.log warn;

        # Reverse Proxy
        location / {
            proxy_pass                         http://127.0.0.1:5000;
            proxy_set_header Host              $host;
            proxy_http_version                 1.1;
            proxy_cache_bypass                 $http_upgrade;

            # Proxy SSL
            proxy_ssl_server_name              on;

            # Proxy Headers
            proxy_set_header Upgrade           $http_upgrade;
            proxy_set_header Connection        $connection_upgrade;
            proxy_set_header X-Real-IP         $remote_addr;
            proxy_set_header Forwarded         $proxy_add_forwarded;
            proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-Host  $host;
            proxy_set_header X-Forwarded-Port  $server_port;
            proxy_set_header Early-Data        $ssl_early_data;
            proxy_set_header Accept-Encoding   "";

            # Proxy Timeouts
            proxy_connect_timeout              60s;
            proxy_send_timeout                 60s;
            proxy_read_timeout                 60s;
        }

	    # Cache
        location ~* \.(css|js|woff|woff2|ttf|webp|png|jpg|jpeg|gif|svg|ico)$ {
            proxy_pass                         http://127.0.0.1:5000;
            expires			                   1y;
            access_log                         off;
            add_header                         Cache-Control "public";
            proxy_ssl_server_name              on;
            proxy_set_header Upgrade           $http_upgrade;
            proxy_set_header Connection        $connection_upgrade;
            proxy_set_header X-Real-IP         $remote_addr;
            proxy_set_header Forwarded         $proxy_add_forwarded;
            proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-Host  $host;
            proxy_set_header X-Forwarded-Port  $server_port;
            proxy_set_header Early-Data $ssl_early_data;
        }

        # favicon.ico
        location = /source/favicon.ico {
	    access_log    off;
	    log_not_found off;
        }

        # robots.txt
        location = /robots.txt {
            log_not_found off;
        }

        # Gzip
        gzip              on;
        gzip_vary         on;
        gzip_proxied      any;
        gzip_comp_level   6;
        gzip_types        text/plain text/css text/xml text/javascript application/json application/javascript application/x-javascript application/rss+xml application/xml application/atom+xml image/svg+xml image/x-icon image/vnd.microsoft.icon image/bmp;

        # Brotli
        brotli            on;
        brotli_comp_level 6;
        brotli_buffers    16 8k;
        brotli_min_length 20;
        brotli_types      text/plain text/css text/xml text/javascript application/json application/javascript application/x-javascript application/rss+xml application/xml application/atom+xml image/svg+xml image/x-icon image/vnd.microsoft.icon image/bmp;
        brotli_static     always;
    }

    # HTTP redirect
    server {
        listen      80;
        listen      [::]:80;
        server_name .cws.linux.do;
        return      301 https://cws.linux.do$request_uri;
    }

    # Ban IP Request
    server {
    listen      80 default_server;
    listen      [::]:80 default_server;
    server_name "";
    return      444;
    }
}

不过可别忘了,我们还没有申请 SSL 证书,以及生成前向保密所需的 dhparam 参数,让我们使用 acme.sh 来申请 SSL 证书,这里通过 DNS API 验证的方式来快捷地生成,首先登录 Cloudflare 控制台,点击右上角的小人图标进入“个人资料”页面,进入左侧“API令牌”栏目,点击“ Global API Key ”右方的“查看”,输入密码查看你的全局 API 密钥,千万不要泄露这个密钥!
接着执行脚本申请 SSL 证书(假定你的域名已托管到 Cloudflare ),下方代码中的【[email protected]】需要替换为自己的邮箱,密钥和邮箱也要替换,域名需替换为自己的域名,这里都以【linux.do】为例。

curl https://get.acme.sh | sh -s [email protected]
acme.sh --set-default-ca --server zerossl
export CF_Key="前面记录的 Cloudflare API Key" 
export CF_Email="你的 Cloudflare 绑定邮箱"
acme.sh --issue \
        --dns dns_cf \
        -d linux.do -d \*.linux.do \
        --keylength ec-256

上面的代码主要进行了如下工作:

  • 安装 acme.sh ;
  • 替换默认 CA 为 ZeroSSL ;
  • 输入 Cloudflare 账号的相关环境变量;
  • 为【linux.do】域名申请 ECC-256 类型的泛域名证书。

接着再安装 SSL 证书到 Nginx 目录,下面的安装目录与前述 Nginx 配置中的目录和文件名是匹配的,仅需修改域名。不要手动复制证书!那样无法自动更新!

acme.sh --install-cert -d linux.do \
--key-file       /etc/nginx/ssl/cws.pem  \
--fullchain-file /etc/nginx/ssl/cws.pem \
--reloadcmd     "nginx -s reload"

为了实现前向安全,我们还需要生成 DH 参数,下面的命令将生成一个 4096 位的 DH 参数,需要运行一段时间。
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096
接下来,重启 Nginx 更新配置,即可享受兼顾安全与高效的网站了。

nginx -t
nginx -s reload
  1. 安全加固(推荐)
    公网上每天都有无数脚本在扫描默认端口的服务器,为了提高 SSH 服务的安全新,我们做一些简单的安全配置即可阻挡大部分自动化攻击。
  • 修改默认端口
  • 使用密钥登录

访问 SSH 服务的默认配置文件路径
vim /etc/ssh/sshd_config
删去 #Port 22 前的注释,并在下面添加一行新端口(千万不要直接修改端口,万一出问题你就连不上服务器了!),形成下面的结构,最好选取一个高位端口,端口号必须介于【 1,65535 】之间。

Port 22
Port 6324
systemctl restart sshd

先不要关闭现有的对话,另建一个使用新端口进行连接的对话,确定新端口可以访问后再删去默认端口并重启 SSH 服务 systemctl restart sshd

为了配置密钥登录,我们先生成一个 SSH 密钥对,助记词( passphrase )自行设置,这是你丢失私钥时登录的方法,不推荐留空。

mkdir -p ~/.ssh && cd ~/.ssh
ssh-keygen -t ed25519
cd .ssh
cat id_ed25519.pub >> authorized_keys
chmod 600 authorized_keys
chmod 700 ~/.ssh

将私钥文件 id_ed25519 下载或复制其内容到本地 cat /root/.ssh/id_ed25519
再打开 SSH 配置文件,确认 PubkeyAuthentication yes 设置为启用,并且前面无#注释。 systemctl restart sshd 重启 SSH 服务后,通过 SSH 终端导入私钥测试能否使用密钥登录,确认可行后禁止密码登录 PasswordAuthentication no ,并再次重启 SSH 服务。

120 Likes

给大佬赞

3 Likes

常规话题软件分享

1 Like

大佬牛逼

4 Likes

mark

2 Likes

热佬还是多 :star_struck: :star_struck:

2 Likes

我猜内网穿透不得不提 zeroTier和Tailscale

5 Likes

坏了,Docker安装的代码块好像有排版错误,但是我搞不定(
更新:搞定了,之前用成了块引用,实际上应该用“预先格式化的文本”。

1 Like

其实我想介绍的是Cloudflare Tunnel,上线网站比较方便点。

4 Likes

哦哦哦等待678讲解

2 Likes

大佬牛B,破音

1 Like

大佬有没有演示站,看看长什么样子

1 Like

@takatorury 可以实现拼车用户之间的对话隔离。

1 Like

丰富,学习

1 Like

大佬都有什么模型阿

1 Like

支持ChatGPT-3.5和ChatGPT-4。

1 Like

cws的docker镜像好像删了

1 Like

啊?我看好像还在啊?

1 Like

可能是hub.docker上的删了

1 Like

可能是,我记得中途好像换过一次镜像源。

1 Like