【最終回】誰でもできる!自宅で始める分散型SNSサーバー構築 ─── Misskeyのセキュリティ対策、バックアップ方法、パフォーマンス向上、機能追加編【Misskey】

この記事は、 KENTEM TechBlog アドベントカレンダー2024 13日目、12月13日の記事です。

みなさんこんにちは! KENTEM第二開発部でフロントエンドを担当しているO・Aと申します😺

この記事では、一般家庭の要らなくなったPCを活用して、自宅で分散型SNS(Misskey)サーバーを構築する方法を、12/9~12/13の5日間に分けて、毎日丁寧に解説していきます。

シリーズ目次

  1. 第1回:分散型SNSとは何か? tech.kentem.jp
  2. 第2回:Ubuntuの環境構築手順 tech.kentem.jp
  3. 第3回:ドメイン取得とCloudflare Tunnelの設定 tech.kentem.jp
  4. 第4回:Misskeyのインストール tech.kentem.jp
  5. 最終回:Misskeyのセキュリティ対策、バックアップ方法、パフォーマンス向上、機能追加 ←本記事 tech.kentem.jp

今回は最終回の第5回:Misskeyのセキュリティ対策、バックアップ方法、パフォーマンス向上、機能追加編です。

misskey-hub.net



セキュリティ

まずはセキュリティ対策です。

IP隠匿→対策済み

まず、今回CDNを通しているのでIPは隠匿済みです。

実際に確認してみましょう。

whoisにSNSのドメインを入力して、IPv4アドレスを取得します。

www.cman.jp

取得できたアドレスを前の画面で入力して、実際に隠匿されているか確認しましょう。

結果はこうなりました。

NetNameやOrganizationがCloudflareになっており、きちんと隠匿されていることが分かりますね。


DDoS対策→対策済み

また、DDoS対策についても、今回はCDNを挟んでいるため問題ありません。

もしCDNを挟まずに立ち上げた場合は、DDoS対策として以下の記事が参考になります。

qiita.com

また、今回はCloudflare Tunnelを使っており SSH接続用のポートすら開放していないため、fail2banの必要性も薄いです。

fail2banとは?

サーバーのセキュリティ対策として広く使われているツールの一つで、主にログファイルを監視して不正なアクセス試行を検出し、一定回数以上の失敗したログイン試行があった場合に、そのIPアドレスからのアクセスを一時的にブロックするツールです。

例えば、SSHへの不正なログイン試行が3回失敗した場合にそのIPアドレスからの接続を10分間ブロックしたり、WordPressの管理画面への不正なログイン試行が5回失敗した場合に24時間ブロックしたりすることができます。

このツールの優れている点として、ブルートフォース攻撃(総当たり攻撃)からサーバーを効果的に保護できること、設定が比較的簡単であること、検出ルールとアクションをカスタマイズできること、そしてシステムリソースへの負荷が少ないことが挙げられます。

ただし、何らかの理由でCloudflare Tunnelが一時的に使えなくなった時に、直接SSHアクセスが必要になる可能性がなくもないので、念の為、fail2banの導入方法を解説している記事を下記にご紹介します。

seritude.com


Bot制御

インターネット上のWebサイトには、実際の人間がアクセスする場合と、ボット(自動プログラム)がアクセスする場合があります。

このボットによるアクセスの中には、スパムの投稿や不正なアカウント作成、サイトに負荷をかける攻撃など、悪意のある行為を目的としたものが含まれることがあります。

そのため、Webサイトを運営する上で、アクセスしてきたのが人間なのかボットなのかを区別する仕組みが必要になってきました。

この課題に対する従来の解決策として、CAPTCHA(キャプチャ)という仕組みが広く使われてきました。

これは例えば、歪んだ文字を読み取って入力したり、信号機が写った画像を選んだり、同じ種類の物が写った画像をすべて選んだりするなど、人間には比較的簡単にできるけれどもコンピュータには難しい課題を出すことで、アクセスしているのが人間かボットかを判断するシステムです。

しかし、この従来のCAPTCHAには大きな課題がありました。ユーザーにとって面倒で時間がかかる上、特にスマートフォンなどのモバイル端末では使いづらく、また視覚障害のある方にとっては利用が困難であるという問題がありました。

そこで注目されているのが、Cloudflareが提供する「Turnstile」です。

このシステムは、ユーザーが特別な操作をする必要がなく、多くの場合バックグラウンドで自動的に人間かボットかの判定を行います。 時にはクリックひとつで認証が完了することもあり、ユーザーの手間を大幅に削減することができます。

さらにTurnstileは、個人情報を収集せずに判定を行うためプライバシーにも配慮されており、Cloudflareの信頼性の高いネットワークを活用しています。

また、無料で利用可能で実装も比較的容易なため、個人のブログから大規模なウェブサービスまで、幅広いWebサイトで活用することができます。

