{
"$type": "com.whtwnd.blog.entry",
"blobs": [
{
"name": "クリップボード01.jpg",
"blobref": {
"$type": "blob",
"ref": {
"$link": "bafkreiescqi2bra5nc4atgysmy33g7lcfmfqtxudhsjjd3mxmhzwoqwk34"
},
"mimeType": "image/jpeg",
"size": 23155
},
"encoding": "image/jpeg"
},
{
"name": "クリップボード02.jpg",
"blobref": {
"$type": "blob",
"ref": {
"$link": "bafkreieoxtc5iil6gsgdbu5d6suecpz7zl5na2y4qrkd3btl2y3xvvo7u4"
},
"mimeType": "image/jpeg",
"size": 6289
},
"encoding": "image/jpeg"
},
{
"name": "クリップボード03.jpg",
"blobref": {
"$type": "blob",
"ref": {
"$link": "bafkreiglgjx674fu7k4rciir3gt3n57urwpypqg6qed4oswb5gnwlfoxb4"
},
"mimeType": "image/jpeg",
"size": 7289
},
"encoding": "image/jpeg"
},
{
"name": "クリップボード04.jpg",
"blobref": {
"$type": "blob",
"ref": {
"$link": "bafkreiaxugfnotfwp3dptfidsv7quh75ye6nvrk2xu4fkqgywdkstd4biq"
},
"mimeType": "image/jpeg",
"size": 17349
},
"encoding": "image/jpeg"
},
{
"name": "クリップボード05.jpg",
"blobref": {
"$type": "blob",
"ref": {
"$link": "bafkreifev5joqz3gc5uw6ejo6xa2kiwxix3u5j6ja4t5pxcz5hyotmyvk4"
},
"mimeType": "image/jpeg",
"size": 57446
},
"encoding": "image/jpeg"
},
{
"name": "クリップボード06.jpg",
"blobref": {
"$type": "blob",
"ref": {
"$link": "bafkreibmcy4b23lh3p6tcsbwsrfypkwb2jxsswu3iwunwyzp7q7rkia3ue"
},
"mimeType": "image/jpeg",
"size": 17805
},
"encoding": "image/jpeg"
}
],
"theme": "github-light",
"title": "PDS間でアカウントの移行を試した話",
"content": "# PDSが1台……PDSが2台……\n10月中旬、Xによるブロックの仕様変更によりBlueskyユーザーが急増することになりました。https://bsky.app/profile/gigazine.net/post/3l6qt3srqr72c\n\n私の運営しているカスタムフィード[RepostNextPost](https://bsky.app/profile/did:plc:6zpjzzdzet62go7lnaoq4xog)もその影響を受けてデータ受信が追いつかず、反映するまで遅延が発生することに……結局1ヶ月ほど遅延と戦ってたんですが、さすがにサーバーの性能も限界かなと思い、新しいサーバーに移行・カスタムフィードのデータ受信をFirehoseからJetstreamに変更することにしました。\nhttps://bsky.app/profile/l-tan.dolciss.net/post/3lbuaef6des25\n\nただこのサーバー、カスタムフィードと一緒にPDSも動いておりまして、新しいサーバーにも空っぽのPDSを入れていました(PDSと一緒に入るCaddyでカスタムフィードのアクセスも捌いていたため)。今までは同じアドレスに設定して、前のサーバーからまるっとPDSのデータを移すことで移行してたんですが、\n\n🤔「せっかくサーバーが2台平行稼働してるんだし、アカウント移行を試せば良いのでは……?」\n\nということで、運営のBryan([@bnewbold.net](https://bsky.app/profile/did:plc:44ybard66vv44zksje25o7dz))さんが書かれた [Migrating PDS Account with `goat`](https://whtwnd.com/did:plc:44ybard66vv44zksje25o7dz/3l5ii332pf32u) を参考にやってみることに。記事内にもありますが、さらにアカウント移行の仕組みや流れはDaniel([@dholms.xyz](https://bsky.app/profile/did:plc:yk4dd2qkboz2yv6tpubpc6co))さんの [ACCOUNT MIGRATION · bluesky-social/pds](https://github.com/bluesky-social/pds/blob/main/ACCOUNT_MIGRATION.md)が詳しいです。\n手順としては自動と手動があり、自動で失敗しても続きを手動でできるとありますが、今回は旧サーバーの期限も迫っていることもあって自動で試してみることにします。\n\n## 注意\n本記事のアカウント移行は、\"サードパーティーPDS\"から\"サードパーティーPDS\"へのアカウント移行です。\nBluesky公式のPDS(*.us-(ea|we)st.host.bsky.network、いわゆるきのこPDS)からの移行も可能かと思いますが、~~2024年現在[公式PDSに戻る方法は用意されていない](https://github.com/bluesky-social/pds/blob/main/ACCOUNT_MIGRATION.md#:~:text=Bluesky%20PDS%20is%20not%20currently%20accepting%20incoming%20migrations)ため、お気を付けください~~当然ながら本記事の手順を実行してアカウントやデータの喪失があったとしても、当方で責任は取れませんのであしからず……\n※2025年9月に公式から移行したアカウントは戻れるようになりました。[Enabling Account Migration Back to Bluesky’s PDS](https://docs.bsky.app/blog/incoming-migration)\n\n# 移行前の準備\n\n## PLCデータ\n\nひとまず移行前のアカウントのPLCデータは次のとおり\nhttps://web.plc.directory/did/did:plc:yudyb347zpi23jrzmiu7g7ar\n```json\n{\n \"@context\": [\n \"https://www.w3.org/ns/did/v1\",\n \"https://w3id.org/security/multikey/v1\",\n \"https://w3id.org/security/suites/secp256k1-2019/v1\"\n ],\n \"alsoKnownAs\": [\n \"at://l-test.pds.dolciss.net\"\n ],\n \"id\": \"did:plc:yudyb347zpi23jrzmiu7g7ar\",\n \"service\": [\n {\n \"id\": \"#atproto_pds\",\n \"serviceEndpoint\": \"https://pds.dolciss.net\",\n \"type\": \"AtprotoPersonalDataServer\"\n }\n ],\n \"verificationMethod\": [\n {\n \"controller\": \"did:plc:yudyb347zpi23jrzmiu7g7ar\",\n \"id\": \"did:plc:yudyb347zpi23jrzmiu7g7ar#atproto\",\n \"publicKeyMultibase\": \"zQ3shMpqkdyUDL2R2xGGahowEcWojP2CoMVGLeHU9wpmAPW7y\",\n \"type\": \"Multikey\"\n }\n ]\n}\n```\n\n## 設定値の準備\n\nまた先述の記事には、以下の情報が必要と書かれていますのであらかじめ準備しておきます。\n\n> 1. your existing account credentials ($ACCOUNTDID, $OLDHANDLE, $OLDPASSWORD)\n> 2. the new PDS host and service DID ($NEWPDSHOST, $NEWPDSSERVICEDID)\n> 3. invite code for the new PDS ($INVITECODE)\n> 4. desired new PDS handle and credentials ($NEWHANDLE, $NEWEMAIL, $NEWPASSWORD)\n\n1つめは移行前のアカウントの情報\n- $ACCOUNTDID → 上のPLCデータからもわかるとおり`did:plc:yudyb347zpi23jrzmiu7g7ar`です\n- $OLDHANDLE → `l-test.pds.dolciss.net`\n- $OLDPASSWORD → 設定したパスワード(アカウント操作を含むので、アプリパスワードではなく本パスワード) \n\n2つめは新しいPDSの情報\n- $NEWPDSHOST → `https://pds2.dolciss.net`としました\n- $NEWPDSSERVICEDID → 基本的にそのまま`did:web:pds2.dolciss.net`\n\n3つめは新しいPDSの招待コード\n- $INVITECODE → 新しいサーバーで`sudo pdsadmin create-invite-code`を実行して生成します \n\n4つめは移行先のアカウント情報\n- $NEWHANDLE → PDSのローカルハンドル(ハンドルの後ろがサーバードメイン)とするので`l-test.pds2.dolciss.net`とします\n- $NEWEMAIL → 同じメールアドレスでよいかと\n- $NEWPASSWORD → 何かしらパスワードを用意します\n\n## goatコマンドのインストール\n\n今回のアカウント移行には、記事に沿ってBluesky公式が用意しているGoのパッケージindigoの中にある[goat](https://github.com/bluesky-social/indigo/tree/main/cmd/goat)を使用します。\n\nインストールは1行コマンドを叩くだけのようです\n```\ndolce@xxx:~$ go install github.com/bluesky-social/indigo/cmd/goat@latest\nCommand 'go' not found, but can be installed with:\nsudo snap install go # version 1.23.3, or\nsudo apt install golang-go # version 2:1.21~2\nsudo apt install gccgo-go # version 2:1.21~2\nSee 'snap info go' for additional versions.\n``` \nあ。新しいサーバーにはそもそもgoが入っていなかった…のでインストールします\n```\ndolce@xxx:~$ sudo apt install golang-go\ndolce@xxx:~$ go version\ngo version go1.22.2 linux/amd64\n```\nこんどこそ\n```\ndolce@xxx:~$ go install github.com/bluesky-social/indigo/cmd/goat@latest\ngo: downloading github.com/bluesky-social/indigo v0.0.0-20241223053147-c130614850e5\ngo: downloading github.com/adrg/xdg v0.5.0\n~以下必要パッケージのダウンロードが続く~\ngo: downloading golang.org/x/sync v0.7.0\ndolce@xxx:~$ goat help\nCommand 'goat' not found, did you mean:\n```\nインストールはできたっぽいけど、こんどはコマンドが見つからない……[go installしたがcommand not found。](https://zenn.dev/awonosuke/articles/47336619a4f039)によると単にPATHが通ってないと。\n```\ndolce@xxx:~$ go env GOPATH\n/home/dolce/go\ndolce@xxx:~$ vi ~/.bashrc \n ~export PATH=\"$HOME/go/bin:$PATH\" を追記する~\ndolce@xxx:~$ source ~/.bashrc \ndolce@xxx:~$ goat -v\ngoat version v0.0.0-20241223053147-c130614850e5\n```\nやったー🙌\n\n# いよいよ移行\n先述の通り自動でアカウント移行をやってみます。\n\nまずは移行前の現在のアカウントにログインします。\n```\ndolce@xxx:~$ goat account login -u l-test.pds.dolciss.net -p 本パスワード\ndolce@xxx:~$ goat account status\nDID: did:plc:yudyb347zpi23jrzmiu7g7ar\nHost: https://pds.dolciss.net\n{\n \"activated\": true,\n \"expectedBlobs\": 19,\n \"importedBlobs\": 20,\n \"indexedRecords\": 84,\n \"privateStateValues\": 0,\n \"repoBlocks\": 110,\n \"repoCommit\": \"bafyreieupcvzb565u3wwdmfpnsqgmvhlwdji5efrpqg2di4cdl7upcusgm\",\n \"repoRev\": \"3leiw3gr75s23\",\n \"validDid\": true\n}\n```\nアカウント操作のためにメールによる2要素認証が必要なため、認証コードをリクエストします。\n```\ndolce@xxx:~$ goat account plc request-token\nSuccess; check email for token.\n```\n\nこれで情報が揃いましたので、アカウント移行のコマンドを実行します。\n```\ndolce@xxx:~$ goat account migrate \\\n> --pds-host https://pds2.dolciss.net \\\n> --new-handle l-test.pds2.dolciss.net \\\n> --new-password 新パスワード \\\n> --new-email 新メールアドレス \\\n> --plc-token メールで送られてきた認証コード \\\n> --invite-code 発行した招待コード\n2024/12/30 15:36:36 INFO new host serviceDID=did:web:pds2.dolciss.net url=https://pds2.dolciss.net\n2024/12/30 15:36:36 INFO creating account on new host handle=l-test.pds2.dolciss.net host=https://pds2.dolciss.net\n2024/12/30 15:36:38 INFO migrating repo\n2024/12/30 15:36:39 INFO migrating preferences\n2024/12/30 15:36:39 INFO migrating blobs\n2024/12/30 15:36:39 INFO transferred blob cid=bafkreia6fq522uxlstp7iwzwhzdnuzg6xduuyy4qepypueizgsvfm2co3i size=168575\n~blob転送がつづく~\n2024/12/30 15:36:42 INFO transferred blob cid=bafkreigwgkw36msftb7qlcnw3kj54t3i6lt6i4mceom6i2d4vnvhw3xduq size=62512\n2024/12/30 15:36:42 INFO account migration status status=\"&{Activated:false ExpectedBlobs:19 ImportedBlobs:19 IndexedRecords:84 PrivateStateValues:0 RepoBlocks:110 RepoCommit:bafyreieupcvzb565u3wwdmfpnsqgmvhlwdji5efrpqg2di4cdl7upcusgm RepoRev:3leiw6iijes2l ValidDid:false}\"\n2024/12/30 15:36:42 INFO updating identity to new host\n2024/12/30 15:36:44 INFO activating new account\n2024/12/30 15:36:44 INFO account migration completed\n```\nblobの数も少ないこともあってか8秒で終わりました。はやっ\n\n# 移行後の確認\n## 旧アカウント\nまずは古いアカウントをみてみます。\n```\ndolce@xxx:~$ goat account status\nDID: did:plc:yudyb347zpi23jrzmiu7g7ar\nHost: https://pds.dolciss.net\n{\n \"activated\": false,\n \"expectedBlobs\": 19,\n \"importedBlobs\": 20,\n \"indexedRecords\": 84,\n \"privateStateValues\": 0,\n \"repoBlocks\": 110,\n \"repoCommit\": \"bafyreieupcvzb565u3wwdmfpnsqgmvhlwdji5efrpqg2di4cdl7upcusgm\",\n \"repoRev\": \"3leiw3gr75s23\",\n \"validDid\": false\n}\n```\ndeactivate状態になっているようです。特に問題なければ削除してもいいとのことですが、公式でログインしても再有効化しますか?と聞かれるので削除ルートはあるのかしら……(この状態で再有効化したらどうなるかは怖くて試してない)\n\n\n## 新アカウント\n新しいアカウントもみてみます(投稿テストを先にしてしまったので数字が増えてる……)\n```\ndolce@xxx:~$ goat account logout\ndolce@xxx:~$ goat account login -u l-test.pds2.dolciss.net -p 新パスワード\ndolce@xxx:~$ goat account status\nDID: did:plc:yudyb347zpi23jrzmiu7g7ar\nHost: https://pds2.dolciss.net\n{\n \"activated\": true,\n \"expectedBlobs\": 19,\n \"importedBlobs\": 19,\n \"indexedRecords\": 86,\n \"privateStateValues\": 0,\n \"repoBlocks\": 113,\n \"repoCommit\": \"bafyreibiovuzjpxjoi6a3pbyuh4w3jy2blj4n4epkdudjwj4jxvmwglziu\",\n \"repoRev\": \"3leix2u6j2k2l\",\n \"validDid\": true\n}\n```\n\n\n\n動かしっぱなしにしていた羽衣でもエラーが\n\n公式でもプロフィールをみようとすると同じエラーが出ています。\n\n\nサインインし直せば新しいPDSでログインできました。\n\nプロフィールもそのまま、フォロワーも画像投稿も全部引き継がれています。\n\n\n## PLCデータ\n冒頭の移行前と比較して、アカウントハンドルの`alsoKnownAs`、PDSの`serviceEndpoint`、公開鍵の`publicKeyMultibase`が新しくなっていることが分かります。\n```json\n{\n \"@context\": [\n \"https://www.w3.org/ns/did/v1\",\n \"https://w3id.org/security/multikey/v1\",\n \"https://w3id.org/security/suites/secp256k1-2019/v1\"\n ],\n \"alsoKnownAs\": [\n \"at://l-test.pds2.dolciss.net\"\n ],\n \"id\": \"did:plc:yudyb347zpi23jrzmiu7g7ar\",\n \"service\": [\n {\n \"id\": \"#atproto_pds\",\n \"serviceEndpoint\": \"https://pds2.dolciss.net\",\n \"type\": \"AtprotoPersonalDataServer\"\n }\n ],\n \"verificationMethod\": [\n {\n \"controller\": \"did:plc:yudyb347zpi23jrzmiu7g7ar\",\n \"id\": \"did:plc:yudyb347zpi23jrzmiu7g7ar#atproto\",\n \"publicKeyMultibase\": \"zQ3shNqnMcCTPqAZm3dEf5uYvYHn4EUiw1vwH3d8xdLVD1PaD\",\n \"type\": \"Multikey\"\n }\n ]\n}\n```\n\n# おわりに\nというわけで、自動のアカウント移行どこかで詰まるかなと思っていたものの、案外すんなり終わってよかったような、もう少しいろいろ試せて方がよかったような……ともあれ無事に移行できたので、これで旧サーバーを安心して爆破(契約切れ)して年を越せます。あとは新しいサーバーの方が性能良くしたので、更新費用をなんとかせねば……みなさま良いお年を。",
"createdAt": "2025-12-30T07:50:30.808Z",
"visibility": "public"
}