PhorumフォーラムをDiscourseに移行する

Phorum フォーラムから Discourse への移行を検討している場合は、このチュートリアルが役立ちます。手順は straightforward で、公式の Phorum インポータースクリプト を使用します。始めましょう。

大まかな流れは以下の通りです。

  • ローカル開発環境の準備
  • 本番環境からのデータベースのエクスポート
  • 本番環境のデータベースをローカルの Discourse インスタンスにインポート
  • Phorum インポータースクリプトの実行

移行可能な項目

  • カテゴリ
    • 各フォーラムとフォルダ ⇒ ルートカテゴリ
  • トピックと投稿
  • ユーザー(以下の属性を含む)
    • 禁止ステータス
    • ユーザー名
    • 実名 ⇒ 名前
    • メールアドレス
    • 管理者ステータス
    • 追加日
    • 最終アクティブ日時

ローカル開発環境の準備

Discourse のインストールについては以下のガイドのいずれかに従ってください。問題が発生した場合は、こちらのガイド を参照してください。

MySQL データベースサーバーをインストールします。

Ubuntu 18.04:

$ sudo apt update
$ sudo apt install mysql-server -y

MySQL のインストールが完了したら、ステータスを確認します。

$ systemctl status mysql.service

実行されていない場合は、以下を実行してください。

$ sudo systemctl start mysql

MacOS:

$ brew install mysql@5.7
$ echo 'export PATH="/usr/local/opt/mysql@5.7/bin:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile

サービスのステータスを確認します。

$ brew services list

以下のような表示が確認できるはずです。

...
mysql@5.7         started
...

表示されない場合は、以下を実行して再度確認してください。

$ brew services start mysql@5.7

Windows の場合は、公式の インストールガイド に従ってください。

この環境が私たちの Discourse サーバー となります。

本番環境からのデータベースのエクスポート

本番環境(Phorum 本番サーバー)からデータベースをエクスポートします。

$ mysqldump -u USER_NAME -p DATABASE_NAME > phorum_dump.sql

データベースダンプを Discourse サーバー にコピーします。

:bulb: データベースのコピーには scp または rsync を使用してください。もちろん、gzip で圧縮してからコピーすることもできます。

本番環境のデータベースを Discourse サーバーにインポート

Discourse サーバー でデータベースを作成します。

$ mysql -u root

:bulb: データベースユーザーにパスワードが設定されている場合は、mysql -u root -p を使用し、パスワードを入力してください。

mysql> CREATE DATABASE phorum;

データベースが作成されたことを確認します。

mysql> SHOW DATABASES;

以下のような表示が確認できるはずです。

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| phorum             |
| sys                |
+--------------------+
5 rows in set (0.04 sec)

これは空のデータベースです。次のステップは、本番環境のデータベースをこれにインポートすることです。

$ mysql -u root phorum < phorum_dump.sql

この機会にテーブルプレフィックスを取得しておきましょう。後で必要になります。

$ mysql -u root
mysql> USE phorum;
mysql> SHOW TABLES;

以下のような表示が確認できるはずです。

+---------------------------+
| Tables_in_phorum          |
+---------------------------+
| pw_banlists           |
| pw_files              |
| pw_forum_group_xref   |
| pw_forums             |
| pw_groups             |
| pw_messages           |
| pw_messages_edittrack |
| pw_pm_buddies         |
| pw_pm_folders         |
| pw_pm_messages        |
| pw_pm_xref            |
| pw_search             |
| pw_settings           |
| pw_subscribers        |
| pw_user_custom_fields |
| pw_user_group_xref    |
| pw_user_newflags      |
| pw_user_permissions   |
| pw_users              |
+---------------------------+
19 rows in set (0.00 sec)

上記の出力から、プレフィックスは pw_ であることがわかります。

Phorum インポータースクリプトの実行

まず、インポーターの依存関係をインストールします。

$ cd ~/discourse
$ echo "gem 'mysql2', require: false" >> Gemfile
$ bundle install

次に、スクリプトを要件に合わせて設定します。例では以下のようになります。

PHORUM_DB = "phorum"
TABLE_PREFIX = "pw_"
BATCH_SIZE = 1000

# ...

host: "localhost",
username: "root",
password: "", # MySQL データベースにパスワードを設定している場合はこれを変更してください
database: PHORUM_DB

URL リダイレクト を作成したい場合は、以下のコメントアウトを外してください。

# categories.each do |category|
#   Permalink.create(url: "list.php?#{category['id']}", category_id: category_id_from_imported_category_id(category['id'].to_i))
# end

#...

# results.each do |post|
#   if post['parent_id'] == 0
#     topic = topic_lookup_from_imported_post_id(post['id'].to_i)
#     Permalink.create(url: "read.php?#{post['category_id']},#{post['id']}", topic_id: topic[:topic_id].to_i)
#   end
# end

以下のようになります。

categories.each do |category|
  Permalink.create(url: "list.php?#{category['id']}", category_id: category_id_from_imported_category_id(category['id'].to_i))
end

#...

