お知らせ

現在サイトのリニューアル作業中のため、表示が崩れているページが存在することがあります。
投稿日:ジャンル::サイト運営

Google Analyticsを廃止してMatomoを導入してみたから一ヶ月が過ぎ去っていたので簡単に集計をまとめてみる。

集計内容

8月17日~9月16日の30日間で自分のIPを除くMatomoの集計結果を出している。今回記事にする対象サイトはこのブログのみ。

主な指標

指標 数値
ページビュー 2,337
ユニークページビュー 2,074
ビジット 1,983
平均滞在時間 1分17秒
バウンス率 80%

ビジットが何なのかについては正直よくわかっていない。PVでもUVでもない概念なのは確かだが、Matomo内の数値は大抵これがベースである。30分以内にもう一度ページを訪れたユーザーと解釈しようにも直帰率80%である以上、直帰して別経路でアクセスされないとカウントされない気がするので謎。ほとんどのユーザーがタブを開きなおしているとか、そんなことはないと思う。

バウンスは直帰率のことらしい。

IPv6対応状況

これはIPv6に対応しているアクセスの数で、IPv6に対応しているがIPv4でアクセスしてきているユーザーは「IPv6対応ユーザー」にカウントしている。

集計方法としてはAAAAレコードを持つドメインに対しJSでfetchし、200OKが出たら対応、それ以外は非対応としている。この関係で、JS非対応ユーザーは集計から外れてしまい「IPv6対応状況不明ユーザー」になっている。

指標 ビジット
IPv6対応ユーザー 886 (37.9%)
IPv6非対応ユーザー 1,079 (46.2%)
IPv6対応状況不明ユーザー 372 (15.9%)

IPv6対応状況不明ユーザーをBOTと仮定した場合、IPv6対応は45.1%で非対応は54.9%となる。およそ半数弱がIPv6に対応した環境でアクセスしていることがわかる。

アクセスページ、上位10位

なぜかここはビジットではなく、PVとUVの表現だった。PVのみ記載する。

OSバージョン別、上位10位

指標 ビジット
Windows 11 924 (46.6%)
Windows 10 293 (14.8%)
iOS 18.6 203 (10.2%)
Mac 15.6 79 (4.0%)
Android 15.0 74 (3.7%)
Mac 10.15 58 (2.9%)
iOS 18.5 54 (2.7%)
Android 16.0 37 (1.9%)
Android 13.0 24 (1.2%)
Android 14.0 23 (1.2%)

概ねWindowsユーザーからのアクセスが多いが、iOS, Mac系のアクセスも無視できない程度にあるようだ。

OS種類別

バージョンやディストリの差異を束ねたもの。

指標 ビジット
Windows 1,217 (61.4%)
iOS 299 (15.1%)
Mac 216 (10.9%)
Android 212 (10.7%)
Linux 37 (1.9%)
Chrome OS 2 (0.1%)

Androidユーザーが少ない…。地味にLinuxやChrome OSもあった。

ブラウザ種類別、上位10位

バージョンは束ねている。

指標 ビジット
Chrome 835 (42.1%)
Microsoft Edge 483 (24.4%)
Mobile Safari 209 (10.5%)
Chrome Mobile 163 (8.2%)
Firefox 96 (4.8%)
Brave 44 (2.2%)
Safari 41 (2.1%)
Chrome Mobile iOS 33 (1.7%)
Yahoo! Japan 23 (1.2%)
Google Search App 22 (1.1%)

意外とEdgeのアクセスが多く、個人的にはうれしい。変わり種ではIronやSleipnir, Operaも見られた。

流入元検索エンジン

指標 ビジット
Google 1285 (75.9%)
Bing 257 (15.2%)
Yahoo! Japan 125 (7.4%)
DuckDuckGo 17 (1.0%)
楽天 5 (0.3%)
ニフティ 2 (0.1%)
Brave 1 (0.1%)
Perplexity 1 (0.1%)