では、早速導入していきましょう!

CloudflareからTurnstileを設定

以下のURLからCloudflareダッシュボードにアクセスします。

dash.cloudflare.com

左のメニューから「Turnstile」をクリックします。

「ウィジェットを追加」をクリックします。

「ウィジェット名」にTurnstileの名前を入力します。

misskey-turnstile」などで良いでしょう。

「+ホスト名の追加」をクリックします。

右に自分のドメインが出てくるので、チェックを入れて、右の「追加」を押し、下の「追加」も押します。

「ウィジェットモード」が「管理対象」になっていることを確認して、「作成」をクリックします。

Turnstileのサイトキーとシークレットキーが表示されます。

Misskey側で設定

新しいウィンドウを開き、自分のSNSのドメインを入力して管理者アカウントでログインします。

開いたら左のメニューから「コントロールパネル」をクリックします。

「設定」の「セキュリティ」をクリックします。

「Botプロテクション」から「Turnstile」を選択し、先程の「サイトキー」と「シークレットキー」を入力して、「保存」をクリックします。


バックアップ

PostgreSQLの中身をCloudflare R2というクラウドのバケットに定期的にバックアップするようにして、サーバーの可用性を高めましょう。

(PCがいつ壊れてもユーザー情報や投稿データが消えないように!)


Cloudflareにバケットを作成

ダッシュボードの左のメニューから「R2オブジェクトストレージ」をクリックします。

毎月10GBまでは無料です。

「R2サブスクリプションをアカウントに追加する」をクリックします。

「バケットを追加する」をクリックします。

バケット名を「misskey-backup」として、「バケットを作成する」をクリックします。

(ここでのバケット名は後ほどのシェルスクリプトでも使用するので、別名にする場合はシェルスクリプトの方でも「misskey-backup」から変更してください。)

「設定」をクリックします。

下の方にある「オブジェクトのライフサイクル ルール」の横の「ルールを追加」をクリックします。

無料範囲のストレージ枠に収まるように、バックアップした2週間後にデータを削除するように設定しましょう。

「ルール名」にいい感じの名前を付け、「ライフサイクル アクション」を14日に設定し、「変更内容を保存」をクリックします。

「misskey-backup」と入力して「変更内容を保存」をクリックします。


サーバー側の設定

コマンドプロンプトを開き、以下のコマンドを入力します。

sudo -i

sudo nano /usr/local/bin/misskey-backup.sh

nanoエディタが開いたら以下の内容を右クリックで貼り付けます。

これはPostgreSQLデータベースのバックアップを作成し、Cloudflare R2にアップロードするためのBashスクリプトです。

途中のmisskey-backup はオブジェクトストレージ名と統一しましょう。

「Ctrl+X」→「y」→「Enter」で保存します。

#!/bin/bash

#=========================================================
# PostgreSQLバックアップスクリプト
# 機能:
# - PostgreSQLデータベースの完全バックアップを作成
# - 7-Zipで圧縮
# - Cloudflare R2にアップロード
# 
# 前提条件:
# - root権限での実行
# - PostgreSQL, 7-Zip, Cloudflare Wranglerのインストール
# - misskeyユーザーの存在
#=========================================================

# バックアップ実行日時を取得 (YYYYMMDD形式)
TIME=$(date +%Y%m%d)

# バックアップ開始を通知
echo "Backup start."

# 一時ディレクトリに移動
cd /tmp

# PostgreSQLの完全バックアップを作成し、7zで圧縮
# - sudo -u postgres: postgresユーザーとして実行
# - pg_dumpall: 全データベースをダンプ
# - 7z a -si: 標準入力から7z形式で圧縮
sudo -u postgres pg_dumpall | 7z a -si db.7z

# バックアップファイルのパーミッション設定
# - 644: 所有者=読み書き可、グループ=読み取り可、その他=読み取り可
# - misskey:misskey: 所有者とグループをmisskeyに変更
chmod 644 db.7z
chown misskey:misskey db.7z

echo "Backup create."

# rootユーザーでの実行を確認
if [ "$(id -u)" -eq 0 ]; then
    # misskeyユーザーとしてCloudflare R2へのアップロードを実行
    su - misskey -c "
        echo 'Send backup file.'
        
        # Cloudflare R2にバックアップファイルをアップロード
        # - misskey-backup/: バックアップ用バケット
        # - db_YYYYMMDD.7z: タイムスタンプ付きファイル名
        npx wrangler r2 object put \"misskey-backup/db_$TIME.7z\" --file=/tmp/db.7z
        
        # 一時ファイルを削除してストレージ容量を節約
        rm /tmp/db.7z
        
        echo 'Backup complete.'
    "
else
    # root以外のユーザーで実行された場合はエラーメッセージを表示
    echo "This script must be run as root"
    exit 1
