How to install a Redmine plugin

Redmine plugins add project management features that are not part of the core application. A safe install places the plugin code under the active application root, runs any database migrations shipped with the plugin, and restarts Redmine so Rails loads the new code.

Work from a shell in the Redmine application root, the directory that contains config.ru, Gemfile, and plugins. The root path depends on the deployment, so use the directory for the running instance rather than copying examples blindly.

Plugin migrations can change the production database, and plugin code runs inside the Redmine process after restart. Install a plugin release that lists compatibility with the running Redmine version, back up the database and uploaded files first, and keep the old plugin directory out of the active path until rollback is no longer needed.

Steps to install a Redmine plugin:

  1. Open a shell on the Redmine host as the application user.
  2. Change to the Redmine application root.
    $ cd /usr/src/redmine

    Replace /usr/src/redmine with the root directory for the running instance. Source installs often use /opt/redmine or /var/www/redmine, package installs may use /usr/share/redmine, and the official container image uses /usr/src/redmine.

  3. Confirm the active Redmine root.
    $ ls config.ru Gemfile plugins/README
    Gemfile
    config.ru
    plugins/README
  4. Back up Redmine before changing plugin code or database tables.

    Back up both the database and uploaded files. Plugin migrations can create or change tables, and a file-only backup cannot reverse those database changes.
    Related: How to back up and restore Redmine

  5. Copy the unpacked plugin directory into plugins.
    $ cp -a /tmp/plugin_install_demo plugins/plugin_install_demo

    Replace /tmp/plugin_install_demo with the extracted plugin release directory. Avoid copying an extra wrapper directory; plugins/plugin_install_demo/init.rb should exist after the copy.

  6. Confirm the plugin entry file is at the top level of the copied directory.
    $ ls plugins/plugin_install_demo/init.rb
    plugins/plugin_install_demo/init.rb

    The sample plugin directory is plugin_install_demo. Use the exact directory name required by the plugin maintainer, because many plugins register controllers, assets, and migrations from that name.

  7. Install any Ruby gems required by the plugin.
    $ bundle install
    Bundle complete! 53 Gemfile dependencies, 96 gems now installed.
    Gems in the groups 'development' and 'test' were not installed.

    The exact dependency count changes by Redmine and plugin version. Keep the deployment's existing Bundler settings, especially excluded groups such as development and test.

  8. Run plugin database migrations.
    $ bundle exec rake redmine:plugins:migrate RAILS_ENV=production
    == 1 CreatePluginInstallDemoNotes: migrating ==================================
    -- create_table(:plugin_install_demo_notes)
       -> 0.0010s
    == 1 CreatePluginInstallDemoNotes: migrated (0.0010s) =========================

    Run this from the Redmine application root after the backup is complete. Failed migrations can leave plugin tables partially changed and should be resolved before restarting production traffic.

  9. Restart the Redmine application server.

    Use the restart path for the deployment, such as the systemd unit for Puma, the web server that runs Passenger, or the Redmine container service.

  10. Check that Redmine responds after restart.
    $ curl --head http://127.0.0.1:3000/
    HTTP/1.1 200 OK
    ##### snipped #####

    Use the local URL, virtual host, or container port for the running instance. A 200 OK response confirms the application booted after loading the plugin.

  11. Confirm Rails can find the plugin registration.
    $ bundle exec rails runner -e production "puts Redmine::Plugin.find(:plugin_install_demo).name"
    Plugin Install Demo
  12. Open AdministrationPlugins in Redmine and confirm the plugin appears.

    If the plugin adds a project module or role permission, enable that feature in the plugin's documented location and load one page that uses it before handing the instance back to users.