地味にBingからの流入が多い。ちなみにこのブログはBingのほうがヒットしやすい。

バックリンク

バックリンク元 備考
adiary official website adiary利用者のページだと思われる
block.opendns.com AdBlocker的な奴の登録場所っぽい?
X 旧Twitter
tgadfs01.toshiba.co.jp 東芝の社内SNSか何か?
dメニュー たぶんdメニューにある検索からの流入
Inoreader – Build your own newsfeed RSSリーダーを使ってこのサイトを読んでいる人がまさか…!?
133.167.8.98 どこかのさくらのレンタルサーバーのIPっぽい。RSSリーダーかな?
Adventar アドベントカレンダーに登録しているので多分その関係
あずきインターネット Azukiという方のMisskeyインスタンス
hatenablog-parts.com はてなブログのブログカードらしい
教えて!goo 質問サイト。今月でサービス終了らしい
Perplexity AI検索エンジン
statics.teams.cdn.office.net どこかの企業ドキュメントからの参照と思われる
ただ、安らかに... adiaryユーザーさん。adiary利用者のページに載せてないタイプの人
@noemi.sakura.ne.jp adiaryユーザーさん。Matomoからは確認できなかったが、被リンクを受けていたので掲載(adiary利用者のページを眺めていて気が付いた)

国内都市別アクセス

基本的に人口比そのままだと思われる。

期間内のアクセスグラフ

日別

昔からそうだが、基本的に平日に伸び、週末や祝日に下がる傾向がある。開発係記事の割合が高いので、恐らく業務中に見られることが多いのだろう。

時間別

業務時間中にアクセスが伸び、通退勤や昼休みには減っているように見える。

雑感

Google Analyticsを使っていたころはUIと動作の重さで、ここまで細かく見る気さえ起きなかったが、MatomoはUIが良く動きも機敏なため、こういったことがしやすいのがいい。事実ほぼ毎日見ているくらいだ。GAのころは年に一回見るかどうか位だった。

何より自分のアクセスが普通に弾けるので、ノイズが減るのもいい。GAでもはじく方法はあるにはあるが、全てのデバイスで無設定に弾くというのは不可能に近いし、設定しても何故か弾けなかったりして困ることが多かった。オプトアウトする拡張機能はほかのサイトにとって迷惑そうなので入れたくなかったし、そもそもスマホでは入れる手段もない。

今回の集計では前回のサーバーログベースの集計を大きく覆す結果が出たのもあり、かなり満足している。

関連記事

集計手法がすべて異なるので単純比較できないが、時期によって順位に変動があることがわかる。

投稿日:ジャンル::サイト運営

adiary組み込みのLightbox2で画像をズームできないことに不満があり、代替を探していてFancyboxという非常に素晴らしい画像スライドツールを見つけたのだが、なんと有料で頭を抱えてしまった。

そこで何とかして無料で同等の機能を実現する方法がないか調べてみた。結論としてはFancybox v3.5.7を使えばよい。

欲しいもの

  • 複数ギャラリー対応
  • ギャラリーグループの識別が要素単位で可能
    • 親タグでグループ化する方式はNG
  • ドラッグ・スワイプで前後の画像に切り替えられる
  • 違和感なく前後の画像に切り替えられる
    • Mastodonみたいに切り替えしようとして閉じない
    • UIがガタついて戻ってきたりしない
  • キーボード操作をサポート
  • 画面サイズより小さい画像は原寸表示
  • 画面サイズより大きい画像はアスペクト比を保って縮小
  • 縮小した画像をクリック・タップすると拡大・縮小
  • 拡大してはみ出た画像をドラッグ可能
  • 拡大した画像をドラッグした時に画面から逸脱しない
  • 自動でキャプションが出せる
  • 非商用利用であれば無料
  • 力業で再現させるようなコードが不要

ライブラリ別まとめ