fi

以下のコマンドで実行権限を付与します。

sudo chmod +x /usr/local/bin/misskey-backup.sh

7zipをインストール

バックアップファイルをzip化するために7zipを入れます。

sudo apt update
sudo apt install p7zip-full

Cloudflare Wranglerをインストール

バックアップ用のシェルスクリプトでR2にアクセスするためにCloudflare Wranglerをインストールしましょう。

適宜Enterを押して進めていきましょう。

以下のターミナルの履歴を参考にしてください。

oa@oa-FMVS75EUV2:~$ sudo npm create cloudflare@latest
Need to install the following packages:
create-cloudflare@2.33.1
Ok to proceed? (y) y

> npx
> create-cloudflare

────────────────────────────────────────────────────────────────────────────────
👋 Welcome to create-cloudflare v2.33.1!
🧡 Let's get started.
📊 Cloudflare collects telemetry about your usage of Create-Cloudflare.

Learn more at: https://github.com/cloudflare/workers-sdk/blob/main/packages/create-cloudflare/telemetry.md
────────────────────────────────────────────────────────────────────────────────

╭ Create an application with Cloudflare Step 1 of 3
│
├ In which directory do you want to create your application?
│ **dir ./steep-cloud-34d2**
│
├ What would you like to start with?
│ **category Hello World example**
│
├ Which template would you like to use?
│ **type Hello World Worker**
│
├ Which language do you want to use?
│ **lang TypeScript**
│
├ Copying template files
│ **files copied to project directory**
│
├ Updating name in `package.json`
│ **updated `package.json`**
│
├ Installing dependencies
│ **installed via `npm install`**
│
╰ Application created 

