Files
upstream-mattermost/docs/main/administration-guide/onboard/migrate-from-rocketchat.mdx
upstream-mirror 240db4e2a7
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
2026-09-16 00:29:55 +05:00

304 lines
19 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Migrate from Rocket.Chat"
---
<PlanAvailability slug="all-commercial" />
## Overview
Mattermost provides a migration path from Rocket.Chat, bringing your users, channels, messages, threads, direct messages, reactions, and file attachments into a self-hosted Mattermost environment.
Rocket.Chat has no hosted "export workspace" feature. Instead, you export the underlying MongoDB database with `mongodump` and transform that dump into a Mattermost bulk import file using the `mmetl` tool. This means the export step is a database operation that typically requires access to the Rocket.Chat server and its MongoDB instance.
The migration is a multi-step process:
1. [Preparations](#1-preparations) — scope the migration, gather MongoDB and attachment-storage details, and prepare the Mattermost server.
2. [Export your Rocket.Chat data](#2-export-your-rocketchat-data) — produce a `mongodump` of the Rocket.Chat database.
3. [Transform the export](#3-transform-the-export-for-mattermost) — validate with `mmetl check rocketchat` and convert with `mmetl transform rocketchat`.
4. [Import into Mattermost](#4-import-into-mattermost) — upload and process the archive with `mmctl`.
5. [Validate, test, and go live](#5-validate-test-and-go-live) — verify the trial import before scheduling the production cutover.
<Note>
These instructions describe a *best effort* migration designed to preserve the majority of your messages, files, and channel structure. Manual adjustments are often required, and larger deployments should plan for multiple trial runs in a staging environment before a production import. Consider [talking to a Mattermost expert](https://mattermost.com/contact-sales/) if your organization needs migration support.
</Note>
## 1. Preparations
This guide assumes you already have a Mattermost server deployed and ready to accept your data. If not, review the [deployment documentation](/deployment-guide/server/deploy-server#deployment-options) first.
### Scope definition
- **Data history**: Decide how much history you need. Because `mongodump` captures the whole database, scoping is done mainly through what you migrate and validate rather than by trimming the export.
- **Export size**: The size of your Rocket.Chat database and attachments directly affects processing and import time. Plan for longer iteration cycles on large deployments.
- **File attachments**: Consider excluding very large or non-critical attachments with `--skip-attachments` for early test runs to speed up iteration.
### Rocket.Chat / MongoDB prerequisites
- You need access to the Rocket.Chat MongoDB instance and the `mongodump` tool from the [MongoDB Database Tools](https://www.mongodb.com/docs/database-tools/).
- Identify the database name (commonly `meteor`) and the connection URI.
- The transform reads these collections from the dump: `users`, `rocketchat_room`, `rocketchat_message`, and `rocketchat_subscription` (all required), plus `rocketchat_uploads` and `rocketchat_uploads.chunks` (for attachments).
<Note>
This tool was validated against **Rocket.Chat v8.5**. Rocket.Chat changes its MongoDB schema between versions, so exports from other versions may parse differently. If you hit unexpected parse errors, check for a newer `mmetl` release before assuming the export is at fault.
</Note>
### Attachment storage: GridFS vs. FileSystem
Rocket.Chat can store uploaded files in one of two ways. Confirm which your deployment uses (**Admin \> Settings \> File Upload \> Storage Type**) before you export, because it changes how you run the transform:
- **GridFS** (stored inside MongoDB): attachments are captured directly in the `mongodump` (`rocketchat_uploads.chunks.bson`) and extracted automatically. No extra flag needed.
- **FileSystem** (stored on disk): the `mongodump` contains only file metadata. You must also copy the Rocket.Chat uploads directory and point `--uploads-dir` at it during the transform.
### Infrastructure considerations
- **Test environment**: Always run the migration in a development or staging environment first. Most migrations require several iterations.
- **Operating system**: `mmetl` is supported on Linux and macOS. Windows (including WSL) is not recommended.
- **Storage requirements**: Ensure you have room for the `mongodump` output, the transformed import file, and the extracted attachments. Plan for several times the size of your Rocket.Chat data.
- **File storage**: Imports into AWS S3 (or S3-compatible storage) typically complete faster than local or NFS storage for large datasets.
### Mattermost server considerations
- **Fresh server**: The most reliable imports happen on a fresh installation. If importing into an existing server, never import over an existing team, and back up the database and data directory first.
- **Server version**: Run the latest supported version of [Mattermost](/product-overview/mattermost-server-releases).
- **The target team must already exist** in Mattermost and be set to **Public Team**.
- **Configuration settings**: Before importing, adjust:
- `TeamSettings.MaxChannelsPerTeam` and `TeamSettings.MaxUsersPerTeam`: set well above the number of channels/users you are migrating.
- `EmailSettings.EnableSignUpWithEmail` and `EmailSettings.EnableSignInWithEmail`: both `true`.
- `FileSettings.MaxFileSize`: higher than the largest file in your export.
- `ElasticsearchSettings.EnableIndexing`, `EnableSearching`, and `EnableAutocomplete`: set to `false` during the import, then purge and reindex afterward.
## 2. Export your Rocket.Chat data
Export the Rocket.Chat MongoDB database with `mongodump`. Replace the URI and database name to match your deployment:
``` sh
mongodump --uri="mongodb://localhost:3001/meteor" --out=/tmp/rc-dump
```
This creates a subdirectory named after the database (for example `/tmp/rc-dump/meteor`) containing the `.bson` files. That database subdirectory — not the parent — is what you pass to `--dump-dir` in the next step.
If your deployment uses **FileSystem** storage for attachments, also copy the Rocket.Chat uploads directory to a known location so you can reference it with `--uploads-dir`.
## 3. Transform the export for Mattermost
[Download the latest release of mmetl](https://github.com/mattermost/mmetl/releases/) for your OS and architecture. Run `mmetl help` to learn more about the tool.
### Validate the export
Before transforming, check the integrity of the dump:
``` sh
./mmetl check rocketchat --dump-dir /tmp/rc-dump/meteor
```
This reports structural issues (for example, missing required collections or invalid records) that would cause the transform or import to fail. Details are written to `check-rocketchat.log`.
`check rocketchat` accepts the same `--guest-handling` flag as the transform, so you can preview how guest users will be treated before running the full transform.
### Run the transform
Convert the dump into a Mattermost bulk import file. Replace `<TEAM-NAME>` with your Mattermost team name, which must be one word and lowercase (a team named `My Team` becomes `my-team`):
``` sh
./mmetl transform rocketchat --team <TEAM-NAME> --dump-dir /tmp/rc-dump/meteor --output mattermost_import.jsonl
```
For **FileSystem** attachment storage, add `--uploads-dir`:
``` sh
./mmetl transform rocketchat --team <TEAM-NAME> --dump-dir /tmp/rc-dump/meteor --uploads-dir /path/to/rocketchat/uploads --output mattermost_import.jsonl
```
The tool produces a [.jsonl](https://jsonlines.org/examples) file containing your users, channels, and posts, plus a `data` folder containing the extracted attachments.
A successful run ends with a summary line in `transform-rocketchat.log` like:
``` text
Transformation succeeded! Users: 152, Public channels: 48, Private channels: 12, Posts: 39184
```
If the run stops with an error instead — for example, `the RocketChat export contains bot users but --bot-owner was not specified` — no valid import file is produced. Resolve the error (see the flags below) and re-run.
<Tip>
**Iterate incrementally.** Run a small trial first: transform, import into a fresh or restored trial target, and confirm a few channels look right before committing to a full production import. Re-running the same import avoids duplicate posts only when the records' identity fields are unchanged; not every imported entity is deduplicated. Don't rely on re-importing into a modified trial target to reset it.
</Tip>
### Useful transform flags
- `--uploads-dir <PATH>`: Path to the Rocket.Chat FileSystem uploads directory. Required when attachments are not stored in GridFS.
- `--bot-owner <USERNAME>`: Username of the Mattermost user who will own all imported bots. **Required if the export contains any bot users** — the transform errors out otherwise.
- `--guest-handling <MODE>`: How to migrate Rocket.Chat guest users (default `guest`):
- `guest` — migrate them as Mattermost guests. Highest fidelity, but the destination server must have Guest Accounts **licensed** (Professional/Enterprise) and **enabled** (`GuestAccountsSettings.Enable`); otherwise the accounts won't behave correctly.
- `user` — migrate them as regular Mattermost members. Works everywhere, but grants guests full member permissions.
- `skip` — drop guest users entirely, along with their memberships and authored posts.
- `--skip-attachments` / `-a`: Skip extracting file attachments. Useful for faster iteration while testing.
- `--attachments-dir <PATH>`: Directory for extracted attachments (default `data`).
- `--default-email-domain <DOMAIN>`: When a user's email is missing, generate one from their username and this domain (for example `example.com`).
- `--skip-empty-emails`: Allow users with empty emails. Note that this produces invalid import data that must be corrected before importing.
- `--debug`: Emit `DEBUG`-level detail to `transform-rocketchat.log` to help diagnose slow or failing runs.
## 4. Import into Mattermost
Package the `.jsonl` file and `data` folder into a single zip:
``` sh
zip -r mattermost-bulk-import.zip data mattermost_import.jsonl
```
Validate the archive locally before uploading:
``` sh
mmctl import validate ./mattermost-bulk-import.zip
```
Ensure `mmctl` is installed and [authenticated](/administration-guide/manage/mmctl-command-line-tool#mmctl-auth). Then choose an upload method.
### Standard upload
For most imports, upload through `mmctl`:
``` sh
mmctl import upload ./mattermost-bulk-import.zip
mmctl import list available
```
Process the import using the name returned by `import list available`:
``` sh
mmctl import process <IMPORT FILE NAME>
```
Check the job status. If it shows `pending`, wait and re-run. The `--json` flag is required to see error messages:
``` sh
mmctl import job show <JOB ID> --json
```
### Large imports (file store method)
For large archives (multiple GB), uploading through `mmctl` is slow and error-prone. Instead, place the archive directly into the server's import directory and let the server process it in place:
1. Copy `mattermost-bulk-import.zip` (with a unique name) into `data/import` in the Mattermost file store — the local data directory, or the `import` prefix of your S3 bucket.
2. Run `mmctl import list available` to confirm the server sees the file.
3. Run `mmctl import process <IMPORT FILE NAME>` and monitor with `mmctl import job show <JOB ID> --json`.
This avoids re-uploading gigabytes through the API and is the recommended path for large migrations.
### Fixing unread channels and threads
After importing, messages may appear unread for all users. The following fix is for PostgreSQL deployments only.
<Important>
Back up the Mattermost database before running these statements. Test the backup and the SQL in a non-production environment first.
</Important>
``` sql
begin;
UPDATE channelmembers
SET
msgcount = channels.totalmsgcount,
lastupdateat = channels.lastpostat,
lastviewedat = channels.lastpostat,
msgcountroot = channels.totalmsgcountroot
FROM channels
WHERE channelmembers.channelid = channels.id;
INSERT INTO preferences (UserId, Category, Name, Value)
SELECT
cm.userid,
'channel_approximate_view_time',
cm.channelid,
cm.lastupdateat::text
FROM
channelmembers cm
ON CONFLICT (userid, category, name)
DO UPDATE SET
Value = EXCLUDED.Value;
update preferences set value = 'false' where category = 'direct_channel_show';
update preferences set value = 'false' where category = 'group_channel_show';
commit;
```
### Placeholder emails and account activation
Mattermost accounts are created from the emails and usernames in the export. Where an email is missing, a placeholder (for example `username@local`) is generated and must be corrected by a system administrator. Search the final `.jsonl` file for placeholder emails before importing.
Users activate their accounts through Mattermost's **Password Reset** screen using their email address:
- **Imports performed by a system administrator**: emails are automatically verified, and users can reset their password immediately.
- **Imports performed by a non-administrator**: users must verify their email address before resetting their password.
See how to [migrate user authentication to LDAP or SAML](/administration-guide/manage/mmctl-command-line-tool#mmctl-user-migrate-auth) if you use SSO.
## 5. Validate, test, and go live
Before production cutover, validate a fresh or restored trial import end to end:
1. Compare the transform and import logs with source counts for users, channels, posts, and attachments, and investigate errors or unexpected omissions.
2. Sign in as representative users and verify public and private channels, direct and group messages, threads, reactions, files, mentions, permissions, and authentication.
3. Recreate integrations and custom emoji, then purge and rebuild the search index before testing search.
4. Back up the production Mattermost database and file store, schedule a maintenance window, stop writes in Rocket.Chat, create a final export, and repeat the validated process on a fresh or restored production target.
5. After final verification, update DNS or client configuration, invite users to activate their accounts, and keep the Rocket.Chat deployment read-only until the migration is accepted.
## What migrates and what doesn't
For core collaboration data — posts, threads, reactions, attachments, users, and channels — you can expect high fidelity. Integrations and Rocket.Chat-specific features do not carry over.
| Content type | Migrates? | Notes |
|----|----|----|
| Posts and threads | Yes | Rocket.Chat threads become Mattermost threaded replies. Oversized posts are split into continuation replies rather than truncated. |
| Public channels | Yes | Display name, purpose (description), and header (topic) are preserved. |
| Private channels | Yes | |
| Discussions | Yes (converted) | Rocket.Chat discussions are converted to standalone Mattermost channels (public or private, matching the discussion's visibility). The parent-child relationship is not preserved. |
| 1:1 direct messages | Yes | Map directly. Self-DMs are preserved as a direct channel with yourself. |
| Group DMs (3–8 members) | Yes (converted) | Become Mattermost **Group Messages** — functionally equivalent, different terminology. |
| Group DMs (over 8 members) | Converted | Mattermost group messages support at most 8 members, so larger group DMs are converted to **private channels**. |
| Reactions | Yes | Emoji skin-tone modifiers are stripped to a default rendering. Custom emoji require matching names (see below). |
| File attachments | Yes | From GridFS or FileSystem storage. Auto-generated thumbnails are skipped to avoid duplicates. |
| Users | Yes | Inactive Rocket.Chat users are imported as deactivated accounts. |
| Bots | Yes | Reassigned to the `--bot-owner` user. |
| Channel mentions | Best effort | `#channel` references are translated to Mattermost `~channel` links where the channel exists. |
| Join / leave / add / remove events | Yes | Converted to Mattermost system messages. |
| Custom emoji images | No | Reaction *names* are preserved, but the emoji images are not imported (see below). |
| Guest users | Configurable | Controlled by `--guest-handling` (default `guest`). By default, Rocket.Chat guest accounts are imported as Mattermost [guest users](/administration-guide/onboard/guest-accounts) — this requires Guest Accounts to be **licensed** (Professional/Enterprise) and [guest access](/administration-guide/configure/authentication-configuration-settings#guest-access) enabled on the target server. Use `--guest-handling user` to import them as regular members instead (no guest licensing needed), or `--guest-handling skip` to drop them entirely. |
| Encrypted (E2E) channels | No | End-to-end encrypted rooms are skipped entirely, including their messages. |
| Apps, integrations, slash commands, webhooks | No | Recreate using Mattermost [integrations](/integrations-guide/integrations-guide-index). |
| Avatars, user status, custom profile fields | No | Users update their profiles in Mattermost after import. |
| Pinned/starred messages, topic-change and mute events | No | These Rocket.Chat-specific records are not migrated. |
### Custom emoji
Custom emoji images are **not** imported with your messages — only the emoji *names* used in reactions are preserved. A reaction is stored as text (`:emoji-name:`) and resolved at render time:
- If a custom emoji with the same name exists in Mattermost, the reaction renders correctly.
- If not, it shows as a placeholder until the emoji is added.
Because resolution happens at render time, you can add custom emoji to Mattermost **at any time** — before or after the import — and reactions on historical messages will render once a matching name exists. Names must match exactly.
## FAQ
**Do I need to create users before importing?** No. `mmetl` and the import process handle user creation and ordering automatically.
**What happens if I run the same import twice?** Re-running the same import avoids duplicate posts when identity fields are unchanged, but not every entity is deduplicated and edits to identifying fields can create additional records. Use a fresh or restored trial target for each test run.
**Where do all my channels and DMs go?** Into the single team you specify with `--team`. Rocket.Chat has no multi-workspace concept, so there is no team-mapping step.
**How are attachments stored, and why do I need `--uploads-dir`?** Rocket.Chat stores files either in MongoDB (GridFS) or on disk (FileSystem). GridFS files are captured in the `mongodump` automatically; FileSystem files are not, so you point `--uploads-dir` at the uploads directory. See [Attachment storage](#attachment-storage-gridfs-vs-filesystem).
**Why are some channels missing after import?** End-to-end encrypted rooms are skipped and their messages are not migrated. Check `transform-rocketchat.log` for skipped rooms.
**Do I need to import custom emoji before messages?** No. Emoji resolve at render time, so you can add them whenever.
**How do I handle a very large import?** Use the file store method — copy the archive directly into the server's `data/import` directory rather than uploading through `mmctl`. See [Large imports](#large-imports-file-store-method).
**I hit a parse error. Is my export broken?** Possibly not. Rocket.Chat changes its MongoDB schema between versions (this tool was validated against v8.5). Run `mmetl check rocketchat` first, and check for a newer `mmetl` release before assuming the data is at fault.