凡例
✅:要件を完全に満たす
⚠️:要件は満たさないが、類似機能がある
❌:要件を満たさない
➖:調べていない

基本的に設定を書くだけか、簡単なスクリプトで実現できるもののみ要件を満たすものとして定義している。また明らかに機能不足で興味が余り湧かなかったものは深く調べていないので情報が間違っている可能性がある。

機能 Lightbox2 GLightbox PhotoSwipe Viewer.js Spotlight.js lightGallery Fancybox v6 Fancybox v3.5.7
クリック・タップで拡大・縮小 ⚠️
複数ギャラリー対応
ギャラリーの識別が要素単位で可能
ドラッグ・スワイプで前後の画像に切り替えられる
違和感なく前後の画像に切り替えられる
キーボード操作のサポート
画面サイズより小さい画像は原寸表示
画面サイズより大きい画像はアスペクト比を保って縮小
拡大してはみ出た画像をドラッグ可能
拡大した画像をドラッグした時に画面から逸脱しない
自動でキャプションが出せる ⚠️
非商用利用無料
複雑なコードが不要 ⚠️

各ライブラリを触ってみた雑感

Lightbox2

拡大機能がないため論外。

GLightbox

画像を開いてからウィンドウを縮小したときにズームできないのが最大の難点。またこのブログに埋め込んだ時、ドラッグで画像を左右に送ろうとしたら妙なガタツキが見られた。

また画像をドラッグすると画面外まで飛んでいくのも、あまり良くない。

理想 現実

他にもUIがカスタマイズ可能なのはいいが、逆に面倒である。

PhotoSwipe

全体的にコールバック関数にフックして自前で実装する要素が色濃く、実装の手間が甚大にかかる。

Lightbox2にあるようなdata-lightbox=<gallary-id>を使ったギャラリーのグループ化が困難で、フルスクラッチでコードを書く必要があるが、Claude Opus 4.1とGPT-5に書かせて上手く行かなかったので諦めた。

lightGallery

一見するとよさそうだが、有料なので論外。

画像切り替え時にロードが入ることや、ドキュメントが読みづらく何が出来るのかイマイチ判らなかったのもマイナス。

Viewer.js

UIが独特的過ぎてみた瞬間論外だったが一応…。

PCではクリック・ドラッグで画像送りできないのがマイナスで、スマホではタップ・スワイプで可能という新しいアプローチが採用されており、開いた画像は画面内のどこにも自在配置できる機能もあった。

要するに完全に要件外だった。

Spotlight.js

アスペクト比によって画像が見切れるほか、小さい画像が全画面表示されて見づらかった。

adiaryの痒い所をちょこちょこ直している。上の画像にはないがCtrl + Vでクリップボードの画像をアップロードできる機能も付けている。

変更差分はもっぱらGitHubで管理していて、今日も最新版に追従させたところだ。

最近はOGPを強制出力するようにしたり、今日はSyntax HighlightをPrism.jsに置き換えるなどしていた。

adiaryはDiscordのようにChromeに詐称してくるBOT相手だとOGPが出ないし、標準のSyntax Highlightはしょっぱい。

比較用に元のやつを撮っておくのを忘れてしまったが、正直かなり良くなったと思う。

スマホで見たときに行折れせずスクロールできるようになったのも良い。

投稿日:ジャンル::サイト運営

定期的に見直しをかけているトップページだが、また変えたのでその記録。

変更前

縦一列びよーんって感じ。

変更後

フルサイズ

横に並べられるやつは横に並べてみた感じ。

タブレットサイズ?

下段が縦になる。

SPビュー

リンク集が二列になる。

まとめ

以前より一覧性がよくなった気がする。少なくとも私は自分の持つ各リソースへのアクセスが楽になり、ブックマークとして有効に機能しているので便利に感じている。

過去の見直しログ

7月31日に立てたMastodon作成ロードマップの最後である、自宅サーバーでMastodonをセルフホスティングするのを達成したので、そのログをここに記す。

