# Undefined method \`sub!' when visiting \`/admin/upgrade\`

**URL:** <https://meta.discourse.org/t/undefined-method-sub-when-visiting-admin-upgrade/274682>\
**Category:** Self-hosting\
**Created:** [August 10, 2023, 2:17pm UTC](https://meta.discourse.org/t/undefined-method-sub-when-visiting-admin-upgrade/274682 "2023-08-10T14:17:24Z")\
**Posts on this page:** 1\
**Showing post:** 10

<div class="post-metadata">

**Author:** ![kdambekalns](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/kdambekalns/32/120408_2.png) [@kdambekalns](https://meta.discourse.org/u/kdambekalns)\
**Post date:** [August 16, 2023, 9:36am UTC](https://meta.discourse.org/t/undefined-method-sub-when-visiting-admin-upgrade/274682/10 "2023-08-16T09:36:41Z")

</div>

This is how the plugins are installed from `app.yml`

```plaintext
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/discourse/discourse-chat-integration.git

```

There was an extra `mkdir plugins` as the first command, that’s why the (empty) `plugins` folder existed. I removed that leftover from the past years…

The folder for the packages installed as per the `app.yml` above all have a `.git` foler inside.

Coming back to listing the remote URLs… as `discourse` user:

```plaintext
discourse@ocean-app:/var/www/discourse/plugins$ for d in *; do echo "$d: $(git -C $d config --get remote.origin.url)"; done
chat:
discourse-chat-integration: https://github.com/discourse/discourse-chat-integration.git
discourse-details:
discourse-lazy-videos:
discourse-local-dates:
discourse-narrative-bot:
discourse-presence:
discourse-solved: https://github.com/discourse/discourse-solved.git
docker_manager: https://github.com/discourse/docker_manager.git
poll:
styleguide:

```

As `root` user:

```plaintext
root@ocean-app:/var/www/discourse/plugins# for d in *; do echo "$d: $(git -C $d config --get remote.origin.url)"; done
chat: https://github.com/discourse/discourse.git
discourse-chat-integration:
discourse-details: https://github.com/discourse/discourse.git
discourse-lazy-videos: https://github.com/discourse/discourse.git
discourse-local-dates: https://github.com/discourse/discourse.git
discourse-narrative-bot: https://github.com/discourse/discourse.git
discourse-presence: https://github.com/discourse/discourse.git
discourse-solved:
docker_manager: https://github.com/discourse/docker_manager.git
poll: https://github.com/discourse/discourse.git
styleguide: https://github.com/discourse/discourse.git

```

My guess: permissions are totally borked. Is this looking correct (inside the container)?

```plaintext
root@ocean-app:/var/www/discourse# ls -la
total 508
drwxr-xr-x 1 root root 4096 Aug 10 15:38 .
drwxr-xr-x 1 root root 4096 Jul 11 00:33 ..
drwxr-xr-x 1 root root 4096 Jul 11 00:34 app
drwxr-xr-x 1 root root 4096 Aug 10 14:36 bin
-rw-r--r-- 1 root root 316 Aug 10 14:36 Brewfile
drwxr-xr-x 1 root root 4096 Jul 11 00:34 .bundle
drwxr-xr-x 1 root root 4096 Aug 10 14:47 config
-rw-r--r-- 1 root root 304 Aug 10 14:36 config.ru
-rw-r--r-- 1 root root 1303 Aug 10 14:36 CONTRIBUTING.md
-rw-r--r-- 1 root root 2347 Aug 10 14:36 COPYRIGHT.md
lrwxrwxrwx 1 root root 10 Aug 10 14:36 d -> bin/docker
drwxr-xr-x 1 root root 4096 Aug 10 14:36 db
drwxr-xr-x 1 root root 4096 Aug 10 14:36 .devcontainer
-rw-r--r-- 1 root root 1315 Aug 10 14:36 discourse.sublime-project
drwxr-xr-x 1 root root 4096 Aug 10 14:36 docs
drwxr-xr-x 1 root root 4096 Aug 10 14:36 documentation
-rw-r--r-- 1 root root 305 Aug 10 14:36 .editorconfig
-rw-r--r-- 1 root root 334 Aug 10 14:36 .eslintignore
-rw-r--r-- 1 root root 1061 Aug 10 14:36 .eslintrc
-rw-r--r-- 1 root root 7146 Aug 10 14:36 Gemfile
-rw-r--r-- 1 root root 15678 Aug 10 14:36 Gemfile.lock
drwxr-xr-x 1 root root 4096 Aug 10 14:36 .git
-rw-r--r-- 1 root root 852 Aug 10 14:36 .gitattributes
-rw-r--r-- 1 root root 2205 Aug 10 14:36 .git-blame-ignore-revs
-rw-r--r-- 1 root root 272 Aug 10 15:38 .gitconfig
drwxr-xr-x 1 root root 4096 Aug 10 14:36 .github
-rw-r--r-- 1 root root 1282 Aug 10 14:36 .gitignore
drwxr-xr-x 1 root root 4096 Aug 10 14:36 images
-rw-r--r-- 1 root root 279 Aug 10 14:36 jsconfig.base.json
-rw-r--r-- 1 root root 432 Aug 10 14:36 .jsdoc
-rw-r--r-- 1 root root 1937 Aug 10 14:36 lefthook.yml
drwxr-xr-x 1 root root 12288 Aug 10 14:36 lib
-rw-r--r-- 1 root root 1470 Aug 10 14:36 .licensed.yml
-rw-r--r-- 1 root root 375 Aug 10 14:36 .licensee.json
-rw-r--r-- 1 root root 18092 Aug 10 14:36 LICENSE.txt
drwxr-xr-x 1 root root 4096 Aug 10 14:36 log
drwxr-xr-x 1 root root 20480 Aug 10 14:37 node_modules
-rw-r--r-- 1 root root 21 Aug 10 14:36 .npmrc
-rw-r--r-- 1 root root 3114 Aug 10 14:36 package.json
drwxr-xr-x 1 discourse discourse 4096 Aug 16 08:44 plugins
-rw-r--r-- 1 root root 728 Aug 10 14:36 .prettierignore
-rw-r--r-- 1 root root 283 Aug 10 14:36 .prettierrc
drwxr-xr-x 1 root root 4096 Aug 14 00:42 public
-rwxr-xr-x 1 root root 305 Aug 10 14:36 Rakefile
-rw-r--r-- 1 root root 6753 Aug 10 14:36 README.md
-rw-r--r-- 1 root root 25 Aug 10 14:36 .rspec
-rw-r--r-- 1 root root 246 Aug 10 14:36 .rspec_parallel
-rw-r--r-- 1 root root 290 Aug 10 14:36 .rubocop.yml
-rw-r--r-- 1 root root 10 Aug 10 14:36 .ruby-gemset.sample
-rw-r--r-- 1 root root 6 Aug 10 14:36 .ruby-version.sample
drwxr-xr-x 1 root root 4096 Aug 10 14:36 script
drwxr-xr-x 1 root root 4096 Aug 10 14:36 spec
-rw-r--r-- 1 root root 66 Aug 10 14:36 .streerc
-rw-r--r-- 1 root root 1054 Aug 10 14:36 .template-lintrc.js
drwxr-xr-x 1 root root 4096 Aug 10 14:36 test
drwxr-xrwx 1 discourse discourse 4096 Aug 10 15:16 tmp
-rw-r--r-- 1 root root 2575 Aug 10 14:36 translator.yml
drwxr-xr-x 1 root root 4096 Jul 11 00:34 vendor
drwxr-xr-x 1 root root 4096 Aug 10 14:36 .vscode-sample
-rw-r--r-- 1 root root 204458 Aug 10 14:36 yarn.lock

```

What is the expected ownership/permissions setup?

---

_[View the full topic](https://meta.discourse.org/t/undefined-method-sub-when-visiting-admin-upgrade/274682)._
