IPB 3.1 フォーラムを Discourse へ移行する

こんにちは、Discourse コミュニティの皆様。

IPB 3.1 フォーラムを Discourse 2.1 にインポートした私の経験をお伝えします。これが皆様のお役に立てれば幸いです。

コミュニティの概要:

  • トピック:Yii PHP フレームワーク(コード関連の議論とサポート)
  • メンバー数:約 26,000 人
  • トピック数:約 64,000
  • ポスト数:約 293,000

このインポートは、16GB の RAM と 4 コアの CPU を搭載したマシンで 27 時間 46 分かかりました。

インポートの要件:

  • メンバーは維持するが、すべてのスパムアカウントをクリーンアップする(約 25 万アカウントのうち、クリーンアップ後は約 2.6 万アカウントが残り)
  • ウェブサイトから SSO を実装する(ユーザーアカウントは Discourse で管理されない)
  • トピック、ポスト、カテゴリを元の URL のまま維持し、ウェブ検索結果や Stackoverflow などのプラットフォームからの他のリンクが引き続き機能するようにする

これは Migrating from Invision Power Board to Discourse - #23 by pfaffman に基づいています。インポーターの素晴らしい作業をしてくれた @pfaffman さんに感謝します。

準備

IPB からのデータエクスポート

mysqldump <databasename> > /tmp/ipb.sql
cd /var/www/yiiframework.com/forum/ && tar czvf uploads.tgz uploads/

SQL ダンプとアップロードファイルを新しいサーバーにコピーし、/var/discourse/shared/standalone/ に配置します。
ここでは Discourse のシンプルな Docker 設定を想定しています。

どのスクリプトを使用するか?

インポートスクリプトは ipboard.rbipboard3.rb の 2 つあります。ipboard3.rb は非常に荒削りで、また私たちが持っているテーブルスキーマにも適合しないため、ipboard.rb を採用しました。

現在の ipboard.rb インポートスクリプトは添付ファイルを適切に処理せず、コードタグの変換も行いません。私たちは PHP コードについて非常に多く話しているため、これは非常に重要です。そのため、スクリプトに以下の修正を加えました。

アップロードされた添付ファイルの利用可能化

インポートスクリプトは、ポストの添付ファイルをアップロードされたファイルへの URL に置き換えます。
IPB インスタンスを以前と同じ URL でオンラインのままにする場合、アップロードディレクトリへの URL を指定するだけで完了します(UPLOADS はインポートスクリプトの設定です、以下参照):

UPLOADS="https://www.yiiframework.com/forum/uploads"

しかし、古いフォーラムを完全に削除するために Discourse にインポートしているため、アップロードファイルを別の場所に配置する必要があります。Discourse の前に nginx プロキシ を使用している場合、サーバー上のディレクトリからアップロードされたファイルを配信するように設定できます。nginx 設定の server パーツに以下を追加してください:

location /ipb_uploads/ {
    alias /var/www/ipb_uploads/;
}

そして、添付ファイルの URL を以下のように設定します(以下参照):

UPLOADS="https://forum.yiiframework.com/ipb_uploads"

Discourse コンテナでの MySQL のセットアップ

Discourse アプリコンテナで bash シェルを起動します:

docker exec -it app bash

コンテナ内で MySQL をインストールし、データベースをインポートします:

apt-get install mysql-server mysql-client libmysqlclient-dev
service mysql start
echo "create database ipb" | mysql -uroot -p
mysql -uroot -p ipb < /shared/ipb.sql

スクリプトをテストするために最初のインポートを試みたところ、20 万人のユーザーをインポートするのに数日間かかりました。そのうち大部分がスパムアカウントであることがわかっていました。そこで、一度も投稿したことのないアカウントを削除するための SQL クエリを作成しました:

SSO を使用するため、削除されたユーザーはログイン時に再作成されます。
SSO を使用しない場合、ユーザー削除の基準は異なるかもしれません。
データをクリーンアップせずにインポートすることも可能です。

mysql -uroot -p
# 次にクリーンアップクエリを適用

次に、インポートスクリプトの依存関係をインストールします:

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

Discourse の Postgres データベースへのデータベースアクセスを許可するために、/etc/postgresql/10/main/pg_hba.confpeertrust に置き換えます。10 は postgres のバージョンを表しています。設定にそのファイルが存在しない場合は、現在実行している postgres のバージョンに 10 を置き換えてください。
変更を読み込むために Postgres を再起動します:service postgresql restart

インポート

アバターとアップロードされたファイルの準備:

mkdir /shared/imports
mv /shared/uploads.tgz /shared/imports
cd /shared/imports && tar xzvf uploads.tgz

インポータースクリプトを実行:

cd /var/www/discourse
DB_HOST="localhost" DB_NAME="yiisite" DB_USER="root" DB_PW="root" TABLE_PREFIX="ipb_" IMPORT_AFTER="1970-01-01" UPLOADS="https://www.forum.yiiframework.com/ipb_uploads" AVATARS_DIR="/shared/imports/uploads/" USERDIR="user" bundle exec ruby script/import_scripts/ipboard.rb | tee import.log

アップロードファイルはポストに元のアップロードファイルへのリンクとして含まれるため、上記で議論した UPLOADS URL を調整してください。

クリーンアップ

すべてが正常に完了したら、service mysql stopapt-get purge mysql-serverrm -rf /var/lib/mysql でクリーンアップします。

URL リダイレクトのセットアップ

既存のフォーラムへの URL を維持するために、インポートスクリプトは IPB のトピックとカテゴリの URL を反映する各トピックのパーマリンクを作成します。
ただし、これらのパーマリンクはトピック内の特定のポストへのリンクや異なるページへのリンクをカバーしていません。
これらの URL が正しく機能するためには、いくつかの URL 書き換えルールを設定する必要があります。3 つのオプションがあります:

  • Discourse の permalink normalizations 設定を使用して、URL から不要な部分を削除する
  • Discourse の前に nginx プロキシがある場合、nginx での書き換えルール
  • 古いフォーラムが Discourse と異なる URL/ホストにあった場合、URL を書き換えるカスタムスクリプトを使用する(これが私が行ったことです)

以下が URL リダイレクトに使用する PHP コードです:

関連リソース

「いいね!」 18

Hello,

sorry to bump this old topic, but i’m also planning to migrate from IPB (v3.4) to Discourse and I’m following this howto. So i figured out I will directly reply in this topic instead of creating a new one.

mysql package is no longer in the distribution, so I followed this guide
basically:

wget http://repo.mysql.com/mysql-apt-config_0.8.13-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.13-1_all.deb
sudo apt update
sudo apt install mysql-server mysql-client libmysqlclient-deb
service mysql start

but then i get below error
mysql: unrecognized service

any idea how I can start mysql ?

Thank you

インストールするはずだったコマンドを実行した際にエラーは発生しましたか?Google検索をお勧めします。

また、OPで参照されているスクリプトではなく、Discourseに含まれるipbスクリプトを使用した方が良いかもしれません。

このスクリプトにアップデートはありますか?IPB 4xでは動作せず、Discourse自体のテーブル構造も変更されているため、スクリプトはそのままでは互換性がありません。

「いいね!」 1

現在ipboardのインポートを行っています。クエリの一部からテーブルや行を削除する必要がありました。それらは多くの異なるテーブル構成を持っているようです。

ipbの生の投稿をマークダウンに変換するのも難しいです。

予算がある場合は、私に連絡してください。現在行っているインポートのためのコードを提供できるかもしれませんが、特定のセットアップには調整が必要になるでしょう。

「いいね!」 2

to help you, IPB 4x tables is as follow:

mysql> SHOW TABLES;
+-------------------------------------------+
| Tables_in_ipboard                         |
+-------------------------------------------+
| ipb_bbcode_mediatag                       |
| ipb_ccs_folders                           |
| ipb_cms_blocks                            |
| ipb_cms_containers                        |
| ipb_cms_custom_database_1                 |
| ipb_cms_custom_database_2                 |
| ipb_cms_database_categories               |
| ipb_cms_database_comments                 |
| ipb_cms_database_fields                   |
| ipb_cms_database_fields_reciprocal_map    |
| ipb_cms_database_fields_thumbnails        |
| ipb_cms_database_reviews                  |
| ipb_cms_database_revisions                |
| ipb_cms_databases                         |
| ipb_cms_folders                           |
| ipb_cms_media                             |
| ipb_cms_media_folders                     |
| ipb_cms_page_database_map                 |
| ipb_cms_page_widget_areas                 |
| ipb_cms_pages                             |
| ipb_cms_template_conflicts                |
| ipb_cms_templates                         |
| ipb_cms_url_store                         |
| ipb_core_achievements_log                 |
| ipb_core_achievements_log_milestones      |
| ipb_core_achievements_rules               |
| ipb_core_acp_notifcations_dismissals      |
| ipb_core_acp_notifications                |
| ipb_core_acp_notifications_preferences    |
| ipb_core_acp_search_index                 |
| ipb_core_acp_tab_order                    |
| ipb_core_acronyms                         |
| ipb_core_admin_login_logs                 |
| ipb_core_admin_logs                       |
| ipb_core_admin_permission_rows            |
| ipb_core_advertisements                   |
| ipb_core_alerts                           |
| ipb_core_alerts_seen                      |
| ipb_core_announcements                    |
| ipb_core_anonymous_posts                  |
| ipb_core_api_keys                         |
| ipb_core_api_logs                         |
| ipb_core_api_webhook_fires                |
| ipb_core_api_webhooks                     |
| ipb_core_applications                     |
| ipb_core_approval_queue                   |
| ipb_core_archive_log                      |
| ipb_core_archive_restore                  |
| ipb_core_attachments                      |
| ipb_core_attachments_map                  |
| ipb_core_automatic_moderation_pending     |
| ipb_core_automatic_moderation_rules       |
| ipb_core_automatic_moderation_types       |
| ipb_core_badges                           |
| ipb_core_banfilters                       |
| ipb_core_bulk_mail                        |
| ipb_core_cache                            |
| ipb_core_club_pages                       |
| ipb_core_clubs                            |
| ipb_core_clubs_fields                     |
| ipb_core_clubs_fieldvalues                |
| ipb_core_clubs_memberships                |
| ipb_core_clubs_node_map                   |
| ipb_core_contact_verify                   |
| ipb_core_content_featured                 |
| ipb_core_content_meta                     |
| ipb_core_deletion_log                     |
| ipb_core_dev                              |
| ipb_core_edit_history                     |
| ipb_core_editor_stored_replies            |
| ipb_core_email_templates                  |
| ipb_core_emoticons                        |
| ipb_core_error_logs                       |
| ipb_core_file_logs                        |
| ipb_core_file_storage                     |
| ipb_core_files                            |
| ipb_core_files_temp                       |
| ipb_core_follow                           |
| ipb_core_follow_count_cache               |
| ipb_core_geoip_cache                      |
| ipb_core_googleauth_used_codes            |
| ipb_core_group_promotions                 |
| ipb_core_groups                           |
| ipb_core_hooks                            |
| ipb_core_hooks_files                      |
| ipb_core_ignored_users                    |
| ipb_core_incoming_emails                  |
| ipb_core_inline_messages                  |
| ipb_core_ips_bulletins                    |
| ipb_core_item_markers                     |
| ipb_core_item_member_map                  |
| ipb_core_item_redirect                    |
| ipb_core_item_statistics_cache            |
| ipb_core_javascript                       |
| ipb_core_leaders                          |
| ipb_core_leaders_groups                   |
| ipb_core_like_cache                       |
| ipb_core_log                              |
| ipb_core_login_failures                   |
| ipb_core_login_handlers                   |
| ipb_core_login_links                      |
| ipb_core_login_methods                    |
| ipb_core_mail_error_logs                  |
| ipb_core_member_badges                    |
| ipb_core_member_history                   |
| ipb_core_member_privacy_actions           |
| ipb_core_member_ranks                     |
| ipb_core_member_recognize                 |
| ipb_core_member_status_replies            |
| ipb_core_member_status_updates            |
| ipb_core_members                          |
| ipb_core_members_feature_seen             |
| ipb_core_members_known_devices            |
| ipb_core_members_known_ip_addresses       |
| ipb_core_members_logins                   |
| ipb_core_members_warn_actions             |
| ipb_core_members_warn_logs                |
| ipb_core_members_warn_reasons             |
| ipb_core_menu                             |
| ipb_core_message_posts                    |
| ipb_core_message_topic_user_map           |
| ipb_core_message_topics                   |
| ipb_core_moderator_logs                   |
| ipb_core_moderators                       |
| ipb_core_modules                          |
| ipb_core_notification_defaults            |
| ipb_core_notification_preferences         |
| ipb_core_notifications                    |
| ipb_core_notifications_pwa_keys           |
| ipb_core_notifications_pwa_queue          |
| ipb_core_oauth_authorize_prompts          |
| ipb_core_oauth_clients                    |
| ipb_core_oauth_server_access_tokens       |
| ipb_core_oauth_server_authorization_codes |
| ipb_core_output_cache                     |
| ipb_core_permission_index                 |
| ipb_core_pfields_content                  |
| ipb_core_pfields_data                     |
| ipb_core_pfields_groups                   |
| ipb_core_plugins                          |
| ipb_core_points_log                       |
| ipb_core_polls                            |
| ipb_core_post_before_registering          |
| ipb_core_profanity_filters                |
| ipb_core_profile_completion               |
| ipb_core_profile_steps                    |
| ipb_core_question_and_answer              |
| ipb_core_queue                            |
| ipb_core_ratings                          |
| ipb_core_rc_author_notification_text      |
| ipb_core_rc_comments                      |
| ipb_core_rc_index                         |
| ipb_core_rc_reports                       |
| ipb_core_reactions                        |
| ipb_core_referral_banners                 |
| ipb_core_referrals                        |
| ipb_core_reputation_index                 |
| ipb_core_reputation_leaderboard_history   |
| ipb_core_reputation_levels                |
| ipb_core_rss_export                       |
| ipb_core_rss_import                       |
| ipb_core_rss_imported                     |
| ipb_core_s3_deletions                     |
| ipb_core_saved_charts                     |
| ipb_core_search_index                     |
| ipb_core_search_index_item_map            |
| ipb_core_search_index_tags                |
| ipb_core_security_answers                 |
| ipb_core_security_questions               |
| ipb_core_seo_meta                         |
| ipb_core_sessions                         |
| ipb_core_share_links                      |
| ipb_core_sitemap                          |
| ipb_core_social_promote                   |
| ipb_core_social_promote_content           |
| ipb_core_social_promote_sharers           |
| ipb_core_soft_delete_log                  |
| ipb_core_solved_index                     |
| ipb_core_spam_service_log                 |
| ipb_core_spam_whitelist                   |
| ipb_core_statistics                       |
| ipb_core_store                            |
| ipb_core_stream_subscriptions             |
| ipb_core_streams                          |
| ipb_core_sys_conf_settings                |
| ipb_core_sys_cp_sessions                  |
| ipb_core_sys_lang                         |
| ipb_core_sys_lang_words                   |
| ipb_core_sys_login                        |
| ipb_core_sys_settings_titles              |
| ipb_core_sys_social_group_members         |
| ipb_core_sys_social_groups                |
| ipb_core_tags                             |
| ipb_core_tags_cache                       |
| ipb_core_tags_perms                       |
| ipb_core_tasks                            |
| ipb_core_tasks_log                        |
| ipb_core_theme_conflict                   |
| ipb_core_theme_content_history            |
| ipb_core_theme_css                        |
| ipb_core_theme_resources                  |
| ipb_core_theme_settings_fields            |
| ipb_core_theme_settings_values            |
| ipb_core_theme_templates                  |
| ipb_core_themes                           |
| ipb_core_upgrade_history                  |
| ipb_core_validating                       |
| ipb_core_view_updates                     |
| ipb_core_voters                           |
| ipb_core_widget_areas                     |
| ipb_core_widget_trash                     |
| ipb_core_widgets                          |
| ipb_custom_bbcode                         |
| ipb_forums_answer_ratings                 |
| ipb_forums_archive_posts                  |
| ipb_forums_archive_rules                  |
| ipb_forums_forums                         |
| ipb_forums_posts                          |
| ipb_forums_question_ratings               |
| ipb_forums_topic_mmod                     |
| ipb_forums_topics                         |
| ipb_forums_view_method                    |
| ipb_nexus_alternate_contacts              |
| ipb_nexus_billing_agreements              |
| ipb_nexus_cart_uploads                    |
| ipb_nexus_coupons                         |
| ipb_nexus_customer_addresses              |
| ipb_nexus_customer_cards                  |
| ipb_nexus_customer_fields                 |
| ipb_nexus_customer_spend                  |
| ipb_nexus_customers                       |
| ipb_nexus_donate_goals                    |
| ipb_nexus_donate_logs                     |
| ipb_nexus_eom                             |
| ipb_nexus_fraud_rules                     |
| ipb_nexus_invoice_tracker                 |
| ipb_nexus_invoices                        |
| ipb_nexus_licensekeys                     |
| ipb_nexus_member_subscription_packages    |
| ipb_nexus_member_subscriptions            |
| ipb_nexus_notes                           |
| ipb_nexus_package_base_prices             |
| ipb_nexus_package_fields                  |
| ipb_nexus_package_filters                 |
| ipb_nexus_package_filters_map             |
| ipb_nexus_package_filters_values          |
| ipb_nexus_package_groups                  |
| ipb_nexus_package_images                  |
| ipb_nexus_packages                        |
| ipb_nexus_packages_ads                    |
| ipb_nexus_packages_products               |
| ipb_nexus_paymethods                      |
| ipb_nexus_payouts                         |
| ipb_nexus_product_options                 |
| ipb_nexus_purchases                       |
| ipb_nexus_referral_rules                  |
| ipb_nexus_reviews                         |
| ipb_nexus_ship_orders                     |
| ipb_nexus_shipping                        |
| ipb_nexus_support_default_content         |
| ipb_nexus_support_departments             |
| ipb_nexus_support_fields                  |
| ipb_nexus_support_notify                  |
| ipb_nexus_support_ratings                 |
| ipb_nexus_support_replies                 |
| ipb_nexus_support_request_log             |
| ipb_nexus_support_requests                |
| ipb_nexus_support_severities              |
| ipb_nexus_support_staff_dpt_order         |
| ipb_nexus_support_staff_preferences       |
| ipb_nexus_support_statuses                |
| ipb_nexus_support_stock_actions           |
| ipb_nexus_support_streams                 |
| ipb_nexus_support_tracker                 |
| ipb_nexus_support_views                   |
| ipb_nexus_tax                             |
| ipb_nexus_transactions                    |
| ipb_rc_reports_index                      |
| x_utf_ipb_convert_session                 |
| x_utf_ipb_convert_session_tables          |
+-------------------------------------------+