Ubuntu実機AMD64環境でDockerを使わず、IPv6シングルスタックで構成している。

自宅サーバーを使ってIPv6シングルスタックで通信を待ち受ける方法はOCNバーチャルコネクト環境でIPv6サーバーをポート443で公開した時にやったことの方に書いている。

確認環境

Ubuntu実機AMD64環境

Env Ver
Ubuntu 24.04.3 LTS
nginx 1.26.1
Mastodon v4.4.3
Ruby 3.2.3
ruby-build 20250811
rbenv 1.3.2-10-gd1a19a3

前提条件

事前準備

  1. 公開用のドメインを検討し、生み出す
  2. Value Domainのコンパネから生み出したドメインをAAAAレコードで登録
  3. 拙作の@lycolia/value-domain-dns-cert-registerを使ってTLS証明書を発行

依存関係のインストールとセットアップ

  1. 以下のコマンドを流す

    sudo apt update
    
    sudo apt install -y \
        imagemagick ffmpeg libvips-tools libpq-dev libxml2-dev libxslt1-dev file git-core \
        g++ libprotobuf-dev protobuf-compiler pkg-config gcc autoconf \
        bison build-essential libssl-dev libyaml-dev libreadline6-dev \
        zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev \
        nginx redis-server redis-tools postgresql \
        certbot python3-certbot-nginx libidn11-dev libicu-dev libjemalloc-dev \
    
    # 最新版を入れないとうまくいかない
    wget https://github.com/rbenv/ruby-build/archive/refs/tags/v20250811.tar.gz
    tar -xzf v20250811.tar.gz
    sudo PREFIX=/usr/local ./ruby-build-20250811/install.sh
    rm v20250811.tar.gz
    rm -Rf ruby-build-20250811
    
    # aptではサポート切れの化石が入るのとnvmで入れたのは自分しか使えないので新しいのをグローバルに入れる
    curl -fsSL https://deb.nodesource.com/setup_24.x -o nodesource_setup.sh
    sudo bash nodesource_setup.sh
    apt install -y nodejs
    rm nodesource_setup.sh
    corepack enable
    
    # メンテナンスでめっちゃ使うのでサービスユーザーにはせず、ログイン可能なユーザーとして作る
    adduser --disabled-password mastodon
    
  2. /etc/redis/redis.confを開きrequirepassのコメントを外し、パスワードを設定

  3. sudo service redis restart

  4. sudo -u postgres psqlでポスグレに入り、ユーザーを作る。ポスグレは不慣れで同時にPW設定する方法が判らなかったので別建てで設定している
    CREATE USER mastodon CREATEDB;
    ALTER ROLE mastodon WITH PASSWORD 'パスワード';
    \q
    

Mastodon本体のセットアップ

