private function addCoreOptions()
 {
     $this->option['vanilla'] = Models\ServiceOptions::create(['parent_service' => $this->service->id, 'name' => 'Vanilla Minecraft', 'description' => 'Minecraft is a game about placing blocks and going on adventures. Explore randomly generated worlds and build amazing things from the simplest of homes to the grandest of castles. Play in Creative Mode with unlimited resources or mine deep in Survival Mode, crafting weapons and armor to fend off dangerous mobs. Do all this alone or with friends.', 'tag' => 'vanilla', 'docker_image' => 'quay.io/pterodactyl/minecraft', 'executable' => null, 'startup' => null]);
     $this->option['spigot'] = Models\ServiceOptions::create(['parent_service' => $this->service->id, 'name' => 'Spigot', 'description' => 'Spigot is the most widely-used modded Minecraft server software in the world. It powers many of the top Minecraft server networks around to ensure they can cope with their huge player base and ensure the satisfaction of their players. Spigot works by reducing and eliminating many causes of lag, as well as adding in handy features and settings that help make your job of server administration easier.', 'tag' => 'spigot', 'docker_image' => 'quay.io/pterodactyl/minecraft:spigot', 'executable' => null, 'startup' => '-Xms128M -Xmx{{SERVER_MEMORY}}M -Djline.terminal=jline.UnsupportedTerminal -jar {{SERVER_JARFILE}}']);
     $this->option['sponge'] = Models\ServiceOptions::create(['parent_service' => $this->service->id, 'name' => 'Sponge (SpongeVanilla)', 'description' => 'SpongeVanilla is the SpongeAPI implementation for Vanilla Minecraft.', 'tag' => 'spigot', 'docker_image' => 'quay.io/pterodactyl/minecraft:sponge', 'executable' => null, 'startup' => null]);
     $this->option['bungeecord'] = Models\ServiceOptions::create(['parent_service' => $this->service->id, 'name' => 'Bungeecord', 'description' => 'For a long time, Minecraft server owners have had a dream that encompasses a free, easy, and reliable way to connect multiple Minecraft servers together. BungeeCord is the answer to said dream. Whether you are a small server wishing to string multiple game-modes together, or the owner of the ShotBow Network, BungeeCord is the ideal solution for you. With the help of BungeeCord, you will be able to unlock your community\'s full potential.', 'tag' => 'bungeecord', 'docker_image' => 'quay.io/pterodactyl/minecraft:bungeecord', 'executable' => null, 'startup' => null]);
 }
Example #2
0
 public function view(Request $request, $id)
 {
     $service = Models\Service::find($id);
     if (!$service) {
         throw new NotFoundHttpException('No service by that ID was found.');
     }
     $options = Models\ServiceOptions::select('id', 'name', 'description', 'tag', 'docker_image')->where('parent_service', $service->id)->get();
     foreach ($options as &$opt) {
         $opt->variables = Models\ServiceVariables::where('option_id', $opt->id)->get();
     }
     return ['service' => $service, 'options' => $options];
 }
Example #3
0
 public function update($id, array $data)
 {
     $option = Models\ServiceOptions::findOrFail($id);
     $validator = Validator::make($data, ['name' => 'sometimes|required|string|max:255', 'description' => 'sometimes|required|string|min:1', 'tag' => 'sometimes|required|string|max:255', 'executable' => 'sometimes|string|max:255', 'docker_image' => 'sometimes|required|string|max:255', 'startup' => 'sometimes|string']);
     if ($validator->fails()) {
         throw new DisplayValidationException($validator->errors());
     }
     if (isset($data['executable']) && empty($data['executable'])) {
         $data['executable'] = null;
     }
     if (isset($data['startup']) && empty($data['startup'])) {
         $data['startup'] = null;
     }
     $option->fill($data);
     $option->save();
 }
