Migration to Redmine

Moving from Jira, Trac, Mantis or Bugzilla to Redmine usually means scripted import over the REST API, not the built-in importers. This page explains what the work covers, what drives its cost and duration, and what you must provide.

On this page

What a Redmine migration involves

The built-in importers are the first thing most teams try, and they are the first thing that fails. Redmine's migration documentation marks the Trac and Mantis importers as obsolete and not working. The third-party scripts listed for systems such as Jira and Bugzilla are described as neither tested nor supported. That leaves a scripted import over the Redmine REST API as the normal route: your team or a partner writes the extraction and mapping code, and Redmine receives issues, users, projects and attachments through its API. Confirm that the REST API is enabled by an administrator before any script runs, since it is off by default.

Migrations are usually triggered by a change in the old tracker's support status, a licensing change, a consolidation of several project tools, or a move to self-hosted infrastructure. Each trigger shapes the work differently. A team leaving an unsupported Trac instance may have decades of wiki pages and ticket history with unusual workflow states. A team leaving a hosted Jira instance may need to map custom fields, sprints and link types that have no direct Redmine equivalent. Inventory the source system first, including attachment storage size and which users are still active.

Teams with a developer who is comfortable with Ruby or scripting, and access to a staging Redmine, often keep part of the work in-house. Extraction from the source system, a dry run against staging and a user mapping table are tasks an internal engineer can own, provided they can read the REST API documentation and test results carefully. The production cutover and the reconciliation checks are harder to repeat under pressure.

A partner is worth considering when the source data is large or inconsistent, when history must be preserved with correct authorship and timestamps, when several source systems feed one Redmine, or when no one on staff can own the script after go-live. Ask any partner for a written mapping specification, a staging run with reconciliation counts, and a rollback plan for the cutover window.

What the work includes

A migration to Redmine moves projects, issues, people and history from a source system into a new tracker that must still answer the same questions afterward. Each component below produces something you can review before cutover.

Source assessment and inventory

We catalog what the source system holds: projects, issue counts, custom fields, workflows, attachment volume, comment history and any plugins or scripts that write data. This inventory sets the scope and shows which records cannot move cleanly. Ask for the inventory to be reviewed by the people who own each project before mapping begins.

Field and status mapping

Each source field, issue type and status is matched to a Redmine tracker, custom field, status or workflow transition, and gaps are recorded as explicit decisions. Lossy mappings, such as several source statuses collapsing into one Redmine status, are listed so stakeholders accept them in writing. The result is a mapping specification that the import scripts follow.

User and group mapping

Source accounts are matched to Redmine users, and group memberships are translated into Redmine groups and roles. Where your directory is LDAP or Active Directory, the mapping decides whether imported users link to existing directory accounts or are created on first login. Confirm how inactive and duplicate accounts should be handled before import.

Project and tracker structure

Source projects, subprojects and components are translated into Redmine projects, hierarchies, trackers and enabled modules. This step also sets which members hold which roles, since Redmine access control depends on them. Decide whether historical projects are imported as active, archived or closed, because that affects visibility and reporting.

Scripted import through the REST API

Issues, journals (comments and field history), relations and attachments are loaded with scripts that call the Redmine REST API, which must be enabled by an administrator beforehand. Scripts run in batches with logged identifiers so a failed run can resume without duplicating records. Check how the source timestamps and author attribution are preserved in the imported history.

Validation and reconciliation reports

After each test and final run, reports compare record counts, identifiers, statuses, authors, dates and attachment checksums between source and target. Discrepancies are classified so they can be fixed in the mapping or accepted by the data owner. Ask for these reports to be retained as evidence of what was migrated and what was not.

Cutover runbook and handover

The cutover runbook sequences the source freeze, final delta import, validation sign-off, redirect or read-only setup for the old system, and rollback criteria. At handover, your administrators receive the mapping specification, import scripts, reconciliation reports and a cutover record that documents the final run. Confirm who owns the source system archive after cutover.

What drives cost and duration

This table lists the factors that most change the effort of a Jira, Trac, Mantis or Bugzilla move into Redmine, why each one adds work, and how to keep it under control.