実際にはかなり行ったり来たりしてるので一部の手順には誤りが含まれている可能性がある。

  1. mastodonユーザーにスイッチしてインストール作業を続行

    # Mastodon本体の導入
    sudo su - mastodon
    git clone https://github.com/mastodon/mastodon.git live
    # 超重要、cd忘れててもなんかそれっぽく進むが、以後すべて破綻する
    cd live
    git checkout $(git tag -l | grep '^v[0-9.]*$' | sort -V | tail -n 1)
    
    git clone https://github.com/rbenv/rbenv.git ~/.rbenv
    
    echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
    echo 'eval "$(rbenv init -)"' >> ~/.bashrc
    exec bash
    
    # 動かないやつなのでコメントアウト
    # 依存関係のインストールとセットアップでやった内容をこっちでやってもいいかもしれない
    # git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
    
    # ここでエラーが出たら何かが間違っているのでやり直し
    RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install
    
    # bundleがないとか、rubyのバージョンが存在しないとかエラーが出たら何かが間違っているのでやり直し
    bundle config deployment 'true'
    bundle config without 'development test'
    bundle install -j$(getconf _NPROCESSORS_ONLN)
    yarn install
    
    # 色々尋ねられるので適当に進める
    RAILS_ENV=production bin/rails mastodon:setup
    
  2. デーモン周りの設定をする

    # 静的ファイルをnginxに見させるために権限を設定
    sudo chmod o+x /home/mastodon
    
    # デーモンの登録と起動
    sudo cp /home/mastodon/live/dist/mastodon-*.service /etc/systemd/system/
    sudo systemctl daemon-reload
    sudo systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming
    sudo service mastodon-web start
    sudo service mastodon-sidekiq start
    sudo service mastodon-streaming start
    
  3. nginxの設定を書く

    map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
    }
    
    upstream backend {
        server 127.0.0.1:3000 fail_timeout=0;
    }
    
    upstream streaming {
        # Instruct nginx to send connections to the server with the least number of connections
        # to ensure load is distributed evenly.
        least_conn;
    
        server 127.0.0.1:4000 fail_timeout=0;
        # Uncomment these lines for load-balancing multiple instances of streaming for scaling,
        # this assumes your running the streaming server on ports 4000, 4001, and 4002:
        # server 127.0.0.1:4001 fail_timeout=0;
        # server 127.0.0.1:4002 fail_timeout=0;
    }
    
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g;
    
    server {
        listen [::]:443 ssl http2;
        server_name  <ドメイン>;
    
        ssl_certificate     /etc/letsencrypt/live/<証明書のパス>/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/<証明書のパス>/privkey.pem;
    
        ssl_protocols TLSv1.2 TLSv1.3;
    
        # You can use https://ssl-config.mozilla.org/ to generate your cipher set.
        # We recommend their "Intermediate" level.
        ssl_ciphers CDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA84:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA38:DHE-RSA-CHACHA20-POLY1305;
    
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_tickets off;
    
        keepalive_timeout    70;
        sendfile             on;
        client_max_body_size 99m;
    
        root /home/mastodon/live/public;
    
        gzip on;
        gzip_disable "msie6";
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss text/javascript image/svg+xml image/x-icon;
        gzip_static on;
    
        location / {
            try_files $uri @proxy;
        }
    
        # If Docker is used for deployment and Rails serves static files,
        # then needed must replace line `try_files $uri =404;` with `try_files $uri @proxy;`.
        location = /sw.js {
            add_header Cache-Control "public, max-age=604800, must-revalidate";
            add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
            try_files $uri =404;
        }
    
        location ~ ^/assets/ {
            add_header Cache-Control "public, max-age=2419200, must-revalidate";
            add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
            try_files $uri =404;
        }
    
        location ~ ^/avatars/ {
            add_header Cache-Control "public, max-age=2419200, must-revalidate";
            add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
            try_files $uri =404;
        }
    
        location ~ ^/emoji/ {
            add_header Cache-Control "public, max-age=2419200, must-revalidate";
            add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
            try_files $uri =404;
        }
    
        location ~ ^/headers/ {
            add_header Cache-Control "public, max-age=2419200, must-revalidate";
            add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
            try_files $uri =404;
        }
    
        location ~ ^/packs/ {
            add_header Cache-Control "public, max-age=2419200, must-revalidate";
            add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
            try_files $uri =404;
        }
    
        location ~ ^/shortcuts/ {
            add_header Cache-Control "public, max-age=2419200, must-revalidate";
            add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
            try_files $uri =404;
        }
    
        location ~ ^/sounds/ {
            add_header Cache-Control "public, max-age=2419200, must-revalidate";
            add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
            try_files $uri =404;
        }
    
        location ~ ^/system/ {
            add_header Cache-Control "public, max-age=2419200, immutable";
            add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
            add_header X-Content-Type-Options nosniff;
            add_header Content-Security-Policy "default-src 'none'; form-action 'none'";
            try_files $uri =404;
        }
    
        location ^~ /api/v1/streaming {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Proxy "";
    
            proxy_pass http://streaming;
            proxy_buffering off;
            proxy_redirect off;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
    
            add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
    
            tcp_nodelay on;
        }
    
        location @proxy {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Proxy "";
            proxy_pass_header Server;
    
            proxy_pass http://backend;
            proxy_buffering on;
            proxy_redirect off;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
    
            proxy_cache CACHE;
            proxy_cache_valid 200 7d;
            proxy_cache_valid 410 24h;
            proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
            add_header X-Cached $upstream_cache_status;
    
            tcp_nodelay on;
        }
    
        error_page 404 500 501 502 503 504 /500.html;
    }
    

