<?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>SSH on 超越网</title><link>https://www.chaoyuewang.cn/tags/ssh/</link><description>Recent content in SSH on 超越网</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Wed, 27 May 2026 13:00:00 +0800</lastBuildDate><atom:link href="https://www.chaoyuewang.cn/tags/ssh/index.xml" rel="self" type="application/rss+xml"/><item><title>SSH密钥持久化：为什么容器内生成的密钥在重启后丢失</title><link>https://www.chaoyuewang.cn/posts/ops/ssh-key-persistence/</link><pubDate>Wed, 27 May 2026 13:00:00 +0800</pubDate><guid>https://www.chaoyuewang.cn/posts/ops/ssh-key-persistence/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;2026年5月，我遇到一个反复出现的问题：容器内生成的SSH密钥在容器重启后丢失，导致无法通过SSH连接到宿主机。&lt;/p&gt;
&lt;p&gt;这个问题看似简单，但背后涉及Docker容器的文件系统隔离机制。这篇文章记录完整的排查过程和最终解决方案。&lt;/p&gt;
&lt;h2 id="一问题现象"&gt;一、问题现象&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;现象：SSH密钥在容器内生成，容器重启后密钥消失，无法连接宿主机
时间：2026-05-18
环境：fnOS虚拟化平台 + Ubuntu 24.04 VM + Docker
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;初始错误&lt;/strong&gt;：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Warning: Permanently added &amp;#39;192.168.0.200&amp;#39; (ED25519) to the list of known hosts.
Permission denied (publickey).
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="二根因分析"&gt;二、根因分析&lt;/h2&gt;
&lt;h3 id="21-docker容器的文件系统隔离"&gt;2.1 Docker容器的文件系统隔离&lt;/h3&gt;
&lt;p&gt;Docker容器使用&lt;strong&gt;联合文件系统（UnionFS）&lt;/strong&gt;，容器内的文件系统是独立的。当容器重启时：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;容器内生成的文件&lt;/strong&gt; → 存储在容器的可写层&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;容器重启&lt;/strong&gt; → 可写层被销毁，所有未持久化的文件丢失&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SSH密钥丢失&lt;/strong&gt; → 无法通过密钥认证连接宿主机&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="22-为什么宿主机ssh拒绝使用容器内密钥"&gt;2.2 为什么宿主机SSH拒绝使用容器内密钥&lt;/h3&gt;
&lt;p&gt;即使密钥被挂载到容器，宿主机SSH服务也会拒绝使用：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# /var/log/auth.log
sshd[12345]: Authentication refused: bad ownership or modes for key file
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：SSH要求私钥文件所有者必须是 &lt;code&gt;root:root&lt;/code&gt;，且权限为 &lt;code&gt;600&lt;/code&gt;。容器内生成的密钥，挂载后文件所有者可能不匹配。&lt;/p&gt;
&lt;h2 id="三解决方案"&gt;三、解决方案&lt;/h2&gt;
&lt;h3 id="31-核心原则"&gt;3.1 核心原则&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;密钥必须在宿主机生成，不能容器内生成。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="32-完整步骤"&gt;3.2 完整步骤&lt;/h3&gt;
&lt;h4 id="步骤1在宿主机生成ssh密钥"&gt;步骤1：在宿主机生成SSH密钥&lt;/h4&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="c1"&gt;# 宿主机执行（192.168.0.200）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh-keygen -t ed25519 -C &lt;span class="s2"&gt;&amp;#34;hermes-agent&amp;#34;&lt;/span&gt; -f /home/ksboy/.ssh/hermes_key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 设置权限&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;600&lt;/span&gt; /home/ksboy/.ssh/hermes_key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;644&lt;/span&gt; /home/ksboy/.ssh/hermes_key.pub
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="步骤2将公钥添加到宿主机授权文件"&gt;步骤2：将公钥添加到宿主机授权文件&lt;/h4&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="c1"&gt;# 宿主机执行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat /home/ksboy/.ssh/hermes_key.pub &amp;gt;&amp;gt; /home/ksboy/.ssh/authorized_keys
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;600&lt;/span&gt; /home/ksboy/.ssh/authorized_keys
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="步骤3在docker-composeyml中挂载密钥"&gt;步骤3：在docker-compose.yml中挂载密钥&lt;/h4&gt;
&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="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&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;hermes-agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&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;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;hermes-agent:latest&lt;/span&gt;&lt;span class="w"&gt;
&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;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&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="c"&gt;# 密钥挂载（只读模式）&lt;/span&gt;&lt;span class="w"&gt;
&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="l"&gt;/home/ksboy/.ssh/hermes_key:/root/.ssh/id_ed25519:ro&lt;/span&gt;&lt;span class="w"&gt;
&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="l"&gt;/home/ksboy/.ssh/hermes_key.pub:/root/.ssh/id_ed25519.pub:ro&lt;/span&gt;&lt;span class="w"&gt;
&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="c"&gt;# SSH配置&lt;/span&gt;&lt;span class="w"&gt;
&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="l"&gt;/home/ksboy/.ssh/config:/root/.ssh/config:ro&lt;/span&gt;&lt;span class="w"&gt;
&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;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&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="l"&gt;SSH_HOST=192.168.0.200&lt;/span&gt;&lt;span class="w"&gt;
&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="l"&gt;SSH_USER=ksboy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="步骤4宿主机ssh配置调整"&gt;步骤4：宿主机SSH配置调整&lt;/h4&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="c1"&gt;# /etc/ssh/sshd_config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 允许Docker网段访问&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ListenAddress 0.0.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 重启SSH服务&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemctl restart sshd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="33-验证"&gt;3.3 验证&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;&lt;span class="c1"&gt;# 容器内测试&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i /root/.ssh/id_ed25519 ksboy@192.168.0.200 &lt;span class="s2"&gt;&amp;#34;echo &amp;#39;连接成功&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 重启容器后再次测试&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-compose restart hermes-agent
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -i /root/.ssh/id_ed25519 ksboy@192.168.0.200 &lt;span class="s2"&gt;&amp;#34;echo &amp;#39;重启后连接成功&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="四关键要点"&gt;四、关键要点&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;要点&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;密钥生成位置&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;必须在宿主机&lt;/strong&gt;，容器内生成的密钥重启后丢失&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;文件所有者&lt;/td&gt;
&lt;td&gt;宿主机密钥必须为 &lt;code&gt;root:root&lt;/code&gt;（容器以root运行）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;挂载模式&lt;/td&gt;
&lt;td&gt;使用 &lt;code&gt;:ro&lt;/code&gt; 只读模式，防止容器内意外修改&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSH监听地址&lt;/td&gt;
&lt;td&gt;宿主机需监听 &lt;code&gt;0.0.0.0&lt;/code&gt;，允许Docker网段访问&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;网络隔离&lt;/td&gt;
&lt;td&gt;容器在Docker网段，宿主机在LAN网段，需正确配置路由&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="五常见错误"&gt;五、常见错误&lt;/h2&gt;
&lt;h3 id="错误1容器内生成密钥"&gt;错误1：容器内生成密钥&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;&lt;span class="c1"&gt;# ❌ 错误做法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it hermes-agent ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 容器重启后密钥丢失&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="错误2密钥权限不正确"&gt;错误2：密钥权限不正确&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;&lt;span class="c1"&gt;# ❌ 错误做法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;644&lt;/span&gt; /home/ksboy/.ssh/hermes_key &lt;span class="c1"&gt;# SSH拒绝使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ 正确做法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;600&lt;/span&gt; /home/ksboy/.ssh/hermes_key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="错误3宿主机ssh只监听localhost"&gt;错误3：宿主机SSH只监听localhost&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;&lt;span class="c1"&gt;# ❌ 错误做法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ListenAddress 127.0.0.1 &lt;span class="c1"&gt;# Docker容器无法连接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ 正确做法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ListenAddress 0.0.0.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="六总结"&gt;六、总结&lt;/h2&gt;
&lt;p&gt;SSH密钥持久化的核心是理解Docker的文件系统隔离机制：&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>2026年5月，我遇到一个反复出现的问题：容器内生成的SSH密钥在容器重启后丢失，导致无法通过SSH连接到宿主机。</p>
<p>这个问题看似简单，但背后涉及Docker容器的文件系统隔离机制。这篇文章记录完整的排查过程和最终解决方案。</p>
<h2 id="一问题现象">一、问题现象</h2>
<pre tabindex="0"><code>现象：SSH密钥在容器内生成，容器重启后密钥消失，无法连接宿主机
时间：2026-05-18
环境：fnOS虚拟化平台 + Ubuntu 24.04 VM + Docker
</code></pre><p><strong>初始错误</strong>：</p>
<pre tabindex="0"><code>Warning: Permanently added &#39;192.168.0.200&#39; (ED25519) to the list of known hosts.
Permission denied (publickey).
</code></pre><h2 id="二根因分析">二、根因分析</h2>
<h3 id="21-docker容器的文件系统隔离">2.1 Docker容器的文件系统隔离</h3>
<p>Docker容器使用<strong>联合文件系统（UnionFS）</strong>，容器内的文件系统是独立的。当容器重启时：</p>
<ol>
<li><strong>容器内生成的文件</strong> → 存储在容器的可写层</li>
<li><strong>容器重启</strong> → 可写层被销毁，所有未持久化的文件丢失</li>
<li><strong>SSH密钥丢失</strong> → 无法通过密钥认证连接宿主机</li>
</ol>
<h3 id="22-为什么宿主机ssh拒绝使用容器内密钥">2.2 为什么宿主机SSH拒绝使用容器内密钥</h3>
<p>即使密钥被挂载到容器，宿主机SSH服务也会拒绝使用：</p>
<pre tabindex="0"><code># /var/log/auth.log
sshd[12345]: Authentication refused: bad ownership or modes for key file
</code></pre><p><strong>原因</strong>：SSH要求私钥文件所有者必须是 <code>root:root</code>，且权限为 <code>600</code>。容器内生成的密钥，挂载后文件所有者可能不匹配。</p>
<h2 id="三解决方案">三、解决方案</h2>
<h3 id="31-核心原则">3.1 核心原则</h3>
<p><strong>密钥必须在宿主机生成，不能容器内生成。</strong></p>
<h3 id="32-完整步骤">3.2 完整步骤</h3>
<h4 id="步骤1在宿主机生成ssh密钥">步骤1：在宿主机生成SSH密钥</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 宿主机执行（192.168.0.200）</span>
</span></span><span class="line"><span class="cl">ssh-keygen -t ed25519 -C <span class="s2">&#34;hermes-agent&#34;</span> -f /home/ksboy/.ssh/hermes_key
</span></span><span class="line"><span class="cl"><span class="c1"># 设置权限</span>
</span></span><span class="line"><span class="cl">chmod <span class="m">600</span> /home/ksboy/.ssh/hermes_key
</span></span><span class="line"><span class="cl">chmod <span class="m">644</span> /home/ksboy/.ssh/hermes_key.pub
</span></span></code></pre></div><h4 id="步骤2将公钥添加到宿主机授权文件">步骤2：将公钥添加到宿主机授权文件</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 宿主机执行</span>
</span></span><span class="line"><span class="cl">cat /home/ksboy/.ssh/hermes_key.pub &gt;&gt; /home/ksboy/.ssh/authorized_keys
</span></span><span class="line"><span class="cl">chmod <span class="m">600</span> /home/ksboy/.ssh/authorized_keys
</span></span></code></pre></div><h4 id="步骤3在docker-composeyml中挂载密钥">步骤3：在docker-compose.yml中挂载密钥</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">hermes-agent</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">hermes-agent:latest</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="c"># 密钥挂载（只读模式）</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">/home/ksboy/.ssh/hermes_key:/root/.ssh/id_ed25519:ro</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">/home/ksboy/.ssh/hermes_key.pub:/root/.ssh/id_ed25519.pub:ro</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="c"># SSH配置</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">/home/ksboy/.ssh/config:/root/.ssh/config:ro</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">SSH_HOST=192.168.0.200</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">SSH_USER=ksboy</span><span class="w">
</span></span></span></code></pre></div><h4 id="步骤4宿主机ssh配置调整">步骤4：宿主机SSH配置调整</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># /etc/ssh/sshd_config</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 允许Docker网段访问</span>
</span></span><span class="line"><span class="cl">ListenAddress 0.0.0.0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 重启SSH服务</span>
</span></span><span class="line"><span class="cl">systemctl restart sshd
</span></span></code></pre></div><h3 id="33-验证">3.3 验证</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 容器内测试</span>
</span></span><span class="line"><span class="cl">ssh -i /root/.ssh/id_ed25519 ksboy@192.168.0.200 <span class="s2">&#34;echo &#39;连接成功&#39;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 重启容器后再次测试</span>
</span></span><span class="line"><span class="cl">docker-compose restart hermes-agent
</span></span><span class="line"><span class="cl">ssh -i /root/.ssh/id_ed25519 ksboy@192.168.0.200 <span class="s2">&#34;echo &#39;重启后连接成功&#39;&#34;</span>
</span></span></code></pre></div><h2 id="四关键要点">四、关键要点</h2>
<table>
	<thead>
			<tr>
					<th>要点</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>密钥生成位置</td>
					<td><strong>必须在宿主机</strong>，容器内生成的密钥重启后丢失</td>
			</tr>
			<tr>
					<td>文件所有者</td>
					<td>宿主机密钥必须为 <code>root:root</code>（容器以root运行）</td>
			</tr>
			<tr>
					<td>挂载模式</td>
					<td>使用 <code>:ro</code> 只读模式，防止容器内意外修改</td>
			</tr>
			<tr>
					<td>SSH监听地址</td>
					<td>宿主机需监听 <code>0.0.0.0</code>，允许Docker网段访问</td>
			</tr>
			<tr>
					<td>网络隔离</td>
					<td>容器在Docker网段，宿主机在LAN网段，需正确配置路由</td>
			</tr>
	</tbody>
