[{"data":1,"prerenderedAt":183},["ShallowReactive",2],{"article-krpvl5itbr9h":3,"$fkmwVzhKrOoDFrhafKryf_9vr168PWO09Yc0U2bhm5Nw":40,"$fyRRLA_tAkoPcHMdmdwhp_R6xZdYoP9oRleBILMlXtYQ":46,"$f5oY62VuXeh2XI8ZDuHdZer_K8uiJ1iQvDUBtU2HPf-M":53,"$fKbiX3hqsJBrRjvk5vi4s7Vsm-AZHxTS8VFJmzGJdSec":60,"prev-article-krpvl5itbr9h":67,"$fD8hzZhjT1zfpkzxc7OJEqvRkh0Y7KIg7IP_0D2khc54":85,"$f5NIqJz26vbohl6ppX0U9ADW5aa7h2Dreqgy_rhqf_-4":92,"$fE6_tIcxh63R6_9QO71bv5Pzv7IEvo40bkcgxtPn1pYM":99,"next-article-krpvl5itbr9h":105,"$fUTMhTQ7Riwi-Jd0qd2IVk4oC7P4AhuIDP9zrE2zNGaU":129,"$ffWi20PZVpucMzEYlNmkiJruhuWOh7LYoqXzzeet7zgM":136,"$fkB7bvuJgaMARo5qofJ8PWvYCJWWvj1UGVyD4CQQ60fQ":141,"$fzOE8Jl2NRKp8uyZys-3XMm2ofy5LQBOwixEWsEZqz00":148,"$fFm6goIhr4adTzjnWtoUKp7Pi8TWVMt5as5EMRXsppRA":154,"$f-odgiAXPrR86wFXgwxM_pgIcxK6KYatg6xl-O7sgsMw":158,"$fCGNQSnRgL0sC-uUMW2RVQF565rY_n7kDzOT3eEgvzSo":165,"$fm6rJvpCDb8uj5V4N2MrrvSXKJ0cojDAkTzRZeJ7AiSs":172,"$fsYEN_SWdT0ud_mUAqdQ76m5NG98bEBc4ihE23EVrJiE":177},{"contents":4,"totalCount":38,"offset":39,"limit":38},[5],{"id":6,"createdAt":7,"updatedAt":8,"publishedAt":9,"revisedAt":8,"title":10,"content":11,"tags":12,"is_no_index":37},"krpvl5itbr9h","2025-07-29T13:13:13.582Z","2026-06-21T14:30:14.475Z","2025-07-30T18:27:14.444Z","Misskeyサーバー構築から爆破までのすべて","\u003Ch1 id=\"h8d027c8ed3\">はじめに\u003C/h1>\u003Cp>巷に溢れるMisskeyインスタンスの構築記事、正直「うーん…」ってなるものが多くないですか？\u003Cbr>xsnsなんかはそもそも話にならないとして、書かれているコマンドの意味もよくわからないままコピペするだけで、本当に大丈夫なのかなって、わたしは少し心配になってしまいます。大した理解もないのに自信満々に記事を書けちゃうメンタル、どこから来るんでしょうね。\u003C/p>\u003Cp>当エントリでは、サーバの構築から、いつか来る爆破の時までを、私のわかる範囲でちゃんとマニュアル化してみようと思います。なるべく理解できる形にするつもりではいますが、手取り足取りという感じではないです。「ちゃんと自分で調べて、理解してから触ろうね」というスタンスですので、その点だけご了承ください。\u003C/p>\u003Cp>言ってしまうと、Misskeyインスタンスを建てること自体は非常に簡単です。小学校低学年くらいの子でも全然できると思います。\u003Cbr>しかし、コマンドをコピペするだけの方、あるいはそれすら難しいと感じる方は、悪いことは言わないので手を出さないほうが良いでしょう。\u003C/p>\u003Cp>さもなくば、何かトラブルがあった際にどう対応するつもりなのでしょうか。問題が生じるたびに、投げ出して破棄するのでしょうか？\u003Cbr>当たり前の話ですが、サーバには継続的なメンテナンスが不可欠です。建てるだけ建てて、後のことは知らないというのは、管理者としてあまりに無責任が過ぎます。\u003C/p>\u003Cp>「習うより慣れろ」だとか「まずは不完全でも動かしてみることが大事」なんて言葉を免罪符に、無知なまま他人のデータを預かろうとするのは、単なる傲慢です。技術的な未熟さを熱意やコミュニティへの貢献で誤魔化せると思っているのなら、それは大きな間違いだと言わざるを得ません。そもそも、この程度の内容を調べながら読んでも理解できないのであれば、明らかに知識不足ですので、出直してください。誰もしあわせにはなれません。\u003C/p>\u003Cp>一方で、高コンテクストな内容を同時に広く扱う都合上、当エントリは全体で短編小説ほどの文量になってしまっています。すべてを律儀に読み通すのはなかなかの苦行でしょうから、目次を活用し、あなたの気になる見出しからご覧いただくことを推奨します。\u003C/p>\u003Cp>また上記の都合から、いたずらに文量を増やさないためにも、技術の導入方法や初歩的な操作手順といった、すでに優れた技術記事や公式ドキュメントで十分に解説されている箇所については一部省略し、参考としてリンクを積極的に記載する方針を採っています。\u003C/p>\u003Cp>結果として当エントリは、サーバを構築するための具体的なHowToは他の記事に譲りつつ、そこで解説を省かれがちな管理者として極めて重要であると考える項目を補完することに重きを置く形となりました。それゆえ、そうした外部の解説記事やドキュメントをひっくるめて、初めてひとつの技術記事として成立するよう設計されています。記載されたリンク先へも適宜目を通していただけると、より理解が深まるはずです。\u003C/p>\u003Cp>なお、エントリ内で「インスタンス」や「サーバ」といったMisskeyのホストを指す語に表記揺れが存在しますが、これらは同義のものとして扱って構いません。Misskey Project公式がインスタンスをサーバと呼称するようになって久しいですが、未だにインスタンスと呼ぶ癖が抜けないのです。\u003Cs>SEO的な浅ましい狙いも否定はしませんが。\u003C/s>\u003C/p>\u003Cp>本エントリを読んでわかることはおおまかに以下の通りです\u003C/p>\u003Cul>\u003Cli>VPSと独自ドメインを使ったMisskeyサーバの構築手順\u003C/li>\u003Cli>Docker + Cloudflare Tunnelによる公開方法\u003C/li>\u003Cli>絵文字・オブジェクトストレージ・メール・監視など運用の実務\u003C/li>\u003Cli>ユーザ増加時のスケール戦略と、最終的な閉鎖手順\u003C/li>\u003C/ul>\u003Ch1 id=\"h392131f5fc\">Misskeyインスタンスを建てるためのVPSを用意する\u003C/h1>\u003Cp>Misskeyサーバを構築するにあたり、まずそのアプリケーションが稼働するための計算基盤、すなわちサーバを用意する必要があります。\u003Cbr>そのアーキテクチャは、大別して二つの選択肢に集約されるでしょう。\u003Cbr>物理的なサーバ実体を自らの管理下に置くか、専門事業者が提供する仮想化された計算資源を利用することです。\u003C/p>\u003Cp>ここでまず、わたしの基本的なスタンスを明確にしておきます。 わたしはこれからMisskeyインスタンスを運用しようとする方に対して、自宅サーバという選択肢を推奨しません。\u003C/p>\u003Cp>もちろん、技術的な探求や学習といった特定のコンテクストにおいては、自宅サーバは依然として優れた選択肢です。\u003Cbr>しかし、安定したサービス提供を目的とするならば、それは合理的な判断とは言えないでしょう。物理的な障害対応や、見過ごされがちな電気代、そして何より人的な運用コストといったものを考慮すると、その経済的・時間的合理性は極めて限定的だからです。\u003C/p>\u003Cp>ここでは、あなたが本来集中すべきアプリケーションの運用から乖離するような、不必要な複雑さからは距離を置きます。\u003C/p>\u003Cp>ということで、いずれかのVPS事業者と契約することになります。(マネージドサービス系はお財布に優しくないので)\u003C/p>\u003Cp>正直なところ、特定の事業者を強く推奨したいのですが、現実問題として、どの事業者を選択しても何かしらの微妙なところが存在します。そのため、ここでは比較的マシであり、特にこだわりがないのであれば大きな失敗には繋がりにくいであろう選択肢を挙げるに留めます。\u003C/p>\u003Cul>\u003Cli>Vultr\u003C/li>\u003Cli>Linode\u003C/li>\u003C/ul>\u003Cp>基本的には、何を契約しても構いません。\u003Cs>(というのは嘘で、国内のベンダはまともなところが少ないので、あまりオススメしません。)\u003C/s>\u003C/p>\u003Cp>仮に公開インスタンスとして運用するとしても、最初は1Core/1GiB程度のスペックを持ちインターネットへの疎通性のある月額2,300円前後のプランで十分です。もちろん、これ以上のスペックがあればより快適ですが、最初から過剰な投資をする必要はありません。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/56985da3f6d24c0b97f33e68e053dad2/image.png\" alt=\"\" width=\"1047\" height=\"809\">\u003C/figure>\u003Cp>安定したサービス運用は、ある種のインフラ投資です。無闇にコストを削ることが、結果として技術的負債や将来的な運用負荷に繋がる可能性を、常に念頭に置いておくべきでしょう。\u003Cbr>あなたが合理的だと判断した事業者とプランを選択し、契約を進めてください。\u003C/p>\u003Cp>今回は3Core/4GBの環境を利用しています。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/4617e6ff91834c4c97e49a1297d0ae22/image.png\" alt=\"\" width=\"841\" height=\"406\">\u003C/figure>\u003Cp>Xserverの無料の子です。検証用途であればきっと差し支えないでしょう。\u003C/p>\u003Ch1 id=\"h2da3fdb1f2\">ドメインを用意する\u003C/h1>\u003Cp>Misskeyのインスタンスを公開するにあたり、固有のドメインが必要になります。既存のドメインがあり、サブドメインを利用する場合、この工程は飛ばして構いません。\u003C/p>\u003Cp>ActivityPubの仕様上、ドメイン名を後から変更することができないので、ある程度は考えて選んでください。\u003Ccode>.com\u003C/code>や\u003Ccode>.dev\u003C/code>といったgTLDであれば、基本的には何でも構いません。\u003C/p>\u003Cp>ドメインはレジストラから取得しますが、どのレジストラを選ぶかは重要です。国内でよく名前が挙がる「お名前.com」のような事業者を個人的には推奨しません。\u003C/p>\u003Cp>もし、あなたに特別なこだわりがないのであれば、\u003Ca href=\"https://www.cloudflare.com/products/registrar/\" target=\"_blank\" rel=\"noopener noreferrer\">Cloudflare Registrar\u003C/a>をお勧めします。 Cloudflareはドメインを卸値で提供しており、余計な手数料がかからず安価です。また、この後利用することになるCDNやセキュリティ機能との連携もスムーズで、管理画面もシンプルです。特別な理由がない限り、Cloudflareを選んでおけば間違いないでしょう。\u003C/p>\u003Cp>Cloudflareのアカウントを作成し、希望のドメインを取得してください。\u003C/p>\u003Cp>ドメインを取得できたら、Auto MinifyとRocket Loader™をすべて無効化しておきます。\u003Cbr>この手順を飛ばすとMisskeyが正常に動作しない場合がありますので、必ず行ってください。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/0c79a3f446b54e54b5a906e2e71b9e5c/image.png\" alt=\"\" width=\"1920\" height=\"929\">\u003C/figure>\u003Cp>\u003Ccode>Domains &gt; Spped &gt; Settings &gt; Content Optimization\u003C/code>から設定が可能です。\u003C/p>\u003Ch1 id=\"h0cb67a7186\">Cloudflare TunnelでMisskeyインスタンスを公開する準備\u003C/h1>\u003Cp>今回の手順では、IPv6のみの環境など、より多くのケースで汎用的に利用できるよう\u003Ca href=\"https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/\" target=\"_blank\" rel=\"noopener noreferrer\">Cloudflare Tunnel\u003C/a>を利用します。\u003Cbr>これはCloudflareが提供するトンネリングサービスで、サーバとCloudflareのデータセンター間を安全な経路で接続し、外部にポートを公開することなくウェブサイトを公開できるものです。後述の手順でトークンが必要になるため、あらかじめ取得しておきます。\u003C/p>\u003Cp>Cloudflareの管理画面は少し分かりにくいのですが、以下の手順で進めてください。\u003C/p>\u003Col>\u003Cli>Cloudflareのダッシュボードにログインし、サイドメニューからZero Trustを選択。\u003C/li>\u003C/ol>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/bfe6a4c4edfc432dbc5d7da24b27c000/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2022.48.25.png\" alt=\"\" width=\"1920\" height=\"929\">\u003C/figure>\u003Col start=\"2\">\u003Cli>Networks &gt; Connectors より Create a tunnelをクリック\u003C/li>\u003C/ol>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/29ebb87f9f72404aa4d9b0015340ba07/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2022.49.21.png\" alt=\"\" width=\"1920\" height=\"929\">\u003C/figure>\u003Col start=\"3\">\u003Cli>Cloudflaredを選択\u003C/li>\u003C/ol>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/e944c6ec6f6f4203962a12876515af5b/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2022.49.30.png\" alt=\"\" width=\"1918\" height=\"928\">\u003C/figure>\u003Col start=\"4\">\u003Cli>任意の名称を入力し、Save Tunnelを押下\u003C/li>\u003C/ol>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/afd3bbd4a3d64ccd9673f38509af9949/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2022.50.24.png\" alt=\"\" width=\"1920\" height=\"929\">\u003C/figure>\u003Col start=\"5\">\u003Cli>トークンを控える\u003C/li>\u003C/ol>\u003Cp>\u003Ccode>cloudflared.exe service install eyJhIjoiYThlODIxMWM2N...\u003C/code>のような文字列がコピーできるので、\u003Ccode>eyJhIjoiYThlODIxMWM2N...\u003C/code>のようなトークン部のみを控え、Nextを押下。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/2cc357c1b9a147fab9d2db6ab30e6370/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2022.50.51.png\" alt=\"\" width=\"1920\" height=\"928\">\u003C/figure>\u003Col start=\"6\">\u003Cli>FQDNとの紐付け\u003C/li>\u003C/ol>\u003Cp>前項の手順で用意したドメインと、サービスを紐付けます。\u003Cbr>このとき、Serviceは必ず\u003Ccode>http://app:3000\u003C/code>となるようにしておいてください。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/995f65dea38747b8bdfbfdd4a117b8c3/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2022.51.47.png\" alt=\"\" width=\"1920\" height=\"931\">\u003C/figure>\u003Cp>ちなみに、ここでServiceにループバックアドレスを指定しても疎通自体は可能です。\u003Cbr>しかしながら、ループバックアドレスを設定してしまうとパフォーマンス上の問題が発生する可能性がでてきます。\u003C/p>\u003Cp>Dockerは、起動時に各サービスが通信するための内部ネットワークを構築します。このネットワーク内では、各コンテナにサービス名を使って直接アクセスできる、一種のDNS機能が提供されます。\u003Cbr>Serviceの向き先として \u003Ccode>http://app:3000\u003C/code> を指定することで、CloudflaredのコンテナからMisskeyコンテナへの通信は、最適化されたDocker内部ネットワークで完結します。 \u003C/p>\u003Cp>一方、ループバックアドレスを指定した場合、通信は一度ホストOSのネットワークスタックを経由し、ポートマッピングの仕組みを介してコンテナへと届けられます。リクエスト数が少ない場合、パフォーマンスへの影響は少ないのですが、大量のリクエストが発生した場合はdocker-proxyが大量のCPUリソースを消費してしまう現象があるようです。\u003C/p>\u003Cp>無駄なことをするのは控えておきましょう。\u003C/p>\u003Ch1 id=\"haf9b57cc17\">DockerでMisskey本体を構築する\u003C/h1>\u003Cp>サーバとドメインの準備が整いました。\u003Cbr>いよいよ、Misskey本体を構築していきます。\u003C/p>\u003Cp>最新のイケイケな技術に惹かれる気持ちは、技術者であれば誰しもが抱くものかもしれません。わたしも、その例外ではありません。 \u003Cbr>しかし、わたしたちの目的が技術的な探求ではなく、インスタンスの安定稼働であるならば、その技術選定はより現実的な視点で行う必要があります。\u003C/p>\u003Cp>例えば、Kubernetesなんかがその典型例でしょう。\u003Cbr>スケーラビリティがそこまで重要ではない小規模なインスタンスにおいて、Kubernetesの導入は無用な複雑さとオーバーヘッドを生み、管理コストを増大させるだけです。期待するほどのメリットは、まず得られません。新しい技術に挑戦する姿勢は評価できますが、目的と手段を見誤った技術選定は賢明と言えないでしょう。\u003C/p>\u003Cp>結論から言えば、個人や小規模なコミュニティが運営するMisskeyインスタンスにおいて、その基盤はシングルノードDockerで十分である、とわたしは考えています。\u003Cbr>できもしない無謀な試みをせず、身の丈に合った選択をしましょう。\u003C/p>\u003Cp>ここでは、その方針に基づき、Dockerを利用してMisskeyを構築していきます。\u003C/p>\u003Ch2 id=\"h64e4921e27\">Dockerの導入\u003C/h2>\u003Cp>契約したVPSにSSHを行い、以下のコマンドを実行します。\u003C/p>\u003Cp>\u003Ccode>sudo apt install curl -y &amp;&amp; curl https://get.docker.com/ | sudo sh -\u003C/code>\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/5ebe2386901c40b5b72406f09a935341/image.png\" alt=\"\" width=\"351\" height=\"40\">\u003C/figure>\u003Cp>現時点で最新のものです。\u003C/p>\u003Ch2 id=\"h581c75cdc4\">環境の用意\u003C/h2>\u003Cp>ディレクトリを作成し、必要なファイル類を作成します。\u003C/p>\u003Cpre>\u003Ccode class=\"language-shell\">mkdir ./misskey ./misskey/config\ncd ./misskey\ntouch ./compose.yaml ./config/.env\ncurl https://raw.githubusercontent.com/misskey-dev/misskey/refs/heads/develop/.config/docker_example.yml &gt; ./config/default.yml\u003C/code>\u003C/pre>\u003Cp>vimやらnanoやらを使って各ファイルを編集します。\u003C/p>\u003Cdiv data-filename=\"./compose.yaml\">\u003Cpre>\u003Ccode class=\"language-yaml\">services:\n  app:\n    image: misskey/misskey:latest\n    restart: always\n    links:\n      - db\n      - redis\n    depends_on:\n      db:\n        condition: service_healthy\n      redis:\n        condition: service_healthy\n    networks:\n      - internal_network\n    volumes:\n      - ./config/default.yml:/misskey/.config/default.yml:ro\n\n  redis:\n    restart: always\n    image: eqalpha/keydb:alpine\n    networks:\n      - internal_network\n    volumes:\n      - ./data/keydb:/data\n    healthcheck:\n      test: &quot;redis-cli ping&quot;\n      interval: 5s\n      retries: 20\n\n  db:\n    restart: always\n    image: groonga/pgroonga:latest-debian-16\n    ports:\n      - &apos;5430:5432&apos;\n    networks:\n      internal_network:\n    env_file:\n      - ./config/.env\n    volumes:\n      - ./data/db:/var/lib/postgresql/data\n    healthcheck:\n      test: &quot;pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB&quot;\n      interval: 5s\n      retries: 20\n\n  tunnel:\n    restart: always\n    image: cloudflare/cloudflared\n    command: tunnel --no-autoupdate run\n    profiles:\n      - tunnel\n    env_file:\n      - ./config/.env\n    networks:\n      - internal_network\n\nnetworks:\n  internal_network:\u003C/code>\u003C/pre>\u003C/div>\u003Cdiv data-filename=\"./config/.env\">\u003Cpre>\u003Ccode class=\"language-yaml\">POSTGRES_PASSWORD=データベースのパスワードとして利用する任意の英数字\nPOSTGRES_USER=misskey\nPOSTGRES_DB=mk1\nDATABASE_URL=&quot;postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}&quot;\n\nTUNNEL_TOKEN=Cloudflare Tunnelのトークン\u003C/code>\u003C/pre>\u003C/div>\u003Cdiv data-filename=\"./config/default.yml\">\u003Cpre>\u003Ccode class=\"language-yaml\">#   ┌─────┐\n#───┘ URL └─────────────────────────────────────────────────────\n\n# Final accessible URL seen by a user.\n# You can set url from an environment variable instead.\nurl: https://利用するドメイン/\u003C/code>\u003C/pre>\u003C/div>\u003Cp>\u003Cs>2025.12.15追記\u003Cbr>Misskey v2025.12.0-alpha.2以降、\u003C/s>\u003Ca href=\"https://github.com/misskey-dev/misskey/security/advisories/GHSA-wwrj-3hvj-prpm\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cs>セキュリティ上の懸念\u003C/s>\u003C/a>\u003Cs>により\u003C/s>\u003Ca href=\"https://github.com/misskey-dev/misskey/commit/5512898463fa8487b9e6488912f35102b91f25f7\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cs>デフォルト値が変更されたため\u003C/s>\u003C/a>\u003Cs>、クライアントのIPを正確に把握するため、プロキシ環境下では\u003C/s>\u003Ccode>trustProxy\u003C/code>\u003Cs>を明示的に\u003C/s>\u003Ccode>true\u003C/code>\u003Cs>にしておく必要があります。\u003Cbr>本エントリの構成においては、CaddyとCloudflare Tunnelを利用しているため、\u003C/s>\u003Ccode>true\u003C/code>\u003Cs>を明示する必要があります。\u003Cbr>また、この設定項目については\u003C/s>\u003Ca href=\"https://github.com/misskey-dev/misskey/issues/16994\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cs>将来的に変更される可能性\u003C/s>\u003C/a>\u003Cs>があります。\u003C/s>\u003C/p>\u003Cp>2025.12.16追記\u003Cbr>\u003Ccode>trustProxy\u003C/code>周りの\u003Ca href=\"https://github.com/misskey-dev/misskey/issues/16994#issuecomment-3659950721\" target=\"_blank\" rel=\"noopener noreferrer\">変更が戻されました\u003C/a>。現時点では、必要がなければ設定する必要はありません。\u003Cbr>また、この設定項目については\u003Ca href=\"https://github.com/misskey-dev/misskey/issues/16994\" target=\"_blank\" rel=\"noopener noreferrer\">将来的に変更される可能性\u003C/a>があります。\u003C/p>\u003Cdiv data-filename=\"./config/default.yml\">\u003Cpre>\u003Ccode class=\"language-yaml\">#   ┌──────────────────────────┐\n#───┘ PostgreSQL configuration └────────────────────────────────\n\ndb:\n... 中略\n  # Database name\n  # You can set db from an environment variable instead.\n  db: mk1\n\n  # Auth\n  # You can set user and pass from environment variables instead.\n  user: misskey\n  pass: データベースのパスワードとして利用する任意の英数字\u003C/code>\u003C/pre>\u003C/div>\u003Cdiv data-filename=\"./config/default.yml\">\u003Cpre>\u003Ccode class=\"language-yaml\">#   ┌───────────────────────────────┐\n#───┘ Fulltext search configuration └─────────────────────────────\n\n# These are the setting items for the full-text search provider.\nfulltextSearch:\n... 中略\n  provider: sqlPgroonga\u003C/code>\u003C/pre>\u003C/div>\u003Cp>\u003Ccode>./config/default.yml\u003C/code>はあまりにも長いので変更部位のみピックアップしています。\u003C/p>\u003Ch2 id=\"hec00bc706e\">DBの準備\u003C/h2>\u003Cp>次のコマンドでデータベースの初期化と全文検索のためのPGroongaの有効化を行います。 \u003Cbr>これにはしばらく時間がかかります。\u003C/p>\u003Cpre>\u003Ccode class=\"language-shell\">sudo docker compose run --rm app pnpm run init\nsudo docker compose exec db psql -U misskey -d mk1 -c &quot;create extension if not exists pgroonga;&quot;\nsudo docker compose exec db psql -U misskey -d mk1 -c &quot;create index idx_note_text_with_pgroonga on note using pgroonga (text);&quot;\u003C/code>\u003C/pre>\u003Ch2 id=\"h1d40932a6f\">起動\u003C/h2>\u003Cp>以下のコマンドでMisskeyを起動できます。\u003C/p>\u003Cpre>\u003Ccode class=\"language-shell\">sudo docker compose --profile tunnel up -d\u003C/code>\u003C/pre>\u003Cp>うまくいくとこんな感じ\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/be983a0182834397b2ae4615c74eaa20/image.png\" alt=\"\" width=\"1096\" height=\"420\">\u003C/figure>\u003Cp>ここでtunnelをprofileとして指定しているのは、misskeyを更新するたびにCloudflare Tunnelのコンテナまで再生成されないようにする意図があります。\u003C/p>\u003Ch1 id=\"h6ae33e7349\">設定\u003C/h1>\u003Ch2 id=\"h69f761e8b8\">セットアップウィザード\u003C/h2>\u003Cp>これまでの手順が正しく完了していれば、取得したドメインにお手元のブラウザからアクセスすると、Misskeyの初期設定画面が表示されるはずです。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/80d40f22d58f476da7cbe5a2077b75e9/image.png\" alt=\"\" width=\"1918\" height=\"909\">\u003C/figure>\u003Cp>ここでは管理者ユーザを作成するのですが、このアカウントは一般ユーザとは扱いが異なり、削除等が通常できません。\u003C/p>\u003Cp>あなたがこのインスタンスを個人的なおひとり様インスタンスとしてではなく、コミュニティとして運用するつもりなのであれば、ここで作成するアカウントを日常的に利用することは避けるべきでしょう。普段使いのアカウントとは別に、管理作業のためだけの専用アカウント(例えば@adminといったユーザ)を作成することを、強く推奨します。\u003C/p>\u003Cp>\u003Cs>わたしはこれで後悔しました。\u003C/s>\u003C/p>\u003Cp>入力後、次を押下するとウィザードへ遷移します。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/9ac6d52c9f1a4553b82a845da6e316d4/image.png\" alt=\"\" width=\"1918\" height=\"906\">\u003C/figure>\u003Cp>この項目をスキップすることもできますが、ここで片付けておきましょう。\u003Cbr>基本的な設定はこれで完了します。\u003C/p>\u003Ch2 id=\"hcae32190de\">オブジェクトストレージ\u003C/h2>\u003Cp>Misskeyではドライブの格納先としてAWS S3または互換のオブジェクトストレージを使う設定ができます。\u003Cbr>これを有効化しておかないと、files/ディレクトリ配下にファイルが蓄積されるのですが、運用上あまり好ましくないので、可能であればオブジェクトストレージの利用をしましょう。\u003Cbr>ここではCloudflare R2を利用します。\u003C/p>\u003Cp>Cloudflareのアカウントホームを開き、\u003Ccode>Storage &amp; databases &gt; R2 Object Storage &gt; Overview\u003C/code>を開き、新規bucketを作成します。\u003C/p>\u003Cp>\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/cc353e7ef83145288617702ada17f758/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2023.06.05.png\" alt=\"\" width=\"1920\" height=\"929\">\u003C/figure>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/53e652db8f4348ba81d53f4cb384c643/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2023.14.17.png\" alt=\"\" width=\"1918\" height=\"930\">\u003C/figure>\u003Cp>名称は何でも構いませんが、ここではmi-testとしています。\u003C/p>\u003Cp>作成後、Settingsを開き、S3 APIのURLを控えておきます。\u003Cbr>また、キャッシュを効かせるためカスタムドメインを追加します。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/518c02b0bfd64dbe84e76bf88ea929f6/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2023.03.30.png\" alt=\"\" width=\"1920\" height=\"929\">\u003C/figure>\u003Cp>カスタムドメインは適当なサブドメインにでもしておきましょう。\u003Cbr>ここでは\u003Ccode>media-mi-test.mq1.dev\u003C/code>を指定しました。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/27bd7b46e2474a43b5c5e3b17f1958a7/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2023.03.54.png\" alt=\"\" width=\"1920\" height=\"928\">\u003C/figure>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/397518301e5c43f8924bcb5c62129b7b/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2023.04.16.png\" alt=\"\" width=\"1920\" height=\"930\">\u003C/figure>\u003Cp>R2のダッシュボードから、\u003Ccode>API Tokens &gt; Manage\u003C/code>を開き、\u003Ccode>Create Account API token\u003C/code>からトークンを新規作成します。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/eaf0036cfbbd48e88bdcf9ea7eb5c8bc/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2023.19.43.png\" alt=\"\" width=\"1920\" height=\"930\">\u003C/figure>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/d93bd20d282a4a83b2b452299a574483/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2023.06.57.png\" alt=\"\" width=\"1920\" height=\"929\">\u003C/figure>\u003Cp>権限はObject Read &amp; Write、スコープを先ほど作成したbucketのみに絞っておきます。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/d9b90711b2404092a6440c868162b162/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2023.07.40.png\" alt=\"\" width=\"1920\" height=\"928\">\u003C/figure>\u003Cp>Create Account API Tokenを押下し、Access Key IDとSecret Access Keyを控えておきます。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/5fdfdd68d2b54d4896dd98fb1611febe/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202026-06-21%2023.08.18.png\" alt=\"\" width=\"1920\" height=\"928\">\u003C/figure>\u003Cp>閉じてしまうと再表示できなくなるので注意してください。\u003C/p>\u003Cp>Misskeyへ戻り、\u003Ccode>コントロールパネル &gt; 設定 &gt; オブジェクトストレージ\u003C/code>より、R2の情報を入力します\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/2ca617b554374fe99e4756b486908805/image.png\" alt=\"\" width=\"1916\" height=\"909\">\u003C/figure>\u003Cp>ここでの入力値は以下のものに対応します。\u003C/p>\u003Cul>\u003Cli>Base URL\u003Cp>設定したカスタムドメイン(末尾に/を入れないでください)\u003Cbr>例: \u003Ccode>https://media-mi-test.mq1.dev\u003C/code>\u003C/p>\u003C/li>\u003Cli>Bucket\u003Cp>Bucket名\u003Cbr>例:  \u003Ccode>mi-test\u003C/code>\u003C/p>\u003C/li>\u003Cli>Prefix\u003Cp>任意のPrefix名\u003Cbr>例: \u003Ccode>drive\u003C/code>\u003C/p>\u003C/li>\u003Cli>Endpoint\u003Cp>控えておいたS3 APIのURL\u003Cbr>例: \u003Ccode>https://a8e8211c674c2b00f3a8996b65b56447.r2.cloudflarestorage.com\u003C/code>\u003C/p>\u003C/li>\u003Cli>Region\u003Cp>\u003Ccode>us-east-1\u003C/code>\u003C/p>\u003C/li>\u003Cli>Access Key\u003Cp>控えておいたAccess Key ID\u003C/p>\u003C/li>\u003Cli>Secret Key\u003Cp>控えておいたSecret Access Key\u003C/p>\u003C/li>\u003C/ul>\u003Cp>すべての項目を入力し、保存を押下します。\u003C/p>\u003Cp>2025.08.21追記\u003Cbr>Endpointの例として\u003Ccode>https://a8e8211c674c2b00f3a8996b65b56447.r2.cloudflarestorage.com/mi-test\u003C/code>を挙げていましたが、これは誤りです。\u003Cbr>正しくはBucket名を含まない上記の例(\u003Ccode>https://a8e8211c674c2b00f3a8996b65b56447.r2.cloudflarestorage.com\u003C/code>)をご参照ください。\u003C/p>\u003Ch2 id=\"hee49c0d379\">メールサーバ\u003C/h2>\u003Cp>メールの配信を行うSMTPサーバの設定を行います。\u003Cbr>公開インスタンスとして運営するつもりであれば、新規登録の確認やパスワードリセットなど、システムからの通知に必須となりますので、必ず設定しておきましょう。\u003C/p>\u003Cp style=\"text-align: start\">SMTPが利用できれば根本的には何でも構いませんが、手軽さと配送品質の観点から、当エントリでは\u003Ca href=\"https://resend.com/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">Resend\u003C/a>の利用を推奨します。\u003C/p>\u003Cp style=\"text-align: start\">\u003Ca href=\"https://resend.com/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">https://resend.com/\u003C/a>\u003C/p>\u003Cp>私はインスタンス設立当初SESを利用していましたが、現在はResendに落ち着いています。メールの送信にTLSを強制している影響か、\u003Cs>d○c○m○をはじめとする\u003C/s>キャリアメール宛への送信がうまくいかない場合がありますが、ガラパゴスな仕様へのサポートは切り落とすに限ります。\u003C/p>\u003Cp>ただし、ResendのFree Planを利用する上で、一つだけ極めて重要な注意点があります。それは、1つのアカウントにつき、紐付けられる独自ドメイン(FQDN)は1つまでという制約です。\u003C/p>\u003Cp>もし将来的に、別のMisskeyインスタンスを別ドメインで立てたり、個人的なプロジェクトでResendを利用する可能性が少しでもあるのなら、アカウント作成時に安易なGitHub等のSSOの利用は避けておくといいでしょう。SSOで紐づけてしまうと、いざ別のアカウントを作ろうとした時に同じメールアドレスが使えず、すごくに面倒なことになります。\u003C/p>\u003Cp>Resendのアカウントを作成し、ドメインの認証が完了したら、API keysからSMTP用のクレデンシャルを発行します。\u003C/p>\u003Cp style=\"text-align: start\">\u003Ccode>コントロールパネル &gt; 設定 &gt; メールサーバー\u003C/code>より、SMTPのクレデンシャルを入力し保存します。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/552c3d5d9960490380f0acd134f3b178/image.png\" alt=\"\" width=\"1918\" height=\"910\">\u003C/figure>\u003Cp>Resendを使う場合、必要なことはすべて\u003Ca href=\"https://resend.com/docs/send-with-smtp\" target=\"_blank\" rel=\"noopener noreferrer\">ここ\u003C/a>に書かれているので参照してください。\u003Cbr>\u003Ca href=\"https://resend.com/docs/send-with-smtp\" target=\"_blank\" rel=\"noopener noreferrer\">https://resend.com/docs/send-with-smtp\u003C/a>\u003C/p>\u003Cp>\u003C/p>\u003Cp>また、「宗教上の理由でResentは使いたくない」「おすすめされたものを使うのは癪だ」という奇特な方のために、GmailをSMTPサーバとして利用する方法も存在します。制限こそありますが、小規模なインスタンスであれば実用に耐え得ます。\u003C/p>\u003Cp>これについては、私が過去に書いた以下の記事に詳細をまとめていますので、興味のある方は参照してみてください。\u003C/p>\u003Cp>\u003Ca href=\"https://qiita.com/mai_llj/items/1002932eb46ce39d4045\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">https://qiita.com/mai_llj/items/1002932eb46ce39d4045\u003C/a>\u003C/p>\u003Cp>\u003C/p>\u003Ch2 id=\"h79c675fda4\">ServiceWorker\u003C/h2>\u003Cp>通知の機能をユーザが利用できるようにするため、ServiceWorkerの設定を行う必要があります。\u003Cbr>以下のコマンドを、任意の環境で実行し、Public KeyとPrivate Keyを生成し、設定を行います。\u003C/p>\u003Cpre>\u003Ccode class=\"language-shell\">sudo apt install nodejs npm -y &amp;&amp; sudo npm install web-push -g &amp;&amp; web-push generate-vapid-keys\u003C/code>\u003C/pre>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/1fa6e99905144fc694bf4a50f0f8a540/image.png\" alt=\"\" width=\"831\" height=\"185\">\u003C/figure>\u003Cp>\u003Ccode>コントロールパネル &gt; 設定 &gt; 全般 &gt; ServiceWorker\u003C/code>より、生成したPublic KeyとPrivate Keyを入力します。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/e3876e30f4724b17b8b5b18a7aa6b5fa/image.png\" alt=\"\" width=\"1919\" height=\"907\">\u003C/figure>\u003Cp>保存を押下し、完了です。\u003C/p>\u003Ch2 id=\"h08b84998b2\">リレー\u003C/h2>\u003Cp>Misskeyにはリレーとよばれるサーバによって投稿を中継配信する機能があります。\u003C/p>\u003Cp>建てたての小規模インスタンスや、お一人様鯖であれば、GTLの流量をかさ増しするために設定することをおすすめします。\u003Cbr>しかし、リレーに参加することでリレーからのノートが大量に発生するため、DBの容量などを考慮した上で設定を行ってください。\u003C/p>\u003Cp style=\"text-align: start\">リレーサーバはいくつかありますが、有名なものであれば。\u003Cbr>このあたりが参考になりそうです。\u003C/p>\u003Cp style=\"text-align: start\">\u003Ca href=\"https://hisubway.online/blog/fediverse_relay/\" target=\"_blank\" rel=\"noopener noreferrer\">https://hisubway.online/blog/fediverse_relay/\u003C/a>\u003C/p>\u003Cp style=\"text-align: start\">\u003Ca href=\"https://note.com/marjo/n/n9eec21c5623a\" target=\"_blank\" rel=\"noopener noreferrer\">https://note.com/marjo/n/n9eec21c5623a\u003C/a>\u003C/p>\u003Cp style=\"text-align: start\">\u003Ccode>コントロールパネル &gt; 設定 &gt; リレー\u003C/code>より追加が可能です。\u003C/p>\u003Ch2 id=\"h0e5871ed38\">Log IP address\u003C/h2>\u003Cp>有無を言わず有効化しておきましょう。\u003C/p>\u003Cp>\u003Ccode>コントロールパネル &gt; 設定 &gt; セキュリティ &gt; Log IP address\u003C/code>をEnable化するだけです。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/344bcbb9b9104fa791af2b9542bb84f6/image.png\" alt=\"\" width=\"1917\" height=\"909\">\u003C/figure>\u003Cp>\u003C/p>\u003Ch2 id=\"h6fa6283080\">ノート検索を許可する\u003C/h2>\u003Cp>デフォルトの状態では、ノート検索ができないようになっています。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/f3a41953583c47ea8512c00ddba77652/image.png\" alt=\"\" width=\"1918\" height=\"910\">\u003C/figure>\u003Cp>今回構築した環境ではPGroongaと呼ばれる全文検索のためのPostgreSQLの拡張機能が導入されているので、ロールを変更するだけで高速な全文検索が利用可能です。\u003C/p>\u003Cp>\u003Ccode>コントロールパネル &gt; 管理 &gt; ロール &gt; ベースロール\u003C/code>より、\u003Ccode>ノート検索の利用\u003C/code>を\u003Ccode>はい\u003C/code>に変更します。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/2bff26665faa444a858b66c3064769c8/image.png\" alt=\"\" width=\"1916\" height=\"908\">\u003C/figure>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/182f55d0492e4f7ab3f6fb39e26c184f/image.png\" alt=\"\" width=\"1918\" height=\"909\">\u003C/figure>\u003Cp>\u003C/p>\u003Ch2 id=\"he7a6755d7e\">その他の諸々\u003C/h2>\u003Cp>ブランディングやBotプロテクションの設定など、Misskeyでは自由度が高い分弄れる項目がかなり多いです。\u003Cbr>その他の細かい部分については、\u003Ca href=\"https://qiita.com/mai_llj/items/a1a4c65651af904cac60\" target=\"_blank\" rel=\"noopener noreferrer\">私が過去に書いたQiitaの記事\u003C/a>にも色々あるので、そちらも併せて参照してください。\u003C/p>\u003Cp>ちなみに、2025年に入ってから行われたMisskey本体のアップデートでかなりの変更が入っているので、若干古い部分があったりします。許してください。\u003C/p>\u003Ch1 id=\"h611365bd16\">絵文字の追加\u003C/h1>\u003Cp>多くの人が知っているように、Misskeyにおけるコミュニケーションは、カスタム絵文字によってその豊かさと深さが定義されると言っても過言ではありません。\u003Cbr>これは単なる装飾機能ではなく、リアクションやノートの文脈を補強し、時に言語以上に雄弁な非言語的コミュニケーションを可能にする、このプラットフォームの根幹を成す文化的なものです。\u003C/p>\u003Cp>インスタンスにの管理者は、この重要な資源を管理する権限を持ちます。\u003C/p>\u003Cp>絵文字の管理は、\u003Ccode>コントロールパネル &gt; 管理 &gt; 絵文字\u003C/code>より行います。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/f1d20e19795e469183769a415e71b5af/image.png\" alt=\"\" width=\"1919\" height=\"905\">\u003C/figure>\u003Cp>\u003C/p>\u003Ch2 id=\"h9150da3d7b\">手動での追加\u003C/h2>\u003Cp>オリジナルの絵文字や、特にあなたのコミュニティで必要とされる特定の画像を追加する際の基本的な方法です。\u003Cbr>カスタム絵文字の管理パネルを開き、右上の\u003Ccode>+\u003C/code>から、画像をアップロードし、名前やカテゴリ、タグ、ライセンス等を割り当てます。\u003C/p>\u003Cp>この過程ににおいて、いくつか留意しておくといい点があります。\u003C/p>\u003Cp>ます、その絵文字に与える名前です。\u003Cbr>この名前は絵文字ピッカーでの検索性に直結します。\u003Cbr>わたしの運用例ですが、主要な名前をキャメルケース(例: \u003Ccode>shahuchan_always_watching_you\u003C/code>)で統一し、エイリアスに、ひらがな、カタカナ、漢字といった様々な呼称とキーワードを複数登録しています。\u003Cbr>登録の手間こそありますが、どのような単語で検索しても、目的の絵文字に辿り着ける可能性が高まり、しあわせになれるかもしれません。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/a1d99231350c4fb081585144b370c175/image.png\" alt=\"\" width=\"1629\" height=\"363\">\u003C/figure>\u003Cp>そして、個々の絵文字の命名規則と同様に、全体を俯瞰した際の秩序を保つのがカテゴリ分類の役割です。\u003Cbr>無秩序に追加された絵文字は、ピッカーの利便性を低下させますから、「リアクション」や「キャラクター」といった分類を設けるべきであると考えます。\u003Cbr>さらにカテゴリが増えた際には、\u003Ccode>001_original\u003C/code>, \u003Ccode>002_blob/001_blobcat\u003C/code>のように接頭詞として連番を割り当てたり、\u003Ccode>002_blob/001_blobcat\u003C/code>, \u003Ccode>002_blob/002_blobika\u003C/code>のように階層化したりすることで、ピッカー内での視認性と表示順を意図通りに制御できるでしょう。\u003C/p>\u003Cp>最後に、これら全ての作業の前提として、権利者への配慮を忘れてはなりません。\u003Cbr>安易な画像の使用が、様々なリスクに繋がる可能性を常に念頭に置いてください。\u003C/p>\u003Ch2 id=\"h8f3007f16f\">他インスタンスからのインポート\u003C/h2>\u003Cp>Misskeyでは、連合先に存在する観測された限りの絵文字をインポートする機能が備わっており、手動での追加とは対照的に、極めて効率的に思えます。\u003Cbr>しかし、その手軽さは、あなたが予期しない種類の、そして極めて面倒なリスクを抱え込むことと表裏一体です。\u003C/p>\u003Cp>あなたが他のインスタンスから絵文字をインポートする時、その絵文字のライセンスに関する一切の責任も同時にインポートしている、という事実を認識しなくてはなりません。\u003Cbr>残念ながら、インターネット上に存在する多くの絵文字は、著作権を全く考慮されずに作成・登録されています。\u003Cbr>アニメの一場面、企業のロゴ、ファンアート。\u003Cbr>その出所は玉石混淆です。\u003C/p>\u003Cp>あなたのサーバ単体で閉じていれば、それは大きな問題にはならないかもしれません。\u003Cbr>しかし、あなたのサーバが他のサーバと連合を始めた瞬間、その絵文字は連合先のタイムラインにも表示されることになります。\u003C/p>\u003Cp>そして、連合先のインスタンスには、時としてライセンスの扱いに極めて厳格な、気難しい連中が必ずと言っていいほど存在します。\u003Cbr>彼ら彼女らは、あなたのサーバのユーザが付けた一つのリアクションからライセンスに反する絵文字を発見し、その出所であるあなたのサーバを突き止め、そして、あなたに苦言を呈すでしょう。\u003C/p>\u003Cp>このような外部からの指摘に対応する時間は、サーバ管理者にとって最も不毛な時間の一つです。\u003Cbr>もちろん、ライセンスの問題に加え、ストレージやデータベースへの負荷、文化的な不一致といった技術的な問題も依然として存在します。\u003C/p>\u003Cp>故に、インポート機能を利用する際は、その手軽さに惑わされてはなりません。\u003Cbr>最も安全なのは、やはりあなた自身がライセンスをクリアできると確信した画像のみを、手動で追加していくことです。\u003Cbr>遠回りに見えても、将来的な紛争の火種を自ら抱え込むよりは、遥かに賢明な選択と言えるでしょう。\u003C/p>\u003Ch2 id=\"h435e240727\">ちょっとした小技\u003C/h2>\u003Cp>しかし、時に、一点ずつ手動で登録するのも、あるいは他のインスタンスからライセンスを確認しつつインポートするのも、煩雑で面倒だと感じることもあるでしょう。\u003C/p>\u003Cp>そのような状況に対応するため、Misskeyには、特定の形式でパッケージ化されたZIPファイルから、絵文字を一括でインポートする機能が存在します。\u003Cbr>これは、絵文字パックを配布・導入する際などに利用される、効率的な手段です。\u003C/p>\u003Cp>パックのZIPファイルが要求する詳細な仕様については、各自で調べていただくとして、ここではいくつかの参考資料を提示するに留めます。\u003C/p>\u003Cp>公式ドキュメント\u003Cbr>\u003Ca href=\"https://misskey-hub.net/ja/docs/for-admin/features/managing-emojis/#%E4%B8%80%E6%8B%AC%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">https://misskey-hub.net/ja/docs/for-admin/features/managing-emojis/#%E4%B8%80%E6%8B%AC%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88\u003C/a>\u003C/p>\u003Cp>仕様解説といい感じのツール\u003Cbr>\u003Ca href=\"https://scrapbox.io/defaultcf/Misskey%E3%81%A7%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E7%B5%B5%E6%96%87%E5%AD%97%E3%82%92%E4%B8%80%E6%B0%97%E3%81%AB%E5%85%A5%E3%82%8C%E3%82%8B\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">https://scrapbox.io/defaultcf/Misskey%E3%81%A7%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E7%B5%B5%E6%96%87%E5%AD%97%E3%82%92%E4%B8%80%E6%B0%97%E3%81%AB%E5%85%A5%E3%82%8C%E3%82%8B\u003C/a>\u003Cbr>\u003Ca href=\"https://tools.e17.dev/emoji-manager/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">https://tools.e17.dev/emoji-manager/\u003C/a>\u003Cbr>\u003Ca href=\"https://github.com/alicerose/misskey-emoji-archive-generator\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">https://github.com/alicerose/misskey-emoji-archive-generator\u003C/a>\u003C/p>\u003Cp>\u003C/p>\u003Ch1 id=\"ha2925ef888\">DBの定期バックアップ\u003C/h1>\u003Cp style=\"text-align: start\">この項目は、本エントリ全体で最も重要です。\u003Cbr>もし、この先の内容を理解し、実行する自信がないのであれば、あなたは自前でMisskeyインスタンスを運用すべきではありません。\u003Cbr>今すぐ、全てを諦めてお布団にはいりましょう。\u003C/p>\u003Cp>万が一何かしらの問題が発生した場合、サーバは再構築できます。\u003Cbr>オブジェクトストレージに保存したファイルも、再設定すれば済む話です。\u003Cbr>しかし、データベースだけは、失ってしまえば二度と元には戻りません。\u003C/p>\u003Cp>そして、Misskeyが利用するActivityPubというプロトコルの仕様上、データベースに保存されている署名鍵を失うことは、そのドメインでサーバを継続することの完全な終わりを意味します。\u003Cbr>新しいサーバを同じドメインで建て直しても、過去の投稿やフォロワーを引き継ぐことはできず、あなたのサーバは連合ネットワークの中で完全に孤立した、全くの別物になってしまうのです。\u003C/p>\u003Cp>何があっても、データベースだけは死守しなければなりません。\u003C/p>\u003Cp>これは、脅しでも、単なる建前でもありません。\u003Cbr>何を隠そう、わたしは過去に土砂崩れで旧自宅の半分とサーバ群を文字通り全て失い、ドメインを変えてゼロからサーバを再構築した経験があります。\u003Cbr>あの時の絶望感と、ユーザに対する申し訳なさは、今でも忘れられません。\u003C/p>\u003Cp>だからこそ、バックアップの重要性だけは、声を大にして、何度でも伝えたいのです。\u003C/p>\u003Ch2 id=\"h883f7f65dd\">バックアップの実行と自動化\u003C/h2>\u003Cp>*2025.11.23追記 簡易的なShell Scriptでの実装を紹介していましたが、不備があったため、当該記述を削除しました。\u003C/p>\u003Cp>今回は、以下のDocker Imageを利用します。\u003C/p>\u003Cp>\u003Ca href=\"https://github.com/team-shahu/misskey-backup/pkgs/container/misskey-backup\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/team-shahu/misskey-backup/pkgs/container/misskey-backup\u003C/a>\u003Cbr>\u003Ca href=\"https://github.com/team-shahu/misskey-backup\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/team-shahu/misskey-backup\u003C/a>\u003C/p>\u003Cp>このコンテナイメージは、定期的なバックアップとファイルの可逆暗号化、R2への転送機能を内包しており、環境変数をいくつか設定するだけで、バックアップからオフサイト転送までの一連のプロセスを、完全に独立したコンテナとして自動実行してくれます。\u003C/p>\u003Cp>具体的には、既存の\u003Ccode>compose.yaml\u003C/code>に、このバックアップコンテナをサービスとして追記するだけで使えます。\u003Cbr>ホストOSはDockerを動かすための最小限の環境に保たれ、アプリケーションに関する全ての責務をコンテナの世界に閉じ込めることができ、より気持ちのいい状態を実現できます。\u003C/p>\u003Cp>詳細な利用方法についてはREADMEに書いてあります。\u003Cbr>よければ使ってください。\u003C/p>\u003Cp>ちなみに、オプションとしてファイルの暗号化に対応していますが、これを利用する場合、リストア時もツールを利用する必要があります。\u003Cbr>コンテナへ入り、\u003Ccode>cd /app &amp;&amp; ./misskey-backup --restore-url &quot;復元するバックアップのファイルを指すURL&quot; --encryption-key &quot;バックアップ時の環境で利用した環境変数BACKUP_ENCRYPTION_KEY&quot;\u003C/code>を実行すると生のdumpが入手可能です。\u003Cbr>リストアが必要になった場合は\u003Ccode>pg_restore\u003C/code>なんかを利用し、DBを再構築しましょう。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/6ba3884288654f2784335c95cdcbd69b/image.png\" alt=\"\" width=\"794\" height=\"375\">\u003C/figure>\u003Cp>* 引数\u003Ccode>--encryption-key\u003C/code>はオプションです。指定がなければ環境変数からロードします。\u003C/p>\u003Ch1 id=\"hbd188c6e62\">ダウン時にメンテナンスページを表示する\u003C/h1>\u003Cp style=\"text-align: start\">サーバの運用において、アプリケーションの更新や予期せぬ障害によるサービスの停止は避けられません。\u003Cbr>その際、利用者にCloudflareの無機質なエラーページを見せてしまうのは、管理者としてあまりにも不親切です。\u003C/p>\u003Cp>ここでは、Misskey本体の前にリバースプロキシとしてCaddyを配置し、Misskeyがダウンしている場合には、あらかじめ別の場所に用意した静的なメンテナンスページへリダイレクトさせる構成を構築します。\u003C/p>\u003Cp>本来、リバースプロキシはアプリケーションサーバとは物理的に別のサーバに設置するのが、可用性やセキュリティの観点から望ましいアーキテクチャです。\u003Cbr>しかし、今回は個人や小規模なコミュニティでの運用を想定しているため、構成の簡潔さを優先し、同一のサーバ上に同居させる構成を採用します。\u003C/p>\u003Cp>メンテナンスページ自体を外部サービスに置くことで、仮にサーバ全体が応答不能になった場合でも、ユーザへの案内が可能になる、より堅牢な構成です。\u003C/p>\u003Ch2 id=\"h0bc4c7ee36\">メンテナンスページの作成\u003C/h2>\u003Cp>まず、メンテナンス中に表示するための簡単なページを作成します。\u003Cbr>何も考えたくない場合は\u003Ca href=\"https://v0.dev/\" target=\"_blank\" rel=\"noopener noreferrer\">v0.dev\u003C/a>あたりを使うといいでしょう。\u003C/p>\u003Cp>サイトが完成したら、VercelやCloudflare Pagesといった、任意の静的ホスティングサービスにデプロイし、そのURLを控えておきます。\u003Cbr>このとき、Misskeyをホストしているドメインのサブドメイン(例: \u003Ccode>maintenance.mi-test.mq1.dev\u003C/code>)に紐づけておくと、後々の管理が少し楽になります。\u003C/p>\u003Ch2 id=\"h9607059ffa\">Caddyfileの作成\u003C/h2>\u003Cp>次に、リバースプロキシの動作を定義するCaddyの設定ファイルを作成します。\u003Ccode>./misskey/config/\u003C/code> ディレクトリ内に \u003Ccode>Caddyfile\u003C/code> という名前で保存してください。\u003C/p>\u003Cdiv data-filename=\"./config/Caddyfile\">\u003Cpre>\u003Ccode>:3000 {\n\tencode gzip\n\theader /assets Cache-Control &quot;public, max-age=31536000, immutable&quot; \n\tfile_server\n\n\treverse_proxy mi:3000 {\n\t\t# Get actual client IP from Cloudflare\n\t\theader_up X-Real-IP {header.CF-Connecting-IP}\n\t\theader_up X-Forwarded-For {header.CF-Connecting-IP}\n\t\theader_up X-Forwarded-Proto {scheme}\n\t\theader_up X-Forwarded-Host {host}\n\n\t\t# health check\n\t\thealth_uri /api/server-info\n\t\thealth_interval 10s\n\t\thealth_timeout 2s\n\t\thealth_status 200\n\t}\n\n\thandle_errors {\n\t\t@backend_down `{err.status_code} in [500, 501, 502, 503, 504, 522]`\n\t\tredir @backend_down メンテナンスページのURL\n\t}\n}\u003C/code>\u003C/pre>\u003C/div>\u003Cp>メンテナンスページのURLの部分を、\u003Ccode>https://maintenance.mi-test.mq1.dev/\u003C/code> のような形式で先ほど用意したメンテナンスページのURLに書き換えてください。\u003C/p>\u003Ch2 id=\"hb8d27cfc08\">compose.yamlの更新\u003C/h2>\u003Cp>これまでの\u003Ccode>compose.yaml\u003C/code>を、CaddyをMisskeyの前に置く構成に変更します。\u003Cbr>Tunnel側の設定変更を避けるため、サービス名を\u003Ccode>app\u003C/code>(Caddy)と\u003Ccode>mi\u003C/code>(Misskey)に変更し、依存関係を整理します。\u003C/p>\u003Cdiv data-filename=\"./compose.yaml\">\u003Cpre>\u003Ccode class=\"language-yaml\">services:\n  app:\n    image: caddy:2\n    profiles:\n      - proxy\n    volumes:\n      - ./config/Caddyfile:/etc/caddy/Caddyfile\n      - ./data/caddy/data:/data\n      - ./data/caddy/config:/config\n    networks:\n      - internal_network\n\n  mi:\n    image: misskey/misskey:latest\n    restart: always\n    links:\n      - db\n      - redis\n    depends_on:\n      db:\n        condition: service_healthy\n      redis:\n        condition: service_healthy\n    networks:\n      - internal_network\n    volumes:\n      - ./config/default.yml:/misskey/.config/default.yml:ro\n\n  redis:\n    restart: always\n    image: eqalpha/keydb:alpine\n    networks:\n      - internal_network\n    volumes:\n      - ./data/keydb:/data\n    healthcheck:\n      test: &quot;redis-cli ping&quot;\n      interval: 5s\n      retries: 20\n\n  db:\n    restart: always\n    image: groonga/pgroonga:latest-debian-16\n    ports:\n      - &apos;5430:5432&apos;\n    networks:\n      internal_network:\n    env_file:\n      - ./config/.env\n    volumes:\n      - ./data/db:/var/lib/postgresql/data\n    healthcheck:\n      test: &quot;pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB&quot;\n      interval: 5s\n      retries: 20\n\n  tunnel:\n    restart: always\n    image: cloudflare/cloudflared\n    command: tunnel --no-autoupdate run\n    profiles:\n      - tunnel\n    env_file:\n      - ./config/.env\n    networks:\n      - internal_network\n\nnetworks:\n  internal_network:\u003C/code>\u003C/pre>\u003C/div>\u003Ch2 id=\"hc369bfbfd2\">反映と動作確認\u003C/h2>\u003Cp>設定をすべて保存したら、以下のコマンドでコンテナを再起動します。\u003Cbr>\u003Ccode>--remove-orphans\u003C/code> オプションは、古い定義のコンテナを削除するために付与しています。\u003C/p>\u003Cpre>\u003Ccode class=\"language-shell\">sudo docker compose --profile proxy --profile tunnel up -d --remove-orphans\u003C/code>\u003C/pre>\u003Cp>正常にサイトが表示されることを確認後、\u003Ccode>sudo docker compose stop mi\u003C/code> コマンドで意図的にMisskeyのコンテナを停止させてみてください。\u003Cbr>ブラウザをリロードし、無機質なエラー画面の代わりに、先ほど作成したメンテナンスページへリダイレクトされれば設定は成功です。\u003C/p>\u003Cp>確認後は \u003Ccode>sudo docker compose start mi\u003C/code> で忘れずにコンテナを起動し直しておきましょう。\u003C/p>\u003Ch1 id=\"he04a3454bf\">最低限のセキュリティ\u003C/h1>\u003Cp>サーバを公開するということは、あなたの城を、悪意に満ちたインターネットの荒野に晒すということです。\u003Cbr>城壁を築き、見張りを立てなければ、その城は一夜にして蹂躙されるでしょう。\u003Cbr>セキュリティはオプションではなく、サーバ管理者の最も基本的な責務です。\u003C/p>\u003Ch2 id=\"h32f0498d5a\">ホストの対策\u003C/h2>\u003Cp>攻撃者が最初に狙うのは、あなたのサーバそのものです。\u003Cbr>OSレベルでの防御は、まず全ての入口を閉ざし、信頼できる経路のみを許可することから始まります。\u003C/p>\u003Cp>従来、SSHポートを公開し、公開鍵認証で保護するのが一般的でした。\u003Cbr>しかし、SSHポートをインターネットに晒すこと自体がリスクであり、鍵の管理も煩雑です。\u003Cbr>そこで、当エントリでは\u003Ca href=\"https://tailscale.com/kb/1193/tailscale-ssh\" target=\"_blank\" rel=\"noopener noreferrer\">Tailscale SSH\u003C/a>の利用を推奨します。\u003Cbr>\u003Ca href=\"https://tailscale.com/kb/1193/tailscale-ssh\">https://tailscale.com/kb/1193/tailscale-ssh\u003C/a>\u003C/p>\u003Cp>\u003Ca href=\"https://tailscale.com/\" target=\"_blank\" rel=\"noopener noreferrer\">Tailscale\u003C/a>は、あなたの所有するデバイス間だけで構成されるプライベートなネットワークを構築するサービスです。\u003Cbr>これをサーバに導入することで、SSHポートをインターネットに一切公開することなく、あなたのTailscaleネットワーク内部からのみ、安全にサーバへアクセスできるようになります。\u003Cbr>認証はTailscaleのアカウントで行われ、定義したACLが適用されるため、鍵管理の手間からも解放されます。\u003C/p>\u003Cp>この構成を、ufwによって強制します。\u003C/p>\u003Cpre>\u003Ccode class=\"language-shell\"># デフォルトですべてのインバウンドを拒否\nsudo ufw default deny incoming\n# デフォルトですべてのアウトバウンドを許可\nsudo ufw default allow outgoing\n# Tailscaleのネットワーク(100.64.0.0/10)からのみSSH(ポート22)への着信を許可\nsudo ufw allow from 100.64.0.0/10 to any port 22\n# ufwを有効化\nsudo ufw enable\u003C/code>\u003C/pre>\u003Cp>この設定により、あなたのサーバのSSHポートは、もはや広大なインターネットからは完全に閉ざされたものとなります。\u003C/p>\u003Cp>許可されたサブネット外からのインバウンド通信はすべて破棄されるため、ブルートフォース攻撃の脅威に晒されることはありません。\u003Cbr>そのため、\u003Ccode>fail2ban\u003C/code>のような侵入防止ツールも基本的には不要になります。\u003C/p>\u003Ch2 id=\"h9a58303d83\">Misskeyの管理者アカウントを保護\u003C/h2>\u003Cp>管理者アカウントの二要素認証を有効化してください。\u003C/p>\u003Cp>これは、交渉の余地なく、必須の作業です。\u003Cbr>あなたの管理者アカウントが乗っ取られることは、城の鍵を敵に渡すことと同義です。\u003C/p>\u003Cp>Misskeyにログイン後、\u003Ccode>設定 &gt; セキュリティ &gt; 二要素認証\u003C/code>より、今すぐ設定を行ってください。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/ee528939471e45a6ba6ff9315581315f/image.png\" alt=\"\" width=\"1919\" height=\"906\">\u003C/figure>\u003Cp>\u003C/p>\u003Ch2 id=\"he5e0b0dbc6\">WAF(おまけ)\u003C/h2>\u003Cp>そもそも、Cloudflare Tunnelを利用している時点で、あなたのサーバのIPアドレスは秘匿されており、直接的な攻撃を受けるリスクは大幅に軽減されています。\u003Cbr>さらに金銭的な余裕がある場合には、Cloudflareが提供する有償のセキュリティ機能を活用します。\u003C/p>\u003Cp>Web Application Firewall (WAF)を有効化してください。\u003Cbr>Cloudflareのダッシュボードから\u003Ccode>Security &gt; WAF\u003C/code>を開き、Managed rulesタブからCloudflare Free Managed Rulesetを有効にします。\u003Cbr>これは、SQLインジェクションやクロスサイトスクリプティングといった、ウェブアプリケーションに対する典型的な攻撃パターンを検知し、自動的にブロックしてくれる盾の役割を果たします。\u003C/p>\u003Ch1 id=\"hb7b57b2068\">ドメインブロックの活用\u003C/h1>\u003Cp>スパムの温床となりやすい特定のドメインからの通信を、根本から遮断する設定も重要です。\u003C/p>\u003Cp>直近の顕著な例として、\u003Ccode>*.trycloudflare.com\u003C/code>のドメインを利用したスパムインスタンスからの攻撃が複数件観測されています。\u003C/p>\u003Cp>これは、CloudflareのQuick Tunnels機能を悪用し、使い捨てのインスタンスから無差別にスパムを送りつけるという、極めて悪質な手法です。\u003Cs>これに対抗する手段として、DNSレベルでの名前解決を曲げる等の解決策もいくつか存在しますがここでは説明しません。\u003C/s>\u003C/p>\u003Cp>しかし、幸いなことにMisskey v13以降には、より手軽で確実な手段が標準機能として備わっています。\u003Ccode>コントロールパネル &gt; モデレーション &gt; ブロックしたサーバー\u003C/code>より設定を行います。ここに\u003Ccode>trycloudflare.com\u003C/code>を追加するだけで、そのサブドメインも含めた全ての通信を一律でブロックすることが可能です。\u003C/p>\u003Cp>そもそも、安定したコミュニティ運営を目指すまともな管理者が、永続的でないQuick Tunnels用のドメインを本番環境で使い続けるはずがありません。したがって、このようなドメインからの通信は一律でブロックしてしまって一切問題ないでしょう。\u003C/p>\u003Cp>あなたのサーバのリソースを、使い捨てのスパマーのために消費してやる義理はどこにもありません。\u003C/p>\u003Ch1 id=\"h101a34749f\">CSAM対策\u003C/h1>\u003Cp>インスタンスを運用する以上、避けては通れない問題があります。CSAM、すなわちChild Sexual Abuse Material(児童性的虐待コンテンツ)への対策です。\u003C/p>\u003Cp>「うちは健全なサーバだから関係ない」と思いましたか？ 残念ながら、その認識は甘すぎます。\u003C/p>\u003Cp>あなたがどれほど慎重にサーバを運用していたとしても、倫理観の乏しい愚かなローカルユーザが、ドライブにCSAMをアップロードしてしまう可能性を完全に排除することはできません。リモートメディアのキャッシュを無効にしていようがいまいが、ローカルユーザが直接アップロードしたファイルは、あなたのドメイン配下のオブジェクトストレージやサーバに保存されます。\u003C/p>\u003Cp>そして、たとえ管理者であるあなたに一切の悪意がなかったとしても、自分が運用するドメイン配下にCSAMが存在するという事態は、日本国内においても(運が悪ければ)刑事罰の対象となり得る極めて深刻な問題です。\u003C/p>\u003Cp>Azure AI Content SafetyのようなAPIを利用する手段もありますが、アプリケーション側の実装が必要な上に、一定以上の利用量になるとコストがかかります。\u003Cbr>ここで活用すべきが、CloudflareのCSAM Scanning Toolです。\u003C/p>\u003Cp>\u003Ca href=\"https://developers.cloudflare.com/cache/reference/csam-scanning/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">https://developers.cloudflare.com/cache/reference/csam-scanning/\u003C/a>\u003C/p>\u003Cp>Cloudflareのダッシュボードにログインし、\u003Ccode>Caching &gt; Configuration\u003C/code>からCSAM Scanning Toolを有効にする。\u003Cbr>以上です。\u003C/p>\u003Cp>メールアドレスの入力を求められますが、これはCSAMが実際に検出された際の通知先です。なるべく早く気付けるものを入力してください。\u003C/p>\u003Cp>ここで、いくつか留意すべき点があります。\u003Cbr>まず、当然ながらCloudflareのDNS設定でプロキシが有効になっている必要があります。本エントリの手順に沿っていればCloudflare Tunnelを利用しているため、この点は問題ないはずです。\u003Cbr>日本国内においては、現時点で直接的に該当する法律は見当たりませんが、地域によってはCSAMを発見した場合、NCMEC等の適切な機関への通報義務がWebサイト管理者に課せられる場合があります。\u003C/p>\u003Cp>サーバ管理者として、自分のドメインが犯罪コンテンツの流通経路にならないよう、この程度の設定は最低限の責務として行っておくべきでしょう。\u003C/p>\u003Ch1 id=\"h0139c46456\">サーバの監視\u003C/h1>\u003Cp>インスタンスを建て、動かし始めたらそれで終わり、ではありません。\u003Cbr>むしろ、そこからが本当の始まりです。\u003Cbr>あなたのインスタンスが健全な状態を保っているか、あるいは何らかの脅威に晒されていないかを常に把握し、問題が発生した際には迅速に対応する。\u003Cbr>そのための目となるのが監視です。\u003C/p>\u003Cp>監視を設定するということは、問題が起きてからユーザに指摘される受動的な対応から、問題が深刻化する前、あるいは利用者が気づく前に問題を検知する能動的な管理へと移行することを意味します。\u003Cbr>そして、あなたの平穏な夜が、いつアラートによって叩き起こされるかもしれないという、新たなスリルを受け入れるということです。\u003C/p>\u003Cp>ようこそ、眠れないサーバ管理者の世界へ。\u003C/p>\u003Ch2 id=\"h70bacab598\">外形監視\u003C/h2>\u003Cp>最も基本的で、そして最も重要なのが、外部からあなたのサーバが正常に応答しているかを確認する「外形監視」です。\u003C/p>\u003Cp>これには、高機能な監視SaaSであるBetter Stackの利用を推奨します。\u003Cbr>無料プランでも十分な数の監視項目と、ステータスベージを作成できます。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/52b4965f68f4475c9a92159efc288437/image.png\" alt=\"\" width=\"1916\" height=\"910\">\u003Cfigcaption>ステータスページの例\u003C/figcaption>\u003C/figure>\u003Cp>Better Stackにサインアップし、最低限以下の項目を監視し、異常を検知した際にはあなたに通知が飛ぶように設定してください。\u003C/p>\u003Cul>\u003Cli>\u003Cstrong>HTTP(s)監視\u003C/strong>\u003Cp>MisskeyインスタンスのURL を定期的に監視します。\u003C/p>\u003C/li>\u003Cli>\u003Cstrong>Ping監視\u003C/strong>\u003Cbr>サーバへの基本的な疎通性を確認します。\u003Cbr>FWでICMPを拒否しないようにしておきましょう。\u003C/li>\u003C/ul>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/647de9f0a2c34414939616a5b83960ec/image.png\" alt=\"\" width=\"1918\" height=\"906\">\u003C/figure>\u003Cp>これにより、「急にインスタンスへのアクセスができなくなってしまった！！なにもしてないのに壊れました！！」という最も致命的な事態を即座に把握できます。\u003C/p>\u003Ch2 id=\"hf81b65eb16\">内部監視\u003C/h2>\u003Cp>外から見えていても、サーバ内部が悲鳴を上げていることは頻繁にあります。\u003Cbr>CPU使用率、メモリ使用量、ディスクI/Oといった内部状況を把握するのが内部監視です。\u003C/p>\u003Cp>ここではNew Relicの導入を推奨します。\u003Cbr>無料プランの範囲が非常に広く、個人利用であればほとんどの機能を無償で利用できます。\u003Cbr>他のものでも要件が満たせれば正直何でも構いません。\u003C/p>\u003Cp>New Relicにサインアップし、表示される手順に従って、あなたのVPSに監視エージェントをインストールしてください。\u003Cbr>Dockerコンテナの監視も自動的に認識され、美しいダッシュボードで各コンテナのパフォーマンスを詳細に可視化できます。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/c703d52aa1dd4aeca9a3fc054c1e4725/image.png\" alt=\"\" width=\"1913\" height=\"908\">\u003C/figure>\u003Cp>特に注意深く見るべきは、CPU使用率、メモリ使用量、そしてディスクの空き容量です。\u003C/p>\u003Ch2 id=\"h196a107197\">ログ監視\u003C/h2>\u003Cp>メトリクスはサーバのバイタルサインですが、ログはサーバの声です。\u003Cbr>アプリケーションで何が起きているのか、エラーの原因は何なのか、その全てはログに記録されています。\u003C/p>\u003Cp>\u003Ccode>docker logs {cid}\u003C/code>コマンドでログを確認することもできますが、それは一時的な確認手段に過ぎません。\u003Cbr>恒久的なログの収集と分析のために、New Relicのログ転送機能を設定することを強く推奨します。\u003C/p>\u003Cp>設定は、New Relicのドキュメントに従い、Docker用のログ転送設定をサーバに追加するだけです。\u003Cbr>これにより、Misskey本体やデータベースなど、全てのコンテナから出力されるログが自動的にNew Relicへ集約され、「特定のエラーログが一定数以上記録された場合に、アラートを発報させるー」みたいなことができます。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/1ea11cb275c144c5bf02e7c0ca0ad07a/image.png\" alt=\"\" width=\"1915\" height=\"910\">\u003C/figure>\u003Cp>これらの監視を設定し、サーバの状態を定常的に把握することが管理者としての最低限の責務です。\u003C/p>\u003Ch1 id=\"hf84a935862\">Misskeyをアップデートする\u003C/h1>\u003Cp>Misskey本体の更新頻度はかなり高く、月に1-3回のアップデートが行われています。\u003Cbr>マイグレーション等、手動実行が必要なものがあれば\u003Ca href=\"https://github.com/misskey-dev/misskey/releases/tag/2025.1.0\" target=\"_blank\" rel=\"noopener noreferrer\">このように\u003C/a>リリースノートに書いてあるので、そちらを参照してください。\u003C/p>\u003Cp>一般的には以下のコマンドでアップデートが可能です。\u003C/p>\u003Cpre>\u003Ccode class=\"language-shell\">sudo docker pull misskey/misskey:latest &amp;&amp; sudo docker compose up -d --build\u003C/code>\u003C/pre>\u003Cp>この時、profileを指定してしまうとメンテナンスページが表示されないので、必ず引数に\u003Ccode>--profile\u003C/code>を含めないようにしてください。\u003C/p>\u003Ch1 id=\"hf4d122a789\">MisskeyのアップデートをGitOpsで自動化する\u003C/h1>\u003Cp>Misskeyのアップデートがある度に、毎回サーバへSSHして \u003Ccode>docker image pull\u003C/code> して \u003Ccode>docker compose up -d\u003C/code> を叩くのって、地味に面倒くさいですよね。\u003Cbr>面倒くさいんですよ。\u003C/p>\u003Cp>リリース頻度もそれなりにあるので、放置しているといつの間にか化石になっていたなんてことも起こり得てしまいます。\u003Cs>(そもそも放置するくらいなら初めからインスタンスを建てるべきではないのですが)\u003C/s>\u003C/p>\u003Cp>そこで、Misskey本体の更新を、ほぼ自動で最新化できる仕組みを導入します。\u003Cbr>ArgoCD Image UpdaterのLatest運用に近いイメージですが、今回は\u003Ca href=\"https://github.com/sksat/compose-cd\" target=\"_blank\" rel=\"noopener noreferrer\">compose-cd\u003C/a>とGitHub Actionsを使って、より手元でコントロールしやすい形で実現します。\u003C/p>\u003Cp>実際の挙動は\u003Ca href=\"https://github.com/team-shahu/shahu-docker-provision/pull/2\" target=\"_blank\" rel=\"noopener noreferrer\">こんな感じ\u003C/a>です。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/2dfd14e0b07b4e909768fb73a7623944/image.png\" alt=\"\" width=\"1917\" height=\"927\">\u003C/figure>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/e6365b8e0e9340188963dcddbdc27bf1/image.png\" alt=\"\" width=\"541\" height=\"209\">\u003C/figure>\u003Cp>\u003Cbr>\u003C/p>\u003Cp>私がこれをやろうとした当初、\u003Ca href=\"https://github.com/containrrr/watchtower\" target=\"_blank\" rel=\"noopener noreferrer\">Watchtower\u003C/a>を使う選択肢もありましたが、無駄にオーバーヘッドがあって微妙ですし、かといってCronで定期的にでシェルを叩くのも、杜撰すぎて気持ちのいいやり方とは到底言えません。\u003Cbr>今回は、その中間的な妥協点として、\u003Ca href=\"https://github.com/sksat/compose-cd\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">compose-cd\u003C/a>に寄せる構成にしています。\u003Cs>(compose-cd自体微妙なところもありますが、今回の用途としては十分ですし、妥協することにします)\u003C/s>\u003C/p>\u003Cp>全体の流れは以下の通りです。\u003C/p>\u003Col>\u003Cli>\u003Ccode>compose.yaml\u003C/code> でMisskeyサービスをdiest pinningしておく\u003C/li>\u003Cli>GitHub Actionsが定期的に、最新イメージのダイジェストと、レポジトリ上にあるものの差分をチェックする\u003C/li>\u003Cli>差分があれば、\u003Ccode>compose.yaml\u003C/code>内のイメージ定義を、新しいイメージダイジェストに書き換えたPull Requestを生成する\u003C/li>\u003Cli>人間が確認後、PRをマージすると、compose-cdがレポジトリの変更差分を検知し、自動でデプロイが走る\u003C/li>\u003C/ol>\u003Cp>これで、定期的に起票されるPRを確認してマージするだけといったとても怠惰な運用が可能になります。\u003C/p>\u003Ch2 id=\"h31fc5cbc4a\">事前準備\u003C/h2>\u003Cp>この仕組みの前提として、Misskeyインスタンスの構成ファイル(\u003Ccode>compose.yaml\u003C/code>,\u003Ccode>.config/default.yml\u003C/code>等)が、GitHub上のレポジトリで管理されている必要があります。\u003C/p>\u003Cp>\u003Ccode>./config/.env\u003C/code>ファイルにパスワードなどの秘密情報を全て集約させ、それを\u003Ccode>.gitignore\u003C/code>に追加した上で、Publicなレポジトリとして運用するのが、Private repo環境でPATの取り回しに苦労するよりも、結果的に楽だとわたしは考えます。\u003Cbr>まぁ、お好みでよしなにしてください。\u003C/p>\u003Ch2 id=\"hb35da9580c\">compose-cdの導入\u003C/h2>\u003Cpre>\u003Ccode class=\"language-shell\">wget https://github.com/sksat/compose-cd/releases/latest/download/compose-cd.tar.zst\ntar xvf compose-cd.tar.zst\n./compose-cd install \\\n    --search-root &quot;&lt;compose.yamlが存在しているパス&gt;&quot; \\\n    --git-pull-user &lt;pullするユーザ(メアド)&gt; \\\n    --discord-webhook &quot;&lt;discord webhook URL&gt;&quot;\u003C/code>\u003C/pre>\u003Cp>基本的にはこれで大丈夫です。\u003Cbr>パスの指定は相対パスでも問題ないはずです。\u003Cbr>また、compose-cdは、\u003Ca href=\"https://github.com/sksat/compose-cd/blob/8cff99c98498d88b053dd934f08c045c70aa04c6/compose-cd#L283\" target=\"_blank\" rel=\"noopener noreferrer\">内部的にgit pullを叩いている\u003C/a>ので、当該ディレクトリ内へのrw権限が必要です。\u003Cbr>(rootで実行することで大概は回避可能ですが、推奨はしません)\u003C/p>\u003Ch2 id=\"hcb50ae6e42\">compose-cdの設定ファイルを用意する\u003C/h2>\u003Cp>\u003Ccode>compose.yaml\u003C/code>と同じディレクトリに、\u003Ccode>.compose-cd\u003C/code>という設定ファイルを置き、レポジトリの変更のみを監視するように設定します。\u003C/p>\u003Cdiv data-filename=\".compose-cd\">\u003Cpre>\u003Ccode class=\"language-yaml\">REPO=&quot;&lt;https://github.com/your/repo.git&gt;&quot;\nUPDATE_REPO_ONLY=true\nUPDATE_IMAGE_BY_REPO=true\n\u003C/code>\u003C/pre>\u003C/div>\u003Cp>\u003Ccode>UPDATE_REPO_ONLY=true\u003C/code>にしておくことで、compose-cdが余計なイメージ更新チェックを行わなくなり、余計なことをしなくなります。\u003C/p>\u003Cp>余談ですが、compose-cdの実装を少し覗いてみると分かる通り、\u003Ccode>compose.yaml\u003C/code>が公式に推奨されるようになった令和の現在においても、旧来の\u003Ccode>docker-compose.yaml\u003C/code>ワークフローに寄ったロジックが残っています。\u003Cbr>\u003Ca href=\"https://github.com/sksat/compose-cd/blob/8cff99c98498d88b053dd934f08c045c70aa04c6/compose-cd#L122-L124\">https://github.com/sksat/compose-cd/blob/8cff99c98498d88b053dd934f08c045c70aa04c6/compose-cd#L122-L124\u003C/a>\u003Cbr>\u003Ca href=\"https://github.com/sksat/compose-cd/blob/8cff99c98498d88b053dd934f08c045c70aa04c6/compose-cd#L359\">https://github.com/sksat/compose-cd/blob/8cff99c98498d88b053dd934f08c045c70aa04c6/compose-cd#L359\u003C/a>\u003C/p>\u003Cp>これは、\u003Ca href=\"https://github.com/compose-spec/compose-spec/blob/main/spec.md#compose-file\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">compose-spec\u003C/a>にも以下のようにちゃんと書かれてますからね\u003C/p>\u003Cblockquote>\u003Cp>The default path for a Compose file is \u003Ccode>compose.yaml\u003C/code> (preferred) or \u003Ccode>compose.yml\u003C/code> that is placed in the working directory. Compose also supports \u003Ccode>docker-compose.yaml\u003C/code> and \u003Ccode>docker-compose.yml\u003C/code> for backwards compatibility of earlier versions. If both files exist, Compose prefers the canonical compose.yaml.\u003C/p>\u003C/blockquote>\u003Cblockquote>\u003Cp>Compose ファイルのデフォルトパスは\u003Ccode>compose.yaml\u003C/code>(推奨)または\u003Ccode>compose.yml\u003C/code>で、作業ディレクトリに置かれます。Composeは、以前のバージョンとの後方互換性のために\u003Ccode>docker-compose.yaml\u003C/code>および \u003Ccode>docker-compose.yml\u003C/code>もサポートしています。両方のファイルが存在する場合は、\u003Ccode>compose.yaml\u003C/code>を優先します。(意訳)\u003C/p>\u003C/blockquote>\u003Cp>\u003C/p>\u003Cp>このため、compose-cdが差分を正しく検知できず、想定外の「差分検知 → 更新失敗」を誘発してしまいます。\u003Cbr>実装を修正するのも手間なので、今回は\u003Ccode>UPDATE_REPO_ONLY=true\u003C/code>を設定して、この挙動を回避しています。\u003C/p>\u003Cp>理想的なものはそうそうないので、ツール選定とは概ね常に何らかの妥協を伴うものみたいです。\u003C/p>\u003Ch2 id=\"h5e0913ac92\">更新対象ファイルの一覧を定義する\u003C/h2>\u003Cp>同じディレクトリに\u003Ccode>.compose-apply\u003C/code>を置き、compose-cdが変更を監視すべき対象ファイルを改行区切りで指定します。\u003C/p>\u003Cdiv data-filename=\".compose-apply\">\u003Cpre>\u003Ccode>compose.yaml\nconfig/*\u003C/code>\u003C/pre>\u003C/div>\u003Cp>\u003Ccode>./data/*\u003C/code>や\u003Ccode>.env\u003C/code>のような更新対象外のディレクトリは含めないようにしてください。\u003C/p>\u003Ch2 id=\"h3abd7c9e55\">compose.yamlの編集\u003C/h2>\u003Cp>Misskeyコンテナのイメージをdiest pinningしておきます。\u003C/p>\u003Cdiv data-filename=\"compose.yaml\">\u003Cpre>\u003Ccode class=\"language-yaml\">略\n  app:\n    image: misskey/misskey:2025.10@sha256:e94e565722df11bc2ca85a46a90103c50353313d1a79476d7ee6ee964cd62ae2\n    restart: always\n略\u003C/code>\u003C/pre>\u003C/div>\u003Cp>利用しているイメージやバージョンに合わせて適宜書き換えてください。\u003C/p>\u003Cp>イメージダイジェストが何か分かれなければ、\u003Ca href=\"https://docs.docker.com/dhi/core-concepts/digests/\" target=\"_blank\" rel=\"noopener noreferrer\">これを読んで\u003C/a>おきましょう\u003C/p>\u003Ch2 id=\"he8ea32746e\">GitHub ActionsでPRを自動生成する\u003C/h2>\u003Cp>最後に、イメージの差分を検知してPRを自動生成するGitHub Actionsを設定します。\u003Cbr>レポジトリの\u003Ccode>.github/workflows/\u003C/code>ディレクトリに、以下のワークフローを作成します。\u003C/p>\u003Cdiv data-filename=\".github/workflows/update-misskey-image.yaml\">\u003Cpre>\u003Ccode class=\"language-yaml\">name: Update Misskey Image\n\non:\n  schedule:\n    - cron: &apos;*/10 * * * *&apos;\n  workflow_dispatch:\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  check-update:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n\n      - name: Set up Docker\n        uses: docker/setup-buildx-action@v3\n\n      - name: Get current image info\n        id: current\n        run: |\n          # compose.yamlから現在のイメージ情報を取得\n          CURRENT_LINE=$(grep &quot;misskey/misskey&quot; compose.yaml)\n          echo &quot;current_line=$CURRENT_LINE&quot; &gt;&gt; $GITHUB_OUTPUT\n          echo &quot;Current line from compose.yaml: $CURRENT_LINE&quot;\n          \n          # 現在のバージョンとダイジェストを抽出\n          CURRENT_VERSION=$(echo &quot;$CURRENT_LINE&quot; | sed -n &apos;s/.*misskey\\/misskey:\\([^@]*\\)@.*/\\1/p&apos;)\n          CURRENT_FULL_DIGEST=$(echo &quot;$CURRENT_LINE&quot; | sed -n &apos;s/.*@\\(sha256:[a-f0-9]*\\).*/\\1/p&apos;)\n          CURRENT_DIGEST=$(echo &quot;$CURRENT_FULL_DIGEST&quot; | sed &apos;s/sha256://&apos;)\n          \n          echo &quot;current_version=$CURRENT_VERSION&quot; &gt;&gt; $GITHUB_OUTPUT\n          echo &quot;current_digest=$CURRENT_DIGEST&quot; &gt;&gt; $GITHUB_OUTPUT\n          echo &quot;current_full_digest=$CURRENT_FULL_DIGEST&quot; &gt;&gt; $GITHUB_OUTPUT\n          echo &quot;Current version: $CURRENT_VERSION&quot;\n          echo &quot;Current digest: $CURRENT_DIGEST&quot;\n          echo &quot;Current full digest: $CURRENT_FULL_DIGEST&quot;\n\n      - name: Get latest image info\n        id: latest\n        run: |\n          # Docker Hubから最新のイメージ情報を取得\n          # まず、利用可能な全てのタグを取得\n          TAGS=$(curl -s &quot;https://hub.docker.com/v2/repositories/misskey/misskey/tags?page_size=100&quot; | jq -r &apos;.results[].name&apos; | grep -E &apos;^[0-9]{4}\\.[0-9]+(\\.[0-9]+)?$&apos; | sort -V | tail -n 1)\n          \n          echo &quot;Latest tag: $TAGS&quot;\n          LATEST_VERSION=&quot;$TAGS&quot;\n          \n          # 最新バージョンの完全なダイジェストを取得\n          FULL_DIGEST=$(docker buildx imagetools inspect &quot;misskey/misskey:$LATEST_VERSION&quot; --format &quot;{{json .Manifest}}&quot; | jq -r &apos;.digest&apos;)\n          LATEST_DIGEST=$(echo &quot;$FULL_DIGEST&quot; | sed &apos;s/sha256://&apos;)\n          \n          echo &quot;latest_version=$LATEST_VERSION&quot; &gt;&gt; $GITHUB_OUTPUT\n          echo &quot;latest_digest=$LATEST_DIGEST&quot; &gt;&gt; $GITHUB_OUTPUT\n          echo &quot;latest_full_digest=$FULL_DIGEST&quot; &gt;&gt; $GITHUB_OUTPUT\n          echo &quot;Latest version: $LATEST_VERSION&quot;\n          echo &quot;Latest digest: $LATEST_DIGEST&quot;\n          echo &quot;Latest full digest: $FULL_DIGEST&quot;\n\n      - name: Check for updates\n        id: check\n        run: |\n          CURRENT_VERSION=&quot;${{ steps.current.outputs.current_version }}&quot;\n          CURRENT_DIGEST=&quot;${{ steps.current.outputs.current_digest }}&quot;\n          LATEST_VERSION=&quot;${{ steps.latest.outputs.latest_version }}&quot;\n          LATEST_DIGEST=&quot;${{ steps.latest.outputs.latest_digest }}&quot;\n          \n          echo &quot;=== Comparing versions and digests ===&quot;\n          echo &quot;  Current version: $CURRENT_VERSION&quot;\n          echo &quot;  Latest version:  $LATEST_VERSION&quot;\n          echo &quot;  Current digest:  $CURRENT_DIGEST&quot;\n          echo &quot;  Latest digest:   $LATEST_DIGEST&quot;\n          echo &quot;&quot;\n          \n          UPDATE_NEEDED=false\n          \n          if [ &quot;$CURRENT_VERSION&quot; != &quot;$LATEST_VERSION&quot; ]; then\n            echo &quot;✓ Version mismatch detected: $CURRENT_VERSION -&gt; $LATEST_VERSION&quot;\n            UPDATE_NEEDED=true\n          else\n            echo &quot;✓ Version is up to date: $CURRENT_VERSION&quot;\n          fi\n          \n          if [ &quot;$CURRENT_DIGEST&quot; != &quot;$LATEST_DIGEST&quot; ]; then\n            echo &quot;✓ Digest mismatch detected&quot;\n            echo &quot;  Current: $CURRENT_DIGEST&quot;\n            echo &quot;  Latest:  $LATEST_DIGEST&quot;\n            UPDATE_NEEDED=true\n          else\n            echo &quot;✓ Digest is up to date&quot;\n          fi\n          \n          echo &quot;&quot;\n          if [ &quot;$UPDATE_NEEDED&quot; = true ]; then\n            echo &quot;update_available=true&quot; &gt;&gt; $GITHUB_OUTPUT\n            echo &quot;🔄 Update available!&quot;\n          else\n            echo &quot;update_available=false&quot; &gt;&gt; $GITHUB_OUTPUT\n            echo &quot;✅ Already up to date&quot;\n          fi\n\n      - name: Update compose.yaml\n        if: steps.check.outputs.update_available == &apos;true&apos;\n        run: |\n          LATEST_VERSION=&quot;${{ steps.latest.outputs.latest_version }}&quot;\n          FULL_DIGEST=&quot;${{ steps.latest.outputs.latest_full_digest }}&quot;\n          \n          # 新しいイメージ行を作成\n          NEW_LINE=&quot;    image: misskey/misskey:${LATEST_VERSION}@${FULL_DIGEST}&quot;\n          \n          # compose.yamlを更新\n          sed -i &quot;s|.*misskey/misskey.*|${NEW_LINE}|&quot; compose.yaml\n          \n          echo &quot;Updated compose.yaml&quot;\n          echo &quot;New image reference: ${NEW_LINE}&quot;\n          \n          # 変更内容を確認\n          echo &quot;--- Git diff ---&quot;\n          git diff compose.yaml\n\n      - name: Create Pull Request\n        if: steps.check.outputs.update_available == &apos;true&apos;\n        uses: peter-evans/create-pull-request@v6\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n          commit-message: &quot;chore: update misskey to ${{ steps.latest.outputs.latest_version }}&quot;\n          title: &quot;chore: Update misskey to ${{ steps.latest.outputs.latest_version }}&quot;\n          body: |\n            ## 🔄 Misskey イメージの更新\n            \n            このPRは自動的に生成されました。\n            \n            ### 📋 変更内容\n            | 項目 | 古いの | 新しいの |\n            |------|------|--------|\n            | バージョン | `${{ steps.current.outputs.current_version }}` | `${{ steps.latest.outputs.latest_version }}` |\n            | ダイジェスト | `${{ steps.current.outputs.current_digest }}` | `${{ steps.latest.outputs.latest_digest }}` |\n            \n            ### 🔍 詳細\n            \n            **以前のイメージ:**\n            ```\n            misskey/misskey:${{ steps.current.outputs.current_version }}@${{ steps.current.outputs.current_full_digest }}\n            ```\n            \n            **新しいイメージ:**\n            ```\n            misskey/misskey:${{ steps.latest.outputs.latest_version }}@${{ steps.latest.outputs.latest_full_digest }}\n            ```\n            \n            ### ✅ 確認事項\n            - [ ] 変更内容を確認しました\n            - [ ] テスト環境で動作確認を行いました（必要に応じて）\n            - [ ] 本番環境への適用準備ができています\n            \n            ### 📚 関連リンク\n            - [Misskey リポジトリ](https://github.com/misskey-dev/misskey)\n            - [Docker Hub イメージ](https://hub.docker.com/r/misskey/misskey)\n            \n            ---\n            \n            🤖 自動生成されたPR | 📅 ${{ github.run_id }}\n          branch: update-misskey-${{ steps.latest.outputs.latest_version }}\n          delete-branch: true\n          labels: |\n            dependencies\n            automated pr\u003C/code>\u003C/pre>\u003C/div>\u003Cp>基本的にはこれで動くはずです。\u003Cbr>独自のフォークを利用している場合は適当に書き換えてください。\u003C/p>\u003Ch2 id=\"h73c11d078e\">実装例\u003C/h2>\u003Cp>参考までに、わたしの環境での実際の実装を以下に示します。\u003Cbr>\u003Ca href=\"https://github.com/team-shahu/shahu-docker-provision/commit/4e34a75ef19403715b17c501f3475c546cd91671#diff-facaded51b7d1c9656ae43b449b69aa398fee9129321a0001d97048c00c8cc1c\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/team-shahu/shahu-docker-provision/commit/4e34a75ef19403715b17c501f3475c546cd91671#diff-facaded51b7d1c9656ae43b449b69aa398fee9129321a0001d97048c00c8cc1c\u003C/a>\u003C/p>\u003Cp>使い回しても加工して利用しても構いません。\u003Cbr>煮るなり焼くなり好きにしてください。\u003C/p>\u003Ch1 id=\"hdd244d9218\">人間を招く(Optional)\u003C/h1>\u003Cp>ここまでの手順は、いわば決定論的な世界の話でした。\u003Cbr>正しく設定すれば、システムは期待通りに動きます。\u003Cbr>しかし、人間を招き入れるという行為は、全く異なる、そして遥かに複雑で非合理な問題領域へと足を踏み入れることを意味します。\u003C/p>\u003Cp>サーバを建てる人間が抱きがちな、最も甘美な幻想の一つは、「まともな人間が集まるだろう」というものです。\u003Cbr>しかし、現実は異なります。\u003Cbr>多くの人間は、あなたが期待するような理知的で配慮のある振る舞いは決してしません。 \u003Cbr>むしろ、あなたの善意を食い潰し、絶え間ないストレスの源泉となりかねない存在です。\u003Cbr>その事実を理解した上で、改めて選択肢を見てみましょう。\u003C/p>\u003Cp>\u003Ccode>コントロールパネル &gt; 設定 &gt; モデレーション\u003C/code>より、新規登録の受け入れ設定が可能です。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/52cca5697dc9475b98907c30359731fa/image.png\" alt=\"\" width=\"1918\" height=\"909\">\u003C/figure>\u003Cp>この点について、わたしは語りたいことが山ほどあるのですが、あまりにも長すぎるので興味があれば、わたしの盛大な失敗談を読んで笑ってやってください。\u003Cbr>\u003Ca href=\"https://mq1.dev/entry/a7dv5t3bip\" target=\"_blank\" rel=\"noopener noreferrer\">Misskey鯖缶後悔記\u003C/a>\u003C/p>\u003Cp>あなたがこれから作るのは、あなたの時間と精神を注ぎ込む、あなたの城です。\u003Cbr>その門の鍵を誰に渡すのかは、あなたが決めることです。\u003C/p>\u003Cp>自身の選択を後々後悔することがないよう祈っています。\u003C/p>\u003Ch1 id=\"h5db7379d72\">ユーザが増えてしまった！どうしよう！？\u003C/h1>\u003Cp>おめでとうございます。そして、ご愁傷様です。 \u003Cbr>あなたの手で生まれた小さな世界に人々が定住し始め、サーバは成長という新たな、そして厄介な段階を迎えました。\u003Cbr>これは喜ばしいことであると同時に、あなたの平穏な日々との別れを意味します。\u003C/p>\u003Ch2 id=\"hd844bd9150\">技術的な対処\u003C/h2>\u003Cp>サーバのユーザ数が増加し始めると、運用は新たなフェーズに移行します。これはサーバの成功を示す喜ばしい兆候であると同時に、これまでとは質の異なる、予測可能な技術的課題の始まりでもあります。\u003Cbr>ここからは、たスケーリングのロードマップを、\u003Ca href=\"https://wiki-misskey-operation.7ka.org/ja/misskey/2k-instance\" target=\"_blank\" rel=\"noopener noreferrer\">一般的？な指標\u003C/a>と共に解説します。\u003C/p>\u003Ch3 id=\"he8f3e6c2b5\">トータル300人規模の壁 (同時接続100人〜)\u003C/h3>\u003Cp>最初に直面するのは、多くの場合、単純なリソース不足です。\u003Cbr>LTLが活発化するにつれて、サーバの性能が追いつかなくなってきます。 \u003Cbr>この段階の最も標準的な対策は、スケールアップです。\u003Cbr>最低でも2CPU / 8GBメモリ程度のスペックが推奨されます。\u003C/p>\u003Ch3 id=\"hffd5841bfc\">トータル700人規模の壁 (同時接続200人〜)\u003C/h3>\u003Cp>この規模になると、問題はより専門的になります。\u003Cbr>単純なスケールアップだけでは解決できない、データベースのボトルネックが顕在化し始めます。\u003C/p>\u003Cul>\u003Cli>RDBの接続詰まり\u003Cp>Misskeyの各ワーカーからの大量の接続要求に、PostgreSQLのデフォルト設定が耐えきれなくなります。\u003Cbr>この問題を解決するには、\u003Ccode>pgBouncer\u003C/code>のようなコネクションプーラを導入する必要がありますが、その設定は非自明であり、かなりめんどくさいものです。\u003C/p>\u003C/li>\u003Cli>ジョブキューの詰まり\u003Cp>サーバ内外への投稿を処理する\u003Ccode>Inbox queue\u003C/code>と\u003Ccode>Deliver queue\u003C/code>が詰まり、投稿が遅延するようになります。\u003Cbr>\u003Ccode>.config/default.yml\u003C/code>のワーカー設定の調整が有効です。\u003Cbr>\u003Ccode>clusterLimit\u003C/code>の値を増やすことでワーカープロセスを増やし、処理能力を向上させることができますが、メモリ消費量もその倍数で増加します。\u003Cbr>サーバが実際に処理できる能力と設定値を乖離させすぎると、スワップが発生してしまいます。\u003C/p>\u003C/li>\u003C/ul>\u003Ch3 id=\"h4129f4dba0\">トータル1000人規模の壁 (同時接続300人〜)\u003C/h3>\u003Cp>データベースへの参照が遅くなり、APIの応答が全体的に緩慢になるという問題が発生します。\u003Cbr>この段階では、データベースにリードレプリカを設置し、読み取り処理をそちらに分散させることで、プライマリデータベースの負荷を軽減するアーキテクチャが一般的です。\u003Cbr>同時接続が400人を超えてくると、プライマリDB自体のスペックアップや、リードレプリカの追加増設も視野に入ってきます。\u003C/p>\u003Ch3 id=\"hb085256c33\">マネージドサービスへの移行\u003C/h3>\u003Cp>もしあなたが幸運にもインスタンスのマネタイズに成功したのであれば、これを機にGCP等のマネージドサービスへ完全に移行するのが、賢明な選択でしょう。\u003C/p>\u003Cp>自前でコネクションプーラを管理し、リードレプリカを運用する煩雑さは、計り知れません。\u003Cbr>その複雑な責務を、料金と引き換えに任意のベンダに丸投げすることで、あなたは本来集中すべきコミュニティの運営にリソースを割くことができます。\u003Cbr>規模が大きくなったサーバの管理は、わりと苦行でしかなさそうです。\u003Cbr>しあわせになりましょう。\u003C/p>\u003Ch2 id=\"h37da0415f9\">人間的な対処\u003C/h2>\u003Cp>技術的なスケーリングと並行して、あるいはそれ以上に重要となるのが、人間的な問題への対処、すなわちコミュニティのスケールアップです。\u003C/p>\u003Cp>ユーザ数の増加は、必然的に利用者間の衝突、ルール違反、そして管理者への様々な要求の増大を招きます。\u003Cbr>これらすべてに自分一人の時間と精神力で対応し続けることは、現実的に厳しいかと思います。\u003C/p>\u003Cp>現に、多くの管理者が役目を終えるのは、単純な資金難等が理由ではなく終わりのない人間的な対応からくる精神的なストレスが原因である、という事実に留意しておくべきでしょう。\u003C/p>\u003Cp>そうなる前に対策を講じる必要があります。\u003Cbr>まずは信頼できる人間にモデレーター権限を委譲し、負荷を分散\u003Cs>もとい押し付け\u003C/s>ましょう。\u003Cbr>あなたのサーバの文化をよく理解しているユーザに声をかけ、権限を付与してください。\u003C/p>\u003Cp>サーバ設立時に定めたはずのルールは、公平なモデレーションを行うための揺るぎない基準となります。\u003Cbr>そのため、不備があればこの際まとめて改定しておくといいでしょう。\u003C/p>\u003Cp>もし、なおコミュニティの成長速度があなたの管理能力を上回っていると感じたなら、迷わず新規登録を一時的に停止してしまいましょう。\u003Cbr>登録を招待制に切り替えることで、問題の流入を止め、コミュニティを安定させるための時間を確保できます。\u003C/p>\u003Cp>インスタンスの成長は、あなたが単なる技術的な管理者から、コミュニティの秩序を設計し、維持する運営者へと役割を変えることを要求します。\u003Cbr>残酷ですね。\u003C/p>\u003Ch1 id=\"h8a55dfed1c\">トラブルシューティングの基本\u003C/h1>\u003Cp>サーバが期待通りに動き続けると考えるのは、楽観的すぎる幻想です。\u003C/p>\u003Cp>問題は必ず、そして多くの場合、最も都合の悪いときに発生します。\u003Cbr>その際に重要なのは、パニックに陥らず、論理的に原因を切り分ける、体系的な考え方です。\u003C/p>\u003Cp>まず、あなたのインスタンスにアクセスできなくなった時、外から内へと問題を切り分けていくのが基本です。\u003C/p>\u003Cp>最初に確認すべきは、あなたのサーバの外側、すなわちCloudflareです。\u003Cbr>あなたが設定した外形監視が、おそらく最初の異常を知らせてくれているはずですが、Cloudflare自体のステータスページを確認し、サービスに障害が発生していないかを見ます。\u003Cbr>次に、Zero Trustダッシュボードで、あなたのTunnelが正常に稼働しているものとして認識されているかを確認してください。\u003C/p>\u003Cp>ここまでが正常であれば、問題はあなたのVPS内部にあると判断できます。\u003C/p>\u003Cp>サーバにSSHで接続したら、最初に行うべきはログを読むことではありません。\u003Cbr>まずは、\u003Ccode>sudo docker ps\u003C/code> コマンドを実行し、各コンテナが意図した通りに稼働しているか、その全体像を把握します。\u003Cbr>今回の構成の場合、\u003Ccode>app\u003C/code>, \u003Ccode>mi\u003C/code>, \u003Ccode>db\u003C/code>, \u003Ccode>redis\u003C/code>、いずれかのコンテナが\u003Ccode>Exited\u003C/code>や\u003Ccode>Restarting\u003C/code>といった異常な状態にないかを確認してください。\u003C/p>\u003Cp>例えば、\u003Ccode>db\u003C/code>コンテナが\u003Ccode>Unhealthy\u003C/code>であれば、問題の根源はデータベースにあると、この時点で大きく絞り込むことができます。\u003C/p>\u003Cp>問題のあるコンテナを特定できて初めて、そのコンテナのログの確認に移ります。\u003Cbr>\u003Ccode>sudo docker compose logs --tail 500 mi | grep -E &apos;ERROR|FATAL&apos; \u003C/code> のように、問題が疑われるサービスのログを追跡し、\u003Ccode>ERROR\u003C/code>や\u003Ccode>FATAL\u003C/code>といったキーワードを頼りに、何が起きているのかを読み解きます。\u003Cbr>New Relicのようなログ集約基盤を導入していれば、過去のログを横断的に検索し、「このエラーはいつから発生しているのか」といった時間軸での分析もかなり楽になるでしょう。\u003C/p>\u003Cp>もし、全てのコンテナが正常に稼働しているにも関わらずサイトが極端に遅い、といった場合は、ホストOS自体の健康状態を疑います。\u003Cbr>\u003Ccode>df -h\u003C/code>でディスクの空き容量を確認し(ストレージの逼迫はデータベースを停止させる致命的な原因です）、\u003Ccode>htop\u003C/code>でCPUやメモリを異常に消費しているプロセスがないかを確認します。\u003Cbr>あるいは\u003Ccode>dmesg\u003C/code>で、カーネルがOOM Killerを発動させていないかといった、より低レイヤーの問題を探ります。\u003C/p>\u003Cp>もちろん、あなたが設定したであろう内部監視は、これらの兆候をグラフとして明確に示しているはずです。\u003C/p>\u003Cp>外形監視 → コンテナの状態 → ログ → ホストOSの健康状態。\u003Cbr>この外から内へという一貫した流れで原因を絞り込んでいく思考こそが、トラブルシューティングの要諦です。\u003C/p>\u003Cp>そして、問題の原因は、多くの場合、あなたが最後に行った変更の中にあります。\u003Cbr>冷静に、一つずつ確認していくことが結局のところ一番早い解決方法でしょう。\u003C/p>\u003Ch1 id=\"h1877a38f6d\">Misskeyインスタンスを閉鎖する手順と410 Gone設定\u003C/h1>\u003Cp>すべてのものには終わりがあります。\u003Cbr>Misskeyインスタンスの運用も例外ではありません。\u003C/p>\u003Cp>燃え尽き、時間的制約、あるいは金銭的な理由。\u003Cbr>いずれ訪れるかもしれないその日のために、ここでは責任ある管理者として、サーバの役割を正式に終わらせる爆破手順について解説します。\u003C/p>\u003Cp>無言でサービスを停止するような夜逃げに等しい行いは、最も無責任で、これまであなたのサーバを利用してくれたユーザを裏切る行為です。\u003Cbr>最後まで、管理者としての責務を全うしましょう。\u003C/p>\u003Ch2 id=\"h4366d09a9d\">告知\u003C/h2>\u003Cp>ユーザが心の準備をし、自身のデータを退避させるための時間を十分に確保することが、倫理的なインスタンス爆破の大前提です。\u003Cbr>最低でも1ヶ月、できれば2ヶ月前には、\u003Ccode>コントロールパネル &gt; 管理 &gt; お知らせ\u003C/code>から、全ユーザに閉鎖の意向を告知してください。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/1a9d698a68604b8c90e6e8508f4c338f/image.png\" alt=\"\" width=\"1919\" height=\"905\">\u003C/figure>\u003Cp>\u003C/p>\u003Ch2 id=\"h8ad95409d5\">新規登録の停止\u003C/h2>\u003Cp>告知と同時に、\u003Ccode>コントロールパネル &gt; 設定 &gt; モデレーション\u003C/code>より、招待制に設定し、これ以上ユーザが増えないようにします。\u003C/p>\u003Ch2 id=\"had4604ca89\">410 Gone\u003C/h2>\u003Cp>ActivityPubで連合しているインスタンスを閉鎖する際には、単にコンテナを停止するだけでは不十分です。\u003Cbr>それは、連合していた他のインスタンスに対して、無駄な通信を永遠に試みさせる厄介な行為に他なりません。\u003C/p>\u003Cp>あなたがサーバを停止すると、あなたをフォローしていた、あるいは過去にあなたの投稿をRNしたサーバは、あなたのサーバが応答しないことを検知します。\u003Cbr>しかし、それが一時的なメンテナンスなのか、恒久的な閉鎖なのかを判断できないため、健気にも何度も再接続を試み続けます。\u003Cbr>この無駄な再試行が、他のサーバのリソースを僅かながら、しかし確実に消費させ続けるのです。\u003C/p>\u003Cp>この問題を解決し、各連合先に対して立つ鳥跡を濁さずの礼儀を尽くすのが、HTTPステータスコード \u003Ccode>410 Gone\u003C/code> です。\u003Cbr>これは、「この場所は完全に、そして永久に消滅した」という明確な意思表示であり、これを受け取った他のサーバは、あなたのサーバへの通信を諦め、キューから削除してくれます。\u003C/p>\u003Cp>設定は簡単です。\u003Cbr>Caddyの設定を410を返すだけのシンプルなものに書き換えて、Caddyコンテナを再起動します。\u003C/p>\u003Cdiv data-filename=\"./config/Caddyfile\">\u003Cpre>\u003Ccode>:3000 {\n\trespond &quot;This server is permanently gone.&quot; 410\n}\u003C/code>\u003C/pre>\u003C/div>\u003Cpre>\u003Ccode class=\"language-shell\">sudo docker compose restart app\u003C/code>\u003C/pre>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/2856d44c7bba4789a55ea6326398a754/image.png\" alt=\"\" width=\"1918\" height=\"909\">\u003C/figure>\u003Cp>この状態で、最低でも数週間、可能であれば1ヶ月ほどオリジンを稼働させ続け、連合先のインスタンスに閉鎖を周知させます。\u003C/p>\u003Cp>注意点として、一度410を返したドメインに対して、他のインスタンスは通信を恒久的に停止します。\u003Cbr>もし将来、同じドメイン名でインスタンスを再建する可能性が少しでもあるならば、この手順は慎重に検討しましょう。\u003C/p>\u003Ch2 id=\"h12acfb3b74\">サービスの完全停止\u003C/h2>\u003Cp>周知期間が十分に経過したら、Misskeyを構成する全てのリソースを完全に停止・削除します。\u003Cbr>最後に、VPS等の契約している各種サービスを整理し、すべての工程が終了します。\u003C/p>\u003Cp>お疲れ様でした。\u003Cbr>これにて、あなたのインスタンスの一生は幕を閉じます。\u003C/p>\u003Cp>サーバはデジタルな塵と消え失せましたが、そこでの経験や繋がった人々との記憶は、あなたの内に残ります。\u003C/p>\u003Ch1 id=\"h1afe451c43\">さいごに\u003C/h1>\u003Cp>ここまでお疲れ様でした。\u003Cbr>サーバの契約から始まり、ドメインの取得、Dockerによる構築、各種設定、そして運用と、いつか訪れるかもしれない爆破に至るまで、このマニュアルはMisskeyインスタンス管理の一生を駆け足で巡るものでした。\u003C/p>\u003Cp>このエントリを通じてわたしが一貫して伝えたかったのは、技術的な手順そのものよりも、その先にある「インスタンスを運用し続ける」という行為の重みです。\u003C/p>\u003Cp>技術的な問題は、時間をかければ、あるいはお金で殴ってしまえば、多くの場合解決できます。\u003Cbr>しかし、あなたが本当に向き合うことになるのは、それ以上に複雑で、そして終わりなき人間という存在です。\u003C/p>\u003Cp>あなたは今、自分だけの城を手にしました。\u003Cbr>その城壁の中で何を守り、何を育み、そして何を拒絶するのか。\u003Cbr>その全ての判断と責任は、あなた一人の肩にかかっています。\u003C/p>\u003Cp>当エントリが少しでも道標となれば幸いです。\u003C/p>\u003Cp>なお、このマニュアルはわたしの知見に基づくものであり、全ての情報を網羅できているわけではありません。\u003Cbr>もし内容に不足している点や、「こういう内容も書き足してほしい」といった要望があれば、何らかの方法でご連絡ください。\u003Cbr>今後の改訂の参考にさせていただきます。\u003C/p>\u003Cp>それでは。\u003C/p>",[13,19,25,31],{"id":14,"createdAt":15,"updatedAt":16,"publishedAt":15,"revisedAt":16,"slug":17,"name":18},"vmhb23sq4","2025-07-29T12:56:07.884Z","2025-12-03T16:06:19.140Z","misskey","Misskey",{"id":20,"createdAt":21,"updatedAt":22,"publishedAt":21,"revisedAt":22,"slug":23,"name":24},"fwj_nwhj1-s","2025-04-30T04:55:28.953Z","2025-12-03T16:07:03.591Z","server","サーバー",{"id":26,"createdAt":27,"updatedAt":28,"publishedAt":27,"revisedAt":28,"slug":29,"name":30},"qfey3yw0z1","2025-04-29T08:44:41.687Z","2025-12-03T16:07:14.622Z","technology","テクノロジー",{"id":32,"createdAt":33,"updatedAt":34,"publishedAt":33,"revisedAt":34,"slug":35,"name":36},"lte0t59xm8sb","2025-05-02T16:12:38.708Z","2025-12-03T16:06:52.753Z","network","ネットワーク",false,1,0,{"url":41,"domain":42,"title":43,"description":44,"type":45},"https://tools.e17.dev/emoji-manager/","tools.e17.dev","リンク","このサイトをチェック","GENERAL",{"url":47,"domain":48,"title":49,"description":50,"image":51,"favicon":52,"type":45},"https://misskey-hub.net/ja/docs/for-admin/features/managing-emojis/#%E4%B8%80%E6%8B%AC%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88","misskey-hub.net","カスタム絵文字の管理 | Misskey","分散型SNS作成ソフトウェア Misskeyの公式サイト。Misskeyサーバーの作り方やサーバー一覧など、Misskeyに関する情報が満載！","https://misskey-hub.net/img/og/misskey-hub-screenshot-l.png","https://misskey-hub.net/favicon.ico",{"url":54,"domain":55,"title":56,"description":57,"image":58,"favicon":59,"type":45},"https://developers.cloudflare.com/cache/reference/csam-scanning/","developers.cloudflare.com","CSAM Scanning Tool","Scan cached content for child sexual abuse material.","https://developers.cloudflare.com/core-services-preview.png","https://developers.cloudflare.com/favicon.png",{"url":61,"domain":62,"title":63,"description":64,"image":65,"favicon":66,"type":45},"https://resend.com/","resend.com","Resend · Email for developers","The best way to reach humans instead of spam folders. Deliver transactional and marketing emails at scale.","https://resend.com/static/cover.png","https://resend.com/static/favicons/favicon-marketing.ico?v=1",{"contents":68,"totalCount":84,"offset":39,"limit":38},[69],{"id":70,"createdAt":71,"updatedAt":72,"publishedAt":72,"revisedAt":72,"title":73,"content":74,"tags":75,"is_no_index":37,"summary":83},"1fxp8h56dbxv","2025-07-14T08:17:06.142Z","2025-07-14T08:27:16.274Z","NASが安いという幻想","\u003Ch1 id=\"h8d027c8ed3\">はじめに\u003C/h1>\u003Cp>現代の情報化社会において、デジタルデータの保管という課題は、個人から企業に至るまで、その規模を問わず普遍的なものとなってしまいました。\u003Cbr>この課題に対する解決策として、NASに代表されるオンプレミス型ストレージと、各種事業者が提供するクラウドストレージは、しばしば比較の対象として俎上に載せられます。\u003Cbr>SNSや任意のコミュニティを見ていると、今日においてもなお、「NASは初期投資のみで済むため、月額料金が発生するクラウドストレージよりも長期的には安価である」という趣旨の言説に、頻繁に遭遇します。\u003C/p>\u003Cp>この見解は、導入時における、CAPEXとOPEXのトレードオフに関する、ある種の古典的な命題の一類型と捉えることができるでしょう。\u003Cbr>物理的な機器を購入・所有することによる初期コストの集中か、あるいはサービス利用料として継続的にコストを支払うか、という選択は、多くの技術的意思決定の場面で現れる構造です。\u003Cbr>NASが安価であるという主張は、この構造においてCAPEXを重視し、OPEXを極小化できるという点にその論拠を置いています。\u003C/p>\u003Cp>しかしながら、わたしはこの通説に触れるたびに、ある種の違和感と、その論理構造の単純さに対する嫌悪感を覚えてしまいます。\u003Cbr>なぜなら、その経済性の比較は、データのAvailability(可用性)やIntegrity(完全性)といった、ストレージシステムが本来担うべき根源的な責務や、総所有コストという、より包括的なコスト評価の観点を見過ごしているように思えてならないからです。\u003C/p>\u003Ch1 id=\"h23bd3a0e7c\">可用性と完全性\u003C/h1>\u003Cp>安価なNAS運用が成り立つ、その土台の危うさを考えていくと、まず「可用性」と「完全性」という、似ているようで全く異なる二つの概念の混同に行き着くように思います。\u003C/p>\u003Cp>オンプレミスの文脈で、データの安全性を語る際、必ずと言っていいほど登場するのがRAIDという技術です。\u003Cbr>これは、複数の物理ディスクを束ねて、性能と耐障害性を担保する仕組みであり、わたし自身もその恩恵を受けてきました。\u003Cbr>けれど、これをデータの安全性のゴールだと考えてしまうのは、やはり少し早計なのではないかと感じます。\u003C/p>\u003Cp>ここで明確に認識すべきは、RAIDが主として解決しようとしている課題が、あくまで「ディスクサブシステムの単一障害点を排除し、ハードウェア故障時におけるシステムの可用性を維持すること」にあるという点です。\u003Cbr>可用性とは、システムが停止することなく、継続して稼働し、ユーザーからのリクエストに応答できる能力を指します。\u003Cbr>ディスクの物理的故障はストレージシステムにおいて最も頻繁に発生する障害の一つであり、RAIDがその対策として極めて有効であることは疑いようのない事実です。\u003C/p>\u003Cp>しかし、データの損失を引き起こす脅威は、ハードウェアの物理的故障だけではなく、この可用性の確保をもって、データの安全性が完全に保証されたと考えるのは、致命的に愚直な解釈です。\u003C/p>\u003Cp>例えば、自分の操作ミスで大切なファイルを消してしまうこと。\u003Cbr>あるいは、ランサムウェア等の外的な要因によって、データが根こそぎ使えなくされてしまうこと。\u003Cbr>こうした論理的な破損の前では、RAIDは何の盾にもなってくれません。\u003Cbr>むしろ、ファイルの削除や暗号化といった操作は、RAIDを構成する健全なディスクにも、悲しいほど忠実に、そして即座に複製されてしまうのです。\u003C/p>\u003Cp>この論理的破損という避けがたいリスクからデータの完全性を保護するための唯一の手段が、バックアップに他なりません。\u003Cbr>バックアップとは、特定時点への復旧(Point-in-Time Recovery)を可能にするための、運用系とは独立した静的なデータコピーを指します。\u003Cbr>これにより、万が一データが論理的に破損した場合でも、破損以前の正常な状態へとシステムを巻き戻すことが可能になります。\u003C/p>\u003Cp>効果的なバックアップ戦略の構築には、業界の標準的プラクティスとして認知されている「3-2-1ルール」というものがあります。\u003Cbr>これは、3つのデータコピーを、2つの異なるメディアに保管し、そのうち1つをオフサイトに補完するといったものです。\u003Cbr>ここで言う「異なるメディア」とは、単に別のSSDを用意するという意味に留まりません。\u003Cbr>例えば、同一製造元の同一ロットのSSDは、ファームウェアのバグや物理的な製造瑕疵により、同時期に故障するリスクを内包します。\u003Cbr>そのため、SSDとLTOテープ、あるいはSSDとクラウドストレージといった、物理特性や障害モードが全く異なる媒体を組み合わせることが推奨されます。\u003C/p>\u003Cp>さらにオフサイトで保管することの重要性は、火災や水害といった物理災害への対策だけでなく、現代的な脅威に対する対策としても有用なものです。\u003Cbr>拠点全体がランサムウェアに感染するような事態を想定した場合、ネットワーク的に隔離された、エアギャップが確保されたオフサイトバックアップの存在が、最後の生命線となり得てしまいます。\u003Cbr>このルールを遵守したデータ保護体制をオンプレミスで構築しようとすれば、追加のハードウェア投資や、オフサイト保管のためのサービス契約が必須となり、「NAS本体の購入費だけで済む」という主張はその妥当性を失います。\u003C/p>\u003Ch1 id=\"hd11c1407a5\">不可視コストの顕在化\u003C/h1>\u003Cp>また、システムの導入から廃棄までのライフサイクル全体で発生するコストを考慮に入れると、オンプレミス型ストレージの経済性は、違った側面を見えてきます。\u003C/p>\u003Cp>直接的なコストには、まずハードウェア本体の購入費用(CAPEX)が含まれます。\u003Cbr>これにはNASアプライアンス本体だけでなく、その性能や信頼性に影響する各種コンポーネント、例えばワークロードに適したストレージ媒体や、24/365での連続稼働を想定したエンタープライズ製品の費用が入ります。\u003Cbr>加えて、運用費用(OPEX)として、常時稼働に伴う電気代や、ストレージの期待寿命に基づく定期的な交換費用といった、継続的な支出も発生します。\u003C/p>\u003Cp>しかし、これらの総費用(TCO)の中でも特に見過ごされがちなのが人的コストです。\u003Cbr>ここで、「個人利用なのだから、専門業者に依頼するわけではなく自分で作業する。したがって人的コストはゼロだ」という意見もあるかもしれません。\u003Cbr>しかし、その考え方は、TCOの本質的な意味合いを見過ごしているように思えます。\u003C/p>\u003Cp>システムの構築・運用には、OSのセットアップ、ストレージプールの設計、VLANやFWといったネットワーク設定、継続的な監視とセキュリティアップデート、そして障害発生時のトラブルシューティングなど、多岐にわたる専門的な作業が伴います。\u003Cbr>これらの作業を適切に行うには、相応の知識が必要であり、もし知識がなければ、それを習得するための学習時間も発生します。\u003C/p>\u003Cp>そして何より重要なのが機会費用という考え方です。\u003Cbr>経済学の観点では、ある選択をするために費やした時間やリソースは、それによって諦められた他の選択肢から得られたであろう価値を失った、と見なされます。\u003Cbr>例えば、NASの構築やメンテナンスに数十時間を費やした場合、その時間を使って自己投資のための学習をしたり、あるいは休息を取ったりすることもできたはずです。\u003Cbr>その失われた価値や便益が、実質的なコストとして存在しているのです。\u003C/p>\u003Ch1 id=\"hc33df07e3d\">抽象化レイヤーが提供する非機能要件\u003C/h1>\u003Cp>これらオンプレミス運用が内包する複雑性とTCOの全体像を理解した上でクラウドストレージを再評価すると、その月額料金は、事業者が提供する高度に抽象化されたレイヤーに対する対価として捉え直すことができます。\u003Cbr>クラウドストレージは、単なるIaaSにおけるディスク領域の提供に留まりません。\u003Cbr>多くの場合、データの冗長化、バックアップ、アクセス制御、暗号化といった機能が組み込まれたPaaSに近いマネージドサービスとして提供されます。\u003Cbr>これにより、利用者はインフラストラクチャの下位レイヤーの運用責任から解放されるのです。\u003C/p>\u003Cp>クラウド事業者は、SLAとして、例えば99.9999%といった極めて高い可用性を契約として保証します。\u003Cbr>このレベルの可用性を個人がオンプレミスで達成・維持することの困難さは、想像に難くありません。\u003Cbr>また、主要なクラウドプロバイダーは、地理的に独立した複数のアベイラビリティゾーンにデータを自動で同期レプリケーションする機能を標準で提供しています。\u003Cbr>これは、個人レベルでは実現困難な地理的分散によるDR対策を、容易に実現できることを意味します。\u003C/p>\u003Cp>さらに、セキュリティとコンプライアンスの観点からも、クラウドの価値は顕著です。\u003Cbr>多くの事業者は、ISO 27001やSOC 2といった国際的な第三者認証を取得しており、そのセキュリティ体制は定期的な監査を受けており、個人運用では達成不可能なレベルの信頼性とコンプライアンス準拠を、誰でも容易に享受できることを意味します。\u003C/p>\u003Ch1 id=\"hba6e05a562\">コンテキストに応じたアーキテクチャ設計\u003C/h1>\u003Cp>以上から導き出されるのは、「NASが安価である」という主張が、データ保護戦略の複雑性と、TCOにおける間接コスト、特に人的資本の価値を過小評価した場合にのみ成立しうる、限定的な命題であるということです。\u003C/p>\u003Cp>もちろん、これはオンプレミスNASの価値を否定するものではありません。大容量データの高速なローカルアクセスが求められるワークロードや、学習目的でのインフラ運用経験の獲得といった特定のコンテキストにおいては、NASは依然として優れた選択肢です。\u003C/p>\u003Cp>NASかクラウドかという二元論に陥ることなく、それぞれのアーキテクチャの特性を深く理解し、ワークロードの性質、求められるRTO/RPO、許容可能なリスクレベル、予算、そして運用者の技術スキルセットといった色々なパラメータを考慮し、総合的な判断を下すことが重要かと思います。\u003C/p>\u003Cp>技術選定とは、単一の正解を求める行為ではなく、常に変化する制約条件下で最適化を図る、継続的な知的なプロセスです。\u003Cbr>そのプロセスにおいて、安易な通説に流されることなく、物事の本質を多角的に見つめる冷静な視座こそが、不可欠なのではないかと、わたしは考えています。\u003C/p>\u003Cp>\u003C/p>",[76,82],{"id":77,"createdAt":78,"updatedAt":79,"publishedAt":78,"revisedAt":79,"slug":80,"name":81},"wia4slp55q","2025-04-28T07:14:14.541Z","2025-12-03T16:08:13.798Z","thoughts","独り言",{"id":26,"createdAt":27,"updatedAt":28,"publishedAt":27,"revisedAt":28,"slug":29,"name":30},"はじめに現代の情報化社会において、デジタルデータの保管という課題は、個人から企業に至るまで、その規模を問わず普遍的なものとなってしまいました。この課題に対する解決策として、NASに代表されるオンプレミス型ストレージと、各種事業者が提供するクラウドストレージは、しばしば比較の対象として俎上に載せられま",25,{"url":86,"domain":87,"title":88,"description":89,"image":90,"favicon":91,"type":45},"https://qiita.com/mai_llj/items/1002932eb46ce39d4045","qiita.com","MisskeyのメールサーバーとしてGmailのSMTPサーバーを利用する - Qiita","なにするの？ MisskeyのメールサーバーとしてGmailを使う方法です。 制限こそありますが、小規模インスタンスであれば充分実用に耐えます。 やり方 アプリパスワードの発行 ここを開き、アプリパスワードを新規発行します。 https://myaccount.goo...","https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Fengineer-festa-ogp-background-074608b13b4bbe67c10ada41e7e2d292.png%3Fixlib%3Drb-4.1.1%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkZxaWl0YS1pbWFnZS1zdG9yZSUyRjAlMkYzMjgzMjQxJTJGOGY2MjNjYjRkNzFjNzIzYzYxN2RhYmI0ZTZkNmUzMTAwOTY5MjQ1OSUyRnhfbGFyZ2UucG5nJTNGMTcyMDI5MDA4ND9peGxpYj1yYi00LjEuMSZhcj0xJTNBMSZmaXQ9Y3JvcCZtYXNrPWVsbGlwc2UmYmc9RkZGRkZGJmZtPXBuZzMyJnM9YzZkMTU4MjlmZjE0MjI1ZjJmYzhkY2M1NzA0MWM0MDY%26blend-x%3D120%26blend-y%3D462%26blend-w%3D90%26blend-h%3D90%26blend-mode%3Dnormal%26mark64%3DaHR0cHM6Ly9xaWl0YS1vcmdhbml6YXRpb24taW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkZxaWl0YS1vcmdhbml6YXRpb24taW1hZ2UlMkY4YTg2MTkzNDM4NWU3MjJjZTVmOTc1MGQxZTRkODE4Y2I4MjQwMzY4JTJGb3JpZ2luYWwuanBnJTNGMTcxOTE0NTQ3Mj9peGxpYj1yYi00LjEuMSZ3PTQ0Jmg9NDQmZml0PWNyb3AmbWFzaz1jb3JuZXJzJmNvcm5lci1yYWRpdXM9OCZiZz1GRkZGRkYmYm9yZGVyPTIlMkNGRkZGRkYmZm09cG5nMzImcz1hMzg1MGMxYzA5MzdmNThkNWY2NmEwOGZjMmJiZDk2NA%26mark-x%3D186%26mark-y%3D515%26mark-w%3D40%26mark-h%3D40%26s%3D3122c6e58f5d3f3453d1412d549d7e5d?ixlib=rb-4.1.1&w=1200&fm=jpg&mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjEuMSZ3PTk2MCZoPTMyNCZ0eHQ9TWlzc2tleSVFMyU4MSVBRSVFMyU4MyVBMSVFMyU4MyVCQyVFMyU4MyVBQiVFMyU4MiVCNSVFMyU4MyVCQyVFMyU4MyU5MCVFMyU4MyVCQyVFMyU4MSVBOCVFMyU4MSU5NyVFMyU4MSVBNkdtYWlsJUUzJTgxJUFFU01UUCVFMyU4MiVCNSVFMyU4MyVCQyVFMyU4MyU5MCVFMyU4MyVCQyVFMyU4MiU5MiVFNSU4OCVBOSVFNyU5NCVBOCVFMyU4MSU5OSVFMyU4MiU4QiZ0eHQtYWxpZ249bGVmdCUyQ3RvcCZ0eHQtY29sb3I9JTIzRkZGRkZGJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTU2JnR4dC1wYWQ9MCZzPTk1YmNlOTJlODFiMzIzZjg1NzRlZGJhYjhiNGFiZjc3&mark-x=120&mark-y=112&blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjEuMSZ3PTgzOCZoPTU4JnR4dD0lNDBtYWlfbGxqJnR4dC1jb2xvcj0lMjNGRkZGRkYmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9MzYmdHh0LXBhZD0wJnM9MDE4NmJlMjNiNWY2ODNjOTZmY2Y0ZTViZDAwNGU2NjU&blend-x=242&blend-y=454&blend-w=838&blend-h=46&blend-fit=crop&blend-crop=left%2Cbottom&blend-mode=normal&txt64=VGVhbSBzaGFodQ&txt-x=242&txt-y=539&txt-width=838&txt-clip=end%2Cellipsis&txt-color=%23FFFFFF&txt-font=Hiragino%20Sans%20W6&txt-size=28&s=054224cccd5cfeecd7a0180ca5fec512","https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico",{"url":93,"domain":94,"title":95,"description":96,"image":97,"favicon":98,"type":45},"https://github.com/team-shahu/misskey-backup/pkgs/container/misskey-backup","github.com","Build software better, together","GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.","https://github.githubassets.com/assets/github-logo-55c5b9a1fe52.png","https://github.githubassets.com/favicons/favicon.svg",{"url":100,"domain":101,"title":102,"description":103,"image":104,"type":45},"https://hisubway.online/blog/fediverse_relay/","hisubway.online","Fediverseリレーサーバー一覧2023（for Mastodon / Misskey / Pleroma）","MastodonやMisskeyにはリレーによって投稿を中継し配信する機能があります。リレーサーバーをまとめた記事はいくつかありますが、すでに消えていたり、情報が古かったりするので、2023年8月時点で利用できるものを挙げていきます。\\n","https://hisubway.online/blog/fediverse_relay/header.jpg",{"contents":106,"totalCount":128,"offset":39,"limit":38},[107],{"id":108,"createdAt":109,"updatedAt":110,"publishedAt":111,"revisedAt":110,"title":112,"content":113,"tags":114,"is_no_index":37,"summary":127},"22xghlwvdi","2025-08-05T10:26:27.343Z","2025-08-05T20:07:53.778Z","2025-08-05T10:31:06.098Z","PetSnowy自動猫トイレを導入したら生活の質が少しだけ向上した話","\u003Cp>1ヶ月ほど前にお迎えした猫(スコ♂, 8ヶ月齢)のモカちゃんが、かけがえのない癒やしとなっています。\u003C/p>\u003Cp>ただ、そんな愛猫との生活の中で一つだけ、どうしても気が重くなるタスクがありました。\u003Cbr>それは、毎日のトイレ掃除です。\u003C/p>\u003Cp>決められた手順を淡々と繰り返すだけのルーティンワークは、できれば機械に任せたい、と思うのは人間の性分なのかもしれません。\u003Cbr>特に気分が落ち込んでいる日は、このトイレ掃除が、精神的な負担として重くのしかかっていました。\u003Cbr>そこで、この種の課題は資本で解決すべきではないかと考え、猫の自動トイレの導入を決意するに至りました。\u003C/p>\u003Cp>様々な製品を比較検討した結果、最後まで候補に残っていたのは、割とみんな使ってるPetkitの新しいモデルと、今回購入したPetSnowyの自動トイレです。\u003C/p>\u003Cp>最終的に私はPetSnowyを選んだのですが、これにはいくつかの理由があります。\u003Cbr>一つ目は、ニオイ漏れに対する配慮がしっかりしていそうだと感じた点です。\u003Cbr>本体がドーム型で完全に覆われ、内部には光触媒を利用した脱臭装置も搭載されているため、超狭いの私の部屋でもニオイを気にせず過ごせるのではないか、と期待しました。\u003Cbr>二つ目の理由は、猫砂の飛び散り対策です。\u003Cbr>トイレの入口に砂を落とすためのスペースが標準で設けられており、部屋が砂で汚れにくくなるという細やかな設計に惹かれました。\u003Cbr>そして何より、トイレという生活感をともなう製品でありながら、どこかオブジェのような佇まいを持つ、その愛らしいデザインが大きな決め手となりました。\u003C/p>\u003Cp>幸いなことに、Amazonのセールで定価より安く、57,259円で購入できました。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/a70234ee24064e509d4a8c24f1e46c20/image.png\" alt=\"\" width=\"941\" height=\"507\">\u003C/figure>\u003Cp>ただ、多くの方に言われていた本体の大きさだけが、最後まで少し気がかりではありました。\u003C/p>\u003Ch1 id=\"hd2180c0467\">製品の到着とデカデカ存在感\u003C/h1>\u003Cp>注文から数日後、自宅に届いた段ボール箱は、噂に違わぬ大きさでした。 \u003Cbr>その巨大さは、一人で室内に運び入れるのにかなり苦労したほどです。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/92ff235bb62746fb91d0e7317a3ff7f3/beauty_1754383937916.jpg\" alt=\"\" width=\"1620\" height=\"911\">\u003C/figure>\u003Cp>箱を開けてまず印象的だったのは、同梱されていたクイックスタートガイドの、常軌を逸したサイズ感でした。\u003Cbr>手元にあるM1 Airと並べてみても、この通りです。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/51810ecd1cad443992b8f32689eb686d/beauty_1754383861165.jpg\" alt=\"\" width=\"1620\" height=\"911\">\u003C/figure>\u003Cp>\u003Cbr>このような巨大な印刷物に、わたしの人生で再び相まみえることは、おそらくないでしょう。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/90ea6af2cafe43d8b41b3612883adb94/beauty_1754383883832.jpg\" alt=\"\" width=\"1620\" height=\"911\">\u003C/figure>\u003Cp>このフォントサイズ、この紙面の占有率。\u003Cbr>おばあちゃんスマホことラクラクフォンのUIでも、これほどのクソデカフォントではないでしょう。\u003C/p>\u003Cp>本体の組み立ては、すごく簡単でした。\u003Cbr>ほとんどのパーツは組み立てられた状態で届き、残りの数点もマグネットで直感的に固定できるようになっています。\u003C/p>\u003Cp>本体は20kgほどあってかなり重いですが、それ以外に設置で迷うようなことは特にありませんでした。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/8e018532101d4d69bdeceeb0b90d3194/beauty_1754384048831.jpg\" alt=\"\" width=\"1620\" height=\"911\">\u003C/figure>\u003Cp>設置してみると、やはりそのデザインはとても洗練されていて、めちゃ可愛い。\u003Cbr>しかし、想像以上に大きかったため、もともと猫用のサークルを置いていたスペースは完全にこのトイレに占有され、結果的にサークルが部屋の外に追いやられてしまうという、予期せぬ事態が発生しました。\u003C/p>\u003Ch1 id=\"he1495c2243\">猫の反応\u003C/h1>\u003Cp>設置が完了すると次に訪れるのは最も重要な検証、モカちゃん自身がこれを受け入れてくれるかどうかを確かめる必要があります。\u003C/p>\u003Cp>以前より自動トイレを怖がってしまう猫もいると聞いていましたし、このタイミングで猫砂も、お迎えの時に近所のホムセンで購入した残念な紙系のものから、推奨されている鉱物系のものへと変更したため、猫にとっては大きな環境の変化となります。\u003C/p>\u003Cp>案の定、最初は新しいトイレを遠巻きに観察するばかりで、なかなか入ろうとはしませんでした。\u003Cbr>そのため、もともと使っていたトイレも隣に置いたままにして、本人(本猫？)の判断に委ねることにしました。\u003C/p>\u003Cp>次の日の朝方、私が爆睡している間に、新しいトイレを使ってくれたようです。\u003C/p>\u003Cfigure>\u003Cimg src=\"https://images.microcms-assets.io/assets/3aba23b5bd6f4b79800a0305d0e4f8aa/bd56ffd6af6e40c3be51bd425e5b5934/image.png\" alt=\"\" width=\"1115\" height=\"707\">\u003C/figure>\u003Cp>スマホのアプリに清掃完了の通知が届いているのを見つけた時は、かなり安堵しました。\u003C/p>\u003Ch1 id=\"h9df8cae6e7\">全体的な感想と、いくつかの気になる点\u003C/h1>\u003Cp>PetSnowyの自動トイレを実際に使ってみて、これは非常に真剣に、そして丁寧に作られた製品だと感じました。\u003C/p>\u003Cp>何よりも、日々のトイレ掃除という定型作業から完全に解放されたことが、私にとって最大のメリットです。\u003Cbr>掃除に費やしていた時間だけでなく、その作業を意識することによる精神的なリソースも解放されたように感じます。\u003Cbr>筐体のサイズが大きいことも、猫が中で窮屈な思いをしないための快適性や、砂の飛び散りを高いレベルで防ぐという機能性を考えれば、十分に合理的な設計だと納得できました。\u003C/p>\u003Cp>しかしその一方で、特にソフトウェア面において、いくつかの看過できない点があるのも事実です。\u003C/p>\u003Cp>まず、スマホアプリの作り込みが、本体の完成度に比べてかなり甘いように感じられます。\u003Cbr>UIのデザインやi18n対応など、いくつか改善の余地があるように思えました。\u003C/p>\u003Cp>そして、APIが公開されていないことです。\u003Cbr>これこそが、この製品における個人的に最大の、そして最も残念に思う点です。 \u003Cbr>なぜ、APIを公開しないのでしょうか。\u003Cbr>もちろんアプリ上では確認することができますが、体重、トイレの回数、滞在時間のようなものは、猫の健康状態を把握する上でのかなり重要なメトリクスです。\u003Cbr>せめてWebhookにでも対応していれば、GASやWorkersなんかを介して、いろいろなことができるというのに、それすらも許されていない。\u003Cbr>結果として、わたしは毎日アプリを手動で起動し、自らの目でデータを確認するという、前時代的な運用を強いられています。\u003Cbr>この閉鎖的な仕様は非常に残念に感じます。ユーザーが自身のペットのデータをより自由に扱えるような設計思想であってほしかった、というのが正直なところです。\u003C/p>\u003Cp>また、アプリに基本的なオートメーション機能は備わっているものの、その設定が単純なものに限られている点も物足りなさを感じます。\u003Cbr>例えば、猫がトイレを出てから何分後に清掃を開始するか、といった設定は可能ですが、「夜間の特定の時間帯は動作を停止する」であるとか、「特定の条件下でのみ通知を送る」といった、ユーザーの生活スタイルに合わせた、より複雑なルール作りはできません。\u003Cbr>用意された選択肢を選ぶだけで、能動的なカスタマイズができないのは、少し窮屈に感じてしまう部分です。\u003Cbr>いい感じのAPIさえ用意されればすべて解決するんですけどね。\u003C/p>\u003Cp>加えて、データの精度にも少し疑問が残ります。\u003Cbr>モカちゃんがトイレの縁に少しだけ体重をかけた際に、別の猫として識別不能のログが記録されてしまうことがありました。\u003Cbr>センサーが取得したデータを解釈するアルゴリズムに、まだ改善の余地があることを示唆しているのかもしれません。\u003C/p>\u003Cp>このように、ソフトウェア面では改善を期待したい点がいくつかあります。\u003C/p>\u003Cp>しかし、そうした不満点を差し引いても、この製品を購入して後悔はありません。\u003Cbr>製品自体の品質は非常に高く、日々の負担から解放されたメリットは、それを遥かに上回ります。\u003C/p>\u003Cp>金で殴って心の余裕を生み出すのは、現代における合理的な選択肢の一つだと思います。\u003C/p>\u003Cp>このベンダからは自動給餌機や給水機も販売されているようですので、いずれはそちらも導入したいなーと思っています。\u003C/p>",[115,121],{"id":116,"createdAt":117,"updatedAt":118,"publishedAt":117,"revisedAt":118,"slug":119,"name":120},"zvbbh2k4o","2025-07-09T17:50:30.110Z","2025-12-03T16:06:32.163Z","cat-life","ネコのいる暮らし",{"id":122,"createdAt":123,"updatedAt":124,"publishedAt":123,"revisedAt":124,"slug":125,"name":126},"4oy2jc8mdg","2025-04-28T07:14:01.179Z","2025-12-03T16:08:24.495Z","diary","日記","1ヶ月ほど前にお迎えした猫(スコ♂, 8ヶ月齢)のモカちゃんが、かけがえのない癒やしとなっています。ただ、そんな愛猫との生活の中で一つだけ、どうしても気が重くなるタスクがありました。それは、毎日のトイレ掃除です。決められた手順を淡々と繰り返すだけのルーティンワークは、できれば機械に任せたい、と思うの",43,{"url":130,"domain":131,"title":132,"description":133,"image":134,"favicon":135,"type":45},"https://note.com/marjo/n/n9eec21c5623a","note.com","Fediverse:Activity Pub対応のリレーサーバーまとめ【2026年6月版】｜まるよ","Mastodon, Misskey, Pleroma, AkkomaなどActivityPub対応 日本語メインのリレーサーバーを紹介します。 リレーサーバーの解説はこちら。   NEW 2026/04/30 Netsune ActivityPub Relay   リレーサーバー一覧（敬称略）  YUKIMOCHI Toot Relay Service    Yukimochi (雪餅)主催のリレー    大規模総合リレー    参加の条件・審査あり    おたそーリレー    Otaku-Social (おたそー)主催のリレー    サブカル向けリレー    参加の条件・審査あり","https://assets.st-note.com/production/uploads/images/189535327/rectangle_large_type_2_0eb02d44f8cd0e8af7711166299ddd2f.png?fit=bounds&quality=85&width=1280","https://assets.st-note.com/poc-image/manual/note-common-images/production/svg/production.ico",{"url":137,"domain":94,"title":138,"description":139,"image":140,"favicon":98,"type":45},"https://github.com/team-shahu/misskey-backup","GitHub - team-shahu/misskey-backup: A tool for periodically backing up the Misskey PostgreSQL database and Redis.","A tool for periodically backing up the Misskey PostgreSQL database and Redis. - team-shahu/misskey-backup","https://opengraph.githubassets.com/c9d0e2f162da9ffafb0e2a8380664ad5b97b3a54a954c36f00a46a7cc831baa2/team-shahu/misskey-backup",{"url":142,"domain":143,"title":144,"description":145,"image":146,"favicon":147,"type":45},"https://scrapbox.io/defaultcf/Misskey%E3%81%A7%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E7%B5%B5%E6%96%87%E5%AD%97%E3%82%92%E4%B8%80%E6%B0%97%E3%81%AB%E5%85%A5%E3%82%8C%E3%82%8B","scrapbox.io","Misskeyでカスタム絵文字を一気に入れる - defaultcf's project","#Misskey https://misskey-hub.net/en/docs/admin/emoji.html#bulk-emoji-import ディレクトリに絵文字を入れる他に meta.json が必要になる JSON ファイルの構造は https://misskey-hub.net/en/docs/admin/emoji.html#packed-emoji-format つまりこんな感","https://scrapbox.io/assets/img/content-logo.png","https://scrapbox.io/assets/img/favicon/favicon.ico",{"url":149,"domain":62,"title":150,"description":151,"image":152,"favicon":153,"type":45},"https://resend.com/docs/send-with-smtp","Send emails with SMTP - Resend","Learn how to integrate Resend via SMTP.","https://resend.mintlify.app/_next/image?url=%2F_mintlify%2Fapi%2Fog%3Fdivision%3DSMTP%26title%3DSend%2Bemails%2Bwith%2BSMTP%26description%3DLearn%2Bhow%2Bto%2Bintegrate%2BResend%2Bvia%2BSMTP.%26logoLight%3Dhttps%253A%252F%252Fmintcdn.com%252Fresend%252Fw4S5Jr48MiquhhSH%252Flogo-black.svg%253Ffit%253Dmax%2526auto%253Dformat%2526n%253Dw4S5Jr48MiquhhSH%2526q%253D85%2526s%253D630be7deea6ea94cc7fc4560ea60a5ac%26logoDark%3Dhttps%253A%252F%252Fmintcdn.com%252Fresend%252Fw4S5Jr48MiquhhSH%252Flogo-white.svg%253Ffit%253Dmax%2526auto%253Dformat%2526n%253Dw4S5Jr48MiquhhSH%2526q%253D85%2526s%253D3843916235739ffb9cb1d24683221341%26primaryColor%3D%2523000000%26lightColor%3D%2523EBECED%26darkColor%3D%25230A0C10%26backgroundLight%3D%2523ffffff%26backgroundDark%3D%2523000000&w=1200&q=100","https://resend.com/docs/_mintlify/favicons/resend/nAzNk0iRWkZBBJ91/_generated/favicon/android-chrome-192x192.png",{"url":155,"domain":94,"title":156,"description":157,"favicon":98,"type":45},"https://github.com/alicerose/misskey-emoji-archive-generator","GitHub - alice37th/misskey-emoji-archive-generator: generate zip file contains meta.json from multiple emoji images","generate zip file contains meta.json from multiple emoji images - alice37th/misskey-emoji-archive-generator",{"url":159,"domain":160,"title":161,"description":162,"image":163,"favicon":164,"type":45},"https://tailscale.com/kb/1193/tailscale-ssh","tailscale.com","Tailscale SSH · Tailscale Docs","Use Tailscale SSH to manage the authentication and authorization of SSH connections in your tailnet.","https://tailscale.com/files/images/og-image.png","https://tailscale.com/favicon.png",{"url":166,"domain":94,"title":167,"description":168,"favicon":98,"type":169,"code":170,"startLine":171,"endLine":171},"https://github.com/sksat/compose-cd/blob/8cff99c98498d88b053dd934f08c045c70aa04c6/compose-cd#L359","compose-cd/compose-cd at 8cff99c98498d88b053dd934f08c045c70aa04c6 · sksat/compose-cd","Continuous Deployment for docker-compose. Contribute to sksat/compose-cd development by creating an account on GitHub.","GITHUB_PERMALINK","\tlocal_img=$(docker images --no-trunc --digests \"${img_location}\" --format '{{.Tag}} {{.ID}}' | grep \"$img_tag\")",359,{"url":173,"domain":94,"title":174,"description":175,"image":176,"favicon":98,"type":45},"https://github.com/team-shahu/shahu-docker-provision/commit/4e34a75ef19403715b17c501f3475c546cd91671#diff-facaded51b7d1c9656ae43b449b69aa398fee9129321a0001d97048c00c8cc1c","feat: compose-cdの追加とGitHub Actionsでのイメージ更新管理 · team-shahu/shahu-docker-provision@4e34a75","- compose-cdスクリプトとGitHub Actionsワークフローの追加\n- イメージ取得の問題を解決するためPRでバージョン管理","https://opengraph.githubassets.com/d23769603962579079cba28d29247c4b8214ccb4a82d8b3da87d67ee3564cbbd/team-shahu/shahu-docker-provision/commit/4e34a75ef19403715b17c501f3475c546cd91671",{"url":178,"domain":94,"title":167,"description":168,"image":179,"favicon":98,"type":169,"code":180,"startLine":181,"endLine":182},"https://github.com/sksat/compose-cd/blob/8cff99c98498d88b053dd934f08c045c70aa04c6/compose-cd#L122-L124","https://opengraph.githubassets.com/aad6cb98e81f22a2990934d4a170e1da443a9e12d6fcb967f919284a74f84ca2/sksat/compose-cd","\tif [ -z ${COMPOSE_IMPL+x} ]; then\n\t\tCOMPOSE_IMPL=\"docker compose\"\n\tfi",122,124,1783975278473]