なんやかんやの末に立ち上がったMastodonインスタンス

なんやかんやあり色々苦戦したが、無事立ち上がってくれて何よりだった。

立ち上がった直後。

そして現在。こうやって動いているのを見ると感慨深い。

実は中学生のころから自宅サーバーを立てるという夢を持っており、こうやって実際に公開できたことは感慨深い。実際のところ、実験用の小規模サーバーや、SHOUTcastサーバーだとか、シンクライアント用のSSHサーバーみたいなのは作った経験があり、いずれも外に出していたのでサーバーを作った経験が全くない、というわけではないのだが、監視環境を整えたりIPv4が実用困難な環境で、IPv6に挑戦してみたりと、ここまで本格的にやったことはなかったのもあり、個人的には結構達成感がある。

トラブルシューティング

Mastdonのlistenしているポートを変更する

3000番はGrafanaをはじめ、様々なNode.js系のポートと干渉するため変えておく。

  1. /etc/systemd/system/mastodon-web.serviceEnvironment="PORT=3000"を変えることでWeb側のポートが変えられる
  2. /etc/systemd/system/mastodon-streaming.serviceWants=mastodon-streaming@4000.service4000の部分を変えることで、Streaming側のポートも変えられる
  3. サービスを再起動する
    sudo systemctl daemon-reload
    sudo service mastodon-web restart
    sudo service mastodon-streaming restart
    
  4. nginxの設定も対応する箇所を変える
  5. nginxを再起動する
    sudo service nginx restart
    

Mastodonのエラーページが表示される・Rubyがないとか出るなどセットアップ時のエラー全般

基本的にどこかの手順が間違ってるのでしつこくやり直すことで改善する。

投稿可能な文字数を増やす

以下の内容で修正すると増やせる。

app/validators/status_length_validator.rb
 class StatusLengthValidator < ActiveModel::Validator
-  MAX_CHARS = 500
+  MAX_CHARS = 50000
app/javascript/mastodon/features/compose/containers/compose_form_container.js

正直このファイルは直さなくても動くし、直しても、ほぼ意味がなさそうなので、直す必要はないかもしれない。

-  maxChars: state.getIn(['server', 'server', 'configuration', 'statuses', 'max_characters'], 500),
+  maxChars: state.getIn(['server', 'server', 'configuration', 'statuses', 'max_characters'], 50000),
備考

変更直後は投稿画面の初期表示に500と出ていて、数文字打つと50000文字に変化する状態だったが、一日くらい経過すると初期値が50000に変わっていたのでキャッシュか何かが悪さをしていた可能性がある。

フォローできるが、フォロー一覧にもTLにも出てこないユーザーが出る

IPv6と疎通してないところは仕方がないね。AAAAレコード持ちでcurl -6 -v https://example.comしても疎通する場所でも起きることがあるが原因は不明。

兵庫丼でも偶に遭遇してたので、そういうものだと割り切るしかない。IPv4滅ぶべし、慈悲はない。

「制限に達しました1:35:00 以降に再度実行してください。」とエラーが出る

APIのレートリミットにかかっているせいっぽい。5分間に300リクエストまでと、かなり渋い。信用するIPを指定することで回避可能らしい。

