<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>部署 on Cloudside</title><link>https://cloudside.icyyan.com/tags/%E9%83%A8%E7%BD%B2/</link><description>Recent content in 部署 on Cloudside</description><generator>Hugo</generator><language>en</language><lastBuildDate>Mon, 29 Jun 2026 17:15:00 +0800</lastBuildDate><atom:link href="https://cloudside.icyyan.com/tags/%E9%83%A8%E7%BD%B2/index.xml" rel="self" type="application/rss+xml"/><item><title>在阿里云 ECS 上最小化部署 Marinara Engine：不在服务器上跑本地模型</title><link>https://cloudside.icyyan.com/posts/marinara-engine-minimal-deployment/</link><pubDate>Mon, 29 Jun 2026 17:15:00 +0800</pubDate><guid>https://cloudside.icyyan.com/posts/marinara-engine-minimal-deployment/</guid><description>&lt;p&gt;Marinara Engine 的官方介绍里把它称为一个本地 AI 聊天、角色扮演和游戏引擎。听起来很容易让人以为：既然是“本地”，是不是服务器上还要准备 GPU、下载模型、跑 llama.cpp 或者 embedding 服务？&lt;/p&gt;
&lt;p&gt;如果只是想把 Marinara 当成一个 Web 应用来用，答案是不需要。我的阿里云 ECS 现在跑的就是这种最小化部署：Docker 里只跑 Marinara Engine 本体，模型能力走外部 API，容器端口只绑定到 &lt;code&gt;127.0.0.1&lt;/code&gt;，再由反向代理对外提供访问。&lt;/p&gt;
&lt;p&gt;本文记录的是这个部署方式。版本核对时间是 &lt;strong&gt;2026-06-29&lt;/strong&gt;：官方最新稳定版是 &lt;code&gt;v2.0.6&lt;/code&gt;，我当前服务器上实际运行的是 &lt;code&gt;ghcr.nju.edu.cn/pasta-devs/marinara-engine:2.0.5-lite&lt;/code&gt;。新部署可以优先用最新稳定版的 &lt;code&gt;*-lite&lt;/code&gt; tag；如果你想完全复刻本文环境，就固定到 &lt;code&gt;2.0.5-lite&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="先理解这个最小化是什么意思"&gt;先理解这个“最小化”是什么意思&lt;/h2&gt;
&lt;p&gt;最小化不是功能阉割到不能用，而是把不适合小云服务器承担的部分拿掉。&lt;/p&gt;
&lt;p&gt;Marinara Engine 官方提供 lite 镜像。根据官方容器安装文档，lite 镜像去掉了三类较重的离线能力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;本地 sidecar 模型，也就是容器内直接跑本地 LLM 的那部分。&lt;/li&gt;
&lt;li&gt;本地 embedding 模型。&lt;/li&gt;
&lt;li&gt;依赖本地 embedding 的语义记忆检索。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;保留下来的能力仍然包括聊天、角色、游戏模式、agent、lorebook、角色卡、远程 LLM API 连接等。也就是说，只要你本来就打算用 OpenAI、OpenRouter、Gemini、Anthropic 或者其他远程 OpenAI-compatible API，这种部署方式就够了。&lt;/p&gt;
&lt;p&gt;我这里的结构是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;浏览器
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; 阿里云安全组开放 80/443
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Pingap / Nginx / Caddy 这类反向代理
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; 127.0.0.1:7860
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Docker 容器内的 Marinara Engine
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; 远程 LLM / 图片 / TTS API
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;看到这里，问题就变成了：服务器上到底需要跑什么？答案很少：Docker、一个 compose 文件、一个 &lt;code&gt;.env&lt;/code&gt; 文件、一个反向代理入口。&lt;/p&gt;</description></item><item><title>用 Pingap 部署反向代理，以及从 Pingora 迁移时容易踩的坑</title><link>https://cloudside.icyyan.com/posts/pingap-reverse-proxy-guide-and-pitfalls/</link><pubDate>Sun, 17 May 2026 16:20:00 +0800</pubDate><guid>https://cloudside.icyyan.com/posts/pingap-reverse-proxy-guide-and-pitfalls/</guid><description>&lt;p&gt;如果你已经看过 Pingora 的最小反向代理示例，很容易产生一个后续问题：生产环境是不是也要自己继续写配置解析、证书加载、日志、热更新和管理界面？通常不需要。Pingap 就是基于 Pingora 做好的反向代理应用，它更接近一个可以直接部署的 Nginx 替代方案。&lt;/p&gt;
&lt;p&gt;这篇文章只讲 Pingap：怎么安装，怎么写一个最小反代配置，怎么加 HTTPS，怎么用 Docker 或 systemd 部署，以及从裸 Pingora 或 Nginx 迁移过来时有哪些容易忽略的坑。&lt;/p&gt;
&lt;p&gt;本文示例版本核对时间：&lt;strong&gt;2026-05-17&lt;/strong&gt;。示例固定使用 Pingap &lt;code&gt;v0.13.4&lt;/code&gt;。实际部署前建议再看一次官方 GitHub Releases 和文档，因为 Pingap 还在快速变化。&lt;/p&gt;
&lt;h2 id="pingap-和-pingora-的关系"&gt;Pingap 和 Pingora 的关系&lt;/h2&gt;
&lt;p&gt;Pingora 是框架，你通过 Rust 代码实现代理逻辑。Pingap 是应用，它把常见反向代理能力包装成 TOML 配置和 Web 管理界面。&lt;/p&gt;
&lt;p&gt;一个最小 Pingap 配置大概长这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;upstreams&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;addrs&lt;/span&gt; = [&lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1:3000&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;locations&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;host&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;app.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;upstream&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;enable_reverse_proxy_headers&lt;/span&gt; = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;servers&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;addr&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;0.0.0.0:6188&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locations&lt;/span&gt; = [&lt;span style="color:#e6db74"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这段配置和一个最小 Pingora 代理做的是同一件事：监听 &lt;code&gt;6188&lt;/code&gt;，把匹配 &lt;code&gt;app.example.com&lt;/code&gt; 的请求转发到 &lt;code&gt;127.0.0.1:3000&lt;/code&gt;。差别在于，你不用实现 &lt;code&gt;ProxyHttp&lt;/code&gt;，也不用自己处理常见代理应用需要的周边能力。&lt;/p&gt;</description></item><item><title>用 Pingora 写一个最小反向代理，并把它部署起来</title><link>https://cloudside.icyyan.com/posts/pingora-minimal-reverse-proxy-guide/</link><pubDate>Sun, 17 May 2026 16:00:00 +0800</pubDate><guid>https://cloudside.icyyan.com/posts/pingora-minimal-reverse-proxy-guide/</guid><description>&lt;p&gt;Cloudflare 开源 Pingora 之后，很多人会问：它能不能替代 Nginx？如果问题只是“能不能把请求转发到后端服务”，答案是能，而且几十行 Rust 就够了。但 Pingora 不是一个读取 &lt;code&gt;nginx.conf&lt;/code&gt; 的服务器，它更像一套用来写代理、网关和网络服务的 Rust 框架。&lt;/p&gt;
&lt;p&gt;这篇只做一件事：用 Pingora 写一个最小反向代理，让 &lt;code&gt;http://127.0.0.1:6188/&lt;/code&gt; 转发到本机的 &lt;code&gt;127.0.0.1:3000&lt;/code&gt;，然后把这个二进制按服务方式部署起来。&lt;/p&gt;
&lt;p&gt;本文示例版本核对时间：&lt;strong&gt;2026-05-17&lt;/strong&gt;。示例使用 &lt;code&gt;pingora = &amp;quot;0.8&amp;quot;&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="先看等价的-nginx-配置"&gt;先看等价的 Nginx 配置&lt;/h2&gt;
&lt;p&gt;如果用 Nginx，最小反代大概长这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;server&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;listen&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6188&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;location&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;proxy_pass&lt;/span&gt; &lt;span style="color:#e6db74"&gt;http://127.0.0.1:3000&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;proxy_set_header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;Host&lt;/span&gt; $host;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;proxy_set_header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;X-Real-IP&lt;/span&gt; $remote_addr;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;proxy_set_header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;X-Forwarded-For&lt;/span&gt; $proxy_add_x_forwarded_for;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;proxy_set_header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span style="color:#e6db74"&gt;http&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pingora 的思路不一样。你不是写配置块，而是实现 &lt;code&gt;ProxyHttp&lt;/code&gt; trait：请求进来以后，代码决定它要转发到哪里，转发前要改哪些请求头，最后日志怎么记。&lt;/p&gt;
&lt;h2 id="创建项目"&gt;创建项目&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cargo new mini-pingora-proxy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd mini-pingora-proxy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Cargo.toml&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;package&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;mini-pingora-proxy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;version&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;0.1.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;edition&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;2021&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;dependencies&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;async-trait&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;env_logger&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;0.11&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;0.4&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;pingora&lt;/span&gt; = { &lt;span style="color:#a6e22e"&gt;version&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;0.8&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;features&lt;/span&gt; = [&lt;span style="color:#e6db74"&gt;&amp;#34;proxy&amp;#34;&lt;/span&gt;] }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里用的是 &lt;code&gt;pingora&lt;/code&gt; 聚合 crate，并启用 &lt;code&gt;proxy&lt;/code&gt; feature。Pingora 没有默认打开所有能力；如果后面要做负载均衡，需要再启用 &lt;code&gt;lb&lt;/code&gt;；如果要监听 HTTPS 或连接 HTTPS upstream，还要选择对应的 TLS feature，比如 &lt;code&gt;openssl&lt;/code&gt;、&lt;code&gt;boringssl&lt;/code&gt;、&lt;code&gt;s2n&lt;/code&gt; 或实验性的 &lt;code&gt;rustls&lt;/code&gt;。&lt;/p&gt;</description></item></channel></rss>