Example #4
0
 public function delete($id)
 {
     $service = Models\Service::findOrFail($id);
     $servers = Models\Server::where('service', $service->id)->get();
     $options = Models\ServiceOptions::select('id')->where('parent_service', $service->id);
     if (count($servers) !== 0) {
         throw new DisplayException('You cannot delete a service that has servers associated with it.');
     }
     DB::beginTransaction();
     try {
         Models\ServiceVariables::whereIn('option_id', $options->get()->toArray())->delete();
         $options->delete();
         $service->delete();
         DB::commit();
     } catch (\Exception $ex) {
         DB::rollBack();
         throw $ex;
     }
 }
 private function addCoreOptions()
 {
     $this->option['tshock'] = Models\ServiceOptions::create(['parent_service' => $this->service->id, 'name' => 'Terraria Server (TShock)', 'description' => 'TShock is a server modification for Terraria, written in C#, and based upon the Terraria Server API. It uses JSON for configuration management, and offers several features not present in the Terraria Server normally.', 'tag' => 'tshock', 'docker_image' => 'quay.io/pterodactyl/terraria:tshock', 'executable' => '', 'startup' => '']);
 }
 private function addCoreOptions()
 {
     $this->option['mumble'] = Models\ServiceOptions::create(['parent_service' => $this->service->id, 'name' => 'Mumble Server', 'description' => 'Mumble is an open source, low-latency, high quality voice chat software primarily intended for use while gaming.', 'tag' => 'mumble', 'docker_image' => 'quay.io/pterodactyl/voice:mumble', 'executable' => './murmur.x86', 'startup' => '-fg']);
     $this->option['ts3'] = Models\ServiceOptions::create(['parent_service' => $this->service->id, 'name' => 'Teamspeak3 Server', 'description' => 'VoIP software designed with security in mind, featuring crystal clear voice quality, endless customization options, and scalabilty up to thousands of simultaneous users.', 'tag' => 'ts3', 'docker_image' => 'quay.io/pterodactyl/voice:ts3', 'executable' => './ts3server_minimal_runscript.sh', 'startup' => 'default_voice_port={{SERVER_PORT}} query_port={{SERVER_PORT}}']);
 }