╭ Configuring your application for Cloudflare Step 2 of 3
│
├ Installing @cloudflare/workers-types
│** installed via npm**
│
├ Adding latest types to `tsconfig.json`
│ **added @cloudflare/workers-types/2023-07-01**
│
├ Retrieving current workerd compatibility date
│ **compatibility date 2024-11-27**
│
├ Do you want to use git for version control?
│ **yes git**
│
├ Must configure `user.name` and user.email` to use git. Continuing without git.
│
╰ Application configured 

╭ Deploy with Cloudflare Step 3 of 3
│
├ Do you want to deploy your application?
│ **no deploy via `npm run deploy`**
│
╰ Done 

────────────────────────────────────────────────────────────
🎉  SUCCESS  Application created successfully!

💻 Continue Developing
Change directories: cd steep-cloud-34d2
Start dev server: npm run start
Deploy: npm run deploy

📖 Explore Documentation
https://developers.cloudflare.com/workers

🐛 Report an Issue
https://github.com/cloudflare/workers-sdk/issues/new/choose

💬 Join our Community
https://discord.cloudflare.com
────────────────────────────────────────────────────────────

npm notice
npm notice New patch version of npm available! 10.9.0 -> 10.9.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.9.1
npm notice To update run: npm install -g npm@10.9.1
npm notice
oa@oa-FMVS75EUV2:~$ 

Wranglerを設定して、Cloudflare R2にアクセスできるようにします。 以下のコマンドを叩きます。

wrangler login

するとブラウザが開かれるので、「Allow」をクリックします。

「You have granted authorization to Wranger!」と表示されたらタブを閉じて構いません。

クローンジョブ作成

定期的にバックアップを実行するために、クーロンジョブを設定します。

以下のコマンドを叩きます。

sudo crontab -e

すると以下のように聞かれます。

「1」と入力してEnterを押します。

Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.tiny
  3. /bin/ed

Choose 1-3 [1]: 1

nanoエディタが開かれるので、以下の行を追加して、毎日午前4時にバックアップを実行するようにします。

「Ctrl+X」→「y」→「Enter」で保存します。

0 4 * * * /usr/local/bin/misskey-backup.sh

これでバックアップの設定は終了です。


手動バックアップで確認

最後に、設定が正しく行われたか確認するために、手動でスクリプトを実行してみましょう。

sudo /usr/local/bin/misskey-backup.sh

ターミナルにURLが表示されるのでクリックして、OAuthを認証します。

Cloudflare R2の「オブジェクト」を確認して、きちんとファイルがアップロードされているか確認します。

サイズが数キロバイト以上あれば、バックアップが正常に行われた可能性が高いです。

おめでとうございます!


パフォーマンス

静的コンテンツ(画像、CSS、JavaScript等)をCDNにキャッシュさせることで、オリジンサーバーへのアクセスを削減したり、繰り返しのリクエストに対して高速なレスポンスが可能サイトのパフォーマンスを向上させることができます。

Misskey Hubによると、以下のように書かれています。

Misskey Webは、完全に静的であり、動作にサーバーを必要としません。したがってMisskey Web全体をCDNでキャッシュすることができます。 Misskey APIはキャッシュすることはできません。

misskey-hub.net

というわけで、サーバー負荷対策にCDNでキャッシュの設定をしましょう。


Cloudflareでキャッシュを設定

Cloudflareのダッシュボードから、ドメインをクリックします。

左のメニューから、「Caching」→「Cache Rules」をクリックします。

「ルールを作成」をクリックします。

「実行内容」で「キャッシュをバイパスする」を選択し、「受信リクエストが一致する場合」で「https://SNSのドメイン/api/*」を入力し、下の「展開」をクリックします。


サイトのパフォーマンス計測

では実際にパフォーマンスを計測していきます。

計測にはGoogleのPageSpeed Insightsを使います。

下のURLからアクセスします。

pagespeed.web.dev

自分のドメインを入力して「分析」をクリックします。

今回はパフォーマンス87点、ユーザー補助82点、おすすめの方法96点、SEO92点でした。

なかなか良いのではないでしょうか?


Misskeyに機能を追加する

さて、ここまででセキュリティ、バックアップ、パフォーマンスと一通りサーバー側の準備は整いました。

ここからは、デフォルトの状態のMisskeyに様々な機能追加を行っていきます。


ユーザ確認のためのメール送受信機能

アカウント登録時にメールアドレスを紐づけるための設定を行っていきます。

cloudflareのEmail settingを設定

Cloudflareダッシュボードからドメインをクリックします。

左のメニューから「メールアドレス」→「Email Routing」をクリックします。

「始める」をクリックします。

「開始をスキップする」をクリックします。

「宛先アドレス」タブを開き、「宛先アドレスを追加」をクリックします。

自分のメールアドレスを入力して「保存」をクリックします。

「Verify Email Routing address」のメールを開き、「Verify email address」をクリックします。

「Email Routingに移動する」をクリックします。

DNSレコードを追加

メールサーバー用にDNSレコードを設定します。

DNSレコードとは?

(DNSについて、詳しくは第3回を参照してください。)

DNSレコードは、ドメインに関する様々な情報を保存する設定項目で、インターネット上の「電話帳」のような役割を果たしています。

例えば、Webサイトにアクセスする時やメールを送信する時に、コンピュータはこのDNSレコードを参照して、どこにアクセスすれば良いのかを判断します。

代表的なDNSレコードとしては、ドメイン名とIPアドレスを紐付けるAレコード、メールサーバーの場所を指定するMXレコード、テキスト情報を保存するTXTレコード、あるドメインを別のドメインの別名として設定するCNAMEレコードなどがあります。

Misskeyでメール機能を設定する場合は、主にMXレコードとTXTレコードの設定が必要になります。MXレコードでメールサーバーの場所を指定し、TXTレコードでメールが正規のサーバーから送信されていることを証明します。

Cloudflareでは、Email Rountingを有効にすると、MXレコードとTXTレコード(SPF)を自動設定してくれます。

「Email Routingを有効にする」をクリックします。

次の画面の下に表示される青いボタンを押すと、DNSの設定は完了します。(すみません、ここだけスクショないです😿)

元の画面に戻り、Email Routingが有効になっていればOKです。

カスタムアドレスの作成

カスタムアドレスとは?

独自ドメインで使用するメールアドレスのことです。

例えば、あなたがドメイン「example.com」を持っているとすると、「info@example.com」や「contact@example.com」のように、@の後ろに自分のドメインを使用したメールアドレスを作成できる機能を指します。

これにより、一般的なGmailなどのアドレスではなく、より専門的で信頼性の高い印象を与えるメールアドレスを使用することができます。

「ルーティング ルール」タブ→「カスタムアドレス」→「アドレスを作成」をクリックします。

カスタムアドレスを作成します。

このアドレスからユーザーにメールが送られてきます。

「カスタムアドレス」と「宛先」を設定して、「保存」を押します。

Gmailと紐づけ

CloudflareのカスタムメールアドレスをGmailと紐づけます。

その理由としては、メールの実際の送受信処理をGmailのシステムに任せるためです。

仕組み:

カスタムアドレス(例:info@yourdomain.com)宛のメールを受信

Cloudflareが自動的にそのメールを紐づけたGmailアドレスに転送

返信時はカスタムアドレスから送信されているように見える

つまり、独自ドメインのメールサーバーを自分で構築・運用する手間を省き、Gmailの信頼性の高いインフラを利用しながら、見た目は独自ドメインのアドレスとして使えるという利点があります。

まずGoogleアカウントの2段階認証の設定から行います。

以下のURLから「2-Step Verification」を選択します。

myaccount.google.com

「Turn on 2-Step Verification」から2段階認証を行います。

2段階認証が完了したら、以下のURLからアプリパスワードを発行します。

myaccount.google.com

アプリ名は「misskey」などでよいでしょう。

入力したら「Create」をクリックします。

アプリパスワードが発行されます。

アプリパスワードは二度と表示されないので絶対にメモしておきましょう。

以下のURLからGmailを開きます。

mail.google.com

右上の歯車アイコンをクリックします。

「See all settings」をクリックします。

「Account and Import」タブから「Add another email address」をクリックします。

「Email address」欄に、先程Cloudflareで設定したメールアドレスを入力して、「Treat as an alias」にチェックを入れて、「Next Step」をクリックします。

SMTPサーバ:smtp.gmail.com

ユーザ名:Google にログインする際に利用するメールアドレス

パスワード:先ほど作成したアプリパスワード

を入力します。

アプリパスワード発行時は4桁ごとに空白が含まれますが、こちらの入力欄では空白を含めないようにしてください。(私はこれで1時間溶かしました…)

以下の画面が表示されたらGmailを開きます。

メールがGmailに届いているので、真ん中のリンクをクリックします。

「Confirm」をクリックしたらOKです。

Misskey側でメールを設定

最後に、Misskeyのコントロールパネルを開き、「メールサーバーの設定がされていません。」から「設定する」をクリックします。

「メール配信機能を有効化する(推奨)」にチェックを入れて、以下のように設定し、「保存」をクリックします。

メールアドレス:Cloudflareで設定したメールアドレス

ホスト:smtp.gmail.com

ポート:465

ユーザー名:googleアカウントの@gmail.comより前の部分(example@gmail.comならexampleの部分)

パスワード:先ほどメモしたアプリパスワード

SMTP接続に暗黙的なSSL/TLSを使用する:オン

先程の画面の「配信テスト」をクリックして、実際にメールが来るかどうか確かめてみましょう。

以下のようなメールが来ていれば完了です。

おめでとうございます!

これでアカウント登録時にメールアドレスを義務付けることが可能になりました。


プッシュ通知機能

publicキーとprivateキーを生成

Web-push用の秘密鍵と公開鍵を作ります。 ターミナルを開き、以下のコードを貼り付けます。

npx web-push generate-vapid-keys

Public KeyとPrivate Keyが生成されるので、メモしておきます。

Misskeyにキーを登録

Misskeyの「コントロールパネル」を開き、「全般」→「ServiceWorker」の「ブラウザへのプッシュ通知を有効にする」にチェックを入れます。

先程のPublic KeyとPrivate Keyを入力して「保存」をクリックします。

これでプッシュ通知が設定されたので、後述のスマホアプリ化した際にも通知が来るようになりました。

やったね!


ノート翻訳機能(DeepL)

以下のURLにアクセスし、「DeepL API Free」の「無料で登録する」をクリックします。

www.deepl.com

メールアドレス、パスワード、住所等を入力すると、DeepLのAuth APIキーを取得できます。

Authキーが取得出来たら、Misskeyの「コントロールパネル」→「設定/外部サービス」→「DeepL Translation」にAuthキーを入力して、保存しましょう。


fediverseと繋がる場合、リレー追加

(社内SNS等 closedな環境にする場合を除き、)fediverseに参加したい場合は、リレーサーバーに参加することで接続できます。

リレーサーバーとは?

異なるfediverseサーバー間の投稿やコンテンツを効率的に共有・伝播させる中継サーバーです。

たとえば、MisskeyインスタンスAの投稿をインスタンスB、C、Dに配信する場合、リレーサーバーを使用しないと個別に3回通信が必要ですが、リレーサーバーを使えば1回の通信で済みます。

これにより、ネットワークの負荷が軽減され、より効率的な情報の伝播が可能になります。

また、ユーザーにとっても、自分のインスタンスが直接フォローしていないサーバーの投稿をリレーサーバーを通じて見ることができるため、コンテンツの発見性が向上するというメリットがあります。

以下のリレーサーバー一覧から、参加したいリレーサーバのリンクを取得します。

hisubway.online

Misskeyの「コントロールパネル」→「設定/リレー」→「+リレーの追加」をクリックします。

リレーのURLを入力して「OK」をクリックしましょう。

この後、リレーサーバー側が参加を許可すれば、参加できます。


プロキシアカウント追加

プロキシアカウントとは?

SNSを利用するユーザーが異なるサーバー上のユーザーをリストに入れた際に投稿を取得・表示するための特別なアカウントです。

通常、他サーバーのユーザーをリストに追加しても、そのユーザーをフォローしているアカウントがサーバー内に存在しない場合、投稿は表示されません。

しかし、プロキシアカウントがリストに追加された他サーバーのユーザーを自動的にフォローすることにより、ユーザーは個別にフォロー操作を行う必要がなく、リストへの追加だけで他サーバーのユーザーの投稿を確実に取得することができます。

左下の「アカウント作成」からプロキシユーザー用のアカウントを作成します。

ユーザー名は何でも構いませんが、プロキシアカウントであることが明らかであるユーザー名が良いでしょう。

プロキシアカウントが作成できたら、そのアカウントで何らかの投稿を行います。

これは、次のステップでアカウントを選択するときに候補に出すためです。

管理者アカウントに移動し、「コントロールパネル」→「設定/全般」→「プロキシアカウント」の「アカウントを選択」をクリックします。

「ユーザー名」にプロキシ用で作成したユーザー名を入力して、プロキシアカウントを選択した後、右上の「✔」をクリックします。

プロキシアカウントとしてアカウント名が表示されていれば成功です。


テーマ色変更

「コントロールパネル」→「全般/ブランディング」 → 「サーバーデフォルトのライトテーマ/サーバーデフォルトのダークテーマ」から変更できます。

ページテーマはJSON形式で入力します。

配色に悩んだ場合は、以下のサイトが参考になるかもしれません。

assets.misskey.io

以下はテーマの一例です。

ライトテーマ

{
  "id": "vivid-yellow",
  "name": "Mi Vivid Yellow",
  "author": "oa",
  "base": "light",
  "props": {
    "bg": "#fafafa",
    "fg": "#444",
    "cwBg": "#b1b9c1",
    "cwFg": "#fff",
    "link": "#E6BE00",
    "warn": "#ecb637",
    "badge": "#FDD000",
    "error": "#ec4137",
    "focus": ":alpha<0.3<@accent",
    "navBg": "@panel",
    "navFg": "@fg",
    "panel": "#fff",
    "accent": "#FDD000",
    "header": ":alpha<0.7<@panel",
    "infoBg": "#FFF8E1",
    "infoFg": "#6D5E1E",
    "renote": "@accent",
    "shadow": "rgba(0, 0, 0, 0.1)",
    "divider": "rgba(0, 0, 0, 0.08)",
    "hashtag": "#D4B000",
    "mention": "@accent",
    "modalBg": "rgba(0, 0, 0, 0.3)",
    "success": "#86b300",
    "buttonBg": "rgba(0, 0, 0, 0.05)",
    "acrylicBg": ":alpha<0.5<@bg",
    "cwHoverBg": "#bbc4ce",
    "indicator": "@accent",
    "mentionMe": "@mention",
    "messageBg": "@panel",
    "navActive": "@accent",
    "infoWarnBg": "#fff0db",
    "infoWarnFg": "#573c08",
    "navHoverFg": ":darken<17<@fg",
    "dateLabelFg": "@fg",
    "inputBorder": "#dae0e4",
    "panelBorder": "rgba(0, 0, 0, 0)",
    "panelShadow": " 0 8px 24px rgb(21 43 75 / 8%)",
    "accentDarken": ":darken<10<@accent",
    "acrylicPanel": ":alpha<0.5<@panel",
    "navIndicator": "@accent",
    "accentLighten": ":lighten<10<@accent",
    "buttonHoverBg": "rgba(0, 0, 0, 0.1)",
    "driveFolderBg": ":alpha<0.3<@accent",
    "fgHighlighted": ":darken<3<@fg",
    "fgTransparent": ":alpha<0.5<@fg",
    "panelHeaderBg": ":lighten<3<@panel",
    "panelHeaderFg": "@fg",
    "htmlThemeColor": "@bg",
    "panelHighlight": ":darken<3<@panel",
    "listItemHoverBg": "rgba(0, 0, 0, 0.03)",
    "scrollbarHandle": "rgba(0, 0, 0, 0.2)",
    "wallpaperOverlay": "rgba(255, 255, 255, 0.5)",
    "fgTransparentWeak": ":alpha<0.75<@fg",
    "panelHeaderDivider": "@divider",
    "scrollbarHandleHover": "rgba(0, 0, 0, 0.4)",
    "X2": ":darken<2<@panel",
    "X3": "rgba(0, 0, 0, 0.05)",
    "X4": "rgba(0, 0, 0, 0.1)",
    "X5": "rgba(0, 0, 0, 0.05)",
    "X6": "rgba(0, 0, 0, 0.25)",
    "X7": "rgba(0, 0, 0, 0.05)",
    "X8": ":lighten<5<@accent",
    "X9": ":darken<5<@accent",
    "X10": ":alpha<0.4<@accent",
    "X11": "rgba(0, 0, 0, 0.1)",
    "X12": "rgba(0, 0, 0, 0.1)",
    "X13": "rgba(0, 0, 0, 0.15)",
    "X14": ":alpha<0.5<@navBg",
    "X15": ":alpha<0<@panel",
    "X16": ":alpha<0.7<@panel",
    "X17": ":alpha<0.8<@bg"
  }
}

ダークテーマ

{
  "id": "dark-vivid-yellow",
  "name": "Mi Vivid Yellow Dark",
  "author": "oa",
  "base": "dark",
  "props": {
    "bg": "#111111",
    "fg": "#dddddd",
    "cwBg": "#687390",
    "cwFg": "#ffffff",
    "link": "#E6BE00",
    "warn": "#ecb637",
    "badge": "#FDD000",
    "error": "#ec4137",
    "focus": ":alpha<0.3<@accent",
    "navBg": "@panel",
    "navFg": "@fg",
    "panel": "#1a1a1a",
    "accent": "#FDD000",
    "header": ":alpha<0.7<@panel",
    "infoBg": "#2C2815",
    "infoFg": "#E6BE00",
    "renote": "@accent",
    "shadow": "rgba(0, 0, 0, 0.3)",
    "divider": "rgba(255, 255, 255, 0.1)",
    "hashtag": "#D4B000",
    "mention": "@accent",
    "modalBg": "rgba(0, 0, 0, 0.5)",
    "success": "#86b300",
    "buttonBg": "rgba(255, 255, 255, 0.05)",
    "acrylicBg": ":alpha<0.5<@bg",
    "cwHoverBg": "#4C5164",
    "indicator": "@accent",
    "mentionMe": "@mention",
    "messageBg": "@panel",
    "navActive": "@accent",
    "infoWarnBg": "#42371D",
    "infoWarnFg": "#FFB84D",
    "navHoverFg": ":lighten<17<@fg",
    "dateLabelFg": "@fg",
    "inputBorder": "#333333",
    "panelBorder": "rgba(255, 255, 255, 0)",
    "panelShadow": "0 8px 24px rgb(0 0 0 / 25%)",
    "accentDarken": ":darken<10<@accent",
    "acrylicPanel": ":alpha<0.5<@panel",
    "navIndicator": "@accent",
    "accentLighten": ":lighten<10<@accent",
    "buttonHoverBg": "rgba(255, 255, 255, 0.1)",
    "driveFolderBg": ":alpha<0.3<@accent",
    "fgHighlighted": ":lighten<3<@fg",
    "fgTransparent": ":alpha<0.5<@fg",
    "panelHeaderBg": ":darken<3<@panel",
    "panelHeaderFg": "@fg",
    "htmlThemeColor": "@bg",
    "panelHighlight": ":lighten<3<@panel",
    "listItemHoverBg": "rgba(255, 255, 255, 0.03)",
    "scrollbarHandle": "rgba(255, 255, 255, 0.2)",
    "wallpaperOverlay": "rgba(0, 0, 0, 0.5)",
    "fgTransparentWeak": ":alpha<0.75<@fg",
    "panelHeaderDivider": "@divider",
    "scrollbarHandleHover": "rgba(255, 255, 255, 0.4)",
    "X2": ":lighten<2<@panel",
    "X3": "rgba(255, 255, 255, 0.05)",
    "X4": "rgba(255, 255, 255, 0.1)",
    "X5": "rgba(255, 255, 255, 0.05)",
    "X6": "rgba(255, 255, 255, 0.15)",
    "X7": "rgba(255, 255, 255, 0.05)",
    "X8": ":lighten<5<@accent",
    "X9": ":darken<5<@accent",
    "X10": ":alpha<0.4<@accent",
    "X11": "rgba(255, 255, 255, 0.1)",
    "X12": "rgba(255, 255, 255, 0.1)",
    "X13": "rgba(255, 255, 255, 0.15)",
    "X14": ":alpha<0.5<@navBg",
    "X15": ":alpha<0<@panel",
    "X16": ":alpha<0.7<@panel",
    "X17": ":alpha<0.8<@bg"
  }
}

KENTEMのブランドカラーであるRGB | R253 G208 B0をアクセントカラーとして使用してみました!😸

brand.kentem.jp

KENTEMのブランドカラー

その他のモデレーション方法

XServer様が細かい設定方法をまとめてくださっているので、そちらが参考になります。

sns.xserver.ne.jp


サイト公開!

ここまでくれば、サイトを第三者に公開してかまいません。

おめでとうございます!!!

本当に長い道のりでしたね……!お疲れ様でした!

一国一城の主として、あなたらしいSNS運営を楽しんでください!🌟


スマホアプリとして使う方法(PWA)

Misskeyはアプリ化(PWA)に対応しています。

以下にスマホアプリとして使用する方法をご紹介します。

ここではSafariでの追加方法をご紹介します。

アプリ化

まず、スマートフォンのブラウザでSNSを開きます。

「ホーム画面に追加」を選択します。

スマートフォンに追加されました。

通知を有効にする

アプリを開いてログインします。

メニューから「設定」→「通知」を選択します。

「プッシュ通知を有効化」を押して通知をONにしましょう。

外出先でも快適SNS生活を送っちゃいましょう🐱


まとめ ──「つながる未来」

この長い長い、10万字弱のシリーズを最後までお読みいただき、ありがとうございました!


本シリーズを通じて、単なる技術的な手順の解説以上のものをお届けしたいと考えていました。

それは、差別や分断や怒りやエコーチェンバーに満ちた負のインターネットからの開放、そして、「インターネットの未来は私たち一人一人の手の中にある」という希望です。


かつて、インターネットは分散型のネットワークとして設計されました。

この設計思想は、1974年にVint CerfとBob Kahnによって提案されたTCP/IPプロトコルに具現化されています。 単一の制御点を持たない分散型アーキテクチャにより、システム全体の耐障害性と拡張性を確保することが意図されていました。

1990年代から2000年代初頭にかけて、個人のホームページや電子掲示板(BBS)が普及しました。

2000年前後には、情報共有の新たな手段としてRSS(Really Simple Syndication)が登場し、ブログの普及とともに広く採用されていきました。

この時期、技術的な知識があれば誰でも自分のサーバーを運営し、比較的対等な立場でインターネット上のコミュニケーションに参加できる環境が整っていました。

しかし、2000年代後半から状況は大きく変化します。Facebook(2004年設立)やTwitter(2006年設立)をはじめとする中央集権型のソーシャルメディアプラットフォームが台頭し始めました。

これらのプラットフォームは、使いやすいインターフェースと強力なネットワーク効果により、急速にユーザーベースを拡大していきました。

2020年代に入ると、この集中化傾向はさらに顕著になります。

主要なソーシャルメディアプラットフォームは、独自のアルゴリズムを用いてコンテンツの表示や配信を制御するようになっています。

これらのアルゴリズムの詳細な仕組みは一般には公開されておらず、コンテンツの可視性や配信範囲は、各プラットフォームの方針とルールによって大きく左右される状況となっています。

かつてのオープンで分散的なウェブの特徴だった自由な情報発信と共有の場は、現在では、特定のプラットフォーム企業が提供する管理された空間へと性質を変えつつあるのです。


そして、このガイドで学んだ知識と技術は、その流れを変えるための第一歩です。

家庭やオフィスで眠りについていたパソコンたちは、もはや机上の飾りではありません。

それらは今、世界を結ぶ星々となり、あなたの想いを運ぶ小さな灯台として、遠く離れた誰かの港を照らすことでしょう。


自前のサーバー運営には確かに多くの課題が伴います。

日々のシステム安定性の維持や、増加するサイバー攻撃に対するセキュリティ対策の実施が必要です。

また、定期的なソフトウェアアップデートやリソース管理、パフォーマンスの最適化など、継続的な技術的対応も求められます。

さらに、貴重なデータを守るためのバックアップ体制の構築と、万が一の際の復旧対策も欠かせません。

公開するサーバーの運営はきっと楽しい事ばかりではなく、時に、昏い海を孤独に航海するかのように感じると思います。

しかし、これらの課題に対しては、すでに多くの解決策と知見が蓄積されています。

Fediverseでは、技術者たちが活発に情報交換を行い、互いにサポートし合うコミュニティを形成しています。

技術的な問題に直面したとき、このコミュニティの存在は大きな支えとなるでしょう。

忘れないでください。この広い広いFediverseの海原には、同じ志を持つ仲間たちが、それぞれの灯台を輝かせながら待っています。

そして、あなたが今回立ち上げたサーバーもまた、誰かにとっての まばゆい希望の光となるはずです。


あなたのこれからの航海が、実り多きものとなることを心より願っています。

Fediverseの海原で、またお会いましょう。では。



おわりに

最後まで読んでいただいた方に向けて、KENTEMの採用情報のご紹介です👇
KENTEMでは、様々な拠点でエンジニアを大募集しています!

・ICTの力で、建設業の「3K」を解決し、働く人に安心安全を届けたい。

・ KENTEMユーザーの現場の方々が、残業規制内に仕事が終わるようにして、18時には家族で食卓を囲めるようにしたい。

・建設業を支えることで、社会全体を「さまざまなリスクに強い安心・安全な場所」に変えていきたい。

このような理念を掲げて我々は働いております。

建設×ITにご興味頂いた方は、是非下記のリンクからご応募ください!😺
recruit.kentem.jp career.kentem.jp



参考文献

ischool.co.jp

www.cman.jp

seritude.com

qiita.com

zenn.dev

blog.adglobe.co.jp

note.com

misskey-hub.net

pagespeed.web.dev

web.archive.org

hide.ac

zenn.dev

sns.xserver.ne.jp

qiita.com

assets.misskey.io

misskey-doc.7ka.org

note.com

www.itmedia.co.jp