<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh_CN">
  <title>安雨落的小站</title>
  <subtitle>记录技术与生活</subtitle>
  <link href="https://blog.anyul.cn/" rel="alternate" type="text/html"/>
  <link href="https://blog.anyul.cn/atom.xml" rel="self" type="application/atom+xml"/>
  <id>https://blog.anyul.cn/</id>
  <updated>2026-09-03T00:00:00.000Z</updated>
  <entry>
    <title>失落的龙约私服部署教程</title>
    <link href="https://blog.anyul.cn/posts/dragalia-private-server/" rel="alternate" type="text/html"/>
    <id>https://blog.anyul.cn/posts/dragalia-private-server/</id>
    <published>2026-09-03T00:00:00.000Z</published>
    <updated>2026-09-03T00:00:00.000Z</updated>
    <summary>使用开源项目 Dawnshard 与 Docker Compose，在自己的服务器上部署失落的龙约私服：服务端、网页前端、反向代理与客户端连接的完整流程。</summary>
    <content type="html"><![CDATA[<h2>前言</h2>
<p>《失落的龙约》（Dragalia Lost）是任天堂与 Cygames 合作推出的手游，已于 2022 年 11 月 30 日停服。社区通过逆向工程实现了服务器模拟器，让这款游戏能在私人服务器上继续运行。目前主要的模拟器项目是 <a href="https://github.com/SapiensAnatis/Dawnshard">Dawnshard</a>（C# / ASP.NET Core，MIT 协议），配套的账号认证服务是 <a href="https://github.com/DragaliaLostRevival/DragaliaBaasServer">DragaliaBaas</a>，客户端改版工具是 LukeFZ 的 <a href="https://github.com/LukeFZ/DragaliPatch">Dragalipatch</a>。</p>
<p>本文基于上述项目的官方自托管文档，介绍在一张 VPS 上部署完整私服的流程：最小服务端 → 网页前端与反向代理 → 域名与 HTTPS → 客户端连接 → 日常维护。</p>
<blockquote>
<p>[!WARNING] 免责声明
失落的龙约的商标与全部游戏资源归任天堂、Cygames 所有。部署私服仅供个人学习与 Preservation 研究用途，请勿将服务对公众开放运营、不要分发游戏客户端与资源文件。由此产生的一切后果自行承担。</p>
</blockquote>
<blockquote>
<p>[!NOTE]
游戏服务端需要真实的服务器（VPS 或家用机）运行 Docker。本文示例中的域名 <code>dl.example.com</code> 与 IP <code>203.0.113.10</code> 均为占位符，部署时替换成自己的值。</p>
</blockquote>
<h2>准备工作</h2>
<p>开始之前，确认以下条件全部满足：</p>
<table>
<thead>
<tr>
<th>项目</th>
<th>要求</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>服务器</td>
<td>1 台 VPS，2 核 2G 起</td>
<td>游戏资源默认走社区公共 CDN，服务器本身压力不大</td>
</tr>
<tr>
<td>操作系统</td>
<td>Ubuntu 22.04 / Debian 12 等</td>
<td>能装 Docker 即可</td>
</tr>
<tr>
<td>Docker</td>
<td>Docker Engine + Compose 插件</td>
<td><code>docker compose version</code> 能输出版本号</td>
</tr>
<tr>
<td>域名（可选）</td>
<td>一个解析到服务器的子域名</td>
<td>公网部署强烈建议，配 HTTPS</td>
</tr>
<tr>
<td>客户端</td>
<td>Android 设备或模拟器</td>
<td>配合 Dragalipatch 改服务器地址</td>
</tr>
</tbody>
</table>
<p>安装 Docker（以 Debian/Ubuntu 为例，已安装可跳过）：</p>
<pre><code>curl -fsSL https://get.docker.com | sh
</code></pre>
<p>创建工作目录，后续所有文件都放在这里：</p>
<pre><code>mkdir -p ~/dragalia &amp;&amp; cd ~/dragalia
</code></pre>
<h2>第一步：最小可用服务端</h2>
<p>这一步启动三个容器：游戏 API（<code>dragaliaapi</code>）、PostgreSQL 数据库、Redis 缓存。</p>
<p>新建 <code>docker-compose.yml</code>，内容如下：</p>
<pre><code>volumes:
  pgdata:
services:
  dragaliaapi:
    image: ghcr.io/sapiensanatis/dragalia-api:4.0.59
    environment:
      - ConnectionStrings__Postgres=Host=postgres;User ID=${POSTGRES_USER};Password=${POSTGRES_PASSWORD};Database=${POSTGRES_DB}
      - ConnectionStrings__Redis=redis
    ports:
      - "80:8080" # 监听 80 端口；公网 HTTP 入口
    env_file:
      - .env
  postgres:
    hostname: postgres
    image: postgres:17
    env_file:
      - .env
    volumes:
      - pgdata:/var/lib/postgresql/data
  redis:
    hostname: redis
    image: redis:8
</code></pre>
<p>镜像 tag <code>4.0.59</code> 是写作时的版本。官方更新较频繁，部署前到 <a href="https://github.com/SapiensAnatis/Dawnshard/pkgs/container/dragalia-api">package 页面</a>确认最新 tag 并替换。</p>
<p>在同目录新建 <code>.env</code>，填入自己的凭据：</p>
<pre><code># PostgreSQL 连接密码（必填）
POSTGRES_PASSWORD=&lt;自定义强密码&gt;
# PostgreSQL 用户名
POSTGRES_USER=postgres
# PostgreSQL 数据库名
POSTGRES_DB=DragaliaAPI
# 管理端点（如手动导入存档）的 Bearer Token
DEVELOPER_TOKEN=&lt;自定义随机 Token&gt;
# 日志上下文中的主机名，可留空
HOSTNAME=
</code></pre>
<blockquote>
<p>[!WARNING]
<code>.env</code> 里的密码和 Token 必须改成自己的随机值，不要照抄任何文档里的示例值，也不要把 <code>.env</code> 提交到公开仓库。</p>
</blockquote>
<p>启动服务：</p>
<pre><code>docker compose up -d
</code></pre>
<p>验证部署结果。浏览器访问 <code>http://203.0.113.10/health</code>，三个检查项均为 <code>Healthy</code> 即为成功：</p>
<pre><code>{
  "status": "Healthy",
  "results": {
    "self": { "status": "Healthy" },
    "ApiContext": { "status": "Healthy" },
    "Redis": { "status": "Healthy" }
  }
}
</code></pre>
<p>任何一项不是 <code>Healthy</code>，先用 <code>docker compose logs dragaliaapi</code> 查看日志，再按文末「故障排查」处理。</p>
<h2>第二步：网页前端 + 反向代理</h2>
<p>第一步的裸 API 只适合本机验证。公网部署需要再加两个组件：</p>
<ul>
<li><strong>Caddy</strong> 反向代理：API 不支持 CORS，网页前端和游戏 API 必须从同一个域名、同一个端口对外服务，由 Caddy 按路径分发；</li>
<li><strong>dawnshard-website</strong>：官方网页前端，提供公告、排行、存档管理等页面。</li>
</ul>
<p>修改 <code>docker-compose.yml</code>：删掉 <code>dragaliaapi</code> 的 <code>ports</code> 段（80 端口让给 Caddy），加入 <code>caddy</code> 和 <code>website</code> 两个服务：</p>
<pre><code>volumes:
  pgdata:
  caddydata:
services:
  caddy:
    image: docker.io/caddy:2
    ports:
      - "80:80"
    volumes:
      - ./config:/etc/caddy  # Caddyfile
      - caddydata:/data      # 证书等持久化数据

  dragaliaapi:
    image: ghcr.io/sapiensanatis/dragalia-api:4.0.59
    environment:
      - ConnectionStrings__Postgres=Host=postgres;User ID=${POSTGRES_USER};Password=${POSTGRES_PASSWORD};Database=${POSTGRES_DB}
      - ConnectionStrings__Redis=redis
    env_file:
      - .env

  website:
    image: ghcr.io/sapiensanatis/dawnshard-website:1.0.138
    environment:
      - DAWNSHARD_API_URL_SSR=http://dragaliaapi:8080

  postgres:
    hostname: postgres
    image: postgres:17
    env_file:
      - .env
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    hostname: redis
    image: redis:8
</code></pre>
<p>创建 Caddy 配置文件：</p>
<pre><code>mkdir -p ./config &amp;&amp; touch ./config/Caddyfile
</code></pre>
<p><code>Caddyfile</code> 内容如下。游戏客户端请求的路径前缀是固定的，必须逐条转发给 API，其余流量交给网页前端：</p>
<pre><code>:80 {
	# 屏蔽健康检查端点的外部访问
	respond /health 404
	respond /ping 404
	respond /metrics 404
	reverse_proxy /api/* dragaliaapi:8080               # 网页前端调用的 API
	reverse_proxy /2.19.0_20220714193707/* dragaliaapi:8080  # 安卓客户端
	reverse_proxy /2.19.0_20220719103923/* dragaliaapi:8080  # iOS 客户端
	reverse_proxy /dragalipatch/config dragaliaapi:8080      # Dragalipatch 配置
	reverse_proxy website:3000                          # 其余流量给网页前端
}
</code></pre>
<p>重启整套服务：</p>
<pre><code>docker compose up -d
</code></pre>
<p>浏览器访问 <code>http://203.0.113.10</code>，能看到网页前端即为成功。前端「新闻」页面此时内容为空是正常现象（数据库还没有公告数据）；只要页面能正常渲染，就说明前端、API、数据库的链路已通。</p>
<blockquote>
<p>[!NOTE]
API 与网页前端的镜像版本没有兼容性保证。升级时把两个镜像都更到同期发布的最新版，是最稳妥的做法。</p>
</blockquote>
<h2>第三步：域名与 HTTPS</h2>
<p>公网开放时，务必启用 HTTPS。Caddy 内置 ACME 客户端，可以自动签发 Let's Encrypt 证书，共四步：</p>
<ol>
<li>在域名服务商处添加 A 记录，把 <code>dl.example.com</code> 解析到 <code>203.0.113.10</code>；</li>
<li>把 <code>Caddyfile</code> 第一行的 <code>:80</code> 改成 <code>dl.example.com</code>；</li>
<li>在 <code>docker-compose.yml</code> 的 <code>caddy</code> 服务中追加 <code>- "443:443"</code> 端口映射；</li>
<li>重启服务：<code>docker compose up -d</code>，等待 Caddy 自动完成 ACME 验证（日志出现 certificate obtained 即可）。</li>
</ol>
<p>完成后访问 <code>https://dl.example.com</code> 确认证书生效。使用自签证书、已购证书或套 Cloudflare 代理等场景的配置方式不同，参考 <a href="https://caddyserver.com/docs">Caddy 官方文档</a>调整。</p>
<h2>第四步：客户端连接</h2>
<ol>
<li>在 Android 设备（或模拟器）上安装原版游戏与 <a href="https://github.com/LukeFZ/DragaliPatch/releases/latest">Dragalipatch</a>；</li>
<li>打开 Dragalipatch，服务器地址填 <code>https://dl.example.com</code>（必须带 <code>http://</code> 或 <code>https://</code> 前缀，不带前缀时 Dragalipatch 默认按 HTTPS 处理）；</li>
<li>资源 CDN 保持默认的公共源即可，自建资源服务属于进阶内容（见文末）；</li>
<li>启动游戏，注册账号并登录。</li>
</ol>
<p>账号认证由 BaaS 服务负责。本文的部署方式不包含自建 BaaS，客户端默认使用社区托管的公共实例；如果希望账号体系完全自托管，参考 <a href="https://github.com/DragaliaLostRevival/DragaliaBaasServer">DragaliaBaasServer</a> 项目自行部署，属于进阶内容。</p>
<h2>日常维护</h2>
<p><strong>升级版本</strong>：到 package 页面确认 <code>dragalia-api</code> 与 <code>dawnshard-website</code> 的最新 tag，更新 <code>docker-compose.yml</code> 中的镜像 tag，然后：</p>
<pre><code>docker compose down
docker compose up -d
</code></pre>
<p><strong>备份数据</strong>：玩家数据全部存放在 <code>pgdata</code> 卷中。定期执行：</p>
<pre><code>docker compose exec postgres pg_dump -U postgres DragaliaAPI &gt; backup_$(date +%F).sql
</code></pre>
<p><strong>查看日志</strong>：<code>docker compose logs -f dragaliaapi</code>。正常的 API 请求日志形如 <code>HTTP GET /api/news responded 200</code>，出现 500 或持续重启再排查。</p>
<h2>故障排查</h2>
<p><strong>80 端口绑定失败</strong>。Linux 上以 rootless 模式运行 Docker 时，绑定 1024 以下端口会被拒绝，报错包含 <code>cannot expose privileged port 80</code>。两种解法任选其一：把 compose 里的端口映射改成 <code>8080:80</code>（Caddy 对外仍走反代或改由外层网关承接），或按官方文档把 <code>net.ipv4.ip_unprivileged_port_start=80</code> 写入 <code>/etc/sysctl.d/</code> 后执行 <code>sudo sysctl --system</code>。修改内核参数前先确认自己了解安全影响。</p>
<p><strong>健康检查不通过</strong>。<code>/health</code> 中 <code>ApiContext</code> 不健康时，通常是数据库连接信息有误：检查 <code>.env</code> 中的 <code>POSTGRES_*</code> 三项与 compose 中连接字符串是否一致。<code>Redis</code> 不健康时，检查 redis 容器是否启动、<code>ConnectionStrings__Redis</code> 是否为 <code>redis</code>。</p>
<p><strong>客户端连不上</strong>。按顺序检查：域名解析是否生效（<code>ping dl.example.com</code> 返回服务器 IP）、Caddy 是否拿到证书、<code>Caddyfile</code> 中两条版本号路径转发是否原样保留（路径中的版本号不是占位符，不能改）。</p>
<h2>已知边界</h2>
<ul>
<li><strong>联机（共斗）</strong>：需要额外部署 Photon Server，官方授权费用较高，个人部署通常只玩单机内容；</li>
<li><strong>自建资源 CDN</strong>：全量资源约 10 GB，含历史活动资源超过 50 GB，且分发游戏资源存在版权风险，默认公共 CDN 不可用时再考虑，方案见官方 Wiki 的 Assets 一节；</li>
<li><strong>版本兼容</strong>：API 不遵循语义化版本，升级前留意官方公告，保留旧镜像 tag 以便回滚。</li>
</ul>
<h2>参考</h2>
<ul>
<li><a href="https://github.com/SapiensAnatis/Dawnshard">Dawnshard 仓库</a> · <a href="https://github.com/SapiensAnatis/Dawnshard/wiki">自托管指南（Wiki）</a></li>
<li><a href="https://github.com/DragaliaLostRevival/DragaliaBaasServer">DragaliaBaasServer</a> · <a href="https://github.com/LukeFZ/DragaliPatch">Dragalipatch</a></li>
<li><a href="https://caddyserver.com/docs">Caddy 文档</a></li>
</ul>
<p>最后，感谢 Dawnshard 及社区逆向团队的持续维护。</p>
]]></content>
    <author><name>安雨落</name></author>
    <category term="折腾手记"/>
  </entry>
</feed>
