<?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 Linkzz&#39;s Blog</title>
    <link>https://linkzz.org/categories/%E6%8A%98%E8%85%BE/</link>
    <description>Recent content in 折腾 on Linkzz&#39;s Blog</description>
    <image>
      <title>Linkzz&#39;s Blog</title>
      <url>https://linkzz.org/logo.png</url>
      <link>https://linkzz.org/logo.png</link>
    </image>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Sat, 02 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://linkzz.org/categories/%E6%8A%98%E8%85%BE/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>内网自部署存储迁移到自部署的 S3</title>
      <link>https://linkzz.org/posts/migrate-self-hosted-storage-to-s3/</link>
      <pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate>
      
      <guid>https://linkzz.org/posts/migrate-self-hosted-storage-to-s3/</guid>
      <description>&lt;h1 id=&#34;内网自部署存储迁移到自部署的-s3&#34;&gt;内网自部署存储迁移到自部署的 S3&lt;/h1&gt;
&lt;h2 id=&#34;1-存储的烦恼&#34;&gt;1. 存储的烦恼&lt;/h2&gt;
&lt;p&gt;我日常会使用一些自部署的服务，如写作的 &lt;a href=&#34;https://affine.pro/&#34;&gt;Affine&lt;/a&gt;、代码服务 &lt;a href=&#34;https://github.com/go-gitea/gitea&#34;&gt;Gitea&lt;/a&gt;、备忘录记录服务 &lt;a href=&#34;https://github.com/usememos/memos&#34;&gt;memos&lt;/a&gt; 记录自己的碎碎念。自部署这些服务的时候通常会涉及一些资源的存储，比如 Affine 中上传的图片资源、Gitea 的 package 制品、memos 中上传的图片等都需要消耗自身的存储空间。而我部署的平台是 PVE 的 Docker LXD 容器，这个容器里面使用 Docker 部署了一堆服务，存储已经扩了一遍又一遍了，然而主机上的存储也见底了。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://img.linkzz.eu.org/main/images/2026/05/711b35ab86bfdf8ee4fb8bd6637255c7.png&#34; alt=&#34;储存已经见底了&#34;  /&gt;
&lt;/p&gt;
&lt;p&gt;正好家里还有一台绿联的 NAS，里面有一个闲置的存储池，正好用来建一个 S3 存储给以上这些服务使用。这样一方面可以在同一个地方管理上传的对象，另一方面也可以利用存储池 Raid 做一些备份。&lt;/p&gt;
&lt;h2 id=&#34;2-部署-rustfs&#34;&gt;2. 部署 Rustfs&lt;/h2&gt;
&lt;p&gt;要说开源 S3 实现就不得不提大名鼎鼎的 &lt;a href=&#34;http://github.com/minio/minio&#34;&gt;Minio&lt;/a&gt; 了，然而其因为商业化已经停止了仓库的维护。况且我的 NAS 也仅是 4C8G 的配置，所以资源能省则省，基于 Rust 开发的 &lt;a href=&#34;https://github.com/rustfs/rustfs&#34;&gt;Rustfs&lt;/a&gt; 就是最好的选择——部署简单，资源占用低，性能还高，简直是居家旅行、自部署常备。&lt;/p&gt;
&lt;p&gt;NAS 上的 Docker 不能命令行，只能图形界面操作，就略过部署过程了。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://img.linkzz.eu.org/main/images/2026/05/c7d3edadea5e5e398ff52b3cad71cce5.png&#34; alt=&#34;Rustfs 部署&#34;  /&gt;
&lt;/p&gt;
&lt;p&gt;部署好了之后打开 console 端口 9001 即可进行存储桶操作。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://img.linkzz.eu.org/main/images/2026/05/c345cf9a65177b41a965d9b58138639d.png&#34; alt=&#34;存储桶管理&#34;  /&gt;
&lt;/p&gt;
&lt;h3 id=&#34;21-使用-aws-cli-测试访问&#34;&gt;2.1 使用 AWS CLI 测试访问&lt;/h3&gt;
&lt;p&gt;创建一个访问密钥，使用 &lt;a href=&#34;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&#34;&gt;AWS CLI&lt;/a&gt; 来测试访问。在 &lt;code&gt;~/.aws/credentials&lt;/code&gt; 中配置好访问密钥，&lt;code&gt;~/.aws/config&lt;/code&gt; 中配置 endpoint 信息：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[default]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;us-east-1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;endpoint_url&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;http://192.168.5.103:9000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;region 随便填一个值就可，测试访问：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;➜ : aws s3 ls s3://
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2026-04-22 00:58:25 affine-storage
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2026-04-22 15:20:44 gitea-storage
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2026-04-22 00:42:14 linkzz-bucket
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;3-使用-rustfs-存储数据&#34;&gt;3. 使用 Rustfs 存储数据&lt;/h2&gt;
&lt;p&gt;下面介绍使用 Rustfs 储存的服务。&lt;/p&gt;
&lt;h3 id=&#34;31-affine&#34;&gt;3.1 Affine&lt;/h3&gt;
&lt;p&gt;内网 Affine 的搭建可以看&lt;a href=&#34;https://wiki.linkzz.hm/workspace/aac4eaa1-d97e-42d2-8e1a-75e477650f0b/4Aqcj_NhG39sVQQzau7LR&#34;&gt;这篇文章&lt;/a&gt;。Affine 的存储引擎默认是本地文件系统，在 admin 页面可以更换为 S3 存储。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://img.linkzz.eu.org/main/images/2026/05/023f075953fd7a7a5c57a38884a01ab7.png&#34; alt=&#34;Affine S3 配置&#34;  /&gt;
&lt;/p&gt;
&lt;p&gt;可以分两个存储桶，一个存上传的媒体文件，一个存用户头像。内网使用用户就一个，单独建一个桶来存媒体文件就好了。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://img.linkzz.eu.org/main/images/2026/05/a72419efd2dbd25029e74b65e69f7d3c.png&#34; alt=&#34;Affine 文件上传&#34;  /&gt;
&lt;/p&gt;
&lt;p&gt;文件已然美美的上传了。&lt;/p&gt;
&lt;h3 id=&#34;32-gitea&#34;&gt;3.2 Gitea&lt;/h3&gt;
&lt;p&gt;Gitea 的代码不支持 S3 存储，但好在自己写的代码也不会太占空间。但是如果用到 Gitea 的 Package 上传一些 Docker 镜像或者是存储流水线存储的制品，这些可是很占空间的。好在这些都是支持 S3 存储的。这里要赞扬一波 Gitea，公司内部的代码库也是我搭的 Gitea，虽然脱胎于 Gogs，但在保持 Gogs 轻量级体验的同时引入了很多 GitHub 相关的功能，如完全兼容 GitHub Actions 的流水线、同样的 Package 系统（支持 Docker 镜像、Java Nexus Maven 仓库、NPM Registry 等），常见的语言依赖仓库都支持，省了很多自建的烦恼，使用起来也是极其丝滑。一个开源的产品能做到这样真的没得说。&lt;/p&gt;
&lt;p&gt;Gitea 需要在配置文件中开启 S3 存储，加入下面的配置项重启即可：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[storage]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;STORAGE_TYPE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;minio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MINIO_ENDPOINT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;192.168.5.103:9000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MINIO_ACCESS_KEY_ID&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;YOUR_AK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MINIO_SECRET_ACCESS_KEY&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;YOUR_SK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MINIO_BUCKET&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;gitea-storage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MINIO_LOCATION&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;us-east-1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;构建一个 Docker 镜像上传试试看：&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://img.linkzz.eu.org/main/images/2026/05/ac5aeb6992bd134e15adea4ab8e18ce4.png&#34; alt=&#34;Gitea Docker 镜像上传&#34;  /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://img.linkzz.eu.org/main/images/2026/05/7f390540d08d5e38332030dfcc141500.png&#34; alt=&#34;Gitea Package 存储桶&#34;  /&gt;
&lt;/p&gt;
&lt;p&gt;gitea-storage 桶里面也有值了，只是为啥这么小，压缩率这么大的吗？后续再研究一下。&lt;/p&gt;
&lt;h3 id=&#34;33-memos&#34;&gt;3.3 Memos&lt;/h3&gt;
&lt;p&gt;Memos 也是原生支持 S3 存储，后台配置一下即可：&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://img.linkzz.eu.org/main/images/2026/05/0ffece1bc2e98d25ae75f4690842f57c.png&#34; alt=&#34;Memos S3 配置&#34;  /&gt;
&lt;/p&gt;
&lt;p&gt;测试一下：&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://img.linkzz.eu.org/main/images/2026/05/e453fd03447be529563f19673764d75c.png&#34; alt=&#34;Memos 上传测试&#34;  /&gt;
&lt;/p&gt;
&lt;p&gt;看下桶里面有没有数据：&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://img.linkzz.eu.org/main/images/2026/05/cf3bfd45a8cbc11344d54612336ec606.png&#34; alt=&#34;Memos 桶数据&#34;  /&gt;
&lt;/p&gt;
&lt;p&gt;没问题！搞定！&lt;/p&gt;
&lt;h2 id=&#34;4-总结&#34;&gt;4. 总结&lt;/h2&gt;
&lt;p&gt;终于是将一些自部署服务的媒体文件都搜集起来了。使用 S3 来集中存储自部署的这些文件，以后部署在甲骨文上的一些服务也可以将存储迁移到 S3 桶里面。后续再做一个定期将服务数据打包上传 S3，再也不怕哪天甲骨文突然被收回了。&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>

