Install Plugins in Discourse

@molly_cushing, Your post was exactly what I needed! Thanks for putting this together.

I personally learn the best by watching someone do something so I created a video tutorial following the steps you outlined, for anyone who’d like to see the process in action:


I’m beginer in Discourse, and after cloned Disourse repository, can’t find container/app.yml fie.
Do I have to create new one?
And also the command “./launcher rebuild app” isn’t working cause there isn’t such file or directory named “launcher” in the project

Sounds like you didn’t fully installed Discourse, you need to follow all these commands : discourse/ at master · discourse/discourse · GitHub

After that, and only after, you can run these commands to install a plugin. You need to be in the discourse folder :
cd /var/discourse

After that, you can open the app file using nano
nano containers/app.yml

And still in the /var/discourse folder, you can run the command to complete the install (this command will take a few minutes)
./launcher rebuild app


There’s actually no need to sudo -s when updating your app.yml, a simple sudo nano containers/app.yml from within /var/discourse will suffice.

The ‘git pull’ is redundant here too.

@sivert If you ran discourse-setup as outlined in the official install guide an app.yml would be created for you at /var/discourse/containers/ with all the necessary settings to get Discourse running. Have you already done this? If so you need to move to /var/discourse before issuing the commands you mentioned above, a simple cd /var/discourse will suffice.

as … means ‘up a level’ it’s very rarely going to be the right way to get there.

1 Like

@Stephen Thanks for your answer. It seems I was confused between dev and pub versions.
Just now I was working on developing version in my MacOS system.
Can I continue follow this guid to test my plugins on developing version or is this thread for only production version and I have to find another way?

I just have followed this tutorial and can’t find any “container” directory or “./launcher” for rebuild command.
Please help me what am I wrong and how can I add plugin this development version.

1 Like

Did you do this? discourse/ at master · discourse/discourse · GitHub

Why cloud? Is it impossible to work with plugin on local development server?

For local you just need to clone the plugin you want under the /plugins directory and restart the web server.


Just circling back on the best way to handle the deployment of multiple private plugins (particularly if you do work for multiple clients), the way I handle this now is:

  1. Create a github “Machine User” for the client.
  1. Add the machine user as a collaborator to the private repo hosted in my Github account. This is a free (unpaid) Github account. Free accounts can be collaborators on private repos.

  2. Create a personal access token for the machine user.

  3. Use the machine user’s personal access token to install the plugin on the client’s server.

This approach:

  • Allows the plugin to be updated via /admin/upgrade
  • Does not cost anything extra
  • Does not expose all private repositories in your account to each client.

Note that Github seems supportive of this kind of use of their account system, see here:

Tip: Our terms of service state:

Accounts registered by “bots” or other automated methods are not permitted.

This means that you cannot automate the creation of accounts. But if you want to create a single machine user for automating tasks such as deploy scripts in your project or organization, that is totally cool.


You can create deploy keys on repositories - that would be much less work.

Indeed, however using deploy keys does not allow the private plugin to be updated via /admin/upgrade, as you have to use custom commands in the app.yml.


hahaha. I also using tab and you know it’s not working :joy:Using space for better, maybe I have been affected by Microsoft Word

Using mac and cannot find the directory. Returns -bash: cd: /var/discourse: No such file or directory

This guide is only about installing plugin in production systems.

In development you clone them into your /plugins directory.


6 posts were split to a new topic: Install plugin from private Git repository?

Is there a way to pin the version of the plugin (i.e. use a specified Git Tag or Branch or somewhat) ? This is essential in production.

Yep, e.g.:

  • git clone <full-plugin-url> -b "your-branch" : branch
  • git clone <full-plugin-url>/tree/<commit_sha> : commit

should work in app.yml. I use the former all the time for testing pull requests.


Have a plugin that installs and runs on a local Mac Docker fine, but seems to fail DO production install:

189:M 23 Aug 2019 23:26:33.015 # Redis is now ready to exit, bye bye...

Pups::ExecError: cd /var/www/discourse/plugins && get clone failed with return #<Process::Status: pid 362 exit 127>
Location of failure: /pups/lib/pups/exec_command.rb:112:in `spawn'
exec failed with the params {"cd"=>"$home/plugins", "cmd"=>["git clone", "git clone", "git clone", "git clone", "git clone", "git clone", "git clone", "git clone", "git clone", "get clone"]}

And when entering the app on the DO server it seems to install fine manually:

root@discourse-staging-app:/var/www/discourse/plugins# git clone
Cloning into 'procourse-memberships'...
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 2797 (delta 0), reused 2 (delta 0), pack-reused 2792
Receiving objects: 100% (2797/2797), 432.10 KiB | 0 bytes/s, done.
Resolving deltas: 100% (1409/1409), done.
Checking connectivity... done.

All plugins but the last one install fine:

    - exec:
        cd: $home/plugins
          - git clone
          - git clone
          - git clone
          - git clone
          - git clone
          - git clone
          - git clone
          - git clone
          - git clone
          - get clone

Suggestions, ideas?

Some lines of log above

189:M 23 Aug 2019 23:26:33.015 # Redis is now ready to exit, bye bye...

should contain the reason.