</table>
<h2 id="五常见错误">五、常见错误</h2>
<h3 id="错误1容器内生成密钥">错误1：容器内生成密钥</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># ❌ 错误做法</span>
</span></span><span class="line"><span class="cl">docker <span class="nb">exec</span> -it hermes-agent ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519
</span></span><span class="line"><span class="cl"><span class="c1"># 容器重启后密钥丢失</span>
</span></span></code></pre></div><h3 id="错误2密钥权限不正确">错误2：密钥权限不正确</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># ❌ 错误做法</span>
</span></span><span class="line"><span class="cl">chmod <span class="m">644</span> /home/ksboy/.ssh/hermes_key  <span class="c1"># SSH拒绝使用</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ✅ 正确做法</span>
</span></span><span class="line"><span class="cl">chmod <span class="m">600</span> /home/ksboy/.ssh/hermes_key
</span></span></code></pre></div><h3 id="错误3宿主机ssh只监听localhost">错误3：宿主机SSH只监听localhost</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># ❌ 错误做法</span>
</span></span><span class="line"><span class="cl">ListenAddress 127.0.0.1  <span class="c1"># Docker容器无法连接</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ✅ 正确做法</span>
</span></span><span class="line"><span class="cl">ListenAddress 0.0.0.0
</span></span></code></pre></div><h2 id="六总结">六、总结</h2>
<p>SSH密钥持久化的核心是理解Docker的文件系统隔离机制：</p>
<ol>
<li><strong>容器内文件不是持久的</strong> → 密钥必须在宿主机生成</li>
<li><strong>权限必须匹配</strong> → 宿主机密钥所有者需与容器运行用户一致</li>
<li><strong>网络必须可达</strong> → 宿主机SSH需监听所有地址</li>
</ol>
<p>这个解决方案已经稳定运行超过2周，容器重启后SSH连接正常。</p>
<hr>
<blockquote>
<p><strong>相关文档</strong>：<a href="~/.hermes/skills/git-credential-persistence/SKILL.md">SSH密钥持久化技能</a></p>
</blockquote>
]]></content:encoded></item></channel></rss>