DriverWhy it adds effortHow to reduce it
Source system and versionEach source has its own data model and export options. Built-in Redmine importers for Trac and Mantis are obsolete, so scripts or the REST API carry the load and must be written and tested for your exact version.Confirm the source version early, pick the extraction method (API, database export or dump), and test on a copy of real data before committing to a plan.
Volume of issues and attachmentsRow counts drive import run time, retries and validation sampling. Attachments add storage transfer, checksum checks and upload limits on the Redmine side.Measure counts per project before scoping. Import in batches by project and move large attachment sets as a separate, verified step.
Number of projects and custom fieldsEvery project, tracker and custom field needs a mapping decision, a target definition in Redmine and a check that values land in the right place. Mapping grows with each field.Retire unused projects and fields before migration. Map fields to existing Redmine custom fields where possible instead of creating new ones.
Workflow and status complexitySource workflows rarely match Redmine trackers, statuses and transitions one to one. Each gap needs a rule, a default or a manual decision, and rules can conflict.Agree a status and transition map with the business owners before scripting. Accept some simplification in historical data.
User identity matchingSource accounts must be matched to Redmine users by email or login. Duplicates, departed staff and service accounts create exceptions that need human review.Export the user list first, resolve duplicates and inactive accounts, and decide how unmatched authors are recorded before the first test run.
History and link preservationJournals, comments, cross-issue references, and links to commits or external systems each require their own mapping. Full history is the most expensive scope.Limit history scope to what users need, such as the last state and recent comments for open items. Document which links are rebuilt and which are kept as text.
Number of target environmentsEach environment needs its own import run, configuration checks and verification pass. Test, staging and production can repeat the same work.Script the import so the same run repeats in each environment. Keep a single dry-run environment for rehearsals and reuse the same validation checks.
Compliance or retention requirementsRetention rules, audit evidence of what was moved, and deletion of old data in the source add review, logging and sign-off steps.Confirm retention rules with the data owner before migration. Archive closed projects in read-only form and keep an import log that records counts and exceptions.

Project phases and outputs

The migration runs as eight phases, each closing with a written output that the next phase depends on, so cutover happens only after the data has been checked against the source.

  1. Discover and inventory the source system

    We and your team catalog the source projects, issue types, workflows, custom fields, users, groups, attachments and integrations, and record which data must move and which can be archived. The output is a signed inventory with record counts, data volumes and a list of items that have no clear equivalent in Redmine.

  2. Design the target Redmine configuration

    We design the target model on a Redmine 7.0.x instance: trackers, workflows, roles, custom fields, and how projects and subprojects are arranged. Your business owners approve the design. The output is a written configuration specification that names every tracker, status, role and field, so the import has a fixed target.

  3. Write the field mapping specification

    For each source object we define how it maps to a Redmine object, including status and priority translations, user matching rules, handling of closed or duplicate issues, and how comments, history and attachments are carried over. The output is a mapping document that your team reviews line by line before any code is run.

  4. Build and test the import on staging

    We write the scripted import, which creates records through the Redmine REST API, and run it against a staging instance built to match production. Problems such as failed attachments, unmatched users and encoding errors are logged and fixed in the script. The output is a repeatable import run with a log of every rejected record and its reason.

  5. Validate and reconcile the data

    We compare record counts, sample issues, attachment sizes and checksums, user assignments and history between source and target. Your business owners sign off on exceptions. The output is a reconciliation report that shows each difference, its cause and whether it was accepted or fixed.

  6. Rehearse the full cutover

    We run the complete sequence, from freezing the source to the final import, to the go-live checks, at least once on a copy of production data. We time each step using your own environment and record the issues found. The output is a runbook with owners, rollback points and a go or no-go checklist.

  7. Run the production cutover

    We freeze the source system, run the final import, repeat the reconciliation checks against production, and switch users to Redmine according to the runbook. Access to the old system is set according to your retention decision. The output is a completed cutover record with the reconciliation results attached.

  8. Support the post-cutover period

    We monitor the first working period after go-live for import defects, user access problems and missing data, and fix them under the agreed support terms. The output is a closure report that lists resolved issues, open items and the handover of the import scripts and documentation to your team.

What stays in-house and what goes to a partner

This table compares the migration decisions and tasks that teams usually keep in-house with those often outsourced, and lists the skills each one requires so you can see where your own staff are needed.

Work areaUsually kept in-houseOften outsourcedSkills required
Status and tracker decisionsDeciding which Jira, Trac, Mantis or Bugzilla statuses, issue types and priorities map to Redmine trackers and workflowsProposing a mapping draft from the source schema and flagging fields that have no Redmine equivalentRedmine administration for trackers and workflows; source system process knowledge
Mapping designApproving the final mapping of users, projects, versions and custom fieldsDesigning the field-by-field mapping document and identifying lossy conversionsSource system export knowledge; Redmine data model understanding; Redmine administration
Import script developmentReviewing script behavior and approving the data rules it appliesWriting the scripted import over the REST API, including idempotent re-runs and attachment handlingRuby or Python scripting; REST API client work; API key and permissions setup
Reconciliation toolingConfirming which counts, totals and sample records prove the migration is completeBuilding comparison reports between source and target counts, attachment checksums and orphaned referencesPython or Ruby scripting; database queries on PostgreSQL or MySQL; source export knowledge
Attachment and file storage handlingChoosing storage location and retention for migrated attachmentsTransferring files, verifying checksums and setting upload path permissionsFile storage operations; Linux administration; Redmine file directory layout
RehearsalsAttending dry runs, timing the steps and signing off the rehearsal resultsRunning full test migrations into a staging Redmine and logging defectsRedmine installation and upgrade experience; database backup and restore; scripting
User acceptance testingTesting real workflows, reports and permissions with business usersProviding test scripts and checking data integrity after each rehearsalDomain knowledge of the team's work; basic Redmine user skills
Access policy and cutover sign-offSetting role-based access, LDAP or SSO rules, and making the final go or no-go decisionPreparing the cutover runbook, freeze steps, rollback plan and post-cutover checksRedmine role and permission administration; LDAP or SSO configuration; change management

