How to recreate symlinks to path-based plugins after moving to live server? I have a couple of custom plugins for a site, which I successfully added by using path repositories in my composer.json file. However, when I upload the site to my staging server (via FTP - no SSH access or Git on this server), the symlinks in craft/vendor/myvendorname (which are automatically created during any composer update) won't upload. Thus, my site breaks, trying to load plugins which it cannot find.

I can manually upload the actual folders to that location (which is my fix for now), but that's not sustainable on an ongoing basis really.

Is there some way I can force Craft (or really Composer I suppose) to recreate those symlinks on the remote server? Or is this a case where I simply need SSH access so I can do it manually?
Symlinks won't transfer over FTP and I'm like 98% sure there isn't a way to get Craft to re-create those symlinks natively.

So you'd need SSH access to the box with Composer installed in the terminal.  Then you could upload your custom plugins, composer.json and run composer update or upload composer.json and composer.lock and run composer install to have the dependencies pulled down and the symlinks re-created.

Alternatively, and this is probably cleaner, you can setup a vcs type of repository in your composer.json file, along side your path repository.  https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository

They'd both point to the same plugin.  When you deploy to production, Composer should see that the path repo doesn't resolve to a valid path on the production file system and move onto the vcs repo for the same plugin and pull the files down that way.

It's compatible with private repositories, too: https://getcomposer.org/doc/05-repositories.md#using-private-repositories and you can setup Github access tokens if you'd rather go that way: https://www.previousnext.com.au/blog/managing-composer-github-access-personal-access-tokens