.env.productionを開き、前述の資料に書かれている信頼できるIPを列挙した後に、自分のIPv6プレフィクス(aaaa:bbbb:cccc:dddd::/64を自分のプレフィクスに置き換え)を追加し、再起動しておいた。これで緩和されると良いのだが、出先では使えないと思うのでどうするか…。

TRUSTED_PROXY_IP=127.0.0.1/8,::1/128,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7,aaaa:bbbb:cccc:dddd::/64

ドキュメントを読む限り、アカウントIDで縛る処理がどこかにあるようなので、自分のIDを除外できれば出先でも起きなくなり、更に良さそうだが、やり方はよくわからなかった。

調べた限りconfig/initializers/rack_attack.rbの中でやっているようなので、暇なときに見てみたいとは思う。

Prometheusでメトリクスを取得する

Mastodonは標準でPrometheusに対応しているので、Exporterの有効化設定を見ながら設定していく。

まず.env.productionを開き、以下の二行を追記し、再起動する。これによってMastodonWebのExporterが有効化され、ローカルホストで動くようになるようだ。Streamingの方は設定せずとも、元から有効になっている模様。

MASTODON_PROMETHEUS_EXPORTER_ENABLED=true
MASTODON_PROMETHEUS_EXPORTER_LOCAL=true

再起動したらcurl http://localhost:{Streamingのポート番号}/metricscurl http://localhost:9394/metricsで動いていることを確認。

次にPrometheusのscrape_configsに以下を追記し、Prometheusを再起動する。

  - job_name: 'mastodon-web'
    static_configs:
      - targets: ['localhost:9394']

  - job_name: 'mastodon-streaming'
    static_configs:
      - targets: ['localhost:5001']

Prometheusの管理画面を開き、Target healthに出て動いていればOK。

【未解決】プロフィールを更新すると更新前の状態にぶり返したり、更新後の状態になったりして安定しない

大まかには、このような感じ。再現したりしなかったりでいい感じの動画が撮れなかった…。

キャッシュ周りで何かの問題が起きている可能性があるが原因はよくわかっていない。3分も待てば改善するので一旦気にしないことにした。

Dockerを使わなかった理由

Dockerがあれば一瞬で立ち上がって便利といえば便利なのだが、Ubuntuのネイティブ環境にPrometheusとGrafanaをIPv6スタックで導入した時に、DockerとIPv6の相性が余りにも悪すぎたのが最大の要因。

後はまぁ変なレイヤー隔ててない方が管理楽だし、リソースも抑えられるかなとか。

実際に導入して驚いた部分

簡単な監視ツールがある

Mastodon自体に監視の仕組みがあること。Sidekiqという名前自体はよく聞くので知っていたが、今まではなんとなくジョブ管理システムだと思っていた。これはTLで見かけていた管理人の人たちがトラブルが起きた時にジョブを殺したりしているのを見かけたためだ。

とはいえ、公式サイトの説明にはRuby's fastest job systemとあるので、あながち認識としては間違ってなかったようだ。ジョブ管理システムのついでにメトリクスとかも見れる機能があるのかもしれない。

Webベースの管理画面がある

環境変数周りの設定項目が多く、コンソールから設定を操作するイメージが強く、コンソールベースなのかと思っていたが実際にはWebベースのGUI管理コンソールもあり、中々便利だ。管理面の操作や、サーバー本体への影響がない簡単な設定はここで出来るだろう。

死ぬほど早い

アップロードが爆速だったり、画面遷移もかなり早い。家で繋ぐ分にはLAN環境だから早いのかと思っていたが、外から5Gで繋いでも早い。

今のところ大したアクセスや負荷もなく、リソースがしこたま余ってるお陰かもしれない。あとは単純に手前にCDNがないとか、VPSといった共有資源とかと比べた時のスペックの差だろうか?

スペックは結構ある方だと思う。具体的にはCPUはAMD Ryzen 5 5600G、メモリはDDR4 32GB、SSDもCrucial P1 CT500P1SSD8JPでNVMeといった感じで、そんなハチャメチャに高スペックというわけではないが、よくある?安い中古ノートPCを流用したサーバーと比べたら充実している。