What usually goes wrong

Most migration problems are predictable and avoidable. Each card names a failure mode, the step that prevents it, and what to check before cutover.

Untested third-party migration scripts

Redmine's migration wiki describes the community scripts for systems such as Jira and Bugzilla as neither tested nor supported. Run any script against a copy of your data, review the code, and confirm it handles your tracker version, custom fields and workflow states. Check record counts per project against the source before accepting its output.

Lost attachments and inline references

Attachments can import as orphaned records, and links inside issue descriptions and comments often point at the old tool's URLs. Map every attachment to its new Redmine record, rewrite inline references to the new issue IDs, and open a sample of each attachment type after import to confirm it downloads and renders.

Mismatched user identities

If imported users do not match Redmine accounts, history shows the wrong author or reporter, and assignments point at the wrong person. Build an explicit mapping from source accounts to Redmine logins before the first test run, decide how to handle former staff, and check the authors on a sample of old issues.

Status and workflow gaps

Source statuses and transitions rarely match Redmine's trackers, statuses and workflows exactly. Unmapped states can fail the import or land as the wrong open or closed state. Map each source status to a Redmine status, confirm which roles may perform each transition, and verify that closed issues remain closed.

API rate and timeout failures

Scripted imports over the REST API can hit timeouts or throttling on large projects, leaving partial data behind. Import in batches, log every created ID, make each batch safe to retry, and reconcile totals after each run. Confirm the API is enabled for the migration account and that the server's timeouts suit your largest batch.

Importing into an unsupported Redmine branch

Redmine 7.0.x is the fully supported line, while 6.0.x receives only important security updates and 5.1.x and older are unsupported. Building the target on an older branch means migrating twice later. Install the current 7.0 release on a supported Ruby version, and confirm that every plugin you need supports it before loading data.

No rehearsal before cutover

A single import run on production data leaves no room to find mapping errors. Run at least one full rehearsal on a copy of the source data, time it, record every reconciliation difference, and have business users check their own projects. Repeat the rehearsal until the reconciliation report is clean.

Missing rollback plan

Without a defined rollback, a failed cutover can leave two systems accepting changes and no clean way back. Freeze the source for writes, take a backup of the new Redmine database and files before the import, and document who decides to roll back, how long that takes, and how users are told where to work.

How the work differs by starting point

Jira exports rarely arrive in a form Redmine can read directly, so the first decision is which export path your Jira edition and data volume support. Confirm the Jira version and deployment type (cloud or self-managed) before choosing one.

  • Export formats: Confirm whether you will use CSV, XML, JSON from the REST API, or a database-level extract, and whether attachments and comments are included.
  • Mapping hotspots: Issue types, custom fields, workflow statuses and priorities rarely match Redmine trackers, statuses and priorities one to one.
  • Users and watchers: Confirm how Jira accounts, including deactivated ones, will map to Redmine users and roles.
  • Links and history: Issue links, sub-tasks and changelog entries need an agreed treatment, because Redmine's relation model is narrower.
  • Version check: Confirm the Jira release, since export options and API behavior change between versions.

What you need to provide

The migration only moves as fast as the decisions and access you supply, so the first thing to settle is who owns each input and who signs off each stage. Read-only export or API access to the source system (Jira, Trac, Mantis or Bugzilla) comes from your side, along with a named business owner for every project being moved. That owner decides which projects, closed issues and attachments are in scope, and approves the mapped result before cutover.

Your team also decides the target model before any data is loaded. This means which trackers, statuses, workflows and custom fields Redmine will use, and how each source item type or status maps onto them. Each of these decisions should be recorded in writing and signed off by the project owners, because changing them after import means re-running the load. A directory or user list is needed for identity matching, so issue authors and assignees resolve to real Redmine accounts. Confirm whether users will be created from LDAP or from a file, and who approves that list.

