Migrar um fórum Phorum para Discourse

If you have an old Phorum forum and thinking to migrate to Discourse, then this tutorial is for you. The process is straightforward and we will be using the official Phorum Importer script. Let’s get started.

On a high level, we will do the following.

  • Preparing the local development environment.
  • Exporting the database from the production environment.
  • Importing the production database to a local Discourse instance.
  • Running the Phorum importer script.

What can be migrated

  • Categories
    • Every forums and folders => Root category
  • Topics & Posts
  • Users (with the following attributes)
    • banned status
    • username
    • real name => name
    • email
    • admin status
    • date added
    • last active

Preparing Local Development Environment

Follow one of these guides to install Discourse itself and consult this guide if you have any problems.

Install MySQL DB server;

Ubuntu 18.04:

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

After finishing installing MySQL, check its status:

$ systemctl status mysql.service

If it is not running, run the following:

$ 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

Check the services status:

$ brew services list

You should see something like this:

...
mysql@5.7         started
...

Otherwise, run the following and check again:

$ brew services start mysql@5.7

For Windows, you can follow the official installation guide.

This environment will be our Discourse server.

Exporting The Database from Production Environment:

Export the production database (from Phorum production server):

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

Copy the database dump to the Discourse server.

:bulb: Use scp or rsync to copy the database. And of course, you can gzip it first.

Importing The Production Database to Discourse server

On Discourse server, Create a database:

$ mysql -u root

:bulb: If your database user has a password you should use: mysql -u root -p then type your password.

mysql> CREATE DATABASE phorum;

Make sure that the database is created:

mysql> SHOW DATABASES;

You should see something like this:

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

This is an empty database. Our next step is to import the production database into it.

$ mysql -u root phorum < phorum_dump.sql

While we are here, let’s get the table prefix. We will need it later:

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

You will see something like this:

+---------------------------+
| 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)

From the output above you can see that the prefix is pw_.

Running Phorum Importer Script

First, install the importer dependencies:

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

Now let’s configure the script to fits our requirements. In our example this will do:

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

# ...

host: "localhost",
username: "root",
password: "", # Change this if you have a password for MySQL database
database: PHORUM_DB

If you want to create a url redirecting, then you should uncomment the following:

# 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

It will be like this:

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

Run the importer with a clean Discourse instance:

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

The importer will connect to the MySQL server and migrates our Phorum database to Discourse database.

Start Discourse server after the importer finish importing:

$ bundle exec rails server

Start Sidekiq to process the migrated data:

$ bundle exec sidekiq

:bulb: You can monitor sidekiq progress at http://localhost:3000/sidekiq/queues.

Setup your Discourse production server by following this tutorial.

Perform a backup for Discourse database and upload it to your Discourse production server by following this tutorial.

It’s done :tada:

7 curtidas

I’m about to start work on migrating a Phorum forum to Discourse. I would like to preserve files attached to posts (mostly pictures). Looks like this is not supported in the current migration script. Has anyone noodled on that already?

1 curtida

I’ve made a couple tweaks to the migration script for “phorum” including migrating attachments/files/uploads. The pull request is here:

1 curtida

Obrigado pelos scripts!

No entanto, acho que o manual está bastante cru e pouco claro. Tive que consultar, por exemplo, o guia de migração do XenForo para realmente entender o que vocês sugerem aqui. Deixe-me adicionar algumas etapas que faltam:

  • Ter o Discourse instalado e funcionando
  • Criar o mysqldump do Phorum original - tudo claro, tudo bem.
  • Copiar o dump do banco de dados para a pasta do Discourse docker cp /path/to/backup/phorum_db.sql.gz app:/shared/phorum_db.sql.gz (assumindo app como nome padrão do contêiner)
    E aqui as partes que faltam:
  • Entrar no contêiner Docker do Discourse e instalar o MySQL lá:
docker exec -it app bash
apt-get update && apt-get upgrade
# pv apenas para conveniência para exibir o progresso, lsb-release é necessário por algo
apt-get install -y lsb-release pv mariadb-server mariadb-client libmariadb-dev
service mariadb start

Note que a instalação do MySQL é um pouco mais complicada, mas o Mariadb deve funcionar bem.

Em seguida, crie um banco de dados: mysqlCREATE database phorum.

Em seguida, preencha-o a partir do backup: pv phorum_db.sql.gz | gunzip | mysql phorum (não é necessário gunzip se o seu dump for sql puro).

Adicione suporte MySql ao Ruby:

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

Modifique os dados no script de migração (credenciais do banco de dados, prefixo, permalinks):

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

E então de volta ao guia do post original, tudo bem lá:

Execute o importador com uma instância limpa do Discourse:

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

Se o seu banco de dados Discourse não estiver realmente limpo, é melhor limpá-lo com bundle exec rake db:drop db:create db:migrate antes.

Se falhar com “PG::ConnectionBad: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "discourse" (PG::ConnectionBad)”:

  1. Se você receber o erro 'Peer authentication failed for user "discourse"':
  2. Edite o arquivo /etc/postgresql/13/main/pg_hba.conf
  3. Mude todos os ‘peer’ para ‘trust’ e salve o arquivo
  4. Recarregue o servidor postgres: /etc/init.d/postgresql reload (ou talvez psql -U postgres -c "SELECT pg_reload_conf();", mas isso falhava para mim às vezes)

Primeiro, ele executa as migrações de usuários, que podem ser relativamente lentas (~1.2k usuários/minuto de acordo com a saída do script. Eu tinha 100k usuários, então…). Em seguida, ele cria categorias e começa a migrar mensagens e tópicos (mesma velocidade, ~1.2k/minuto), mas a essa altura você já pode acessar o site e ver como está.

Parece bem mais suave do que eu esperaria para um motor tão antigo quanto o Phorum. Parece que não há migração de Mensagens Privadas (PM), mas isso não deve ser um bloqueador para mim, pelo menos.

Obrigado novamente pelo script e pelos esforços!

É difícil escrever um guia para algo tão complicado que cubra todas as etapas. Descobrir exatamente quais partes um usuário específico pode precisar que lhe sejam ditas é complexo. Bom trabalho em encontrar outro guia com as partes que faltam.

Você poderia ter incluído o template do mysql para instalar o mysql, ou talvez você acessasse um servidor mysql que já estava instalado de alguma forma (o que eu costumo fazer).

Se você quisesse, poderia olhar alguns outros scripts que importam PMs para usar como exemplo.