Example #7
0
 /**
  * Adds a new server to the system.
  * @param   array  $data  An array of data descriptors for creating the server. These should align to the columns in the database.
  * @return  integer
  */
 public function create(array $data)
 {
     // Validate Fields
     $validator = Validator::make($data, ['owner' => 'required|email|exists:users,email', 'node' => 'required|numeric|min:1|exists:nodes,id', 'name' => 'required|regex:/^([\\w -]{4,35})$/', 'memory' => 'required|numeric|min:0', 'swap' => 'required|numeric|min:-1', 'io' => 'required|numeric|min:10|max:1000', 'cpu' => 'required|numeric|min:0', 'disk' => 'required|numeric|min:0', 'allocation' => 'numeric|exists:allocations,id|required_without:ip,port', 'ip' => 'required_without:allocation|ip', 'port' => 'required_without:allocation|numeric|min:1|max:65535', 'service' => 'required|numeric|min:1|exists:services,id', 'option' => 'required|numeric|min:1|exists:service_options,id', 'startup' => 'string', 'custom_image_name' => 'required_if:use_custom_image,on']);
     // Run validator, throw catchable and displayable exception if it fails.
     // Exception includes a JSON result of failed validation rules.
     if ($validator->fails()) {
         throw new DisplayValidationException($validator->errors());
     }
     // Get the User ID; user exists since we passed the 'exists:users,email' part of the validation
     $user = Models\User::select('id')->where('email', $data['owner'])->first();
     // Get Node Information
     $node = Models\Node::getByID($data['node']);
     // Verify IP & Port are a.) free and b.) assigned to the node.
     // We know the node exists because of 'exists:nodes,id' in the validation
     if (!isset($data['allocation'])) {
         $allocation = Models\Allocation::where('ip', $data['ip'])->where('port', $data['port'])->where('node', $data['node'])->whereNull('assigned_to')->first();
     } else {
         $allocation = Models\Allocation::where('id', $data['allocation'])->where('node', $data['node'])->whereNull('assigned_to')->first();
     }
     // Something failed in the query, either that combo doesn't exist, or it is in use.
     if (!$allocation) {
         throw new DisplayException('The selected IP/Port combination or Allocation ID is either already in use, or unavaliable for this node.');
     }
     // Validate those Service Option Variables
     // We know the service and option exists because of the validation.
     // We need to verify that the option exists for the service, and then check for
     // any required variable fields. (fields are labeled env_<env_variable>)
     $option = Models\ServiceOptions::where('id', $data['option'])->where('parent_service', $data['service'])->first();
     if (!$option) {
         throw new DisplayException('The requested service option does not exist for the specified service.');
     }
     // Load up the Service Information
     $service = Models\Service::find($option->parent_service);
     // Check those Variables
     $variables = Models\ServiceVariables::where('option_id', $data['option'])->get();
     $variableList = [];
     if ($variables) {
         foreach ($variables as $variable) {
             // Is the variable required?
             if (!$data['env_' . $variable->env_variable]) {
                 if ($variable->required === 1) {
                     throw new DisplayException('A required service option variable field (env_' . $variable->env_variable . ') was missing from the request.');
                 }
                 $variableList = array_merge($variableList, [['id' => $variable->id, 'env' => $variable->env_variable, 'val' => $variable->default_value]]);
                 continue;
             }
             // Check aganist Regex Pattern
             if (!is_null($variable->regex) && !preg_match($variable->regex, $data['env_' . $variable->env_variable])) {
                 throw new DisplayException('Failed to validate service option variable field (env_' . $variable->env_variable . ') aganist regex (' . $variable->regex . ').');
             }
             $variableList = array_merge($variableList, [['id' => $variable->id, 'env' => $variable->env_variable, 'val' => $data['env_' . $variable->env_variable]]]);
             continue;
         }
     }
     // Check Overallocation
     if (is_numeric($node->memory_overallocate) || is_numeric($node->disk_overallocate)) {
         $totals = Models\Server::select(DB::raw('SUM(memory) as memory, SUM(disk) as disk'))->where('node', $node->id)->first();
         // Check memory limits
         if (is_numeric($node->memory_overallocate)) {
             $newMemory = $totals->memory + $data['memory'];
             $memoryLimit = $node->memory * (1 + $node->memory_overallocate / 100);
             if ($newMemory > $memoryLimit) {
                 throw new DisplayException('The amount of memory allocated to this server would put the node over its allocation limits. This node is allowed ' . ($node->memory_overallocate + 100) . '% of its assigned ' . $node->memory . 'Mb of memory (' . $memoryLimit . 'Mb) of which ' . $totals->memory / $node->memory * 100 . '% (' . $totals->memory . 'Mb) is in use already. By allocating this server the node would be at ' . $newMemory / $node->memory * 100 . '% (' . $newMemory . 'Mb) usage.');
             }
         }
         // Check Disk Limits
         if (is_numeric($node->disk_overallocate)) {
             $newDisk = $totals->disk + $data['disk'];
             $diskLimit = $node->disk * (1 + $node->disk_overallocate / 100);
             if ($newDisk > $diskLimit) {
                 throw new DisplayException('The amount of disk allocated to this server would put the node over its allocation limits. This node is allowed ' . ($node->disk_overallocate + 100) . '% of its assigned ' . $node->disk . 'Mb of disk (' . $diskLimit . 'Mb) of which ' . $totals->disk / $node->disk * 100 . '% (' . $totals->disk . 'Mb) is in use already. By allocating this server the node would be at ' . $newDisk / $node->disk * 100 . '% (' . $newDisk . 'Mb) usage.');
             }
         }
     }
     DB::beginTransaction();
     try {
         $uuid = new UuidService();
         // Add Server to the Database
         $server = new Models\Server();
         $generatedUuid = $uuid->generate('servers', 'uuid');
         $server->fill(['uuid' => $generatedUuid, 'uuidShort' => $uuid->generateShort('servers', 'uuidShort', $generatedUuid), 'node' => $data['node'], 'name' => $data['name'], 'suspended' => 0, 'owner' => $user->id, 'memory' => $data['memory'], 'swap' => $data['swap'], 'disk' => $data['disk'], 'io' => $data['io'], 'cpu' => $data['cpu'], 'oom_disabled' => isset($data['oom_disabled']) ? true : false, 'allocation' => $allocation->id, 'service' => $data['service'], 'option' => $data['option'], 'startup' => $data['startup'], 'daemonSecret' => $uuid->generate('servers', 'daemonSecret'), 'username' => $this->generateSFTPUsername($data['name'])]);
         $server->save();
         // Mark Allocation in Use
         $allocation->assigned_to = $server->id;
         $allocation->save();
         // Add Variables
         $environmentVariables = [];
         $environmentVariables = array_merge($environmentVariables, ['STARTUP' => $data['startup']]);
         foreach ($variableList as $item) {
             $environmentVariables = array_merge($environmentVariables, [$item['env'] => $item['val']]);
             Models\ServerVariables::create(['server_id' => $server->id, 'variable_id' => $item['id'], 'variable_value' => $item['val']]);
         }
         $client = Models\Node::guzzleRequest($node->id);
         $client->request('POST', '/servers', ['headers' => ['X-Access-Token' => $node->daemonSecret], 'json' => ['uuid' => (string) $server->uuid, 'user' => $server->username, 'build' => ['default' => ['ip' => $allocation->ip, 'port' => (int) $allocation->port], 'ports' => [(string) $allocation->ip => [(int) $allocation->port]], 'env' => $environmentVariables, 'memory' => (int) $server->memory, 'swap' => (int) $server->swap, 'io' => (int) $server->io, 'cpu' => (int) $server->cpu, 'disk' => (int) $server->disk, 'image' => isset($data['custom_image_name']) ? $data['custom_image_name'] : $option->docker_image], 'service' => ['type' => $service->file, 'option' => $option->tag], 'keys' => [(string) $server->daemonSecret => $this->daemonPermissions], 'rebuild' => false]]);
         DB::commit();
         return $server->id;
     } catch (\GuzzleHttp\Exception\TransferException $ex) {
         DB::rollBack();
         throw new DisplayException('There was an error while attempting to connect to the daemon to add this server.', $ex);
     } catch (\Exception $ex) {
         DB::rollBack();
         Log:
         error($ex);
         throw $ex;
     }
 }
 private function addCoreOptions()
 {
     $this->option['insurgency'] = Models\ServiceOptions::create(['parent_service' => $this->service->id, 'name' => 'Insurgency', 'description' => 'Take to the streets for intense close quarters combat, where a team\'s survival depends upon securing crucial strongholds and destroying enemy supply in this multiplayer and cooperative Source Engine based experience.', 'tag' => 'srcds', 'docker_image' => 'quay.io/pterodactyl/srcds', 'executable' => null, 'startup' => '-game {{SRCDS_GAME}} -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} -strictportbind -norestart']);
     $this->option['tf2'] = Models\ServiceOptions::create(['parent_service' => $this->service->id, 'name' => 'Insurgency', 'description' => 'Team Fortress 2 is a team-based first-person shooter multiplayer video game developed and published by Valve Corporation. It is the sequel to the 1996 mod Team Fortress for Quake and its 1999 remake.', 'tag' => 'srcds', 'docker_image' => 'quay.io/pterodactyl/srcds', 'executable' => null, 'startup' => '-game {{SRCDS_GAME}} -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} -strictportbind -norestart']);
     $this->option['custom'] = Models\ServiceOptions::create(['parent_service' => $this->service->id, 'name' => 'Custom Source Engine Game', 'description' => 'This option allows modifying the startup arguments and other details to run a custo SRCDS based game on the panel.', 'tag' => 'srcds', 'docker_image' => 'quay.io/pterodactyl/srcds', 'executable' => null, 'startup' => null]);
 }
Example #9
0
 /**
  * Returns a JSON tree of all avaliable variables for a given service option.
  *
  * @param  \Illuminate\Http\Request $request
  * @return \Illuminate\Contracts\View\View
  */
 public function postNewServerServiceVariables(Request $request)
 {
     if (!$request->input('option')) {
         return response()->json(['error' => 'Missing option in request.'], 500);
     }
     $option = Models\ServiceOptions::select(DB::raw('COALESCE(service_options.executable, services.executable) as executable'), DB::raw('COALESCE(service_options.startup, services.startup) as startup'))->leftJoin('services', 'services.id', '=', 'service_options.parent_service')->where('service_options.id', $request->input('option'))->first();
     return response()->json(['variables' => Models\ServiceVariables::where('option_id', $request->input('option'))->get(), 'exec' => $option->executable, 'startup' => $option->startup]);
 }
Example #10
0
 public function getNewVariable(Request $request, $service, $option)
 {
     return view('admin.services.options.variable', ['service' => Models\Service::findOrFail($service), 'option' => Models\ServiceOptions::where('parent_service', $service)->where('id', $option)->firstOrFail()]);
 }