<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>BINGBlog</title><link>https://20.48.50.55.sslip.io/</link><description>Recent content on BINGBlog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Thu, 17 Sep 2026 17:00:00 +0800</lastBuildDate><atom:link href="https://20.48.50.55.sslip.io/index.xml" rel="self" type="application/rss+xml"/><item><title>把 dsh 挂上公网：两道闸与自动登录</title><link>https://20.48.50.55.sslip.io/posts/2026-09-17-dsh-public-web/</link><pubDate>Thu, 17 Sep 2026 17:00:00 +0800</pubDate><guid>https://20.48.50.55.sslip.io/posts/2026-09-17-dsh-public-web/</guid><description>&lt;p&gt;dsh（DeepSeek Harness）是 DeepSeek 开源的 agent harness，有 CLI 也有 Web UI，默认只监听 &lt;code&gt;127.0.0.1:3080&lt;/code&gt;，CLI 明确拒绝 &lt;code&gt;--host 0.0.0.0&lt;/code&gt;。它自带启动 token 与签名 cookie 两道鉴权，但没有 TLS、没有账号体系，官方也把「网络部署」列为不支持。想在服务器上用，就得自己在前面架一层。下面是完整过程，机器是 Azure 上那台 892MB 的小 VPS。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="整体链路" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/dsh-public-web/architecture.svg"&gt;&lt;/p&gt;&#10;&lt;h2 id="一为什么不能直接开出去"&gt;&lt;a href="#%e4%b8%80%e4%b8%ba%e4%bb%80%e4%b9%88%e4%b8%8d%e8%83%bd%e7%9b%b4%e6%8e%a5%e5%bc%80%e5%87%ba%e5%8e%bb" class="header-anchor"&gt;&lt;/a&gt;一、为什么不能直接开出去&#10;&lt;/h2&gt;&lt;p&gt;dsh 的 Web 宿主在 &lt;code&gt;/api&lt;/code&gt; 前缀上有一道「浏览器信任栅栏」，代码注释写得很直白：它挡的是 DNS rebinding 和跨站请求，不是身份认证。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;检查&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;规则&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Host&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;必须是回环地址，或与 &lt;code&gt;--trusted-host&lt;/code&gt; 声明的 authority 匹配&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Origin（带了才查）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;必须与 Host 完全一致&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;sec-fetch-site&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;cross-site&lt;/code&gt; 一律拒&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;POST 媒体类型&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;必须是 &lt;code&gt;application/json&lt;/code&gt;，否则 415&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;认证是另一层：每个进程随机生成一个启动 token，只有 &lt;code&gt;GET /?token=...&lt;/code&gt; 能把它换成签名 cookie（HttpOnly、SameSite=Strict、绑定 &lt;code&gt;host:port&lt;/code&gt;、默认 30 天）。token 不落盘、每次启动都变；签名密钥存在 &lt;code&gt;$DSH_HOME/.credentials.yaml&lt;/code&gt;，所以 cookie 能跨重启继续用。&lt;/p&gt;&#10;&lt;p&gt;两条结论直接决定反代怎么写：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;Host 必须原样转发&lt;/strong&gt;。写成 &lt;code&gt;$host:443&lt;/code&gt; 会当场 403 —— 浏览器发来的 Origin 是 &lt;code&gt;https://域名&lt;/code&gt;，归一化后不带端口，和 &lt;code&gt;host:443&lt;/code&gt; 对不上。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;必须传 &lt;code&gt;--trusted-host &amp;lt;域名&amp;gt;&lt;/code&gt;&lt;/strong&gt;，否则 &lt;code&gt;/api&lt;/code&gt; 全部被 Host 栅栏拒掉。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="二安装与首启"&gt;&lt;a href="#%e4%ba%8c%e5%ae%89%e8%a3%85%e4%b8%8e%e9%a6%96%e5%90%af" class="header-anchor"&gt;&lt;/a&gt;二、安装与首启&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo useradd -m -s /bin/bash dsh &lt;span class="c1"&gt;# 独立账号，不进 sudo 组&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo npm i -g @deepseek-ai/dsh &lt;span class="c1"&gt;# 本次装到 0.1.5-rc.1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;首次启动会从内置模板生成 profile（&lt;code&gt;$DSH_HOME/profiles&lt;/code&gt;，要装一批插件依赖），所以第一遍慢一些：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo -u dsh env &lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/dsh &lt;span class="nv"&gt;DSH_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/dsh/.dsh &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; dsh web --port &lt;span class="m"&gt;3080&lt;/span&gt; --no-open --trusted-host dsh-xxxx.你的域名&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# dsh web: http://127.0.0.1:3080/?token=...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--no-open&lt;/code&gt; 不弹浏览器，&lt;code&gt;--trusted-host&lt;/code&gt; 只扩信任栅栏，不给身份。&lt;/p&gt;&#10;&lt;h2 id="三systemd-托管"&gt;&lt;a href="#%e4%b8%89systemd-%e6%89%98%e7%ae%a1" class="header-anchor"&gt;&lt;/a&gt;三、systemd 托管&#10;&lt;/h2&gt;&lt;p&gt;机器只有 892MB 内存，必须给上限；再按 RCE 服务的标准一并做隔离：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /etc/systemd/system/dsh-web.service&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;DeepSeek Harness (dsh) Web UI&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Wants&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;simple&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dsh&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dsh&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/home/dsh/workspace # 工作区就是启动目录&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;HOME=/home/dsh&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;DSH_HOME=/home/dsh/.dsh&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;EnvironmentFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/etc/dsh/dsh.env # DEEPSEEK_API_KEY，600 root&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/dsh web --port 3080 --no-open --trusted-host dsh-xxxx.你的域名&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;RestartSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;MemoryMax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;800M&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;TasksMax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;512&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;NoNewPrivileges&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;PrivateTmp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;PrivateDevices&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ProtectSystem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;strict&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ProtectHome&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;read-only&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ReadWritePaths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/home/dsh&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ProtectKernelTunables&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ProtectKernelModules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ProtectControlGroups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;RestrictSUIDSGID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;LockPersonality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;CapabilityBoundingSet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;AmbientCapabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;RestrictAddressFamilies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;AF_UNIX AF_INET AF_INET6 AF_NETLINK&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;UMask&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0077&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ProtectSystem=strict&lt;/code&gt; 把整个根文件系统挂成只读，唯一能写的是 &lt;code&gt;ReadWritePaths&lt;/code&gt; 指定的 &lt;code&gt;/home/dsh&lt;/code&gt;。&lt;code&gt;systemd-analyze security dsh-web&lt;/code&gt; 实测 4.1 OK。&lt;/p&gt;&#10;&lt;h2 id="四key-走环境变量"&gt;&lt;a href="#%e5%9b%9bkey-%e8%b5%b0%e7%8e%af%e5%a2%83%e5%8f%98%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;四、Key 走环境变量&#10;&lt;/h2&gt;&lt;p&gt;内置的 &lt;code&gt;llm-deepseek&lt;/code&gt; 适配器默认凭据引用就是 &lt;code&gt;DEEPSEEK_API_KEY&lt;/code&gt;，用 systemd &lt;code&gt;EnvironmentFile&lt;/code&gt; 注入：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /etc/dsh/dsh.env（600 root:root）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DEEPSEEK_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-xxxxxxxx&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;由环境变量供值的引用在 Web 设置里是只读的（&lt;code&gt;writable: false&lt;/code&gt;），key 不进应用可写状态，轮换只要改这个文件加一次 restart。&lt;/p&gt;&#10;&lt;h2 id="五公网入口"&gt;&lt;a href="#%e4%ba%94%e5%85%ac%e7%bd%91%e5%85%a5%e5%8f%a3" class="header-anchor"&gt;&lt;/a&gt;五、公网入口&#10;&lt;/h2&gt;&lt;h3 id="为什么用子域名"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e7%94%a8%e5%ad%90%e5%9f%9f%e5%90%8d" class="header-anchor"&gt;&lt;/a&gt;为什么用子域名&#10;&lt;/h3&gt;&lt;p&gt;dsh 前端是标准 SPA，静态资源与 &lt;code&gt;/api&lt;/code&gt; 都走绝对路径，用路径前缀反代要动一堆地方，cookie 的 authority 绑定也更绕。子域名最省事；没有域名就用 sslip.io：&lt;code&gt;dsh-xxxx.&amp;lt;IP&amp;gt;.sslip.io&lt;/code&gt; 会解析到那个 IP，Let&amp;rsquo;s Encrypt 照签。&lt;/p&gt;&#10;&lt;p&gt;随机子域名本身当第一层&amp;quot;隐藏&amp;quot;：串不可猜。证书用 webroot 签，80 端口的 server 块只放行 ACME 校验：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="s"&gt;^~&lt;/span&gt; &lt;span class="s"&gt;/.well-known/acme-challenge/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/var/www/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;auth_basic&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo certbot certonly --webroot -w /var/www/html -d dsh-xxxx.你的域名&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Basic Auth 账号，密码用 openssl 生成 apr1 哈希（服务器上没装 htpasswd 也能用）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dsh:%s\n&amp;#39;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;openssl passwd -apr1 &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PASS&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo install -m &lt;span class="m"&gt;640&lt;/span&gt; -o root -g www-data /dev/stdin /etc/nginx/.htpasswd-dsh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="反代与限速"&gt;&lt;a href="#%e5%8f%8d%e4%bb%a3%e4%b8%8e%e9%99%90%e9%80%9f" class="header-anchor"&gt;&lt;/a&gt;反代与限速&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;dsh-xxxx.你的域名&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# 只有这个名字能进&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;auth_basic&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;DeepSeek&lt;/span&gt; &lt;span class="s"&gt;Harness&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# 第一道闸&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;auth_basic_user_file&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/.htpasswd-dsh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;limit_req&lt;/span&gt; &lt;span class="s"&gt;zone=dsh_zone&lt;/span&gt; &lt;span class="s"&gt;burst=120&lt;/span&gt; &lt;span class="s"&gt;nodelay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;client_max_body_size&lt;/span&gt; &lt;span class="mi"&gt;100m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:3080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# 不带端口，理由见第一节&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="nv"&gt;$connection_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_buffering&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# SSE / 流式必需&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_read_timeout&lt;/span&gt; &lt;span class="s"&gt;3600s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# 长任务别被 60s 掐断&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_request_buffering&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="六第二道闸的坑"&gt;&lt;a href="#%e5%85%ad%e7%ac%ac%e4%ba%8c%e9%81%93%e9%97%b8%e7%9a%84%e5%9d%91" class="header-anchor"&gt;&lt;/a&gt;六、第二道闸的坑&#10;&lt;/h2&gt;&lt;p&gt;只过 Basic Auth 会被 dsh 自己挡住：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dsh web authentication required; reopen the URL printed by dsh web.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这是启动 token 那道闸。手动过的话，从服务日志里捞当前进程的 URL：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;journalctl -u dsh-web -o cat &lt;span class="p"&gt;|&lt;/span&gt; grep -o &lt;span class="s1"&gt;&amp;#39;token=[A-Za-z0-9_-]*&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tail -1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;两个容易踩的点：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;上游返回的 401 &lt;strong&gt;不会&lt;/strong&gt;触发 &lt;code&gt;error_page&lt;/code&gt;：nginx 默认 &lt;code&gt;proxy_intercept_errors off&lt;/code&gt;，只拦自己产生的错误码，要在这个 location 里显式打开&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;map $http_upgrade $connection_upgrade&lt;/code&gt; 得定义在 http 块；漏了 WebSocket 升级会失败，页面上表现为一直转圈&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="七让闸门无感"&gt;&lt;a href="#%e4%b8%83%e8%ae%a9%e9%97%b8%e9%97%a8%e6%97%a0%e6%84%9f" class="header-anchor"&gt;&lt;/a&gt;七、让闸门无感&#10;&lt;/h2&gt;&lt;p&gt;token 每进程都在 journal 里，可以让 nginx 自己拿它换 cookie：首页拿到 401 时内部重试一次带 token 的请求，把 &lt;code&gt;303 + Set-Cookie&lt;/code&gt; 原样透给浏览器。浏览器地址栏全程不带 token，比手动粘贴 URL 更干净。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;error_page&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@dsh_login&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_intercept_errors&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# 关键：否则不触发 error_page&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:3080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="s"&gt;@dsh_login&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:3080/?token=&lt;/span&gt;&lt;span class="nv"&gt;$dsh_launch_token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;$dsh_launch_token&lt;/code&gt; 由一个小脚本同步：从 journal 取当前进程 token，写进 &lt;code&gt;/etc/nginx/conf.d/dsh-token.conf&lt;/code&gt; 里的 &lt;code&gt;map&lt;/code&gt;，再 reload nginx。挂到服务启动钩子上，重启后 token 自动跟上：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /etc/systemd/system/dsh-web.service.d/token-sync.conf&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStartPost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;+/usr/local/bin/dsh-token-sync # + 前缀 = 以 root 跑，才能读 journal、reload nginx&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="两道闸的时序" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/dsh-public-web/auth-flow.svg"&gt;&lt;/p&gt;&#10;&lt;p&gt;代价要说清楚：这样一来对外实际只剩 Basic Auth 一道闸，加上它前面的随机子域名。想恢复两道闸，屏蔽掉内部重试即可：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo touch /etc/dsh/auto-login.off &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo dsh-token-sync --now &lt;span class="c1"&gt;# 关&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo rm /etc/dsh/auto-login.off &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo dsh-token-sync --now &lt;span class="c1"&gt;# 开&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="八验证"&gt;&lt;a href="#%e5%85%ab%e9%aa%8c%e8%af%81" class="header-anchor"&gt;&lt;/a&gt;八、验证&#10;&lt;/h2&gt;&lt;p&gt;鉴权矩阵，全部从公网入口测：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;请求&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;结果&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;无 Basic Auth&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;401&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;密码错误&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;401&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Basic Auth、无 cookie&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;303 + Set-Cookie（自动登录）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Basic Auth、带 cookie&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;200&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;直连 &lt;code&gt;127.0.0.1:3080&lt;/code&gt; 并伪造 &lt;code&gt;Host: localhost&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;401（信任栅栏与 cookie 双查）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;最后用无头浏览器跑一轮真实任务，确认 &lt;code&gt;/api&lt;/code&gt;、工具调用、模型都通：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="dsh Web UI 里跑一轮任务" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/dsh-public-web/ui.png"&gt;&lt;/p&gt;&#10;&lt;h2 id="九隔离与限制"&gt;&lt;a href="#%e4%b9%9d%e9%9a%94%e7%a6%bb%e4%b8%8e%e9%99%90%e5%88%b6" class="header-anchor"&gt;&lt;/a&gt;九、隔离与限制&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;同机隔离&lt;/strong&gt;：dsh 能执行任意命令，这台机器上还跑着网关和博客，它的进程不该读到后者的凭据。除 &lt;code&gt;ProtectHome=read-only&lt;/code&gt; 外再补一条 ACL，把整个家目录对它关掉：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo setfacl -m u:dsh:--- /home/你的用户 &lt;span class="c1"&gt;# 撤销：sudo setfacl -x u:dsh /home/你的用户&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;同机其他服务的家目录里若有 world-readable 的凭据文件（&lt;code&gt;~/.cli-proxy-api/config.yaml&lt;/code&gt;、&lt;code&gt;~/.pi&lt;/code&gt;、&lt;code&gt;~/.codex&lt;/code&gt;），一并收成 700。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;设置页在非回环访问下不可用&lt;/strong&gt;：客户端会判断页面自身是不是 loopback，不是就把设置持久化降级成内存（源码里是 &lt;code&gt;isLoopback ? 'host' : 'memory'&lt;/code&gt;），于是「设置 → 模型」直接报 &lt;code&gt;settings are unavailable in this browser&lt;/code&gt;。模型与凭据都改服务端文件：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# /home/dsh/.dsh/settings.yaml，改完下一次请求生效，不用重启&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;llm-deepseek&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;reasoningEffort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;high&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;公网暴露 RCE 的现实&lt;/strong&gt;：过了 Basic Auth 就是一个能跑命令的 agent。密码用 24 位随机串、限定单域名、开限速，能做的都做了；要更稳就关掉自动登录，只用一次性 token URL 进。&lt;/p&gt;&#10;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#10;&lt;/h2&gt;&lt;ol&gt;&#10;&lt;li&gt;dsh 默认只回环，反代要原样转发 Host 并传 &lt;code&gt;--trusted-host&lt;/code&gt;，否则 &lt;code&gt;/api&lt;/code&gt; 被信任栅栏拒掉&lt;/li&gt;&#10;&lt;li&gt;上游 401 不触发 &lt;code&gt;error_page&lt;/code&gt;，&lt;code&gt;proxy_intercept_errors on&lt;/code&gt; 是自动换 cookie 的前提&lt;/li&gt;&#10;&lt;li&gt;token 每进程轮换、cookie 签名密钥持久化；用 &lt;code&gt;ExecStartPost=+脚本&lt;/code&gt; 把 token 同步给 nginx，重启后进入无感&lt;/li&gt;&#10;&lt;li&gt;按 RCE 服务对待：独立用户、只读根、只写自己 home、清空 capability，再用 ACL 挡住同机其他家目录&lt;/li&gt;&#10;&lt;li&gt;非回环页面的设置页是禁用的，模型与凭据统一走 &lt;code&gt;settings.yaml&lt;/code&gt; 和环境变量&lt;/li&gt;&#10;&lt;/ol&gt;&#10;</description></item><item><title>RAG 入门：检索增强生成的原理与 AWS 方案</title><link>https://20.48.50.55.sslip.io/posts/2026-09-17-what-is-rag/</link><pubDate>Thu, 17 Sep 2026 15:20:00 +0800</pubDate><guid>https://20.48.50.55.sslip.io/posts/2026-09-17-what-is-rag/</guid><description>&lt;p&gt;本文整理自 AWS 官方页面 &lt;a class="link" href="https://aws.amazon.com/cn/what-is/retrieval-augmented-generation/" target="_blank" rel="noopener"&#10; &gt;什么是 RAG（检索增强生成）？&lt;/a&gt;，内容与观点归 Amazon Web Services 所有，这里做了中文归纳、结构化与配图重绘。&lt;/p&gt;&#10;&lt;h2 id="一rag-是什么"&gt;&lt;a href="#%e4%b8%80rag-%e6%98%af%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;一、RAG 是什么&#10;&lt;/h2&gt;&lt;p&gt;检索增强生成（Retrieval-Augmented Generation，RAG）指在生成回答之前，先让大语言模型（LLM）去检索一份权威知识库，用检索到的内容来约束和补充输出。&lt;/p&gt;&#10;&lt;p&gt;模型本身不用重新训练，只是多了一个「查资料」的动作。原文的判断是：这是低成本改进 LLM 输出的方法，让回答在具体场景下保持相关性、准确性和实用性。&lt;/p&gt;&#10;&lt;h2 id="二为什么需要-rag"&gt;&lt;a href="#%e4%ba%8c%e4%b8%ba%e4%bb%80%e4%b9%88%e9%9c%80%e8%a6%81-rag" class="header-anchor"&gt;&lt;/a&gt;二、为什么需要 RAG&#10;&lt;/h2&gt;&lt;p&gt;LLM 的训练数据是静态的，知识有截止日期；而它的输出又足够自信。原文把这种状态比作一个过于热情的新员工：不了解时事，但什么问题都答得斩钉截铁。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;常见问题&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;表现&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;无中生有&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;没有答案时给出虚假信息&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;信息过时&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;用户要最新的具体信息，模型给宽泛的旧内容&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;来源不权威&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;依据非权威来源组织回答&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;术语混淆&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不同训练来源对同一术语的定义不同，导致答非所问&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;RAG 的应对方式是：把模型重定向到预先确定的权威知识来源，组织对输出有更强的控制，用户也能看清答案是怎么来的。&lt;/p&gt;&#10;&lt;h2 id="三rag-的四个好处"&gt;&lt;a href="#%e4%b8%89rag-%e7%9a%84%e5%9b%9b%e4%b8%aa%e5%a5%bd%e5%a4%84" class="header-anchor"&gt;&lt;/a&gt;三、RAG 的四个好处&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;好处&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;说明&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;成本低&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;针对领域数据重训基础模型的算力和费用都很高；RAG 只要接外部数据，不动模型&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;信息新鲜&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;可以直接对接实时社媒、新闻网站等频繁更新的来源&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;可追溯&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;输出可以附带引文与来源，用户能自己核对原文，信任度更高&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;可控&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;开发者能更换信息来源、按权限限制敏感内容的检索范围，也能在答案引错来源时排错修复&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="四rag-怎么工作"&gt;&lt;a href="#%e5%9b%9brag-%e6%80%8e%e4%b9%88%e5%b7%a5%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;四、RAG 怎么工作&#10;&lt;/h2&gt;&lt;p&gt;没有 RAG 时，模型只凭训练记忆回答；有了 RAG，流程里多出一个信息检索组件：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="RAG 工作流程：先建知识库，再带着检索结果提问" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/what-is-rag/flow.svg"&gt;&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;创建外部数据&lt;/strong&gt;：把 API、数据库、文档库里训练集之外的数据，用嵌入模型转成向量，存进向量数据库，形成模型能理解的知识库。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;检索相关信息&lt;/strong&gt;：把用户查询也转成向量，与向量库匹配，返回最相关的片段。原文的例子是 HR 机器人——员工问「我有多少年假？」，系统会同时检索年假政策文档和该员工的历史休假记录。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;增强提示&lt;/strong&gt;：把检索到的内容拼进提示词，这一步靠提示工程与模型有效沟通，让模型基于「训练知识 + 新知识」作答。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;更新外部数据&lt;/strong&gt;：数据会过期，需要异步更新文档及其嵌入表示，可以走实时流程或定期批处理。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="五rag-和语义搜索的区别"&gt;&lt;a href="#%e4%ba%94rag-%e5%92%8c%e8%af%ad%e4%b9%89%e6%90%9c%e7%b4%a2%e7%9a%84%e5%8c%ba%e5%88%ab" class="header-anchor"&gt;&lt;/a&gt;五、RAG 和语义搜索的区别&#10;&lt;/h2&gt;&lt;p&gt;语义搜索是提升 RAG 效果的一环，适合想把大量外部知识接进 LLM 应用的组织。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;传统/关键字搜索&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;语义搜索&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;检索方式&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;字面匹配&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;问题映射到相关文档，返回具体文本段落&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;开发者负担&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;要自己处理词嵌入、文档分块等准备工序&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;知识库准备由服务完成&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;输出&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;搜索结果列表&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;语义相关的段落 + 按相关性排序的标记词&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;原文举的例子：问「去年在机械维修上花了多少钱？」，语义搜索返回的是相关文档中的具体文本，而不是一堆链接，开发者拿这段答案去给 LLM 补充上下文即可。&lt;/p&gt;&#10;&lt;h2 id="六aws-上的三种落地方式"&gt;&lt;a href="#%e5%85%adaws-%e4%b8%8a%e7%9a%84%e4%b8%89%e7%a7%8d%e8%90%bd%e5%9c%b0%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;六、AWS 上的三种落地方式&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;方式&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;说明&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Amazon Bedrock 知识库&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;全托管，几次点击把基础模型接到 RAG 数据源，向量转换、检索、生成都自动处理&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Amazon Kendra&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;机器学习驱动的高精度企业搜索，提供检索 API 与语义排序器，可作为 RAG 工作流的企业检索器&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Amazon SageMaker JumpStart&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;想要更多自定义时用，提供基础模型、内置算法与现成方案，参考 notebook 与示例代码加速实现&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Kendra 检索 API 的几个具体能力：单次最多返回 100 个语义相关段落（每段最多 200 个 token，按相关性排序）、提供 S3 / SharePoint / Confluence 等预置连接器、支持 HTML / Word / PowerPoint / PDF / Excel / 纯文本，并能按最终用户权限过滤文档。&lt;/p&gt;&#10;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;RAG 不改模型，只给模型加一个「先查资料再回答」的检索步骤&lt;/li&gt;&#10;&lt;li&gt;它解决的是训练数据静态、模型过度自信带来的四类问题：编造、过时、来源不权威、术语混淆&lt;/li&gt;&#10;&lt;li&gt;流程四步：准备外部数据 → 检索相关片段 → 增强提示 → 持续更新数据&lt;/li&gt;&#10;&lt;li&gt;语义搜索与 RAG 互补，前者负责把大量非结构化知识变成可检索、可排序的段落&lt;/li&gt;&#10;&lt;li&gt;不想自建就用 Amazon Bedrock 知识库，要企业级检索用 Kendra，要深度定制用 SageMaker JumpStart&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;&lt;strong&gt;来源&lt;/strong&gt;：本文整理自 AWS 官方页面《&lt;a class="link" href="https://aws.amazon.com/cn/what-is/retrieval-augmented-generation/" target="_blank" rel="noopener"&#10; &gt;什么是 RAG（检索增强生成）？&lt;/a&gt;》，原文版权归 Amazon Web Services, Inc. 或其关联公司所有；文中观点、案例与数据均引自该页面，配图为本站自制。&lt;/p&gt;&#10;</description></item><item><title>一句话提示词：Codex 写出 3D 天气预报页</title><link>https://20.48.50.55.sslip.io/posts/2026-09-17-codex-3d-weather/</link><pubDate>Thu, 17 Sep 2026 13:10:00 +0800</pubDate><guid>https://20.48.50.55.sslip.io/posts/2026-09-17-codex-3d-weather/</guid><description>&lt;p&gt;给 Codex 发一句提示词，模型走服务器上的 CPA 网关（别名 &lt;code&gt;deepseek-flash&lt;/code&gt;，推理强度 high），19 分 59 秒后拿到一个能直接双击打开的单文件 3D 天气页。本文放上在线演示、实现要点，以及顺手做的「正文内嵌 HTML」验证。&lt;/p&gt;&#10;&lt;h2 id="一提示词与产出"&gt;&lt;a href="#%e4%b8%80%e6%8f%90%e7%a4%ba%e8%af%8d%e4%b8%8e%e4%ba%a7%e5%87%ba" class="header-anchor"&gt;&lt;/a&gt;一、提示词与产出&#10;&lt;/h2&gt;&lt;p&gt;提示词只有一句，没有补充任何设计稿或数据：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="提示词原文" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/codex-3d-weather/prompt.png"&gt;&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;项&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;值&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;模型&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;deepseek-flash&lt;/code&gt;（CPA 网关别名，&lt;code&gt;codex --profile deepseek&lt;/code&gt;，reasoning high）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;耗时&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;19 分 59 秒&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;产出&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单个 &lt;code&gt;index.html&lt;/code&gt;，52 KB&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;运行方式&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;three.js r160（jsdelivr CDN），无构建、无本地服务器，&lt;code&gt;file://&lt;/code&gt; 直接打开&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;数据&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;武汉（30.59°N / 114.31°E）未来 7 天，Open-Meteo 抓取后写死在文件里&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="二在线演示"&gt;&lt;a href="#%e4%ba%8c%e5%9c%a8%e7%ba%bf%e6%bc%94%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;二、在线演示&#10;&lt;/h2&gt;&lt;figure class="demo-embed"&gt;&#10; &lt;iframe src="https://20.48.50.55.sslip.io/demos/wuhan-weather-3d/index.html" title="武汉未来 7 天 3D 天气可视化（可交互）" loading="lazy" allowfullscreen&gt;&lt;/iframe&gt;&#10; &lt;figcaption class="demo-bar"&gt;&#10; &lt;span&gt;真实可交互页面（WebGL 实时渲染）&lt;/span&gt;&#10; &lt;a href="https://20.48.50.55.sslip.io/demos/wuhan-weather-3d/index.html" target="_blank" rel="noopener"&gt;全屏打开 ↗&lt;/a&gt;&#10; &lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;场景里的星空、镜面地面、泛光都是实时渲染的，不是贴图；演示页需要 WebGL，并从 CDN 拉 three.js。加载不出来时看下面的截图：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="3D 天气预报页截图" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/codex-3d-weather/preview.webp"&gt;&lt;/p&gt;&#10;&lt;h2 id="三数据怎么变成画面"&gt;&lt;a href="#%e4%b8%89%e6%95%b0%e6%8d%ae%e6%80%8e%e4%b9%88%e5%8f%98%e6%88%90%e7%94%bb%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;三、数据怎么变成画面&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;视觉元素&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;编码的数据&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;柱体高度&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;当日气温（18–32℃ 映射到世界坐标）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;柱体颜色&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;温度色带：蓝 → 青 → 绿 → 黄 → 橙 → 红&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;柱顶亮点 / 底座光环&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;当日最高温 / 最低温&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;云团体积&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;云量（由 WMO 天气代码推出）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;雨丝密度&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;降水量&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;水平流线速度&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;风速&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;跨日发光带&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;每日温差区间：上沿最高温曲线，下沿最低温&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;底部日期卡&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;日期、天气、最高/最低温、温度条&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;这层映射是模型自己定的，提示词里只给了「炫酷」两个字。&lt;/p&gt;&#10;&lt;h2 id="四实现要点"&gt;&lt;a href="#%e5%9b%9b%e5%ae%9e%e7%8e%b0%e8%a6%81%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;四、实现要点&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;单文件结构：&lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; + &lt;code&gt;&amp;lt;script type=&amp;quot;importmap&amp;quot;&amp;gt;&lt;/code&gt; + &lt;code&gt;&amp;lt;script type=&amp;quot;module&amp;quot;&amp;gt;&lt;/code&gt;，没有任何构建步骤&lt;/li&gt;&#10;&lt;li&gt;后处理：&lt;code&gt;EffectComposer&lt;/code&gt; + &lt;code&gt;UnrealBloomPass&lt;/code&gt; 泛光，ACES Filmic 色调映射&lt;/li&gt;&#10;&lt;li&gt;地面是 &lt;code&gt;Reflector&lt;/code&gt; 实时镜面反射，叠一层自定义着色器网格&lt;/li&gt;&#10;&lt;li&gt;云、雨、风、光柱都用自定义 &lt;code&gt;ShaderMaterial&lt;/code&gt; / Points，几何体经 &lt;code&gt;mergeGeometries&lt;/code&gt; 合并&lt;/li&gt;&#10;&lt;li&gt;HUD 是普通 DOM：底部 7 张日期卡、右侧单日明细（含逐小时气温 canvas）、左上信息牌、右上图例&lt;/li&gt;&#10;&lt;li&gt;数据写死在文件顶部 &lt;code&gt;DAYS&lt;/code&gt; / &lt;code&gt;HOURLY&lt;/code&gt; 常量，换城市只改 &lt;code&gt;CITY&lt;/code&gt; 与这两个数组&lt;/li&gt;&#10;&lt;li&gt;交互：&lt;code&gt;OrbitControls&lt;/code&gt; 轨道相机，点柱子或日期卡选中单日，&lt;code&gt;←/→&lt;/code&gt; 切换，空格视角漂移&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="五正文内嵌-html-的验证"&gt;&lt;a href="#%e4%ba%94%e6%ad%a3%e6%96%87%e5%86%85%e5%b5%8c-html-%e7%9a%84%e9%aa%8c%e8%af%81" class="header-anchor"&gt;&lt;/a&gt;五、正文内嵌 HTML 的验证&#10;&lt;/h2&gt;&lt;p&gt;结论：可以。本站的 goldmark 渲染器开着 &lt;code&gt;unsafe = true&lt;/code&gt;（&lt;code&gt;config/_default/markup.toml&lt;/code&gt;），Markdown 里的原始 HTML 原样输出，上面的演示就是直接嵌进正文的 &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;能力&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;结果&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;行内标签（&lt;code&gt;&amp;lt;kbd&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;mark&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt;）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;生效&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; 内联样式&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;生效&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; 嵌同站静态页&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;生效&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; 折叠块&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;生效&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;嵌别的站点&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;被 &lt;code&gt;X-Frame-Options: SAMEORIGIN&lt;/code&gt; 挡掉，只影响别人嵌我们&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;样式作用域&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;必须套自己的容器 class，否则会污染整站&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;演示页放在 &lt;code&gt;static/demos/wuhan-weather-3d/index.html&lt;/code&gt;，Hugo 原样复制到站点根目录，nginx 当普通静态页返回。&lt;/p&gt;&#10;&lt;details&gt;&#10;&lt;summary&gt;展开看这段演示的原始 HTML 写法&lt;/summary&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;demo-embed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;iframe&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/demos/wuhan-weather-3d/index.html&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;武汉未来 7 天 3D 天气可视化（可交互）&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;lazy&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;allowfullscreen&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;figcaption&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;demo-bar&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;真实可交互页面（WebGL 实时渲染）&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/demos/wuhan-weather-3d/index.html&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;_blank&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;noopener&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;全屏打开 ↗&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;figcaption&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;样式写在 &lt;code&gt;assets/scss/custom.scss&lt;/code&gt; 的 &lt;code&gt;.demo-embed&lt;/code&gt; 里，&lt;code&gt;iframe&lt;/code&gt; 用 &lt;code&gt;aspect-ratio&lt;/code&gt; 控制高度。注意主题给 &lt;code&gt;figure&lt;/code&gt; 加了铺满卡片的负外边距：自定义样式只改上下间距、别用 &lt;code&gt;margin&lt;/code&gt; 简写覆盖，否则外边距被重置、加宽的 &lt;code&gt;width&lt;/code&gt; 还在，块就会向右溢出被裁切。&lt;/p&gt;&#10;&lt;/details&gt;&#10;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;一句提示词 + 推理强度 high 的模型，20 分钟拿到能用的单文件可视化页面&lt;/li&gt;&#10;&lt;li&gt;效果取决于数据映射想没想清楚：柱高对气温、云量对云团体积、降水对雨丝密度&lt;/li&gt;&#10;&lt;li&gt;产物零依赖、零构建，&lt;code&gt;file://&lt;/code&gt; 双击即开，部署时当一个静态文件丢出去即可&lt;/li&gt;&#10;&lt;li&gt;博客正文支持原始 HTML：本站 goldmark 已开 &lt;code&gt;unsafe&lt;/code&gt;，&lt;code&gt;iframe&lt;/code&gt; / &lt;code&gt;style&lt;/code&gt; / &lt;code&gt;details&lt;/code&gt; 都能用&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;X-Frame-Options: SAMEORIGIN&lt;/code&gt; 只允许嵌本站资源，需要嵌外站就得改响应头&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>用 CLIProxyAPI 在服务器搭多上游统一网关</title><link>https://20.48.50.55.sslip.io/posts/2026-09-17-codex-cpa-gateway/</link><pubDate>Thu, 17 Sep 2026 01:30:00 +0800</pubDate><guid>https://20.48.50.55.sslip.io/posts/2026-09-17-codex-cpa-gateway/</guid><description>&lt;p&gt;同时用几个 AI 上游很麻烦：每个都要单独配 key、单独改客户端，额度也各管各的。用 CLIProxyAPI 在服务器上把它们聚合成一个端点，对外只给一把 key，客户端改个 &lt;code&gt;base_url&lt;/code&gt; 就能用，&lt;code&gt;/model&lt;/code&gt; 随时切模型。下面是完整部署流程，新服务器按顺序执行即可。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="整体链路" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/codex-cpa-gateway/architecture.svg"&gt;&lt;/p&gt;&#10;&lt;h2 id="适用场景"&gt;&lt;a href="#%e9%80%82%e7%94%a8%e5%9c%ba%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;适用场景&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;多上游自用&lt;/strong&gt;：官方 OAuth 与第三方 API 共用一个 &lt;code&gt;base_url&lt;/code&gt;，&lt;code&gt;/model&lt;/code&gt; 切模型不用改配置；服务器在境外且国内可直连（本文是日本节点）时，客户端也不必自己再挂代理&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;对外分发&lt;/strong&gt;：账号额度用不完（比如 GPT Pro 20x），装到服务器上就能公网分发——本机版只能服务自己或局域网，一把 key 给团队 / 朋友，不用再搭 VPN&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;多客户端复用&lt;/strong&gt;：Codex、Claude Code、Gemini CLI、Cursor 等共用同一把 key，新增或替换上游时客户端不动&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="一准备"&gt;&lt;a href="#%e4%b8%80%e5%87%86%e5%a4%87" class="header-anchor"&gt;&lt;/a&gt;一、准备&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;项&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;说明&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;服务器&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;能跑 nginx 的 Linux（本文 Ubuntu 24.04），CPA 常驻内存约 57MB&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;域名 + 证书&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;反代必须有 HTTPS；没有就用 &lt;code&gt;certbot --nginx -d 你的域名&lt;/code&gt; 申请&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;nginx&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;反代与鉴权都在这一层&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;上游账号（可选）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ChatGPT / Claude / xAI / Kimi 等任一，用于 OAuth 登录&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;第三方 Key（可选）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DeepSeek 等 OpenAI 兼容服务，官方额度用完后接管&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;版本：CPA &lt;code&gt;v7.3.4&lt;/code&gt;、codex-cli &lt;code&gt;0.154.0&lt;/code&gt;。&lt;/p&gt;&#10;&lt;h2 id="二安装-cpa"&gt;&lt;a href="#%e4%ba%8c%e5%ae%89%e8%a3%85-cpa" class="header-anchor"&gt;&lt;/a&gt;二、安装 CPA&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL -o cpa.tar.gz &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://github.com/router-for-me/CLIProxyAPI/releases/download/v7.3.4/CLIProxyAPI_7.3.4_linux_amd64.tar.gz&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tar xzf cpa.tar.gz&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p ~/cliproxyapi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;install -m &lt;span class="m"&gt;0755&lt;/span&gt; cli-proxy-api ~/cliproxyapi/cli-proxy-api&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;单文件 Go 程序，约 64MB。用 systemd 托管：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /etc/systemd/system/cli-proxy-api.service&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;CLIProxyAPI - unified upstream gateway&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Wants&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;simple&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;azureuser # 改成你的运行用户&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/home/azureuser/cliproxyapi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/home/azureuser/cliproxyapi/cli-proxy-api -config /home/azureuser/.cli-proxy-api/config.yaml&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-failure&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;RestartSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;MemoryMax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;384M&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl daemon-reload&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; --now cli-proxy-api&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="三写配置"&gt;&lt;a href="#%e4%b8%89%e5%86%99%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;三、写配置&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;~/.cli-proxy-api/config.yaml&lt;/code&gt;：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 只监听本机：公网必须先过 nginx&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8317&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;remote-management&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;allow-remote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 反代场景建议 true&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;secret-key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;管理密钥&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 明文填，启动时自动 bcrypt 加密回写&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;auth-dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/home/azureuser/.cli-proxy-api&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# OAuth 凭证目录&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;api-keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 客户端访问 CPA 用的密钥&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;sk-cpa-xxxxxxxx&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;三个关键点：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;host&lt;/code&gt; 绑 &lt;code&gt;127.0.0.1&lt;/code&gt;，公网只能从 nginx 进&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;secret-key&lt;/code&gt; 管管理接口，&lt;code&gt;api-keys&lt;/code&gt; 管客户端调用，两者别混&lt;/li&gt;&#10;&lt;li&gt;上游 provider 全部在&lt;strong&gt;管理面板&lt;/strong&gt;里配，配置文件保持干净&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="四登录上游账号"&gt;&lt;a href="#%e5%9b%9b%e7%99%bb%e5%bd%95%e4%b8%8a%e6%b8%b8%e8%b4%a6%e5%8f%b7" class="header-anchor"&gt;&lt;/a&gt;四、登录上游账号&#10;&lt;/h2&gt;&lt;p&gt;CPA 内置多种 OAuth 登录，按需挑：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;上游&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;命令&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ChatGPT / Codex&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;-codex-device-login&lt;/code&gt;（服务器）、&lt;code&gt;-codex-login&lt;/code&gt;（本机浏览器）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Claude&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;-claude-login&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;xAI&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;-xai-login&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Kimi&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;-kimi-login&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Meta&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;-meta-login&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Devin&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;-devin-login&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Antigravity&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;-antigravity-login&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Google Vertex&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;-vertex-import 服务账号.json&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;以无浏览器的服务器为例，用设备码登录 Codex：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./cli-proxy-api -config ~/.cli-proxy-api/config.yaml -codex-device-login&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Codex device URL: https://auth.openai.com/codex/device&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Codex device code: XXXX-XXXX&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;打开网址输码授权，凭证落到 &lt;code&gt;auth-dir&lt;/code&gt;。&lt;/p&gt;&#10;&lt;p&gt;当然也可以直接在 &lt;strong&gt;Web 面板&lt;/strong&gt;里点「认证文件 → 对应上游 → 发起登录」。OAuth 回调端口被占用时用 &lt;code&gt;-oauth-callback-port&lt;/code&gt; 指定，无浏览器加 &lt;code&gt;-no-browser&lt;/code&gt;。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;⚠️ &lt;strong&gt;不要照搬&lt;/strong&gt;教程里的 &lt;code&gt;forced_login_method = &amp;quot;api&amp;quot;&lt;/code&gt; / &lt;code&gt;preferred_auth_method = &amp;quot;apikey&amp;quot;&lt;/code&gt;：已有 ChatGPT 登录态时，Codex 会判定「要用 API key 登录」，登出并删掉 &lt;code&gt;auth.json&lt;/code&gt;。加 provider 只靠 &lt;code&gt;env_key&lt;/code&gt;。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h2 id="五nginx-反代分发核心"&gt;&lt;a href="#%e4%ba%94nginx-%e5%8f%8d%e4%bb%a3%e5%88%86%e5%8f%91%e6%a0%b8%e5%bf%83" class="header-anchor"&gt;&lt;/a&gt;五、nginx 反代分发（核心）&#10;&lt;/h2&gt;&lt;p&gt;CPA 只监听本机，对外必须经 nginx。策略：&lt;strong&gt;隐藏路径 + Basic Auth + 限速&lt;/strong&gt;，三条路径分开管面板页、管理 API、客户端 API。&lt;/p&gt;&#10;&lt;h3 id="1-建账号密码"&gt;&lt;a href="#1-%e5%bb%ba%e8%b4%a6%e5%8f%b7%e5%af%86%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;1. 建账号密码&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo htpasswd -c /etc/nginx/.htpasswd-cpa cpadmin &lt;span class="c1"&gt;# 没有 htpasswd 就先装 apache2-utils&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-写反代片段"&gt;&lt;a href="#2-%e5%86%99%e5%8f%8d%e4%bb%a3%e7%89%87%e6%ae%b5" class="header-anchor"&gt;&lt;/a&gt;2. 写反代片段&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /etc/nginx/snippets/cpa.conf（用 include 引入 server 块）&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 限速区（放 http 块；已定义过就跳过）&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;limit_req_zone&lt;/span&gt; &lt;span class="nv"&gt;$binary_remote_addr&lt;/span&gt; &lt;span class="s"&gt;zone=admin_zone:10m&lt;/span&gt; &lt;span class="s"&gt;rate=10r/m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/cpa-adm-XXXXXXXX&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;/cpa-adm-XXXXXXXX/management.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/cpa-adm-XXXXXXXX/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;/cpa-adm-XXXXXXXX/management.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ① 面板静态页：Basic Auth + 限速&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="s"&gt;^~&lt;/span&gt; &lt;span class="s"&gt;/cpa-adm-XXXXXXXX/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;auth_basic&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;CPA&lt;/span&gt; &lt;span class="s"&gt;Admin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;auth_basic_user_file&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/.htpasswd-cpa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;limit_req&lt;/span&gt; &lt;span class="s"&gt;zone=admin_zone&lt;/span&gt; &lt;span class="s"&gt;burst=60&lt;/span&gt; &lt;span class="s"&gt;nodelay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8317/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_buffering&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# SSE / 流式必需&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_read_timeout&lt;/span&gt; &lt;span class="s"&gt;3600s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# 长任务别被 60s 掐断&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;client_max_body_size&lt;/span&gt; &lt;span class="mi"&gt;200m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ② 管理 API：面板默认就调这里，鉴权交给 CPA&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="s"&gt;^~&lt;/span&gt; &lt;span class="s"&gt;/v0/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8317/v0/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_buffering&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ③ 客户端 API：隐藏路径 + api-key&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="s"&gt;^~&lt;/span&gt; &lt;span class="s"&gt;/cpa-api-XXXXXXXX/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8317/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_buffering&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_read_timeout&lt;/span&gt; &lt;span class="s"&gt;3600s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;client_max_body_size&lt;/span&gt; &lt;span class="mi"&gt;200m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;XXXXXXXX&lt;/code&gt; 换成自己的随机串（路径本身就是一层防护）。没有现成 server 块的话，最小骨架：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;你的域名&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="s"&gt;/etc/letsencrypt/live/你的域名/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="s"&gt;/etc/letsencrypt/live/你的域名/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/snippets/cpa.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-为什么要拆路径"&gt;&lt;a href="#3-%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e6%8b%86%e8%b7%af%e5%be%84" class="header-anchor"&gt;&lt;/a&gt;3. 为什么要拆路径&#10;&lt;/h3&gt;&lt;p&gt;nginx 的 &lt;code&gt;auth_basic&lt;/code&gt; 用 &lt;code&gt;Authorization: Basic ...&lt;/code&gt; 认证，而 CPA 面板用 &lt;code&gt;Authorization: Bearer &amp;lt;管理密钥&amp;gt;&lt;/code&gt; 调 API（&lt;code&gt;management.html&lt;/code&gt; 里写死了 &lt;code&gt;Bearer ${managementKey}&lt;/code&gt;）。两者共用同一个头：Bearer 会顶掉 Basic，&lt;code&gt;auth_basic&lt;/code&gt; 直接 401；用变量喂空值也不会关闭认证（实测返回 &lt;code&gt;realm=&amp;quot;&amp;quot;&lt;/code&gt; 的 401）。&lt;/p&gt;&#10;&lt;p&gt;所以面板页归 Basic Auth，管理 API 走一条不带 &lt;code&gt;auth_basic&lt;/code&gt; 的路径，由 CPA 自己校验密钥；客户端 API 再走一条隐藏路径：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;路径&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;用途&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;鉴权&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;/cpa-adm-XXXXXXXX/&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;面板静态页&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Basic Auth&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;/v0/&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;管理 API（面板默认调用）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CPA 管理密钥（Bearer）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;/cpa-api-XXXXXXXX/v1/&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;客户端 API&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CPA api-key（Bearer）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3 id="4-面板默认服务地址不带路径"&gt;&lt;a href="#4-%e9%9d%a2%e6%9d%bf%e9%bb%98%e8%ae%a4%e6%9c%8d%e5%8a%a1%e5%9c%b0%e5%9d%80%e4%b8%8d%e5%b8%a6%e8%b7%af%e5%be%84" class="header-anchor"&gt;&lt;/a&gt;4. 面板默认服务地址不带路径&#10;&lt;/h3&gt;&lt;p&gt;面板取的是 &lt;code&gt;window.location&lt;/code&gt; 里不带路径的协议 + 域名 + 端口：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;$f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Zf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;//&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="sb"&gt;`:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;所以请求会打到 &lt;code&gt;https://域名/v0/management/...&lt;/code&gt;（根路径），而不是 &lt;code&gt;/cpa-mgmt-.../&lt;/code&gt; 下的那条。这样配会 404，nginx 日志里能看到 &lt;code&gt;/v0/management/config&lt;/code&gt; 没有路由。&lt;/p&gt;&#10;&lt;p&gt;两个解法：面板里手动把服务地址填全，或在 nginx 补一条根路径 &lt;code&gt;/v0/&lt;/code&gt; 路由。上面片段用的是后者。&lt;/p&gt;&#10;&lt;p&gt;改完检查并重载：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo nginx -t &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo systemctl reload nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="六接入第三方-api以-deepseek-为例"&gt;&lt;a href="#%e5%85%ad%e6%8e%a5%e5%85%a5%e7%ac%ac%e4%b8%89%e6%96%b9-api%e4%bb%a5-deepseek-%e4%b8%ba%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;六、接入第三方 API（以 DeepSeek 为例）&#10;&lt;/h2&gt;&lt;p&gt;登录面板（&lt;code&gt;https://域名/cpa-adm-XXXXXXXX/management.html&lt;/code&gt;）后，在「提供商」里加一条 OpenAI 兼容：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;字段&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;值&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;名称&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;deepseek&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;base-url&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;https://api.deepseek.com&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;api-key&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DeepSeek 的 &lt;code&gt;sk-...&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;模型&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;deepseek-flash&lt;/code&gt;（要更大就再加 &lt;code&gt;deepseek-v4-pro&lt;/code&gt;）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&lt;code&gt;base-url&lt;/code&gt; 带不带 &lt;code&gt;/v1&lt;/code&gt; 都行；&lt;code&gt;alias&lt;/code&gt; 留空会用 &lt;code&gt;name&lt;/code&gt; 当模型名。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;任何 OpenAI 兼容服务同理：填 &lt;code&gt;base-url&lt;/code&gt; + &lt;code&gt;api-key&lt;/code&gt; 即可，官方 OAuth 与这些第三方模型会一起出现在 &lt;code&gt;/v1/models&lt;/code&gt; 里。保存后面板会把配置写回 &lt;code&gt;config.yaml&lt;/code&gt; 并热重载，无需重启。&lt;/p&gt;&#10;&lt;h2 id="七验证"&gt;&lt;a href="#%e4%b8%83%e9%aa%8c%e8%af%81" class="header-anchor"&gt;&lt;/a&gt;七、验证&#10;&lt;/h2&gt;&lt;p&gt;三种协议各测一遍（走公网入口）：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://域名/cpa-api-XXXXXXXX/v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-cpa-xxxxxxxx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1) 模型列表（官方 OAuth 与第三方模型的合集）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -s &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/models&amp;#34;&lt;/span&gt; -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$KEY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2) OpenAI 协议&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -s &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/chat/completions&amp;#34;&lt;/span&gt; -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$KEY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d &lt;span class="s1"&gt;&amp;#39;{&amp;#34;model&amp;#34;:&amp;#34;deepseek-flash&amp;#34;,&amp;#34;messages&amp;#34;:[{&amp;#34;role&amp;#34;:&amp;#34;user&amp;#34;,&amp;#34;content&amp;#34;:&amp;#34;回复：A-OK&amp;#34;}]}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# → A-OK&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3) Responses 协议（Codex 用的就是它）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -s &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/responses&amp;#34;&lt;/span&gt; -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$KEY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d &lt;span class="s1"&gt;&amp;#39;{&amp;#34;model&amp;#34;:&amp;#34;deepseek-flash&amp;#34;,&amp;#34;input&amp;#34;:&amp;#34;回复：R-OK&amp;#34;}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;鉴权矩阵（都应满足）：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;面板页 无认证 → 401&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;面板页 Basic → 200&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;管理API 正确 Bearer → 200&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;管理API 错误/无 密钥 → 401&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;分发API 正确 key → 200&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;分发API 无 key → 401&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="八客户端接入"&gt;&lt;a href="#%e5%85%ab%e5%ae%a2%e6%88%b7%e7%ab%af%e6%8e%a5%e5%85%a5" class="header-anchor"&gt;&lt;/a&gt;八、客户端接入&#10;&lt;/h2&gt;&lt;p&gt;Codex 指向 CPA（&lt;code&gt;~/.codex/config.toml&lt;/code&gt;）：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;model_provider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;cpa&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;gpt-5.6-sol&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;model_providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cpa&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;CPA&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;base_url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://127.0.0.1:8317/v1&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;experimental_bearer_token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sk-cpa-xxxxxxxx&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;wire_api&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;responses&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;supports_websockets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;/model&lt;/code&gt; 里会同时出现官方 OAuth 的模型和第三方模型，额度用光时切过去，会话不断。&lt;/p&gt;&#10;&lt;p&gt;分发给其他客户端（同一把 key）：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# OpenAI 兼容&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;OPENAI_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; https://域名/cpa-api-XXXXXXXX/v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; sk-cpa-xxxxxxxx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Claude Code&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://域名/cpa-api-XXXXXXXX&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;ANTHROPIC_AUTH_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;sk-cpa-xxxxxxxx&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="九安全与分发建议"&gt;&lt;a href="#%e4%b9%9d%e5%ae%89%e5%85%a8%e4%b8%8e%e5%88%86%e5%8f%91%e5%bb%ba%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;九、安全与分发建议&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;CPA 只绑 &lt;code&gt;127.0.0.1&lt;/code&gt;，公网必须过 nginx（HTTPS）&lt;/li&gt;&#10;&lt;li&gt;面板页 Basic Auth + 管理密钥双因素；管理 API 连续 5 次失败封禁约 30 分钟&lt;/li&gt;&#10;&lt;li&gt;客户端 API 只靠 api-key，可随时增删（泄露一个删一个）&lt;/li&gt;&#10;&lt;li&gt;隐藏路径 + 限速，降低被扫概率&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;风险&lt;/strong&gt;：分发出去的官方模型请求烧的是自己账号的额度，给的人越多越可能封号。分发给不熟的人，建议只发第三方付费模型（按量计费）或加 IP 白名单。&lt;/p&gt;&#10;&lt;h2 id="附录为什么需要这层网关"&gt;&lt;a href="#%e9%99%84%e5%bd%95%e4%b8%ba%e4%bb%80%e4%b9%88%e9%9c%80%e8%a6%81%e8%bf%99%e5%b1%82%e7%bd%91%e5%85%b3" class="header-anchor"&gt;&lt;/a&gt;附录：为什么需要这层网关&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/model&lt;/code&gt; 弹出的是当前 provider 的模型目录，切的是模型 slug，不是 provider。翻 Codex 源码可确认：&lt;code&gt;ModelPreset&lt;/code&gt; 没有 provider 字段。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ModelPreset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 只有模型 slug&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// ... 没有 provider&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;会话里 provider 固定，想在多个上游之间切只有两条路：退出后用不同 &lt;code&gt;--profile&lt;/code&gt; 重开，或&lt;strong&gt;把上游合成一个 provider&lt;/strong&gt;——后者就是第 2–6 节做的事。&lt;/p&gt;&#10;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#10;&lt;/h2&gt;&lt;ol&gt;&#10;&lt;li&gt;部署顺序：装 CPA → 写配置 → 登录上游 → nginx 反代 → 加第三方 API → 验证&lt;/li&gt;&#10;&lt;li&gt;登录方式按上游选：Codex 用设备码，Claude/xAI/Kimi 等用对应 &lt;code&gt;-xxx-login&lt;/code&gt;，Vertex 导入服务账号&lt;/li&gt;&#10;&lt;li&gt;反代必须拆路径：面板页走 Basic Auth，管理/客户端 API 走 Bearer&lt;/li&gt;&#10;&lt;li&gt;面板默认服务地址不带路径，记得补 &lt;code&gt;/v0/&lt;/code&gt; 路由&lt;/li&gt;&#10;&lt;li&gt;网关让客户端只配一个 &lt;code&gt;base_url&lt;/code&gt; 就能跨上游切换；对外分发的额度风险要提前评估&lt;/li&gt;&#10;&lt;/ol&gt;&#10;</description></item><item><title>Claude Code 接入 DeepSeek API</title><link>https://20.48.50.55.sslip.io/posts/2026-09-16-claude-code-api/</link><pubDate>Thu, 17 Sep 2026 00:30:00 +0800</pubDate><guid>https://20.48.50.55.sslip.io/posts/2026-09-16-claude-code-api/</guid><description>&lt;p&gt;Claude Code 默认要登录 Anthropic 官方账号；换成自己的 API 只需要两个变量：&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; 和 &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt;。本文以 DeepSeek 为例（撰写时版本：Claude Code 2.1.178，模型 &lt;code&gt;deepseek-v4-pro[1m]&lt;/code&gt; / &lt;code&gt;deepseek-flash&lt;/code&gt;）。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="配置来源与请求链路" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/claude-code-api/config-flow.svg"&gt;&lt;/p&gt;&#10;&lt;h2 id="一最小配置"&gt;&lt;a href="#%e4%b8%80%e6%9c%80%e5%b0%8f%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;一、最小配置&#10;&lt;/h2&gt;&lt;p&gt;配置文件位置：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;系统&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;路径&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Linux / macOS / WSL&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Windows&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;C:\Users\&amp;lt;用户名&amp;gt;\.claude\settings.json&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;把下面这段抄进 &lt;code&gt;settings.json&lt;/code&gt;（BASE_URL、TOKEN、模型名换成自己的）：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;env&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ANTHROPIC_BASE_URL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://api.deepseek.com/anthropic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ANTHROPIC_AUTH_TOKEN&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sk-你的key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ANTHROPIC_MODEL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deepseek-v4-pro[1m]&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ANTHROPIC_DEFAULT_HAIKU_MODEL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deepseek-flash&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ANTHROPIC_DEFAULT_SONNET_MODEL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deepseek-flash&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ANTHROPIC_DEFAULT_OPUS_MODEL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deepseek-v4-pro[1m]&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;model&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;haiku&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;includeCoAuthoredBy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;字段含义：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;字段&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;作用&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;请求发到哪：官方、兼容端点或中转站&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;鉴权 token（服务商给的 &lt;code&gt;sk-...&lt;/code&gt;）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ANTHROPIC_MODEL&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;默认模型名&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ANTHROPIC_DEFAULT_*_MODEL&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;把 Claude Code 的档位映射到服务商的模型&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;model&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;默认用哪一档：&lt;code&gt;haiku&lt;/code&gt; / &lt;code&gt;sonnet&lt;/code&gt; / &lt;code&gt;opus&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;includeCoAuthoredBy&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;提交信息里是否带 Claude 署名，一般关掉&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="二模型档位映射"&gt;&lt;a href="#%e4%ba%8c%e6%a8%a1%e5%9e%8b%e6%a1%a3%e4%bd%8d%e6%98%a0%e5%b0%84" class="header-anchor"&gt;&lt;/a&gt;二、模型档位映射&#10;&lt;/h2&gt;&lt;p&gt;Claude Code 内部按&lt;strong&gt;档位&lt;/strong&gt;（不是具体模型名）发请求，2.x 共四档：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;档位&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;环境变量&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;用途&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;fable&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ANTHROPIC_DEFAULT_FABLE_MODEL&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;新增档位&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;haiku&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ANTHROPIC_DEFAULT_HAIKU_MODEL&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;后台小任务、快速响应&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;sonnet&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ANTHROPIC_DEFAULT_SONNET_MODEL&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;日常主力&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;opus&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ANTHROPIC_DEFAULT_OPUS_MODEL&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;复杂任务&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;不映射也能启动，但服务商不认识 &lt;code&gt;claude-*&lt;/code&gt; 这类模型名就会报错。DeepSeek 只有两个模型，本机这样映射：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;opus → deepseek-v4-pro[1m] # 复杂任务用 pro&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sonnet → deepseek-flash&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;haiku → deepseek-flash # 小任务用便宜的 flash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;模型名实测：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;名称&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;结果&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;deepseek-flash&lt;/code&gt; / &lt;code&gt;deepseek-v4-pro&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;✅ 官方 ID&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;deepseek-v4-pro[1m]&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;✅ 1M 上下文变体，服务商不支持时去掉后缀&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;deepseek-v4-flash&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;✅ 旧别名，仍可用&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;❌ 400，不是有效模型名&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;官方列表可自查：&lt;code&gt;curl -H &amp;quot;Authorization: Bearer $KEY&amp;quot; https://api.deepseek.com/models&lt;/code&gt;。&lt;/p&gt;&#10;&lt;p&gt;老配置里常见的 &lt;code&gt;ANTHROPIC_SMALL_FAST_MODEL&lt;/code&gt; 等价于 haiku 档。&lt;/p&gt;&#10;&lt;h2 id="三配置来源与优先级"&gt;&lt;a href="#%e4%b8%89%e9%85%8d%e7%bd%ae%e6%9d%a5%e6%ba%90%e4%b8%8e%e4%bc%98%e5%85%88%e7%ba%a7" class="header-anchor"&gt;&lt;/a&gt;三、配置来源与优先级&#10;&lt;/h2&gt;&lt;p&gt;三个地方都能改，优先级从高到低：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;code&gt;--settings &amp;lt;file-or-json&amp;gt;&lt;/code&gt;：只对当前这条命令生效&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt; 的 &lt;code&gt;env&lt;/code&gt; 段：最常用，一次配好&lt;/li&gt;&#10;&lt;li&gt;Shell 环境变量：&lt;code&gt;export ANTHROPIC_BASE_URL=...&lt;/code&gt;，适合临时测试&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;实测：shell 里给错的 BASE_URL，&lt;code&gt;settings.json&lt;/code&gt; 的 &lt;code&gt;env&lt;/code&gt; 仍然覆盖。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;--setting-sources user,project,local&lt;/code&gt; 可以控制加载哪些来源。&lt;/p&gt;&#10;&lt;h2 id="四多套配置切换"&gt;&lt;a href="#%e5%9b%9b%e5%a4%9a%e5%a5%97%e9%85%8d%e7%bd%ae%e5%88%87%e6%8d%a2" class="header-anchor"&gt;&lt;/a&gt;四、多套配置切换&#10;&lt;/h2&gt;&lt;p&gt;需要对比不同服务商时，把配置存成不同文件名，切换时用 &lt;code&gt;--settings&lt;/code&gt; 指定：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="settings.json 配置与多套配置切换" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/claude-code-api/settings-terminal.svg"&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls ~/.claude/settings.json*&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# settings.json settings.json.bak settings.json.relay-a settings.json.relay-b&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;claude --settings ~/.claude/settings.json.relay-a &lt;span class="c1"&gt;# 这次用它跑&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;要固定切换就做成别名：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ~/.bashrc&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; claude-d&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;claude --settings ~/.claude/settings.json&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# 默认：DeepSeek&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; claude-a&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;claude --settings ~/.claude/settings.json.relay-a&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# 备用线路&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;配置&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;BASE_URL&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;opus / haiku 映射&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;默认（DeepSeek）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;https://api.deepseek.com/anthropic&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;deepseek-v4-pro[1m]&lt;/code&gt; / &lt;code&gt;deepseek-flash&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;中转 A&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;https://中转站域名&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;claude-opus-4-8&lt;/code&gt; / &lt;code&gt;claude-haiku-4-5&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;中转 B&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;https://另一个中转站&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;claude-opus-4-8&lt;/code&gt; / &lt;code&gt;gpt-5.5&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="五windows-端"&gt;&lt;a href="#%e4%ba%94windows-%e7%ab%af" class="header-anchor"&gt;&lt;/a&gt;五、Windows 端&#10;&lt;/h2&gt;&lt;p&gt;同样放 &lt;code&gt;%USERPROFILE%\.claude\settings.json&lt;/code&gt;，结构完全一致。环境变量写法不同：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 临时（当前窗口）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$env:ANTHROPIC_BASE_URL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://api.deepseek.com/anthropic&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$env:ANTHROPIC_AUTH_TOKEN&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sk-你的key&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 永久（写入用户环境变量，重开终端生效）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;setx&lt;/span&gt; &lt;span class="n"&gt;ANTHROPIC_BASE_URL&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://api.deepseek.com/anthropic&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;setx&lt;/span&gt; &lt;span class="n"&gt;ANTHROPIC_AUTH_TOKEN&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sk-你的key&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="六验证"&gt;&lt;a href="#%e5%85%ad%e9%aa%8c%e8%af%81" class="header-anchor"&gt;&lt;/a&gt;六、验证&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;claude -p &lt;span class="s2"&gt;&amp;#34;只回复 ok&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 返回 ok 就通了&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;交互模式里用 &lt;code&gt;/status&lt;/code&gt; 查看当前生效的 BASE_URL 和模型。&lt;/p&gt;&#10;&lt;h2 id="七常见报错"&gt;&lt;a href="#%e4%b8%83%e5%b8%b8%e8%a7%81%e6%8a%a5%e9%94%99" class="header-anchor"&gt;&lt;/a&gt;七、常见报错&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;现象&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;原因&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;解法&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;401 Unauthorized&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;TOKEN 错、过期或没配&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;重新生成并更新 &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;400&lt;/code&gt; / &lt;code&gt;model not found&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;模型名不在服务商列表&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;用 &lt;code&gt;/models&lt;/code&gt; 接口核对；DeepSeek 只有 &lt;code&gt;deepseek-v4-pro&lt;/code&gt; / &lt;code&gt;deepseek-flash&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;404&lt;/code&gt; / &lt;code&gt;invalid path&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;BASE_URL 少了路径&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;兼容端点通常有固定路径（DeepSeek 是 &lt;code&gt;/anthropic&lt;/code&gt;），按服务商文档填全&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;缓存相关报错&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;中转不支持 prompt caching&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;设 &lt;code&gt;DISABLE_PROMPT_CACHING=1&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;网关要求额外 header&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;中转鉴权方式不同&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ANTHROPIC_CUSTOM_HEADERS&lt;/code&gt;，如 &lt;code&gt;&amp;quot;x-api-key: xxx&amp;quot;&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;请求发去了奇怪的地方&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;代理环境变量劫持&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;检查 &lt;code&gt;HTTP_PROXY&lt;/code&gt; / &lt;code&gt;HTTPS_PROXY&lt;/code&gt;，必要时 unset&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;配了 env 仍走官方&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;交互模式里 &lt;code&gt;/login&lt;/code&gt; 登录过官方账号&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;settings.json&lt;/code&gt; 的 &lt;code&gt;env&lt;/code&gt; 优先级更高；必要时 &lt;code&gt;/logout&lt;/code&gt; 清除登录态&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="八安全"&gt;&lt;a href="#%e5%85%ab%e5%ae%89%e5%85%a8" class="header-anchor"&gt;&lt;/a&gt;八、安全&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;key 只放本机&lt;/strong&gt;：不要提交进仓库，也不要用共享 &lt;code&gt;settings.json&lt;/code&gt; 的方式「同步配置」&lt;/li&gt;&#10;&lt;li&gt;文件权限：&lt;code&gt;chmod 600 ~/.claude/settings.json&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;权限白名单放 &lt;code&gt;settings.local.json&lt;/code&gt;：本机就是这么分的——&lt;code&gt;settings.json&lt;/code&gt; 放 provider 配置，&lt;code&gt;settings.local.json&lt;/code&gt; 放工具权限&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#10;&lt;/h2&gt;&lt;ol&gt;&#10;&lt;li&gt;切 API = 改 &lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; + &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt;，写进 &lt;code&gt;~/.claude/settings.json&lt;/code&gt; 的 &lt;code&gt;env&lt;/code&gt; 段&lt;/li&gt;&#10;&lt;li&gt;服务商不认 &lt;code&gt;claude-*&lt;/code&gt; 模型名时，用 &lt;code&gt;ANTHROPIC_DEFAULT_{HAIKU,SONNET,OPUS}_MODEL&lt;/code&gt; 做映射&lt;/li&gt;&#10;&lt;li&gt;模型名以服务商 &lt;code&gt;/models&lt;/code&gt; 列表为准，不要凭记忆写&lt;/li&gt;&#10;&lt;li&gt;多套配置存成不同文件，&lt;code&gt;claude --settings xxx.json&lt;/code&gt; 临时切换&lt;/li&gt;&#10;&lt;li&gt;key 不进仓库，文件权限 600&lt;/li&gt;&#10;&lt;/ol&gt;&#10;</description></item><item><title>C 盘爆红怎么办：先清理，再扩容</title><link>https://20.48.50.55.sslip.io/posts/2026-09-16-c-drive-full/</link><pubDate>Wed, 16 Sep 2026 23:50:00 +0800</pubDate><guid>https://20.48.50.55.sslip.io/posts/2026-09-16-c-drive-full/</guid><description>&lt;p&gt;C 盘变红只有两种原因：&lt;strong&gt;垃圾太多&lt;/strong&gt;，或者&lt;strong&gt;分区给太小&lt;/strong&gt;。前者靠清理，后者靠扩容。扩容也可以用 Windows 自带的磁盘管理，但代价通常是先删掉 D 盘；用 DiskGenius 可以无损完成，分两步走。&lt;/p&gt;&#10;&lt;p&gt;本机就是典型场景：一块 954GB 的盘，C 在左（295GB），D 在右（657GB，空着 292GB）。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="本机磁盘布局：同一块盘上的 C 与 D" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/c-drive-full/dg-layout.png"&gt;&lt;/p&gt;&#10;&lt;h2 id="一先判断清理还是扩容"&gt;&lt;a href="#%e4%b8%80%e5%85%88%e5%88%a4%e6%96%ad%e6%b8%85%e7%90%86%e8%bf%98%e6%98%af%e6%89%a9%e5%ae%b9" class="header-anchor"&gt;&lt;/a&gt;一、先判断：清理还是扩容&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;现象&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;原因&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;做法&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;C 盘 200–300GB，D 盘空一大半&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;分区分配不合理&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;扩容（第四节）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;C 盘 500GB+ 仍然爆红&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;文件太多：缓存 / 更新残留 / 休眠文件 / 还原点&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;清理（第三节）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;两者都有&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;—&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;先清理，再扩容&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;先看清两个数字：C 盘总容量和实际占用（&lt;code&gt;设置 → 系统 → 存储&lt;/code&gt;，或 DiskGenius 的分区信息）。&lt;/p&gt;&#10;&lt;h2 id="二为什么不用自带的磁盘管理"&gt;&lt;a href="#%e4%ba%8c%e4%b8%ba%e4%bb%80%e4%b9%88%e4%b8%8d%e7%94%a8%e8%87%aa%e5%b8%a6%e7%9a%84%e7%a3%81%e7%9b%98%e7%ae%a1%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;二、为什么不用自带的磁盘管理&#10;&lt;/h2&gt;&lt;p&gt;Windows 自带「磁盘管理 → 扩展卷」有个硬性要求：&lt;strong&gt;未分配空间必须紧贴在 C 盘右侧&lt;/strong&gt;。而 C 右边就是 D，所以自带工具只剩三条路：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;删掉 D → 扩展 C → 重建 D：数据要来回搬，耗时且容易出错&lt;/li&gt;&#10;&lt;li&gt;用第三方工具把 D 左侧的空间挪出来&lt;/li&gt;&#10;&lt;li&gt;不扩容，继续清理&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;DiskGenius 做的是第 2 条。&lt;/p&gt;&#10;&lt;h2 id="三清理先榨干现有空间"&gt;&lt;a href="#%e4%b8%89%e6%b8%85%e7%90%86%e5%85%88%e6%a6%a8%e5%b9%b2%e7%8e%b0%e6%9c%89%e7%a9%ba%e9%97%b4" class="header-anchor"&gt;&lt;/a&gt;三、清理：先榨干现有空间&#10;&lt;/h2&gt;&lt;p&gt;按「释放量 / 风险」排序，以下都安全：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;项目&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;入口 / 命令&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;典型释放&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;说明&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Windows 更新缓存&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;设置 → 存储 → 临时文件&lt;/code&gt;，或 &lt;code&gt;cleanmgr&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;3–20 GB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不要手删 &lt;code&gt;SoftwareDistribution&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;旧版本组件&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;Dism /Online /Cleanup-Image /StartComponentCleanup&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2–10 GB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;WinSxS 只能靠它清&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;上一版系统&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;设置 → 存储 → 临时文件 → 以前的 Windows 安装&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;10–30 GB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;确认不回滚再删&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;休眠文件&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;powercfg /h off&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;≈ 内存大小&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;关掉会失去快速启动&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;系统还原点&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;vssadmin delete shadows /for=c: /oldest&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;视情况&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;保留最近的还原点&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;浏览器 / 开发缓存&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;各自设置里清&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;视情况&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;npm / pip / uv 的 cache 同理&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;回收站&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;右键清空&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;视情况&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;—&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;&lt;strong&gt;不要手动删&lt;/strong&gt;：&lt;code&gt;C:\Windows&lt;/code&gt;、&lt;code&gt;C:\Program Files&lt;/code&gt;、&lt;code&gt;C:\Users\...\AppData&lt;/code&gt; 下不认识的目录。&lt;/p&gt;&#10;&lt;h2 id="四diskgenius-两步法"&gt;&lt;a href="#%e5%9b%9bdiskgenius-%e4%b8%a4%e6%ad%a5%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;四、DiskGenius 两步法&#10;&lt;/h2&gt;&lt;p&gt;入口都在 &lt;strong&gt;Partition 菜单&lt;/strong&gt;：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="DiskGenius 的 Partition 菜单：Resize / Extend / Split" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/c-drive-full/dg-menu.png"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;前提&lt;/strong&gt;：C 与 D 在同一物理磁盘，且 C 在左、D 在右（DiskGenius 的磁盘图上能直接看出来）；重要数据先备份。&lt;/p&gt;&#10;&lt;h3 id="第一步拆分分区从-d-左侧划出空间"&gt;&lt;a href="#%e7%ac%ac%e4%b8%80%e6%ad%a5%e6%8b%86%e5%88%86%e5%88%86%e5%8c%ba%e4%bb%8e-d-%e5%b7%a6%e4%be%a7%e5%88%92%e5%87%ba%e7%a9%ba%e9%97%b4" class="header-anchor"&gt;&lt;/a&gt;第一步：拆分分区，从 D 左侧划出空间&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Partition → Split Partition&lt;/code&gt;，选 D 盘，从&lt;strong&gt;左侧&lt;/strong&gt;划出想要的大小（例如 100GB）。&lt;/p&gt;&#10;&lt;p&gt;这一步不动 D 的数据，只是把它缩小，并在 C 与 D 之间留出一块「未分配」空间。&lt;/p&gt;&#10;&lt;h3 id="第二步扩容分区把空间给-c"&gt;&lt;a href="#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e6%89%a9%e5%ae%b9%e5%88%86%e5%8c%ba%e6%8a%8a%e7%a9%ba%e9%97%b4%e7%bb%99-c" class="header-anchor"&gt;&lt;/a&gt;第二步：扩容分区，把空间给 C&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Partition → Extend Partition&lt;/code&gt;，选 C，把右侧的未分配空间并入。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="两步法示意" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/c-drive-full/two-step.svg"&gt;&lt;/p&gt;&#10;&lt;p&gt;两步的本质和「直接用 DiskGenius 扩容 C」一样，拆开的好处是：任何一步出问题都能立即停下，不会卡在中间状态。&lt;/p&gt;&#10;&lt;p&gt;操作完成后跑一次 &lt;code&gt;chkdsk C: /f&lt;/code&gt; 检查。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;思路参考：知乎&lt;a class="link" href="https://zhuanlan.zhihu.com/p/1940066958809760807" target="_blank" rel="noopener"&#10; &gt;《用 DiskGenius 扩充 C 盘空间》&lt;/a&gt;。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h2 id="五风险检查清单"&gt;&lt;a href="#%e4%ba%94%e9%a3%8e%e9%99%a9%e6%a3%80%e6%9f%a5%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;五、风险检查清单&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;检查项&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;原因&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;备份重要数据&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;分区操作有失败概率&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;BitLocker 先暂停或解密&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;加密卷上动分区容易出问题&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;笔记本接电源、关闭休眠&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;操作中断可能损坏分区表&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;尽量在 PE 下操作&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;系统盘正在使用时，部分操作会被占用&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;关掉其他磁盘工具&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;避免两个程序同时改分区表&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;操作后验证&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;重启、&lt;code&gt;chkdsk&lt;/code&gt;、确认 D 盘数据完好&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#10;&lt;/h2&gt;&lt;ol&gt;&#10;&lt;li&gt;C 盘红了先分清：&lt;strong&gt;文件多&lt;/strong&gt;就清理，&lt;strong&gt;分区小&lt;/strong&gt;才扩容&lt;/li&gt;&#10;&lt;li&gt;自带磁盘管理要求「右侧紧邻未分配」，C 在左时基本用不了&lt;/li&gt;&#10;&lt;li&gt;DiskGenius 的稳妥姿势是&lt;strong&gt;两步&lt;/strong&gt;：先 Split 出空间，再 Extend 给 C&lt;/li&gt;&#10;&lt;li&gt;操作前备份、暂停 BitLocker、接电源；操作后 &lt;code&gt;chkdsk&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;清理和扩容不冲突：先清理释放，再扩容治本&lt;/li&gt;&#10;&lt;/ol&gt;&#10;</description></item><item><title>白嫖 Azure 学生订阅：$100 额度 + 一台常驻 VPS</title><link>https://20.48.50.55.sslip.io/posts/2026-09-16-azure-student-vps/</link><pubDate>Wed, 16 Sep 2026 23:30:00 +0800</pubDate><guid>https://20.48.50.55.sslip.io/posts/2026-09-16-azure-student-vps/</guid><description>&lt;p&gt;这个博客和代理服务跑在一台 &lt;strong&gt;Azure 学生订阅&lt;/strong&gt;的小机器上：日本东部、2 vCPU / 892MB，由 $100 学生额度覆盖。以下是从认证到能用的全过程，数据来自这台机器的实测。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="五步流程" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/azure-student-vps/azure-flow.svg"&gt;&lt;/p&gt;&#10;&lt;h2 id="一入口学生认证"&gt;&lt;a href="#%e4%b8%80%e5%85%a5%e5%8f%a3%e5%ad%a6%e7%94%9f%e8%ae%a4%e8%af%81" class="header-anchor"&gt;&lt;/a&gt;一、入口：学生认证&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Azure for Students&lt;/strong&gt;：用学校邮箱完成学籍认证，就能拿到 &lt;strong&gt;$100 额度 / 年&lt;/strong&gt;，在读期间每年可续，&lt;strong&gt;不需要信用卡&lt;/strong&gt;。额度可以花在虚拟机、磁盘、流量等几乎所有资源上。&lt;/p&gt;&#10;&lt;p&gt;几点经验：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;edu&lt;/code&gt; 邮箱认证最快；没有的话按页面提示走其他学籍验证&lt;/li&gt;&#10;&lt;li&gt;免费服务清单里还有一批「12 个月免费」和「永久免费」的小资源，轻量用途基本够&lt;/li&gt;&#10;&lt;li&gt;认证通过后先别急着点创建——下一步更重要&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="二先查区域学生订阅有白名单"&gt;&lt;a href="#%e4%ba%8c%e5%85%88%e6%9f%a5%e5%8c%ba%e5%9f%9f%e5%ad%a6%e7%94%9f%e8%ae%a2%e9%98%85%e6%9c%89%e7%99%bd%e5%90%8d%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;二、先查区域：学生订阅有白名单&#10;&lt;/h2&gt;&lt;p&gt;注意：&lt;strong&gt;能列出的区域 ≠ 你能创建的区域&lt;/strong&gt;。学生订阅常有区域限制，创建时报 &lt;code&gt;RequestDisallowedByAzure&lt;/code&gt;，就是被策略拦了。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 列出推荐区域&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;az account list-locations &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --query &lt;span class="s2"&gt;&amp;#34;[?metadata.regionCategory==&amp;#39;Recommended&amp;#39;].{name:name, display:displayName}&amp;#34;&lt;/span&gt; -o table&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 查区域策略限制&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;az policy assignment list &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --query &lt;span class="s2"&gt;&amp;#34;[?contains(properties.displayName,&amp;#39;ocation&amp;#39;)].{name:name, display:properties.displayName}&amp;#34;&lt;/span&gt; -o table&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;选区域的思路：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;目的&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;区域&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;国内低延迟&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;japaneast&lt;/code&gt; / &lt;code&gt;koreacentral&lt;/code&gt; / &lt;code&gt;southeastasia&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;美区解锁&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;westus2&lt;/code&gt; / &lt;code&gt;westus3&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;这台机器在 &lt;code&gt;japaneast&lt;/code&gt;：实测国内直连 443 正常，22 端口会被干扰（TCP 握手能过，SSH 随即被 reset）——这也是本站 SSH 走代理连接的原因。&lt;/p&gt;&#10;&lt;h2 id="三开机器b-系列突发型"&gt;&lt;a href="#%e4%b8%89%e5%bc%80%e6%9c%ba%e5%99%a8b-%e7%b3%bb%e5%88%97%e7%aa%81%e5%8f%91%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;三、开机器：B 系列突发型&#10;&lt;/h2&gt;&lt;p&gt;个人用途首选 &lt;strong&gt;B 系列突发型&lt;/strong&gt;：便宜、平时攒 CPU 积分、闲时省额度。这台用的是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VM_SIZE = Standard_B2ats_v2 # 2 vCPU / 1 GiB，约 $8/月&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IMAGE = ubuntu-24_04-lts&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;创建时的三个要点：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;SSH 公钥 + 禁用密码登录&lt;/strong&gt;（&lt;code&gt;disablePasswordAuthentication=true&lt;/code&gt;）&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;NSG 只开必要端口&lt;/strong&gt;：22（建议限制来源）、80 / 443，代理端口按需&lt;/li&gt;&#10;&lt;li&gt;系统盘标准 SSD 就够：61G 实测只用了 4.6G&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="四开机后三件事"&gt;&lt;a href="#%e5%9b%9b%e5%bc%80%e6%9c%ba%e5%90%8e%e4%b8%89%e4%bb%b6%e4%ba%8b" class="header-anchor"&gt;&lt;/a&gt;四、开机后三件事&#10;&lt;/h2&gt;&lt;h3 id="1-加-swap小内存必做"&gt;&lt;a href="#1-%e5%8a%a0-swap%e5%b0%8f%e5%86%85%e5%ad%98%e5%bf%85%e5%81%9a" class="header-anchor"&gt;&lt;/a&gt;1. 加 swap（小内存必做）&#10;&lt;/h3&gt;&lt;p&gt;892MB 内存跑 nginx + Hugo 构建 + 代理，不加 swap 迟早 OOM：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo fallocate -l 2G /swapfile &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo chmod &lt;span class="m"&gt;600&lt;/span&gt; /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkswap /swapfile &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo swapon /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/swapfile none swap sw 0 0&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee -a /etc/fstab&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-开-bbr"&gt;&lt;a href="#2-%e5%bc%80-bbr" class="header-anchor"&gt;&lt;/a&gt;2. 开 BBR&#10;&lt;/h3&gt;&lt;p&gt;跨境线路建议开 BBR：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;net.core.default_qdisc=fq&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee -a /etc/sysctl.d/99-bbr.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;net.ipv4.tcp_congestion_control=bbr&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee -a /etc/sysctl.d/99-bbr.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo sysctl --system&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sysctl net.ipv4.tcp_congestion_control &lt;span class="c1"&gt;# 应输出 bbr&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-防火墙nsg-和系统防火墙只管一层"&gt;&lt;a href="#3-%e9%98%b2%e7%81%ab%e5%a2%99nsg-%e5%92%8c%e7%b3%bb%e7%bb%9f%e9%98%b2%e7%81%ab%e5%a2%99%e5%8f%aa%e7%ae%a1%e4%b8%80%e5%b1%82" class="header-anchor"&gt;&lt;/a&gt;3. 防火墙：NSG 和系统防火墙只管一层&#10;&lt;/h3&gt;&lt;p&gt;Azure 的 NSG 在云侧挡流量，系统里还有一层（ufw / iptables）。&lt;strong&gt;两层要么都配好、要么明确交给一层&lt;/strong&gt;。常见问题：NSG 放行了 443，机器里 ufw 却拦着。&lt;/p&gt;&#10;&lt;p&gt;这台机器实测 ufw 是 &lt;code&gt;inactive&lt;/code&gt;，访问控制统一交给 NSG。&lt;/p&gt;&#10;&lt;h2 id="五成本账100-能跑多久"&gt;&lt;a href="#%e4%ba%94%e6%88%90%e6%9c%ac%e8%b4%a6100-%e8%83%bd%e8%b7%91%e5%a4%9a%e4%b9%85" class="header-anchor"&gt;&lt;/a&gt;五、成本账：$100 能跑多久&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;B2ats_v2&lt;/code&gt; 约 &lt;strong&gt;$8/月&lt;/strong&gt; → $100 差不多正好&lt;strong&gt;一年&lt;/strong&gt;&lt;/li&gt;&#10;&lt;li&gt;只在需要时开机能更久，但注意：&lt;strong&gt;「停止」≠ 停止计费&lt;/strong&gt;，要在门户里选「停止(释放) / deallocate」&lt;/li&gt;&#10;&lt;li&gt;公网 IP、磁盘、流量都是单独计费项，删机器时别忘了一起清理&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="六踩坑清单"&gt;&lt;a href="#%e5%85%ad%e8%b8%a9%e5%9d%91%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;六、踩坑清单&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;坑&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;现象&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;解法&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;区域白名单&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;建 VM 报 &lt;code&gt;RequestDisallowedByAzure&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;换区域，或先跑第二步的查询&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Cloud Shell 没建存储&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;每次重开连不上 VM&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;首次使用时按提示创建存储账户&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;NSG 与系统防火墙不一致&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;端口「明明开了」却不通&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;两层都查，或统一交给 NSG&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;国内直连 22 端口&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SSH 被 reset（TCP 握手却成功）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;走代理连，或换高位端口观察&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;B 系列 CPU 积分&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;跑重活突然变慢&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;它是突发型，别当计算型用&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;892MB 内存&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;构建时 OOM&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;加 swap（见上）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="七这台机器的现状实测"&gt;&lt;a href="#%e4%b8%83%e8%bf%99%e5%8f%b0%e6%9c%ba%e5%99%a8%e7%9a%84%e7%8e%b0%e7%8a%b6%e5%ae%9e%e6%b5%8b" class="header-anchor"&gt;&lt;/a&gt;七、这台机器的现状（实测）&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="本机实测" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/azure-student-vps/vm-facts.svg"&gt;&lt;/p&gt;&#10;&lt;p&gt;它同时跑三件事：&lt;strong&gt;sing-box 代理、这个博客（nginx）、Filebrowser 文件管理&lt;/strong&gt;。日常内存 ~500MB，swap 仅 88MB，不跑重活完全够用。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;参考：linux.do&lt;a class="link" href="https://linux.do/t/topic/2717418" target="_blank" rel="noopener"&#10; &gt;《学生版 Azure 部署教程（含踩坑与解决方法）》&lt;/a&gt;，区域白名单和 NSG 的坑记录得更细。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#10;&lt;/h2&gt;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;学生认证是最划算的入口&lt;/strong&gt;：$100/年、免信用卡，够一台小机器跑一整年&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;动手前先查区域白名单&lt;/strong&gt;：能列出来 ≠ 能创建&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;B 系列突发型 + swap + BBR&lt;/strong&gt; 是小机器的标准三件套&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;NSG 和系统防火墙只管一层&lt;/strong&gt;，并记住是哪一层&lt;/li&gt;&#10;&lt;li&gt;不用时记得 &lt;strong&gt;deallocate&lt;/strong&gt;，否则额度会静默消耗&lt;/li&gt;&#10;&lt;/ol&gt;&#10;</description></item><item><title>把云主机挂成本地盘：WSL + Windows 双端实战</title><link>https://20.48.50.55.sslip.io/posts/2026-09-16-mount-azure-vm/</link><pubDate>Wed, 16 Sep 2026 22:40:00 +0800</pubDate><guid>https://20.48.50.55.sslip.io/posts/2026-09-16-mount-azure-vm/</guid><description>&lt;p&gt;博客和代理跑在同一台 Azure 小机器上，改文件只能 &lt;code&gt;ssh&lt;/code&gt; + &lt;code&gt;vim&lt;/code&gt;。于是把它的家目录挂成本地盘：WSL 里是普通路径，Windows 里是盘符。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="最终效果：资源管理器里的 Z: 盘" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/mount-azure-vm/z-drive.png"&gt;&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;场景&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;方案&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;终端 / VS Code&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;WSL：&lt;code&gt;~/remote/vm&lt;/code&gt;（sshfs + systemd，断线自愈）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;资源管理器&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Windows：&lt;strong&gt;Z: 盘&lt;/strong&gt;（rclone + WinFsp）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;前提：这台机器&lt;strong&gt;直连不通&lt;/strong&gt;——TCP 握手能通，SSH 立刻被 reset，所有流量必须走本机 clash 代理（&lt;code&gt;127.0.0.1:7890&lt;/code&gt;）。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="架构" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/mount-azure-vm/architecture.svg"&gt;&lt;/p&gt;&#10;&lt;h2 id="wsl-侧sshfs--systemd-自愈"&gt;&lt;a href="#wsl-%e4%be%a7sshfs--systemd-%e8%87%aa%e6%84%88" class="header-anchor"&gt;&lt;/a&gt;WSL 侧：sshfs + systemd 自愈&#10;&lt;/h2&gt;&lt;p&gt;sshfs 协议成熟、支持断线重连，用起来和本地路径没差别。先让 SSH 走代理：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Host proxy-vm&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; HostName 20.48.50.55&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; User azureuser&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; IdentityFile ~/.ssh/id_rsa&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ProxyCommand nc -X connect -x 127.0.0.1:7890 %h %p&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再交给 systemd user 服务托管，断线自动重挂：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ~/.config/systemd/user/azure-proxy-vm-mount.service&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Mount Azure proxy-vm home via SSHFS&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;StartLimitIntervalSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;simple&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStartPre&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;-/usr/bin/fusermount3 -uz %h/remote/vm # 清掉残留挂载&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/sshfs proxy-vm:/home/azureuser %h/remote/vm -f \&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/fusermount3 -u %h/remote/vm&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;RestartSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;default.target&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemctl --user &lt;span class="nb"&gt;enable&lt;/span&gt; --now azure-proxy-vm-mount&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo loginctl enable-linger &lt;span class="nv"&gt;$USER&lt;/span&gt; &lt;span class="c1"&gt;# 不登录也保活&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;实测：&lt;code&gt;kill -9&lt;/code&gt; 后 10 秒内自动恢复。&lt;/p&gt;&#10;&lt;h2 id="windows-侧为什么最后选了-rclone"&gt;&lt;a href="#windows-%e4%be%a7%e4%b8%ba%e4%bb%80%e4%b9%88%e6%9c%80%e5%90%8e%e9%80%89%e4%ba%86-rclone" class="header-anchor"&gt;&lt;/a&gt;Windows 侧：为什么最后选了 rclone&#10;&lt;/h2&gt;&lt;p&gt;目标：资源管理器里出现一个盘符。&lt;/p&gt;&#10;&lt;p&gt;先试了 &lt;strong&gt;SSHFS-Win&lt;/strong&gt;（WinFsp 上的 sshfs 移植），挂载直接报 &lt;code&gt;read: Connection reset by peer&lt;/code&gt;：它不支持 SOCKS 代理，Windows 上也没有 &lt;code&gt;connect&lt;/code&gt; / &lt;code&gt;ncat&lt;/code&gt; 这类跳板工具，直连又会被 reset。&lt;/p&gt;&#10;&lt;p&gt;换成 &lt;strong&gt;rclone&lt;/strong&gt;：自带 SSH 客户端，一行 &lt;code&gt;socks_proxy&lt;/code&gt; 就能走 clash，私钥、known_hosts 校验都支持：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# %APPDATA%\rclone\rclone.conf&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[azure]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;sftp&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;20.48.50.55&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;azureuser&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;key_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;C:/Users/&amp;lt;用户名&amp;gt;/.ssh/id_rsa&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;socks_proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1:7890&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;known_hosts_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;C:/Users/&amp;lt;用户名&amp;gt;/.ssh/known_hosts&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;rclone&lt;/span&gt; &lt;span class="nb"&gt;mount &lt;/span&gt;&lt;span class="n"&gt;azure&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;azureuser&lt;/span&gt; &lt;span class="n"&gt;Z:&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-vfs-cache-mode&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;盘符出现，&lt;code&gt;Z:\&lt;/code&gt; 也能列目录，但&lt;strong&gt;资源管理器里没有&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;h2 id="最大的坑盘符按登录会话隔离"&gt;&lt;a href="#%e6%9c%80%e5%a4%a7%e7%9a%84%e5%9d%91%e7%9b%98%e7%ac%a6%e6%8c%89%e7%99%bb%e5%bd%95%e4%bc%9a%e8%af%9d%e9%9a%94%e7%a6%bb" class="header-anchor"&gt;&lt;/a&gt;最大的坑：盘符按登录会话隔离&#10;&lt;/h2&gt;&lt;p&gt;结论：&lt;strong&gt;Windows 的盘符按登录会话隔离。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;量一下进程令牌里的 &lt;code&gt;AuthenticationId&lt;/code&gt;（登录会话 ID）：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="会话隔离验证" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://20.48.50.55.sslip.io/images/posts/mount-azure-vm/session-check.svg"&gt;&lt;/p&gt;&#10;&lt;p&gt;WSL 的 interop 进程也在同一个 Windows 会话里，但令牌属于&lt;strong&gt;另一个登录会话&lt;/strong&gt;——从那儿挂载的 Z:，Explorer 看不见。&lt;/p&gt;&#10;&lt;p&gt;（小坑：&lt;code&gt;GetTokenInformation&lt;/code&gt; 的 &lt;code&gt;TokenStatistics&lt;/code&gt; 类号是 &lt;strong&gt;10&lt;/strong&gt;，不是 12——12 是 &lt;code&gt;TokenSessionId&lt;/code&gt;；&lt;code&gt;AuthenticationId&lt;/code&gt; 在结构体偏移 8 字节。）&lt;/p&gt;&#10;&lt;p&gt;解法：挂载必须从&lt;strong&gt;交互会话&lt;/strong&gt;启动。两个入口：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;计划任务&lt;/strong&gt;：登录时自动跑（隐藏窗口）&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;code&gt;azure-vm-remount.cmd&lt;/code&gt;&lt;/strong&gt;：需要手动重挂时双击一下&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;至此，Z: 可见、可用、可自启。&lt;/p&gt;&#10;&lt;h2 id="另一个问题wsllocalhost-看不到-fuse-挂载"&gt;&lt;a href="#%e5%8f%a6%e4%b8%80%e4%b8%aa%e9%97%ae%e9%a2%98wsllocalhost-%e7%9c%8b%e4%b8%8d%e5%88%b0-fuse-%e6%8c%82%e8%bd%bd" class="header-anchor"&gt;&lt;/a&gt;另一个问题：&lt;code&gt;\\wsl.localhost&lt;/code&gt; 看不到 FUSE 挂载&#10;&lt;/h2&gt;&lt;p&gt;WSL 里挂好了，但从 &lt;code&gt;\\wsl.localhost\Ubuntu\...&lt;/code&gt; 访问是空的。&lt;/p&gt;&#10;&lt;p&gt;原因：这个入口由 WSL 的 &lt;strong&gt;9p 文件服务器&lt;/strong&gt;提供，只导出 ext4 根文件系统与 &lt;code&gt;/mnt/c&lt;/code&gt; 这类 drvfs；&lt;strong&gt;FUSE 挂载（sshfs / rclone / NFS / CIFS）一概不导出&lt;/strong&gt;。这是 WSL 的架构限制，没有开关。&lt;/p&gt;&#10;&lt;p&gt;所以 Windows 端要自己挂一份，不能借 WSL 的挂载。&lt;/p&gt;&#10;&lt;h2 id="日常使用"&gt;&lt;a href="#%e6%97%a5%e5%b8%b8%e4%bd%bf%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;日常使用&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemctl --user restart azure-proxy-vm-mount &lt;span class="c1"&gt;# WSL 挂载卡住时&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Z:\ # Windows 直接访问&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;C:\Users\&amp;lt;用户名&amp;gt;\bin\azure-vm-remount.cmd # 重挂&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;C:\Users\&amp;lt;用户名&amp;gt;\bin\azure-vm-umount.cmd # 卸载&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;直连不通就全线走代理&lt;/strong&gt;：sshfs 用 &lt;code&gt;ProxyCommand&lt;/code&gt;，rclone 用 &lt;code&gt;socks_proxy&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;挂载要有自愈&lt;/strong&gt;：systemd 的 &lt;code&gt;Restart=always&lt;/code&gt;、rclone 的 &lt;code&gt;--vfs-cache-mode&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;盘符是登录会话级的&lt;/strong&gt;：务必从交互会话启动挂载，否则 Explorer 看不见&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;code&gt;\\wsl.localhost&lt;/code&gt; 不导出 FUSE 挂载&lt;/strong&gt;：Windows 端直接另挂一份&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>我是怎么搭这个博客的</title><link>https://20.48.50.55.sslip.io/posts/how-i-built-this-blog/</link><pubDate>Wed, 16 Sep 2026 21:10:00 +0800</pubDate><guid>https://20.48.50.55.sslip.io/posts/how-i-built-this-blog/</guid><description>&lt;img src="https://20.48.50.55.sslip.io/images/uploads/Default.jpg" alt="Featured image of post 我是怎么搭这个博客的" /&gt;&lt;p&gt;这台博客跑在一台只有 &lt;strong&gt;892MB 内存&lt;/strong&gt;的 Azure 小机器上，同时兼着代理服务。整套方案的第一原则是：&lt;strong&gt;轻&lt;/strong&gt;。以下只讲思路和取舍，代码只放关键几段。&lt;/p&gt;&#10;&lt;h2 id="全貌写作--存储--展示"&gt;&lt;a href="#%e5%85%a8%e8%b2%8c%e5%86%99%e4%bd%9c--%e5%ad%98%e5%82%a8--%e5%b1%95%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;全貌：写作 → 存储 → 展示&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 你在浏览器里写作&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ┌─────────────────┐&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ Sveltia CMS │ 写作后台（/admin/）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 文章 + 图片 │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └────────┬────────┘&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 保存时直接提交&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ┌─────────────────┐&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ GitHub 私有仓库 │ ← 唯一的“真相来源”，也是备份&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └────────┬────────┘&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 每 1 分钟自动拉取&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ┌─────────────────┐&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 小机器 (VM) │ git pull → Hugo 构建 → nginx 托管&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └────────┬────────┘&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 访客访问博客&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一句话：&lt;strong&gt;GitHub 是内容的家，小机器只负责渲染和展示。&lt;/strong&gt; 好处很直接：内容永远有一份私有仓库备份；机器只负责构建，压力小；换设备也能写。&lt;/p&gt;&#10;&lt;h2 id="选型"&gt;&lt;a href="#%e9%80%89%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;选型&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Hugo&lt;/strong&gt;：单文件二进制，整站构建几十毫秒，内存占用几乎可以忽略——在 1GB 小机器上是决定性优势。对比过 Hexo（依赖多）、WordPress（太重）、Ghost（官方建议 1GB 起步）。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Stack 主题&lt;/strong&gt;：卡片式、自带暗色模式、搜索、归档、目录，社区里最成熟的 Hugo 主题之一。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Sveltia CMS&lt;/strong&gt;：最初自己写了个网页后台，能用但很土：图片手动传、预览自己写、格式容易出错。换成 Sveltia 后：富文本 + 实时预览、图片拖拽上传、用表单生成 front matter（不会再因格式写错导致文章不显示）、支持草稿和修订历史。它是纯前端（一个 JS 文件从 CDN 加载），不占服务器内存；支持&lt;strong&gt;用 GitHub Token 登录&lt;/strong&gt;，省掉了自建 OAuth 的麻烦。&lt;/p&gt;&#10;&lt;h2 id="为什么不直接用-github-pages"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%b8%8d%e7%9b%b4%e6%8e%a5%e7%94%a8-github-pages" class="header-anchor"&gt;&lt;/a&gt;为什么不直接用 GitHub Pages？&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;内容都在 GitHub 了，为什么不直接用 GitHub Pages 托管？&lt;/strong&gt; 有三个现实约束：&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;1. 仓库是私有的，Pages 用不了。&lt;/strong&gt; 免费账号只能从&lt;strong&gt;公开&lt;/strong&gt;仓库发布 Pages，私有仓库发布需要 Pro/Team 付费计划。想省掉这台机器，就得把整个仓库转公开。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;2. github.io 在国内基本不可达。&lt;/strong&gt; 实测：直连 &lt;code&gt;https://xxxx.github.io/&lt;/code&gt; 超时，而自己的 Azure IP 是通的。GitHub Pages 走 Fastly CDN，国内访问不可靠；换一个「更省事」的方案，结果自己和读者都打不开，没有意义。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;3. 那台小机器本来 24 小时开着。&lt;/strong&gt; 它同时兼着代理服务，博客只是「蹭」在上面：nginx + 构建，平时内存占用不到 20MB，边际成本约等于零。&lt;/p&gt;&#10;&lt;p&gt;这个架构也没有绑死：内容全在 Git 里，换机器 &lt;code&gt;git clone&lt;/code&gt; + 构建就能恢复。哪天仓库转公开、或者 GitHub 访问不再是问题，迁到 Pages 也就十分钟。&lt;/p&gt;&#10;&lt;h2 id="没有域名怎么上-https"&gt;&lt;a href="#%e6%b2%a1%e6%9c%89%e5%9f%9f%e5%90%8d%e6%80%8e%e4%b9%88%e4%b8%8a-https" class="header-anchor"&gt;&lt;/a&gt;没有域名，怎么上 HTTPS？&#10;&lt;/h2&gt;&lt;p&gt;没有域名就签不了证书，而写作后台的密码不能明文传输。取巧的办法是 &lt;strong&gt;sslip.io&lt;/strong&gt;——一个公共通配 DNS 服务，把 IP 写进域名就能用：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;20.48.50.55.sslip.io → 自动解析到 20.48.50.55&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;有了它，就能走标准 HTTP 验证，用 certbot 签一张浏览器信任的真证书，并自动续期。代价是依赖 sslip.io 这个第三方服务——对个人博客够用。&lt;/p&gt;&#10;&lt;h2 id="核心github-私有仓库--双向同步"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83github-%e7%a7%81%e6%9c%89%e4%bb%93%e5%ba%93--%e5%8f%8c%e5%90%91%e5%90%8c%e6%ad%a5" class="header-anchor"&gt;&lt;/a&gt;核心：GitHub 私有仓库 + 双向同步&#10;&lt;/h2&gt;&lt;p&gt;写作后台直接往 GitHub 提交，小机器上也可能有本地改动，所以需要&lt;strong&gt;双向同步&lt;/strong&gt;：GitHub → 机器（拉新文章），机器 → GitHub（推本地改动），两个方向处理不好容易冲突。&lt;/p&gt;&#10;&lt;p&gt;做法是一个每分钟跑一次的脚本，逻辑四步：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;先拉取&lt;/strong&gt;：&lt;code&gt;git pull --rebase --autostash&lt;/code&gt;，把远端新文章合并进来&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;判断要不要重建&lt;/strong&gt;：只有「有新提交」或「本地有改动」才构建，避免空转&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;重新构建&lt;/strong&gt;：Hugo 生成静态页&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;再推送&lt;/strong&gt;：本地有改动就提交并推回 GitHub&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;两个细节：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;加锁&lt;/strong&gt;：定时任务和手动触发可能撞车，用 &lt;code&gt;flock&lt;/code&gt; 保证同一时间只有一个同步在跑&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;记住上次构建的版本&lt;/strong&gt;：用标记文件记录上次构建的 commit，精确判断站点是否最新&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这正是备份：&lt;strong&gt;所有会变化的东西——文章、图片、站点配置——都在 Git 里&lt;/strong&gt;。换机器 &lt;code&gt;git clone&lt;/code&gt; 几分钟复原整站；误删文章 &lt;code&gt;git revert&lt;/code&gt; 就能回来；每次改动有完整历史。&lt;strong&gt;版本控制本身就是最好的备份。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h2 id="顺带搭的几件小事"&gt;&lt;a href="#%e9%a1%ba%e5%b8%a6%e6%90%ad%e7%9a%84%e5%87%a0%e4%bb%b6%e5%b0%8f%e4%ba%8b" class="header-anchor"&gt;&lt;/a&gt;顺带搭的几件小事&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;HTTPS 自动续期&lt;/strong&gt;：certbot 定时器自动检查、自动续&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;缓存策略&lt;/strong&gt;：HTML 每次校验（刷新即最新），带哈希指纹的 CSS/JS 长期缓存&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;安全加固&lt;/strong&gt;：后台路径随机化、Basic Auth、登录限速、响应头加固&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="踩过的坑"&gt;&lt;a href="#%e8%b8%a9%e8%bf%87%e7%9a%84%e5%9d%91" class="header-anchor"&gt;&lt;/a&gt;踩过的坑&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;坑&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;现象&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;解法&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;未来日期&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;文章发了但不显示&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Hugo 默认不构建未来文章，开 &lt;code&gt;buildFuture&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;缺少 front matter&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;随手记的笔记泄漏到公开页面&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Hugo 会把它当页面处理，后加了自动告警&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;并发推送&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;git 报 &lt;code&gt;remote rejected&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;同步脚本加 &lt;code&gt;flock&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;中文文件名&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;后台打不开&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;校验规则放宽到支持中文&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="成本"&gt;&lt;a href="#%e6%88%90%e6%9c%ac" class="header-anchor"&gt;&lt;/a&gt;成本&#10;&lt;/h2&gt;&lt;p&gt;机器是 Azure 最低配（2 vCPU / 892MB），本来就在跑代理，博客算是「蹭」的；域名 0 元（sslip.io）；证书 0 元（Let&amp;rsquo;s Encrypt）；仓库 0 元（GitHub 私有仓库免费）。平时内存占用不到 20MB。&lt;/p&gt;&#10;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#10;&lt;/h2&gt;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;用静态站点保证「轻」，用 Git 仓库保证「稳」，用成熟的 CMS 保证「好写」，用自动化把三者串起来。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;它不是最省事的方案（想省事直接用 Ghost 或 WordPress），但在&lt;strong&gt;一台很小的机器上、不花钱、有完整掌控权&lt;/strong&gt;的前提下，这是我能找到的最好平衡。&lt;/p&gt;&#10;</description></item></channel></rss>