Comment on page
⛲
Setting up plugins mount
Learn how to setup plugins repository as a mount for your Pterodactyl servers.
In order for your players to be able to install plugins via plugin management GUI, we need to mount the plugins repository folder to each of your virtualised containers (servers).
Unfortunately, Pterodactyl doesn't provide an API for that at the moment (until v2 is out), so we will need to perform a quick modification on your Pterodactyl's code.
You will need to perform these modifications every time you update Pterodactyl.
- 2.Open up
app/Http/Controllers/Api/Application/Servers/ServerManagementController.php
preferably using some sort of text editor, like VSCode or Notepad++.- 1.If you're a more advanced user, just making sure to merge this differences will be enough. For everyone else, please carefully follow the instructions below.
- 2.Below all imports, paste
use Pterodactyl\Models\MountServer;
Your imports should look like the following:ServerManagementController.php1<?php23namespace Pterodactyl\Http\Controllers\Api\Application\Servers;45use Illuminate\Http\Response;6use Pterodactyl\Models\Server;7use Pterodactyl\Services\Servers\SuspensionService;8use Pterodactyl\Services\Servers\ReinstallServerService;9use Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest;10use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;11use Pterodactyl\Models\MountServer; # This is the line we added - 3.Below reinstall function, paste the following code block:ServerManagementController.phppublic function mount(ServerWriteRequest $request, Server $server): Response{$mountServer = (new MountServer())->forceFill(['mount_id' => $request->input('mount_id'),'server_id' => $server->id,]);$mountServer->saveOrFail();return $this->returnNoContent();}
- 4.The end result will be the following file (which you may as well just copy and replace your whole file contents with, but a more manual approach like in steps 1 and 2 is recommended):ServerManagementController.php1<?php23namespace Pterodactyl\Http\Controllers\Api\Application\Servers;45use Illuminate\Http\Response;6use Pterodactyl\Models\Server;7use Pterodactyl\Services\Servers\SuspensionService;8use Pterodactyl\Services\Servers\ReinstallServerService;9use Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest;10use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;11use Pterodactyl\Models\MountServer; # This is the line we added1213class ServerManagementController extends ApplicationApiController14{15/**16* ServerManagementController constructor.17*/18public function __construct(19private ReinstallServerService $reinstallServerService,20private SuspensionService $suspensionService21) {22parent::__construct();23}2425/**26* Suspend a server on the Panel.27*28* @throws \Throwable29*/30public function suspend(ServerWriteRequest $request, Server $server): Response31{32$this->suspensionService->toggle($server);3334return $this->returnNoContent();35}3637/**38* Unsuspend a server on the Panel.39*40* @throws \Throwable41*/42public function unsuspend(ServerWriteRequest $request, Server $server): Response43{44$this->suspensionService->toggle($server, SuspensionService::ACTION_UNSUSPEND);4546return $this->returnNoContent();47}4849/**50* Mark a server as needing to be reinstalled.51*52* @throws \Pterodactyl\Exceptions\DisplayException53* @throws \Pterodactyl\Exceptions\Model\DataValidationException54* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException55*/56public function reinstall(ServerWriteRequest $request, Server $server): Response57{58$this->reinstallServerService->handle($server);5960return $this->returnNoContent();61}6263# Our mount function64public function mount(ServerWriteRequest $request, Server $server): Response65{66$mountServer = (new MountServer())->forceFill([67'mount_id' => $request->input('mount_id'),68'server_id' => $server->id,69]);7071$mountServer->saveOrFail();7273return $this->returnNoContent();74}75}
- 3.Now navigate to app/routes/api-application.php and open it.
- 1.Below the following line:Route::post('/{server:id}/reinstall', [Application\Servers\ServerManagementController::class, 'reinstall'])->name('api.application.servers.reinstall');Paste this lineRoute::post('/{server:id}/mount', [Application\Servers\ServerManagementController::class, 'mount'])->name('api.application.servers.mount');
- 2.The end result should look like the following. You can also just use it to completely copy-paste the content to your api-application.php, but a more manual approach like in step 1 is preferred as Pterodactyl may do additional modifications to this file in the future.api-application.php1<?php23use Illuminate\Support\Facades\Route;4use Pterodactyl\Http\Controllers\Api\Application;56/*7|--------------------------------------------------------------------------8| User Controller Routes9|--------------------------------------------------------------------------10|11| Endpoint: /api/application/users12|13*/1415Route::group(['prefix' => '/users'], function () {16Route::get('/', [Application\Users\UserController::class, 'index'])->name('api.application.users');17Route::get('/{user:id}', [Application\Users\UserController::class, 'view'])->name('api.application.users.view');18Route::get('/external/{external_id}', [Application\Users\ExternalUserController::class, 'index'])->name('api.application.users.external');1920Route::post('/', [Application\Users\UserController::class, 'store']);21Route::patch('/{user:id}', [Application\Users\UserController::class, 'update']);2223Route::delete('/{user:id}', [Application\Users\UserController::class, 'delete']);24});2526/*27|--------------------------------------------------------------------------28| Node Controller Routes29|--------------------------------------------------------------------------30|31| Endpoint: /api/application/nodes32|33*/34Route::group(['prefix' => '/nodes'], function () {35Route::get('/', [Application\Nodes\NodeController::class, 'index'])->name('api.application.nodes');36Route::get('/deployable', Application\Nodes\NodeDeploymentController::class);37Route::get('/{node:id}', [Application\Nodes\NodeController::class, 'view'])->name('api.application.nodes.view');38Route::get('/{node:id}/configuration', Application\Nodes\NodeConfigurationController::class);3940Route::post('/', [Application\Nodes\NodeController::class, 'store']);41Route::patch('/{node:id}', [Application\Nodes\NodeController::class, 'update']);4243Route::delete('/{node:id}', [Application\Nodes\NodeController::class, 'delete']);4445Route::group(['prefix' => '/{node:id}/allocations'], function () {46Route::get('/', [Application\Nodes\AllocationController::class, 'index'])->name('api.application.allocations');47Route::post('/', [Application\Nodes\AllocationController::class, 'store']);48Route::delete('/{allocation:id}', [Application\Nodes\AllocationController::class, 'delete'])->name('api.application.allocations.view');49});50});5152/*53|--------------------------------------------------------------------------54| Location Controller Routes55|--------------------------------------------------------------------------56|57| Endpoint: /api/application/locations58|59*/60Route::group(['prefix' => '/locations'], function () {61Route::get('/', [Application\Locations\LocationController::class, 'index'])->name('api.applications.locations');62Route::get('/{location:id}', [Application\Locations\LocationController::class, 'view'])->name('api.application.locations.view');6364Route::post('/', [Application\Locations\LocationController::class, 'store']);65Route::patch('/{location:id}', [Application\Locations\LocationController::class, 'update']);6667Route::delete('/{location:id}', [Application\Locations\LocationController::class, 'delete']);68});6970/*71|--------------------------------------------------------------------------72| Server Controller Routes73|--------------------------------------------------------------------------74|75| Endpoint: /api/application/servers76|77*/78Route::group(['prefix' => '/servers'], function () {79Route::get('/', [Application\Servers\ServerController::class, 'index'])->name('api.application.servers');80Route::get('/{server:id}', [Application\Servers\ServerController::class, 'view'])->name('api.application.servers.view');81Route::get('/external/{external_id}', [Application\Servers\ExternalServerController::class, 'index'])->name('api.application.servers.external');8283Route::patch('/{server:id}/details', [Application\Servers\ServerDetailsController::class, 'details'])->name('api.application.servers.details');84Route::patch('/{server:id}/build', [Application\Servers\ServerDetailsController::class, 'build'])->name('api.application.servers.build');85Route::patch('/{server:id}/startup', [Application\Servers\StartupController::class, 'index'])->name('api.application.servers.startup');8687Route::post('/', [Application\Servers\ServerController::class, 'store']);88Route::post('/{server:id}/suspend', [Application\Servers\ServerManagementController::class, 'suspend'])->name('api.application.servers.suspend');89Route::post('/{server:id}/unsuspend', [Application\Servers\ServerManagementController::class, 'unsuspend'])->name('api.application.servers.unsuspend');90Route::post('/{server:id}/reinstall', [Application\Servers\ServerManagementController::class, 'reinstall'])->name('api.application.servers.reinstall');91# The line we added (below)92Route::post('/{server:id}/mount', [Application\Servers\ServerManagementController::class, 'mount'])->name('api.application.servers.mount');9394Route::delete('/{server:id}', [Application\Servers\ServerController::class, 'delete']);95Route::delete('/{server:id}/{force?}', [Application\Servers\ServerController::class, 'delete']);9697// Database Management Endpoint98Route::group(['prefix' => '/{server:id}/databases'], function () {99Route::get('/', [Application\Servers\DatabaseController::class, 'index'])->name('api.application.servers.databases');100Route::get('/{database:id}', [Application\Servers\DatabaseController::class, 'view'])->name('api.application.servers.databases.view');101102Route::post('/', [Application\Servers\DatabaseController::class, 'store']);103Route::post('/{database:id}/reset-password', [Application\Servers\DatabaseController::class, 'resetPassword']);104105Route::delete('/{database:id}', [Application\Servers\DatabaseController::class, 'delete']);106});107});108109/*110|--------------------------------------------------------------------------111| Nest Controller Routes112|--------------------------------------------------------------------------113|114| Endpoint: /api/application/nests115|116*/117Route::group(['prefix' => '/nests'], function () {118Route::get('/', [Application\Nests\NestController::class, 'index'])->name('api.application.nests');119Route::get('/{nest:id}', [Application\Nests\NestController::class, 'view'])->name('api.application.nests.view');120121// Egg Management Endpoint122Route::group(['prefix' => '/{nest:id}/eggs'], function () {123Route::get('/', [Application\Nests\EggController::class, 'index'])->name('api.application.nests.eggs');124Route::get('/{egg:id}', [Application\Nests\EggController::class, 'view'])->name('api.application.nests.eggs.view');125});126});
- 4.Now cd into your Pterodactyl folder via the following command:
cd /var/www/pterodactyl
- 5.Execute the following commands:root@pterodactyl:/var/www/pterodactyl# php artisan optimize:clearINFO Clearing cached bootstrap files.events .................................................................................................................................. 5ms DONEviews ................................................................................................................................... 6ms DONEcache ................................................................................................................................... 6ms DONEroute ................................................................................................................................... 1ms DONEconfig .................................................................................................................................. 1ms DONEcompiled ................................................................................................................................ 2ms DONEroot@pterodactyl:/var/www/pterodactyl# php artisan optimizeINFO Caching the framework bootstrap files.config ................................................................................................................................. 25ms DONEroutes ................................................................................................................................. 59ms DONE
- 6.After that's done, we can now create our mount. Go to the mounts tab on your Pterodactyl admin panel and click the Create New and fill the fields as in the following example. Make sure to name Target folder as /plugins-repo. Source folder should be set to the path of your plugins folder.Mount creation example
Last modified 7mo ago