results.each do |post|
  if post['parent_id'] == 0
    topic = topic_lookup_from_imported_post_id(post['id'].to_i)
    Permalink.create(url: "read.php?#{post['category_id']},#{post['id']}", topic_id: topic[:topic_id].to_i)
  end
end

クリーンな Discourse インスタンスでインポーターを実行します。

bundle exec rake db:drop db:create db:migrate
bundle exec ruby script/import_scripts/phorum.rb

インポーターは MySQL サーバーに接続し、Phorum データベースを Discourse データベースに移行します。

インポートが完了したら Discourse サーバーを起動します。

$ bundle exec rails server

移行されたデータを処理するために Sidekiq を起動します。

$ bundle exec sidekiq

:bulb: Sidekiq の進行状況は http://localhost:3000/sidekiq/queues で監視できます。

この チュートリアル に従って、Discourse 本番サーバーをセットアップしてください。

Discourse データベースをバックアップし、この チュートリアル に従って Discourse 本番サーバーにアップロードしてください。

完了です :tada:

「いいね!」 7

PhorumフォーラムをDiscourseに移行する作業を間もなく開始します。投稿に添付されたファイル(主に画像)を保持したいと考えていますが、現在の移行スクリプトではそれがサポートされていないようです。これについて既に検討された方はいますか?

「いいね!」 1

「phorum」の移行スクリプトに、添付ファイル・ファイル・アップロードの移行を含むいくつかの調整を行いました。プルリクエストはこちらです:

「いいね!」 1

スクリプトをありがとうございます!

しかし、マニュアルはかなり粗く、不明瞭だと感じました。例えば、Xenforo移行ガイドなどを参照して、ここで何を提案しているのかを実際に理解する必要がありました。いくつか不足している手順を追加させてください。

  • Discourse を起動して実行する
  • 元の Phorum から mysqldump を作成する - すべてクリア、すべて良好。
  • データベースダンプを Discourse フォルダにコピーする docker cp/path/to/backup/phorum_db.sql.gz app:/shared/phorum_db.sql.gz (標準コンテナ名として app を想定)

ここで不足している部分です。

  • 実際に Discourse Docker コンテナに入り、そこに MySQL をインストールします。
docker exec -it app bash
apt-get update && apt-get upgrade
# pv は進行状況を表示するために便利ですが、lsb-release は何かに必要です
apt-get install -y lsb-release pv mariadb-server mariadb-client libmariadb-dev
service mariadb start

MySQL のインストールは少しトリッキーですが、MariaDB で十分機能するはずです。

次にデータベースを作成します: mysqlCREATE database phorum

次にバックアップからデータを投入します: pv phorum_db.sql.gz | gunzip | mysql phorum (ダンプが生の SQL の場合は gunzip は不要です)。

Ruby に MySQL サポートを追加します。

cd /var/www/discourse/
echo "gem 'mysql2'" >>Gemfile
bundle config unset deployment
bundle install --no-deployment

移行スクリプトでデータを変更します (データベース認証情報、プレフィックス、パーマリンク):

nano /var/www/discourse/script/import_scripts/phorum.rb

そして元の投稿ガイドに戻ると、すべて順調です。

クリーンな Discourse インスタンスでインポータを実行します。

git config --global --add safe.directory /var/www/discourse
bundle exec ruby script/import_scripts/phorum.rb

もし Discourse データベースが実際にはクリーンでない場合は、事前に bundle exec rake db:drop db:create db:migrate でクリーンアップすることをお勧めします。

“PG::ConnectionBad: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "discourse" (PG::ConnectionBad)” で失敗した場合:

  1. ‘Peer authentication failed for user “discourse”’ というエラーが発生した場合:
  2. ファイル /etc/postgresql/13/main/pg_hba.conf を編集します。
  3. すべての ‘peer’ を ‘trust’ に変更してファイルを保存します。
  4. postgresql サーバーをリロードします: /etc/init.d/postgresql reload (または psql -U postgres -c "SELECT pg_reload_conf();" かもしれませんが、これは時々失敗しました)。

最初にユーザー移行が実行されます。これは比較的遅い可能性があります (~1.2k ユーザー/分、スクリプト出力による。私は 100k ユーザーを持っていましたので…)。次にカテゴリが作成され、メッセージとトピックの移行が開始されます (同じ速度、~1.2k/分)。しかし、この時点ですでにウェブサイトにアクセスして、どのように見えるかを確認できます。

Phorum のような古いエンジンにしては、予想よりもはるかにスムーズに進んでいるようです。プライベートメッセージ (PM) の移行はないようですが、少なくとも私にとっては問題にはならないでしょう。

スクリプトと労力に改めて感謝します!

非常に複雑で、すべての手順を網羅するガイドを書くのは難しいです。特定のユーザーが知る必要があるのはどの部分なのかを特定するのは複雑です。不足している部分を別のガイドで見つけたのは素晴らしいことです。

MySQLのインストールを取得するためにMySQLテンプレートを含めることもできたかもしれませんが、あるいは何らかの方法で既にインストールされているMySQLサーバーにアクセスすることもできたかもしれません(私が通常行うことです)。

もし望むなら、PMをインポートする他のスクリプトを例として参照することもできたでしょう。