On the Redmine side, an administrator must enable the REST API on a staging instance, since scripted import depends on it. Your team should also provide database and file storage access for attachments, plus a cutover window agreed in advance with the people who use the source system. Name one acceptance owner who signs off the validation report and the final cutover. Ask your partner to state, in the written scope, which person approves each stage: mapping, staging load, validation and production cutover.

Frequently asked questions

Can our team migrate to Redmine without an implementation partner?

Yes, if your team has Ruby on Rails or scripting skills, a staging server, and time to validate the data, but the work is more than copying files. Redmine is licensed under GPL v2, so the software itself has no license fee, and the main cost is staff time. The work involves mapping each source system's statuses, trackers, users and custom fields to Redmine equivalents, writing or adapting an import script, and proving the result in staging. Teams with an administrator who has run a platform migration before, and a named business owner for sign-off, often manage it internally. Confirm your team's capacity before you commit to the work.

Can we use Redmine's built-in importers for Jira, Trac, Mantis or Bugzilla?

Usually not for a current migration. The built-in importers for Trac and Mantis are marked obsolete and do not work, so they cannot be relied on. The migration wiki lists third-party scripts for systems such as Jira and Bugzilla, but the Redmine project describes those as neither tested nor supported. Treat them as starting points that you must review, adapt and test against your own data, including custom fields, workflows and history. Check the current state of any importer against the Redmine version you plan to run before you rely on it.

What drives the effort of a Redmine migration from another tracker?

The main drivers are the amount of customization in the source system and the condition of its data. Expect more work when:

  • Workflows, statuses and custom fields must map to Redmine trackers, roles and workflows.
  • Users must be matched to accounts, including duplicates, departed staff and shared logins.
  • Attachments are large, numerous or stored outside the database.
  • Issue links, subprojects and history must keep their relationships after the move.
  • Business owners must review samples from each project before sign-off.
Why is the Redmine REST API the usual route for migrating data?

The REST API is the usual route because requests pass through Redmine's own validation, and its core resources are marked stable. An administrator must enable the API first. Requests return JSON or XML and authenticate with HTTP basic authentication or a per-user API key, sent as a parameter or in the X-Redmine-API-Key header. Issues, projects, users and time entries are core resources, so a script can create them in a controlled order and record each new ID against its source record. Direct database inserts skip that validation, which makes errors harder to find. Confirm which resources and fields your Redmine version exposes before you design the script.

How are users and attachments handled when moving data into Redmine?

Users are matched or created first, and attachments are uploaded as part of the issues that own them. Each source user needs a Redmine account with the correct status, email address and group membership, so the script should map old identities to new user IDs before it writes any issue. If you use Redmine's LDAP support, authentication can stay in your directory, but imported accounts still need a plan for passwords and departed staff. Check attachment size limits, file types and storage paths against the target server settings. Verify each file after upload, and keep a mapping table that traces every migrated record back to its source.

How does a Redmine cutover avoid losing data?

A cutover avoids loss by running the import more than once, comparing results, and freezing the source before the final run. Trial imports against a staging copy should reconcile record counts and sample issues for each project until business owners accept the output. On cutover day, the source is set to read-only, a final delta import captures recent changes, and full backups of the source and the Redmine database are taken first. Keep the old system available in read-only mode for an agreed period so people can check history. Plan the rollback in advance, including who decides to use it and how the old system is restored.

How DeployOpen delivers Redmine migrations

DeployOpen scopes, builds, validates and hands over Redmine migrations from Jira, Trac, Mantis or Bugzilla in infrastructure you control. Each engagement follows a written scope, and the import runs through Redmine's REST API when the built-in importers no longer work.

How we scope

  • The written scope lists which source systems, projects, trackers, users and attachments move into Redmine.
  • Field mapping covers statuses, priorities, custom fields, versions and workflows agreed with your team before any data is loaded.
  • Engagements are fixed-scope, so deliverables and timelines are agreed in writing before work starts.

How we build

  • Import scripts run against the Redmine REST API, which your administrator must enable beforehand.
  • Test imports run into a non-production Redmine instance so mapping errors surface before the real load.
  • Attachments, user accounts and issue relationships are checked against the source export after each trial run.

How we hand over

  • Deliverables include the mapping specification, import scripts, validation reports and a cutover runbook.
  • Your team receives documented steps for rerunning the import, reconciling differences and rolling back a failed cutover.
  • Handover covers the access, credentials and API key handling your administrators need to operate the result.

How we support

  • Ongoing support is available as a retainer for questions that come up after the cutover window closes.
  • Support can cover Redmine upgrades to the supported 7.0 line, including plugin compatibility checks and database migrations.
  • Your team can ask for a post-cutover review of user access, issue history and attachment completeness.

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.