今後やっていきたい部分

主に監視周りの強化をしていきたい。現在のロードマップは以下のような感じだ。

  • Grafanaでnginxのダッシュボードを整備
  • Lokiの導入
  • GrafanaからMastodonのメトリクスを見れるように
  • OpenWrt本体でメトリクスをとれるようにしたい
    • 本体が死ぬとテレメトリ取れないので鯖側のPrometheusだと役不足
    • 問題はストレージどうするか…
    • 寿命の関係でeMMCには書けないからNVMe拡張するのか
  • OpenWrtのメトリクスを鯖側でも取れるようにする(いるかこれ?
  • 外部ステータスページの用意
  • 簡単な外形監視の導入?(やるならさくらに乗せる)

まず、Grafanaをセットアップしたもののnginxのダッシュボードが空っぽなので作っていく必要がある。

次にLokiを入れてログ監視もできた方がいい。個別のログファイルを見るのは割とつらい。

Grafanaで統合管理できると便利なのでMastodonのメトリクスも取れると良いので、これもやっていきたい。

他にも今回のセットアップ中にOpenWrtがOutOfMemoryで落ちるケースがあり、原因不明のネットワーク切断が多発したため、こちらのメトリクス収集も必要だ。ネットワーク自体が死ぬと中身が見れないため、基本的に本体側で、収集して見れるようにしたい。今でも簡単なものは入れているが情報量が少なく、役不足だ。

ストレージ寿命の問題もありeMMCにログを吐くとストレージの寿命がマッハになる恐れがあるため、メモリ管理や追加でストレージを用意するなど、手法についても検討する必要がある。

OpenWrtのメトリクスを鯖側でも取れるようにするのはオプションプランだが、これは別にどうでもいい気はする。平時は統合的に見れて便利かもしれない。

あとは外部環境にステータスページを配置したいと考えている。実用性があるかどうかは謎だが、あるとそれっぽいから。ツールとしてはCachetを採用し、さくらのレンタルサーバー側で運用する予定だ。

簡単な外形監視の導入についても、Cachetで担える可能性がある。

監視面以外ではセルフホスティング方式のWAFであるAnubisに興味があり、これも入れていきたいと考えている。

更に中長期では、現在運用しているlycolia.info配下の全サイトを自宅サーバーへ移行し、メールサーバーやネームサーバーなど、現在あるWebサイトの一切を移行する野望も抱いている。

とにかくやることが沢山あるので、当面は暇になることはなさそうで、充実した生活を送れそうだ。

あとがき:OSグローバルのRubyを消してみた

本来手順になく、私の勘違いで追加して作業してしまっていたOSグローバルのRubyを消しても動くのか試してみた。

# 通常ユーザー作業
ls -la /usr/local/bin | grep ruby
rm /usr/local/bin/ruby-build
sudo rm -Rf /usr/local/bin/ruby-build
ls -la /usr/local/share
sudo rm -Rf /usr/local/share/ruby-build
sudo rm -Rf /usr/local/share/man/man1/ruby-build*
ruby -v
sudo apt remove ruby
sudo su - mastodon

# mastodonユーザー作業
mkdir -p "$(rbenv root)"/plugins/ruby-build
cp ruby-build-20250811/. "$(rbenv root)"/plugins/ruby-build
ls -la "$(rbenv root)"/plugins/ruby-build
cd live
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install
ruby -v
exit

# 通常ユーザー作業
sudo service mastodon-web restart
sudo service mastodon-sidekiq restart
sudo service mastodon-streaming restart

一旦ここまでは上手くいったので、上の方にある手順よりこっちでやった方がいいかもしれない。Mastodonのビルドが通るかまでは試してないので、実際に動くかどうかまでは不明だが、まぁ次回考えればよいだろう。