Starting CRUD server

main
anulax1225 ago%!(EXTRA string=2 months)
parent 662f2909f3
commit 99a810c02b
  1. 32
      Servers/ArkServer/Dockerfile
  2. 0
      Servers/ArkServer/pre-run.sh
  3. 4
      Servers/ArkServer/run.sh
  4. 18
      Servers/MinecraftBedrock/Dockerfile
  5. BIN
      Servers/MinecraftBedrock/bedrock-server-1.21.60.10.zip
  6. 2
      Servers/MinecraftJava/Dockerfile
  7. 34
      app/Console/Kernel.php
  8. 36
      app/Docker/Container.php
  9. 9
      app/Docker/Docker.php
  10. 56
      app/Docker/Exec.php
  11. 96
      app/Http/Controllers/ServerController.php
  12. 65
      app/Jobs/InitServer.php
  13. 13
      app/Models/ExposedPort.php
  14. 53
      app/Models/Server.php
  15. 22
      app/Models/Service.php
  16. 15
      app/Models/Spec.php
  17. 13
      app/Models/Status.php
  18. 5
      app/Models/User.php
  19. 40
      app/Netstat.php
  20. 45
      config/docker.php
  21. 1
      database/migrations/0001_01_01_000000_create_users_table.php
  22. 32
      database/migrations/2025_02_14_231757_create_ports_table.php
  23. 62
      database/migrations/2025_02_14_231822_create_services_table.php
  24. 50
      database/migrations/2025_02_14_231846_create_server_statuses_table.php
  25. 54
      database/migrations/2025_02_14_232205_create_specs_table.php
  26. 39
      database/migrations/2025_02_14_234835_create_servers_table.php
  27. 32
      database/migrations/2025_02_16_230802_create_server_exposed_port.php
  28. 4
      public/icons/arrow-icon.svg
  29. 4
      public/icons/auto-icon.svg
  30. 5
      public/icons/copy-icon.svg
  31. 8
      public/icons/delete-icon.svg
  32. 11
      public/icons/details-icon.svg
  33. 4
      public/icons/edit-icon.svg
  34. 34
      public/icons/game-icon.svg
  35. 2
      public/icons/hardware-icon.svg
  36. 4
      public/icons/link-icon.svg
  37. 37
      public/icons/play-icon.svg
  38. 2
      public/icons/process-icon.svg
  39. 5
      public/icons/public-icon.svg
  40. 2
      public/icons/rocket-icon.svg
  41. 14
      public/icons/security-icon.svg
  42. 4
      public/icons/server-icon.svg
  43. 4
      public/icons/share-icon.svg
  44. 2
      public/icons/start-icon.svg
  45. 17
      public/icons/stats-icon.svg
  46. 4
      public/icons/status-icon.svg
  47. 4
      public/icons/stop-icon.svg
  48. 5
      public/icons/user.svg
  49. BIN
      public/img/ark.avif
  50. BIN
      public/img/ark.jpeg
  51. BIN
      public/img/banner.jpg
  52. BIN
      public/img/logo.png
  53. BIN
      public/img/minecraft-bedrock.webp
  54. BIN
      public/img/minecraft-java.webp
  55. 41
      resources/css/app.css
  56. 2
      resources/js/Components/TextInput.vue
  57. 17
      resources/js/Layouts/Layout.vue
  58. 14
      resources/js/Pages/Auth/Login.vue
  59. 30
      resources/js/Pages/Dashboard.vue
  60. 58
      resources/js/Pages/Home.vue
  61. 39
      resources/js/Pages/Server/Create.vue
  62. 29
      resources/js/Pages/Server/Index.vue
  63. 49
      resources/js/Pages/Server/Paritals/ServerElement.vue
  64. 132
      resources/js/Pages/Server/Show.vue
  65. 2
      resources/views/app.blade.php
  66. 18
      routes/console.php
  67. 38
      routes/web.php
  68. 1
      storage/framework/sessions/jI3U5ZEiiHFkCvRoPtnLUtIXez0iMLTTjvzivOpi
  69. 11
      svg
  70. 27
      text.json

@ -0,0 +1,32 @@
FROM ubuntu:latest
WORKDIR /app
COPY ./run.sh ./run.sh
RUN apt -y update
RUN apt -y upgrade
RUN apt -y install sudo software-properties-common
RUN dpkg --add-architecture i386
RUN apt-add-repository multiverse
RUN apt -y update
RUN echo steam steam/question select "I AGREE" | sudo debconf-set-selections
RUN echo steam steam/license note '' | sudo debconf-set-selections
RUN apt install -y steamcmd lib32gcc-s1
RUN echo "fs.file-max=100000" > /etc/sysctl.conf
RUN echo "* soft nofile 100000" > /etc/security/limits.conf
RUN echo "* hard nofile 100000" > /etc/security/limits.conf
RUN echo "session required pam_limits.so" > /etc/pam.d/common-session
RUN useradd -m ark
RUN chown -R ark:ark .
RUN sudo -u ark -s
RUN chmod +x ./run.sh
RUN ulimit -n 100000
RUN /usr/games/steamcmd +force_install_dir /app +login anonymous +app_update 376030 validate +exit
#RUN chmod +x ./ShooterGame/Binaries/Linux/ShooterGameServer
ENTRYPOINT [ "./run.sh" ]

@ -0,0 +1,4 @@
#!/bin/bash
#./ShooterGame/Binaries/Linux/ShooterGameServer TheIsland?listen?SessionName=ArkServer?ServerPassword=123456?ServerAdminPassword=123456 -server -log -crossplay
./ShooterGame/Binaries/Linux/ShooterGameServer TheIsland?listen?SessionName=ArkServer -server -log -crossplay

@ -0,0 +1,18 @@
FROM ubuntu:latest
WORKDIR /app
ENV LD_LIBRARY_PATH=.
COPY ./bedrock-server-1.21.60.10.zip ./bedrock-server.zip
RUN apt -y update
RUN apt -y upgrade
RUN apt install -y 7zip curl
RUN 7z x ./bedrock-server.zip
RUN chmod +x ./bedrock_server
RUN rm -rf ./bedrock-server.zip
VOLUME [ "/app" ]
ENTRYPOINT [ "./bedrock_server" ]

@ -2,13 +2,11 @@ FROM ubuntu:latest
WORKDIR /app WORKDIR /app
RUN apt -y update RUN apt -y update
RUN apt -y upgrade RUN apt -y upgrade
RUN apt install -y default-jre wget RUN apt install -y default-jre wget
RUN wget https://piston-data.mojang.com/v1/objects/4707d00eb834b446575d89a61a11b5d548d8c001/server.jar RUN wget https://piston-data.mojang.com/v1/objects/4707d00eb834b446575d89a61a11b5d548d8c001/server.jar
RUN echo 'eula=true' > eula.txt RUN echo 'eula=true' > eula.txt
VOLUME [ "/app" ] VOLUME [ "/app" ]
ENTRYPOINT ["java", "-Xmx2048M", "-Xms1024M", "-jar", "./server.jar", "nogui"] ENTRYPOINT ["java", "-Xmx2048M", "-Xms1024M", "-jar", "./server.jar", "nogui"]

@ -0,0 +1,34 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->call(function() {
Log::info("Hello");
})->everyThreeMinutes();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}

@ -3,6 +3,7 @@
namespace App\Docker; namespace App\Docker;
use Exception; use Exception;
use Illuminate\Support\Facades\Log;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use React\Http\Browser; use React\Http\Browser;
use React\Socket\FixedUriConnector; use React\Socket\FixedUriConnector;
@ -83,7 +84,7 @@ public function kill($context)
public function inspect($size = false) public function inspect($size = false)
{ {
try { try {
$response = await($this->browser->post( $response = await($this->browser->get(
Docker::endpoint("/containers/" . $this->id . "/json?size=" . $size), Docker::endpoint("/containers/" . $this->id . "/json?size=" . $size),
[ "Content-Type" => "text/plain" ] [ "Content-Type" => "text/plain" ]
)); ));
@ -93,13 +94,44 @@ public function inspect($size = false)
} }
} }
public function logs($args = [])
{
try {
$response = await($this->browser->requestStreaming("GET",
Docker::endpoint("/containers/" . $this->id . "/logs?stdout=true?stderr=true"),
[ "Content-Type" => "text/plain" ]
));
return $response->getBody();
} catch (Exception $e) {
throw $e;
}
}
public function exec($command)
{
try {
$response = await($this->browser->post(
Docker::endpoint("/containers/" . $this->id . "/exec"),
[ "Content-Type" => "application/json" ],
json_encode([
'AttachStdout' => true,
'AttachStderr' => true,
'Cmd' => $command
])
));
return new Exec(json_decode($response->getBody())->Id);
} catch (Exception $e) {
throw $e;
}
}
public static function create($name, $config) public static function create($name, $config)
{ {
try { try {
$connection = Docker::connect(); $connection = Docker::connect();
$response = await($connection->browser->post(Docker::endpoint('/containers/create?name='. $name), $response = await($connection->browser->post(Docker::endpoint('/containers/create?name='. $name),
[ "Content-Type" => "application/json" ], [ "Content-Type" => "application/json" ],
json_encode($config) json_encode($config, JSON_UNESCAPED_SLASHES)
)); ));
$data = json_decode($response->getBody()); $data = json_decode($response->getBody());
$container = new Container($data->Id); $container = new Container($data->Id);

@ -6,21 +6,24 @@
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use React\Http\Browser; use React\Http\Browser;
use React\Socket\FixedUriConnector; use React\Socket\FixedUriConnector;
use React\Socket\ConnectorInterFace; use React\Socket\Connector;
use React\Socket\UnixConnector; use React\Socket\UnixConnector;
use function React\Async\await; use function React\Async\await;
class Docker class Docker
{ {
static protected $connection = null;
public static function connect($fromSocket = true, $socket = 'unix:///var/run/docker.sock') public static function connect($fromSocket = true, $socket = 'unix:///var/run/docker.sock')
{ {
$connector = $fromSocket ? new FixedUriConnector( $connector = $fromSocket ? new FixedUriConnector(
$socket, $socket,
new UnixConnector() new UnixConnector()
) : new ConnectorInterface(); ) : null;
$browser = new Browser($connector); $browser = new Browser($connector);
return (object)[ "connector" => $connector, "browser" => $browser ]; Docker::$connection = (object)[ "connector" => $connector, "browser" => $browser ];
return Docker::$connection;
} }
public static function endpoint($url) public static function endpoint($url)

@ -0,0 +1,56 @@
<?php
namespace App\Docker;
use Exception;
use Illuminate\Support\Facades\Log;
use Psr\Http\Message\ResponseInterface;
use React\Http\Browser;
use React\Socket\FixedUriConnector;
use React\Socket\UnixConnector;
use function React\Async\await;
class Exec
{
protected $id;
protected $connector;
protected $browser;
public function __construct($id)
{
$this->id = $id;
$connection = Docker::connect();
$this->connector = $connection->connector;
$this->browser = $connection->browser;
}
public function getId() { return $this->id; }
public function start($args = [])
{
try {
Log::info("Starting exec :" . Docker::endpoint("/exec/" . $this->id . "/start"));
$response = await($this->browser->post(
Docker::endpoint("/exec/" . $this->id . "/start"),
[ "Content-Type" => "application/json"],
));
return json_decode($response->getBody());
} catch (Exception $e) {
throw $e;
}
}
public function inspect()
{
try {
$response = await($this->browser->get(
Docker::endpoint("/exec/" . $this->id . "/json"),
[ "Content-Type" => "text/plain" ]
));
return json_decode($response->getBody());
} catch (Exception $e) {
throw $e;
}
}
}

@ -0,0 +1,96 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use App\Docker\Container;
use App\Jobs\InitServer;
use App\Models\ExposedPort;
use App\Models\Server;
use App\Models\Service;
use Exception;
use Illuminate\Support\Facades\Auth;
use Inertia\Inertia;
class ServerController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return Inertia::render("Server/Index", [
"servers" => Server::all()->jsonSerialize(),
]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return Inertia::render('Server/Create', [
"services" => Service::all()
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$request->validate([
"name" => "required|string",
"service" => "required|string",
]);
$service = Service::where("uuid", $request->service)->firstOrFail();
$server = Server::create([
"uuid" => Str::uuid(),
"name" => preg_replace('/[^a-zA-Z0-9_.-]/', '', $request->name),
"service_id" => $service->id,
"status_id" => 3,
"user_id" => Auth::user()->id
]);
dispatch(new InitServer($server));
return redirect(route("servers.index"));
}
/**
* Display the specified resource.
*/
public function show(Request $request)
{
$server = Server::where("uuid", $request->id)->firstOrFail();
return Inertia::render("Server/Show", [
"server" => $server
]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

@ -0,0 +1,65 @@
<?php
namespace App\Jobs;
use App\Docker\Container;
use App\Models\ExposedPort;
use Exception;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
class InitServer implements ShouldQueue
{
use Queueable;
protected $server;
/**
* Create a new job instance.
*/
public function __construct($server)
{
$this->server = $server;
$server->update(["status_id" => 2]);
}
/**
* Execute the job.
*/
public function handle(): void
{
try {
$config = config($this->server->service->config);
$ports = explode("|", $this->server->service->ports);
for ($i = 0; $i < count($ports); $i++) {
$port = ExposedPort::where("usable", true)->first();
if(!$port) throw new Exception("All ports are used, please try later.");
$this->server->exposedPorts()->attach($port->id);
$port->update(["usable" => false]);
$config["ExposedPorts"][$ports[$i] . "/" . $this->server->service->protocol] = (object)[];
$config["HostConfig"]["PortBindings"][$ports[$i] . "/" . $this->server->service->protocol] = [[ "HostPort" => "" . $port->number ]];
}
Log::info(json_encode($config, JSON_UNESCAPED_SLASHES));
$container = Container::create($this->server->name . Str::random(5), $config);
$container->start();
$this->server->update([
"container" => $container->getId(),
"status_id" => 1,
"start" => now()
]);
}catch(Exception $e) {
$this->fail($e);
}
}
public function fail($e): void
{
$this->server->update([
"status_id" => 4,
"end" => now()
]);
$this->server->exposedPorts()->detach();
Log::info($e->getResponse()->getBody());
}
}

@ -0,0 +1,13 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ExposedPort extends Model
{
protected $fillable = [
'number',
'usable'
];
}

@ -0,0 +1,53 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Server extends Model
{
protected $fillable = [
"uuid",
'name',
"container",
"start",
"end",
"service_id",
"user_id",
"status_id",
];
public function jsonSerialize(): mixed
{
return [
"uuid" => $this->uuid,
'name' => $this->name,
"start" => $this->start,
"end" => $this->end,
"service" => $this->service,
"user" => $this->user,
"status" => $this->status,
"ports" => $this->exposedPorts()->pluck("number"),
];
}
public function exposedPorts()
{
return $this->belongsToMany(ExposedPort::class);
}
public function service()
{
return $this->belongsTo(Service::class);
}
public function status()
{
return $this->belongsTo(Status::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}

@ -0,0 +1,22 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Service extends Model
{
protected $fillable = [
"uuid",
'name',
"image",
"config",
"ports",
"protocol"
];
public function servers()
{
return $this->hasMany(Server::class);
}
}

@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Spec extends Model
{
protected $fillable = [
"uuid",
"cpus",
"memory",
"storage"
];
}

@ -0,0 +1,13 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Status extends Model
{
protected $fillable = [
'title',
'message'
];
}

@ -23,6 +23,11 @@ class User extends Authenticatable
'password', 'password',
]; ];
public function servers()
{
return $this->hasMany(Server::class);
}
/** /**
* The attributes that should be hidden for serialization. * The attributes that should be hidden for serialization.
* *

@ -0,0 +1,40 @@
<?php
class Netstat
{
public static function parseArgs($ssOutput)
{
$lines = explode("\n", $ssOutput);
// Step 2: Skip the header line
array_shift($lines);
// Step 3: Parse each line and extract relevant details
$connections = [];
foreach ($lines as $line) {
// Ignore empty lines
if (empty(trim($line))) {
continue;
}
// Use regex to match the structured output
if (preg_match('/(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+users:\(\("([^"]+)",pid=(\d+),fd=(\d+)\)\)/', $line, $matches)) {
$connections[] = [
'State' => $matches[1], // e.g., LISTEN
'Recv-Q' => $matches[2], // e.g., 0
'Send-Q' => $matches[3], // e.g., 128
'LocalAddress' => $matches[4], // e.g., 0.0.0.0:80
'ForeignAddress' => $matches[5], // e.g., 0.0.0.0:*
'Program' => $matches[6], // e.g., nginx
'PID' => $matches[7], // e.g., 1234
'FD' => $matches[8], // e.g., 6
];
}
}
return $connections;
}
}

@ -0,0 +1,45 @@
<?php
return [
"endpoint" => "http://localhost",
"minecraftJava" => [
"Hostname" => "mincraft-server",
"User" => "root",
"Image" => "minecraftjava:latest",
"AttachStdout" => false,
"AttachStderr" => false,
"OpenStdin" => true,
"Tty" => true,
"ExposedPorts" => [],
"HostConfig" => [
"PortBindings" => [],
]
],
"minecraftBedrock" => [
"Hostname" => "mincraft-server",
"User" => "root",
"Image" => "minecraftbedrock:latest",
"OpenStdin" => true,
"AttachStdout" => false,
"AttachStderr" => false,
"Tty" => true,
"ExposedPorts" => [],
"HostConfig" => [
"PortBindings" => [],
]
],
"arkserver" => [
"Hostname" => "ark-server",
"User" => "root",
"Image" => "arkserver:latest",
"OpenStdin" => true,
"AttachStdout" => false,
"AttachStderr" => false,
"Tty" => true,
"ExposedPorts" => [],
"HostConfig" => [
"PortBindings" => [],
]
]
];

@ -14,6 +14,7 @@ public function up(): void
Schema::create('users', function (Blueprint $table) { Schema::create('users', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('name'); $table->string('name');
$table->boolean("admin")->default(false);
$table->string('email')->unique(); $table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable(); $table->timestamp('email_verified_at')->nullable();
$table->string('password'); $table->string('password');

@ -0,0 +1,32 @@
<?php
use App\Models\ExposedPort;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('exposed_ports', function (Blueprint $table) {
$table->id();
$table->unsignedSmallInteger("number");
$table->boolean("usable");
$table->timestamps();
});
for($i = 25000; $i < 30000; $i++) ExposedPort::create([ "number" => $i, "usable" => true ]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('exposed_ports');
}
};

@ -0,0 +1,62 @@
<?php
use App\Models\Service;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('services', function (Blueprint $table) {
$table->id();
$table->uuid();
$table->string("name");
$table->string("image");
$table->string("config");
$table->string("protocol");
$table->string("ports");
$table->timestamps();
});
Service::create([
"uuid" => Str::uuid(),
"name" => "Minecraft Java edition",
"image" => "/img/minecraft-java.webp",
"config" => "docker.minecraftJava",
"protocol" => "tcp",
"ports" => "25565"
]);
Service::create([
"uuid" => Str::uuid(),
"name" => "Minecraft Bedrock edition",
"image" => "/img/minecraft-bedrock.webp",
"config" => "docker.minecraftBedrock",
"protocol" => "udp",
"ports" => "19132|19133"
]);
Service::create([
"uuid" => Str::uuid(),
"name" => "Ark Survial Evolved",
"image" => "/img/ark.jpeg",
"config" => "docker.arkserver",
"protocol" => "udp",
"ports" => "27015|7777"
]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('services');
}
};

@ -0,0 +1,50 @@
<?php
use App\Models\Status;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('statuses', function (Blueprint $table) {
$table->id();
$table->string("title");
$table->string("message");
$table->timestamps();
});
Status::create([
"title" => "Running",
"message" => "",
]);
Status::create([
"title" => "Pending",
"message" => "",
]);
Status::create([
"title" => "Offline",
"message" => "",
]);
Status::create([
"title" => "Failed",
"message" => "",
]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('server_statuses');
}
};

@ -0,0 +1,54 @@
<?php
use App\Models\Spec;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('specs', function (Blueprint $table) {
$table->id();
$table->uuid("uuid");
$table->unsignedTinyInteger("cpus");
$table->unsignedBigInteger("memory");
$table->unsignedBigInteger("storage");
$table->timestamps();
});
Spec::create([
"uuid" => Str::uuid(),
"cpus" => 1,
"memory" => 2000000000,
"storage" => 20000000000
]);
Spec::create([
"uuid" => Str::uuid(),
"cpus" => 1,
"memory" => 3000000000,
"storage" => 50000000000
]);
Spec::create([
"uuid" => Str::uuid(),
"cpus" => 2,
"memory" => 5000000000,
"storage" => 40000000000
]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('specs');
}
};

@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('servers', function (Blueprint $table) {
$table->id();
$table->uuid("uuid");
$table->string("container", 511)->nullable();
$table->string("name");
$table->dateTime("start")->nullable();
$table->dateTime("end")->nullable();
$table->unsignedBigInteger("service_id");
$table->unsignedBigInteger("user_id");
$table->unsignedBigInteger("status_id");
$table->timestamps();
$table->foreign("service_id")->references("id")->on("services");
$table->foreign("user_id")->references("id")->on("users");
$table->foreign("status_id")->references("id")->on("statuses");
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('servers');
}
};

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('exposed_port_server', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger("server_id");
$table->unsignedBigInteger("exposed_port_id")->unique();
$table->timestamps();
$table->foreign("server_id")->references("id")->on("servers");
$table->foreign("exposed_port_id")->references("id")->on("exposed_ports");
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('exposed_port_server');
}
};

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11 9L8 12M8 12L11 15M8 12H16M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 463 B

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
<path d="M144.282 145.51A32.19 32.19 0 0 1 150 145c4.032 0 7.89.746 11.444 2.107L175.584 127l.54.306A31.88 31.88 0 0 1 168 106c0-17.673 14.327-32 32-32 17.673 0 32 14.327 32 32 0 17.673-14.327 32-32 32-3.672 0-7.2-.619-10.485-1.757l-14.31 21.038A31.863 31.863 0 0 1 182 177c0 17.673-14.327 32-32 32-17.673 0-32-14.327-32-32 0-9.767 4.376-18.512 11.274-24.382l-20.764-41.28A32.14 32.14 0 0 1 102 112a32.05 32.05 0 0 1-8.16-1.05l-14.716 25.93C85.21 142.705 89 150.91 89 160c0 17.673-14.327 32-32 32-17.673 0-32-14.327-32-32 0-17.673 14.327-32 32-32 2.655 0 5.234.323 7.7.932l14.809-26.17C73.638 96.963 70 88.907 70 80c0-17.673 14.327-32 32-32 17.673 0 32 14.327 32 32 0 9.563-4.195 18.146-10.844 24.01l21.126 41.5zM200 122c8.837 0 16-7.163 16-16s-7.163-16-16-16-16 7.163-16 16 7.163 16 16 16zM57 176c8.837 0 16-7.163 16-16s-7.163-16-16-16-16 7.163-16 16 7.163 16 16 16zm45-80c8.837 0 16-7.163 16-16s-7.163-16-16-16-16 7.163-16 16 7.163 16 16 16zm48 97c8.837 0 16-7.163 16-16s-7.163-16-16-16-16 7.163-16 16 7.163 16 16 16z" fill-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 -0.5 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.676 14.248C17.676 15.8651 16.3651 17.176 14.748 17.176H7.428C5.81091 17.176 4.5 15.8651 4.5 14.248V6.928C4.5 5.31091 5.81091 4 7.428 4H14.748C16.3651 4 17.676 5.31091 17.676 6.928V14.248Z" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.252 20H17.572C19.1891 20 20.5 18.689 20.5 17.072V9.75195" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 713 B

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 11V17" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14 11V17" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4 7H20" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 7H12H18V18C18 19.6569 16.6569 21 15 21H9C7.34315 21 6 19.6569 6 18V7Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 5C9 3.89543 9.89543 3 11 3H13C14.1046 3 15 3.89543 15 5V7H9V5Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 859 B

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Menu / More_Vertical">
<g id="Vector">
<path d="M11 18C11 18.5523 11.4477 19 12 19C12.5523 19 13 18.5523 13 18C13 17.4477 12.5523 17 12 17C11.4477 17 11 17.4477 11 18Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11 12C11 12.5523 11.4477 13 12 13C12.5523 13 13 12.5523 13 12C13 11.4477 12.5523 11 12 11C11.4477 11 11 11.4477 11 12Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11 6C11 6.55228 11.4477 7 12 7C12.5523 7 13 6.55228 13 6C13 5.44772 12.5523 5 12 5C11.4477 5 11 5.44772 11 6Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 924 B

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.8477 1.87868C19.6761 0.707109 17.7766 0.707105 16.605 1.87868L2.44744 16.0363C2.02864 16.4551 1.74317 16.9885 1.62702 17.5692L1.03995 20.5046C0.760062 21.904 1.9939 23.1379 3.39334 22.858L6.32868 22.2709C6.90945 22.1548 7.44285 21.8693 7.86165 21.4505L22.0192 7.29289C23.1908 6.12132 23.1908 4.22183 22.0192 3.05025L20.8477 1.87868ZM18.0192 3.29289C18.4098 2.90237 19.0429 2.90237 19.4335 3.29289L20.605 4.46447C20.9956 4.85499 20.9956 5.48815 20.605 5.87868L17.9334 8.55027L15.3477 5.96448L18.0192 3.29289ZM13.9334 7.3787L3.86165 17.4505C3.72205 17.5901 3.6269 17.7679 3.58818 17.9615L3.00111 20.8968L5.93645 20.3097C6.13004 20.271 6.30784 20.1759 6.44744 20.0363L16.5192 9.96448L13.9334 7.3787Z" fill="#0F0F0F"/>
</svg>

After

Width:  |  Height:  |  Size: 995 B

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg height="800px" width="800px" version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512" xml:space="preserve">
<style type="text/css">
.st0{fill:#000000;}
</style>
<g>
<path class="st0" d="M510.002,309.835l-0.068-0.326l-0.076-0.334l-26.508-112.721l-0.106-0.417l-0.106-0.418
c-16.668-62.217-73.294-105.666-137.712-105.666H166.579c-64.418,0-121.045,43.449-137.712,105.666l-0.114,0.418l-0.099,0.417
L2.147,309.174l-0.076,0.326l-0.068,0.326c-9.749,46.43,16.926,92.496,62.036,107.168l1.586,0.509
c9.24,3.012,18.89,4.544,28.624,4.544c32.668,0,63.128-17.404,79.758-45.489l22.556-33.343l0.561-0.835l0.509-0.872
c0.796-1.388,2.276-2.253,3.861-2.253h109.02c1.586,0,3.066,0.865,3.862,2.253l0.508,0.872l0.562,0.835l22.555,33.343
c16.63,28.085,47.09,45.489,79.766,45.489c9.734,0,19.384-1.532,28.67-4.56l1.533-0.493
C493.07,402.331,519.737,356.257,510.002,309.835z M439.318,390.397l-1.54,0.501c-6.608,2.154-13.353,3.186-20.014,3.186
c-22.646,0-44.283-11.949-56.088-32.433l-23.064-34.101c-5.788-10.053-16.508-16.258-28.101-16.258h-109.02
c-11.592,0-22.312,6.206-28.101,16.258l-23.063,34.101c-11.804,20.484-33.434,32.433-56.081,32.433
c-6.661,0-13.405-1.032-20.013-3.186l-1.548-0.501c-31.431-10.219-50.102-42.485-43.311-74.819l26.508-112.722
c13.42-50.102,58.826-84.94,110.696-84.94h178.847c51.869,0,97.276,34.838,110.696,84.94l26.508,112.722
C489.413,347.912,470.75,380.178,439.318,390.397z"/>
<polygon class="st0" points="157.453,172.061 123.912,172.061 123.912,210.579 85.387,210.579 85.387,244.105 123.912,244.105
123.912,282.637 157.453,282.637 157.453,244.105 195.978,244.105 195.978,210.579 157.453,210.579 "/>
<path class="st0" d="M365.721,206.247c11.668,0,21.113-9.445,21.113-21.098c0-11.669-9.445-21.114-21.113-21.114
c-11.653,0-21.098,9.445-21.098,21.114C344.622,196.802,354.068,206.247,365.721,206.247z"/>
<path class="st0" d="M323.509,206.247c-11.653,0-21.106,9.453-21.106,21.098c0,11.669,9.453,21.122,21.106,21.122
c11.661,0,21.106-9.453,21.106-21.122C344.615,215.7,335.17,206.247,323.509,206.247z"/>
<path class="st0" d="M365.721,248.459c-11.653,0-21.098,9.445-21.098,21.114c0,11.653,9.445,21.098,21.098,21.098
c11.668,0,21.113-9.445,21.113-21.098C386.834,257.904,377.388,248.459,365.721,248.459z"/>
<path class="st0" d="M407.933,206.247c-11.653,0-21.099,9.453-21.099,21.098c0,11.669,9.446,21.122,21.099,21.122
c11.66,0,21.113-9.453,21.113-21.122C429.046,215.7,419.593,206.247,407.933,206.247z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><title>ionicons-v5-l</title><rect x="80" y="80" width="352" height="352" rx="48" ry="48" style="fill:none;stroke:#000000;stroke-linejoin:round;stroke-width:32px"/><rect x="144" y="144" width="224" height="224" rx="16" ry="16" style="fill:none;stroke:#000000;stroke-linejoin:round;stroke-width:32px"/><line x1="256" y1="80" x2="256" y2="48" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="336" y1="80" x2="336" y2="48" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="176" y1="80" x2="176" y2="48" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="256" y1="464" x2="256" y2="432" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="336" y1="464" x2="336" y2="432" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="176" y1="464" x2="176" y2="432" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="432" y1="256" x2="464" y2="256" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="432" y1="336" x2="464" y2="336" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="432" y1="176" x2="464" y2="176" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="48" y1="256" x2="80" y2="256" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="48" y1="336" x2="80" y2="336" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="48" y1="176" x2="80" y2="176" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg">
<path d="m1311.326 891.546-61.666-61.666 107.294-107.407-159.698-159.698-107.52 107.633-61.553-60.311 384.338-384.904 282.127 281.45-383.322 384.903ZM891.863 1309.43 508.54 1694.332l-283.143-281.45 384.339-384.903 61.214 61.214-110.005 109.892 159.699 159.699 110.117-110.005 61.102 60.65Zm962.484-961.92-283.03-283.03c-88.546-86.288-231.19-85.95-317.93 1.016L868.484 450.398c-87.53 87.642-87.53 230.061 0 317.704l61.666 61.778-99.502 99.502-60.31-60.198c-42.127-43.144-98.372-67.087-158.57-67.426h-1.355c-60.197 0-116.894 23.605-159.812 66.41L65.698 1253.184c-87.642 87.642-87.642 230.061 0 317.704L348.84 1854.03c43.822 43.821 101.309 65.732 158.909 65.732 57.487 0 115.087-21.91 158.908-65.732l384.903-384.903c43.257-43.257 66.862-100.518 66.523-161.168-.452-60.197-24.396-116.442-66.523-157.665l-61.214-61.102 99.614-99.614 61.666 61.78c43.821 43.707 101.309 65.618 158.909 65.618 57.487 0 115.087-21.91 158.795-65.732l385.016-384.903c86.852-86.852 87.304-229.497 0-318.833Z" fill-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg height="800px" width="800px" version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512" xml:space="preserve">
<style type="text/css">
.st0{fill:#000000;}
</style>
<g>
<path class="st0" d="M389.488,226.899H122.512C54.854,226.899,0,281.746,0,349.412c0,67.658,54.854,122.512,122.512,122.512
c42.653,0,80.199-21.812,102.135-54.854h62.706c21.936,33.042,59.49,54.854,102.135,54.854C457.154,471.924,512,417.07,512,349.412
C512,281.746,457.154,226.899,389.488,226.899z M389.488,440.332c-30.535,0-58.881-15.226-75.818-40.74l-9.372-14.115h-16.945
h-62.706h-16.945l-9.371,14.115c-16.938,25.514-45.282,40.74-75.819,40.74c-50.134,0-90.92-40.786-90.92-90.92
c0-50.134,40.786-90.921,90.92-90.921h266.976c50.134,0,90.92,40.786,90.92,90.921
C480.408,399.545,439.622,440.332,389.488,440.332z"/>
<path class="st0" d="M268.927,110.897c0-2.46,0.486-4.72,1.366-6.803c1.311-3.116,3.548-5.8,6.332-7.69
c2.8-1.89,6.085-2.97,9.757-2.97c2.437,0,4.705,0.494,6.788,1.373c3.116,1.311,5.799,3.533,7.689,6.333
c1.882,2.8,2.97,6.085,2.97,9.756c0,5.893,1.203,11.593,3.394,16.752c3.278,7.744,8.716,14.292,15.58,18.928
c6.849,4.643,15.21,7.374,24.08,7.366c5.916,0,11.616-1.211,16.768-3.394c7.728-3.278,14.284-8.716,18.92-15.58
c4.643-6.857,7.366-15.21,7.366-24.072v-70.82h-25.607v70.82c0,2.437-0.478,4.705-1.357,6.78c-1.319,3.124-3.556,5.808-6.333,7.69
c-2.808,1.881-6.093,2.969-9.757,2.969c-2.436,0-4.705-0.486-6.787-1.365c-3.116-1.311-5.8-3.548-7.682-6.333
c-1.889-2.8-2.977-6.1-2.992-9.741c0.016-5.924-1.188-11.616-3.378-16.768c-3.279-7.744-8.716-14.292-15.58-18.928
c-6.864-4.651-15.21-7.374-24.08-7.366c-5.909-0.008-11.608,1.203-16.768,3.394c-7.743,3.263-14.292,8.716-18.927,15.58
c-4.644,6.857-7.359,15.21-7.359,24.088v104.71h25.599V110.897z"/>
<polygon class="st0" points="138.363,293.338 105.452,293.338 105.452,331.124 67.658,331.124 67.658,364.051 105.452,364.051
105.452,401.829 138.363,401.829 138.363,364.051 176.156,364.051 176.156,331.124 138.363,331.124 "/>
<path class="st0" d="M375.126,289.698c-7.937,7.929-7.921,20.794,0,28.723c7.936,7.929,20.794,7.929,28.716,0
c7.936-7.929,7.936-20.794,0-28.723C395.92,281.769,383.063,281.769,375.126,289.698z"/>
<path class="st0" d="M329.774,335.05c-7.929,7.929-7.929,20.794,0,28.723c7.937,7.929,20.794,7.929,28.723,0
c7.93-7.929,7.93-20.794,0-28.731C350.568,327.121,337.711,327.121,329.774,335.05z"/>
<path class="st0" d="M375.126,380.402c-7.937,7.929-7.937,20.786,0,28.715c7.936,7.929,20.794,7.929,28.716,0.008
c7.936-7.937,7.936-20.794,0-28.739C395.92,372.457,383.063,372.473,375.126,380.402z"/>
<path class="st0" d="M449.193,335.05c-7.921-7.929-20.786-7.929-28.723,0c-7.937,7.929-7.937,20.794,0,28.723
c7.937,7.929,20.802,7.929,28.723,0C457.123,355.844,457.123,342.979,449.193,335.05z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24"><path d="M8.5,6H6.7C8.2,4.7,10,4,12,4c0.3,0,0.6,0,0.9,0.1c0,0,0,0,0,0c0.5,0.1,1-0.3,1.1-0.9c0.1-0.5-0.3-1-0.9-1.1C12.7,2,12.4,2,12,2C9.6,2,7.3,2.9,5.5,4.4V3c0-0.6-0.4-1-1-1s-1,0.4-1,1v4c0,0.6,0.4,1,1,1h4c0.6,0,1-0.4,1-1S9.1,6,8.5,6z M7,14.5c-0.6,0-1,0.4-1,1v1.8C4.7,15.8,4,14,4,12c0-0.3,0-0.6,0.1-0.9c0,0,0,0,0,0c0.1-0.5-0.3-1-0.9-1.1c-0.5-0.1-1,0.3-1.1,0.9C2,11.3,2,11.6,2,12c0,2.4,0.9,4.7,2.4,6.5H3c-0.6,0-1,0.4-1,1s0.4,1,1,1h4c0.3,0,0.6-0.2,0.8-0.4c0,0,0,0,0,0c0,0,0,0,0,0c0-0.1,0.1-0.2,0.1-0.3c0-0.1,0-0.1,0-0.2c0,0,0-0.1,0-0.1v-4C8,14.9,7.6,14.5,7,14.5z M21,5.5c0.6,0,1-0.4,1-1s-0.4-1-1-1h-4c-0.1,0-0.1,0-0.2,0c0,0,0,0,0,0c-0.1,0-0.2,0.1-0.3,0.1c0,0,0,0,0,0c-0.1,0.1-0.2,0.1-0.2,0.2c0,0,0,0,0,0c0,0,0,0,0,0c0,0.1-0.1,0.2-0.1,0.2c0,0.1,0,0.1,0,0.2c0,0,0,0.1,0,0.1v4c0,0.6,0.4,1,1,1s1-0.4,1-1V6.7c1.3,1.4,2,3.3,2,5.3c0,0.3,0,0.6-0.1,0.9c-0.1,0.5,0.3,1,0.9,1.1c0,0,0.1,0,0.1,0c0.5,0,0.9-0.4,1-0.9c0-0.4,0.1-0.7,0.1-1.1c0-2.4-0.9-4.7-2.4-6.5H21z M20.3,16.5c-0.1-0.1-0.2-0.2-0.3-0.3c0,0,0,0,0,0c0,0,0,0,0,0c-0.1-0.1-0.2-0.1-0.3-0.1c0,0-0.1,0-0.1,0c0,0-0.1,0-0.1,0h-4c-0.6,0-1,0.4-1,1s0.4,1,1,1h1.8c-1.4,1.3-3.3,2-5.3,2c-0.3,0-0.6,0-0.9-0.1c0,0,0,0,0,0c-0.5-0.1-1,0.3-1.1,0.9s0.3,1,0.9,1.1c0.4,0,0.7,0.1,1.1,0.1c2.4,0,4.7-0.9,6.5-2.4V21c0,0.6,0.4,1,1,1s1-0.4,1-1v-4C20.5,16.8,20.4,16.6,20.3,16.5C20.3,16.5,20.3,16.5,20.3,16.5z"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.5 16.5854C13.5 17.4138 12.8284 18.0854 12 18.0854C11.1716 18.0854 10.5 17.4138 10.5 16.5854C10.5 15.7569 11.1716 15.0854 12 15.0854C12.8284 15.0854 13.5 15.7569 13.5 16.5854Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.33367 10C6.20971 9.64407 6.09518 9.27081 5.99836 8.88671C5.69532 7.68444 5.54485 6.29432 5.89748 4.97439C6.26228 3.60888 7.14664 2.39739 8.74323 1.59523C10.3398 0.793061 11.8397 0.806642 13.153 1.32902C14.4225 1.83396 15.448 2.78443 16.2317 3.7452C16.4302 3.98851 16.6166 4.23669 16.7907 4.48449C17.0806 4.89706 16.9784 5.45918 16.5823 5.7713C16.112 6.14195 15.4266 6.01135 15.0768 5.52533C14.9514 5.35112 14.8197 5.17831 14.6819 5.0094C14.0088 4.18414 13.2423 3.51693 12.4138 3.18741C11.6292 2.87533 10.7252 2.83767 9.64112 3.38234C8.55703 3.92702 8.04765 4.6748 7.82971 5.49059C7.5996 6.35195 7.6774 7.36518 7.93771 8.39788C8.07953 8.96054 8.26936 9.50489 8.47135 10H18C19.6569 10 21 11.3431 21 13V20C21 21.6569 19.6569 23 18 23H6C4.34315 23 3 21.6569 3 20V13C3 11.3431 4.34315 10 6 10H6.33367ZM19 13C19 12.4477 18.5523 12 18 12H6C5.44772 12 5 12.4477 5 13V20C5 20.5523 5.44772 21 6 21H18C18.5523 21 19 20.5523 19 20V13Z" fill="#0F0F0F"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:none;stroke:#020202;stroke-miterlimit:10;stroke-width:1.91px;}</style></defs><path class="cls-1" d="M13.11,16.55,7.45,10.89l7.27-7.27a7.24,7.24,0,0,1,7.41-1.75h0a7.24,7.24,0,0,1-1.75,7.41Z"/><ellipse class="cls-1" cx="14.85" cy="9.09" rx="0.94" ry="0.91"/><polygon class="cls-1" points="9.57 17.26 6.74 14.43 8.16 11.6 12.4 15.84 9.57 17.26"/><path class="cls-1" d="M12.88,14.11h0a4,4,0,0,1,4,4v3a0,0,0,0,1,0,0h0a4,4,0,0,1-4-4v-3A0,0,0,0,1,12.88,14.11Z" transform="translate(16.81 -5.36) rotate(45)"/><path class="cls-1" d="M8.39,5.62h0a0,0,0,0,1,0,0v3a4,4,0,0,1-4,4h0a0,0,0,0,1,0,0v-3a4,4,0,0,1,4-4Z" transform="translate(4.46 20.1) rotate(-135)"/><path class="cls-1" d="M3.73,16.27A3,3,0,0,1,8,16a3,3,0,0,1-.27,4.27C5.45,22.55,1.5,22.5,1.5,22.5S1.45,18.55,3.73,16.27Z"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
<title>security-verified</title>
<g id="Layer_2" data-name="Layer 2">
<g id="invisible_box" data-name="invisible box">
<rect width="48" height="48" fill="none"/>
</g>
<g id="icons_Q2" data-name="icons Q2">
<path d="M24,6.2c5.3,1.5,11.1,3.3,14,4.3V26.2c0,3.4-3.7,9.4-14,15.4-10.3-6.1-14-12-14-15.4V10.5c2.9-1.1,8.7-2.8,14-4.3M24,2S6,7.1,6,8V26.2c0,9.2,13.3,17.3,17,19.5a1.8,1.8,0,0,0,2,0c3.8-2.1,17-10.3,17-19.5V8c0-.9-18-6-18-6Z"/>
<path d="M19.6,29.4l-5-4.9a2.1,2.1,0,0,1-.2-2.7,1.9,1.9,0,0,1,3-.2L21,25.2l9.6-9.6a2,2,0,0,1,2.8,2.8l-11,11A1.9,1.9,0,0,1,19.6,29.4Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 846 B

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 7H18.01M15 7H15.01M18 17H18.01M15 17H15.01M6 10H18C18.9319 10 19.3978 10 19.7654 9.84776C20.2554 9.64477 20.6448 9.25542 20.8478 8.76537C21 8.39782 21 7.93188 21 7C21 6.06812 21 5.60218 20.8478 5.23463C20.6448 4.74458 20.2554 4.35523 19.7654 4.15224C19.3978 4 18.9319 4 18 4H6C5.06812 4 4.60218 4 4.23463 4.15224C3.74458 4.35523 3.35523 4.74458 3.15224 5.23463C3 5.60218 3 6.06812 3 7C3 7.93188 3 8.39782 3.15224 8.76537C3.35523 9.25542 3.74458 9.64477 4.23463 9.84776C4.60218 10 5.06812 10 6 10ZM6 20H18C18.9319 20 19.3978 20 19.7654 19.8478C20.2554 19.6448 20.6448 19.2554 20.8478 18.7654C21 18.3978 21 17.9319 21 17C21 16.0681 21 15.6022 20.8478 15.2346C20.6448 14.7446 20.2554 14.3552 19.7654 14.1522C19.3978 14 18.9319 14 18 14H6C5.06812 14 4.60218 14 4.23463 14.1522C3.74458 14.3552 3.35523 14.7446 3.15224 15.2346C3 15.6022 3 16.0681 3 17C3 17.9319 3 18.3978 3.15224 18.7654C3.35523 19.2554 3.74458 19.6448 4.23463 19.8478C4.60218 20 5.06812 20 6 20Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M23 5.5C23 7.98528 20.9853 10 18.5 10C17.0993 10 15.8481 9.36007 15.0228 8.35663L9.87308 10.9315C9.95603 11.2731 10 11.63 10 11.9971C10 12.3661 9.9556 12.7247 9.87184 13.0678L15.0228 15.6433C15.8482 14.6399 17.0993 14 18.5 14C20.9853 14 23 16.0147 23 18.5C23 20.9853 20.9853 23 18.5 23C16.0147 23 14 20.9853 14 18.5C14 18.1319 14.0442 17.7742 14.1276 17.4318L8.97554 14.8558C8.1502 15.8581 6.89973 16.4971 5.5 16.4971C3.01472 16.4971 1 14.4824 1 11.9971C1 9.51185 3.01472 7.49713 5.5 7.49713C6.90161 7.49713 8.15356 8.13793 8.97886 9.14254L14.1275 6.5682C14.0442 6.2258 14 5.86806 14 5.5C14 3.01472 16.0147 1 18.5 1C20.9853 1 23 3.01472 23 5.5ZM16.0029 5.5C16.0029 6.87913 17.1209 7.99713 18.5 7.99713C19.8791 7.99713 20.9971 6.87913 20.9971 5.5C20.9971 4.12087 19.8791 3.00287 18.5 3.00287C17.1209 3.00287 16.0029 4.12087 16.0029 5.5ZM16.0029 18.5C16.0029 19.8791 17.1209 20.9971 18.5 20.9971C19.8791 20.9971 20.9971 19.8791 20.9971 18.5C20.9971 17.1209 19.8791 16.0029 18.5 16.0029C17.1209 16.0029 16.0029 17.1209 16.0029 18.5ZM5.5 14.4943C4.12087 14.4943 3.00287 13.3763 3.00287 11.9971C3.00287 10.618 4.12087 9.5 5.5 9.5C6.87913 9.5 7.99713 10.618 7.99713 11.9971C7.99713 13.3763 6.87913 14.4943 5.5 14.4943Z" fill="#0F0F0F"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#000000"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.25 3l1.166-.624 8 5.333v1.248l-8 5.334-1.166-.624V3zm1.5 1.401v7.864l5.898-3.932L5.75 4.401z"/></svg>

After

Width:  |  Height:  |  Size: 376 B

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="-3 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<title>stats</title>
<desc>Created with Sketch Beta.</desc>
<defs>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Icon-Set-Filled" sketch:type="MSLayerGroup" transform="translate(-314.000000, -673.000000)" fill="#000000">
<path d="M328,673 L326,673 C324.896,673 324,673.896 324,675 L324,703 C324,704.104 324.896,705 326,705 L328,705 C329.104,705 330,704.104 330,703 L330,675 C330,673.896 329.104,673 328,673 L328,673 Z M338,689 L336,689 C334.896,689 334,689.896 334,691 L334,703 C334,704.104 334.896,705 336,705 L338,705 C339.104,705 340,704.104 340,703 L340,691 C340,689.896 339.104,689 338,689 L338,689 Z M318,682 L316,682 C314.896,682 314,682.896 314,684 L314,703 C314,704.104 314.896,705 316,705 L318,705 C319.104,705 320,704.104 320,703 L320,684 C320,682.896 319.104,682 318,682 L318,682 Z" id="stats" sketch:type="MSShapeGroup">
</path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path fill="#000000" fill-rule="evenodd" d="M7.0513157,1.68377223 C7.34140089,0.813516663 8.52958649,0.773959592 8.90131717,1.56510102 L8.9486823,1.68377223 L11.999,10.838 L13.0513157,7.68377223 C13.1750557,7.31255211 13.5021221,7.05117665 13.8839548,7.00672177 L13.999999,7 L14.999999,7 C15.5522837,7 15.999999,7.44771525 15.999999,8 C15.999999,8.51283584 15.6139588,8.93550716 15.1166201,8.99327227 L14.999999,9 L14.72,9 L12.9486823,14.3162278 C12.6585971,15.1864833 11.4704115,15.2260404 11.0986808,14.434899 L11.0513157,14.3162278 L7.999999,5.161 L5.9486823,11.3162278 C5.66748671,12.1598145 4.52796777,12.2312701 4.12404882,11.4837549 L4.07152231,11.3713907 L2.961,8.596 L2.89017501,8.6833128 C2.73101502,8.85332296 2.51533249,8.96455528 2.27945404,8.99286635 L2.16,9 L0.999999,9 C0.44771425,9 -1e-06,8.55228475 -1e-06,8 C-1e-06,7.48716416 0.38603919,7.06449284 0.883377875,7.00672773 L0.999999,7 L1.495,7 L2.07801673,5.61276791 C2.40786899,4.82740446 3.48655852,4.79910618 3.87548912,5.51555754 L3.92847569,5.62860932 L4.914,8.094 L7.0513157,1.68377223 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill="none">
<path fill="#000000" fill-rule="evenodd" d="M5.781 4.414a7 7 0 019.62 10.039l-9.62-10.04zm-1.408 1.42a7 7 0 009.549 9.964L4.373 5.836zM10 1a9 9 0 100 18 9 9 0 000-18z"/>
</svg>

After

Width:  |  Height:  |  Size: 399 B

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 7C9.65685 7 11 5.65685 11 4C11 2.34315 9.65685 1 8 1C6.34315 1 5 2.34315 5 4C5 5.65685 6.34315 7 8 7Z" fill="#000000"/>
<path d="M14 12C14 10.3431 12.6569 9 11 9H5C3.34315 9 2 10.3431 2 12V15H14V12Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

@ -9,3 +9,44 @@ .scale-hover:hover { transform: scale(1.05); transition: transform 0.3s ease-in-
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
/* Nouvelle animation : rotation au survol */
.rotate-on-hover {
transition: transform 0.5s ease-in-out;
}
.rotate-on-hover:hover {
transform: rotate(360deg);
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.pulse {
animation: pulse 2s infinite;
}
/* Nouvelle animation : Bounce */
@keyframes bounce {
0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
40% { transform: translateY(-20px); }
60% { transform: translateY(-10px); }
}
.bounce {
animation: bounce 2s infinite;
}
/* Nouvelle animation : Shake */
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
.shake {
animation: shake 0.5s ease-in-out;
}
/* Nouvelle animation : Glow on hover */
.glow-on-hover {
transition: box-shadow transform 0.1s ease-in-out;
}
.glow-on-hover:hover {
transform: scale(1.05);
box-shadow: 0 0 2px 2px rgba(51, 51, 51, 0.8);
}

@ -19,7 +19,7 @@ defineExpose({ focus: () => input.value.focus() });
<template> <template>
<input <input
class="rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500" class="rounded-md border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
v-model="model" v-model="model"
ref="input" ref="input"
/> />

@ -4,23 +4,22 @@ import { Link } from '@inertiajs/vue3';
</script> </script>
<template> <template>
<nav class="fixed top-0 right-0 left-0 h-16 w-full z-40"> <nav class="fixed top-0 right-0 left-0 h-16 w-full z-40 bg-gray-950/25">
<div class="w-full h-full bg-gray-800/15 flex items-center justify-between px-[10%]"> <div class="w-full h-full flex items-center justify-between px-[10%]">
<div class="flex text-lg text-textColor-100 items-center font-medium"> <div class="flex text-lg text-textColor-100 items-center font-medium">
<Link :href="route('home')" class="mr-4"><img src="/img/logo.svg" class="rotate-180 h-11"></Link> <Link :href="route('home')" class="mr-2"><img src="/img/logo.png" class="h-[6.8rem]"></Link>
<Link :href="route('home')" class="mr-5">Home</Link> <Link :href="route('home')" class="mr-5">Home</Link>
<Link :href="route('docker.create')" class="mr-5">Spawn server</Link> <Link :href="route('servers.create')" class="mr-5">Spawn server</Link>
<Link :href="route('docker.info')">Management</Link> <Link :href="'/servers'">Management</Link>
</div> </div>
<div class="flex text-lg text-textColor-300 items-center font-medium"> <div class="flex text-lg text-textColor-300 items-center font-medium">
<Link :href="route('login')" class="mr-5">Login</Link> <Link :href="route('login')" class=""><img src="/icons/user.svg" class="h-8 invert"></Link>
<Link :href="route('register')">Register</Link>
</div> </div>
</div> </div>
</nav> </nav>
<main class="w-full max-h-full overflow-y-auto text-white"> <main class="w-full max-h-full overflow-y-auto text-white">
<div class="w-full h-80 flex items-center justify-between overflow-hidden"> <div class="w-full h-80 flex items-center justify-between overflow-hidden">
<img src="/img/cover.avif" class="w-full"> <img src="/img/banner.jpg" class="w-full pb-96">
</div> </div>
<slot /> <slot />
</main> </main>
@ -31,6 +30,6 @@ import { Link } from '@inertiajs/vue3';
<p class="text-gray-400 mt-4">Code source disponible sur <a href="https://github.com/anulax1225/minecraft.anulax.ch" class="text-green-400 hover:underline">GitHub</a></p> <p class="text-gray-400 mt-4">Code source disponible sur <a href="https://github.com/anulax1225/minecraft.anulax.ch" class="text-green-400 hover:underline">GitHub</a></p>
</section> </section>
<footer class="bg-gray-800 text-center py-6"> <footer class="bg-gray-800 text-center py-6">
<p class="text-gray-400">&copy; 2024 Minecraft Hosting - Tous droits réservés</p> <p class="text-gray-400">&copy; 2024 Hosting - Tous droits réservés</p>
</footer> </footer>
</template> </template>

@ -77,8 +77,15 @@ const submit = () => {
> >
</label> </label>
</div> </div>
<div class="flex justify-between items-center mt-4">
<div class="mt-4 flex items-center justify-end"> <Link
v-if="canResetPassword"
:href="route('register')"
class="rounded-md text-sm text-textColor-600 underline hover:text-textColor-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
New account
</Link>
<div class="flex items-center justify-end">
<Link <Link
v-if="canResetPassword" v-if="canResetPassword"
:href="route('password.request')" :href="route('password.request')"
@ -95,6 +102,9 @@ const submit = () => {
Log in Log in
</PrimaryButton> </PrimaryButton>
</div> </div>
</div>
</form> </form>
</GuestLayout> </GuestLayout>
</template> </template>

@ -1,30 +0,0 @@
<script setup>
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import { Head } from '@inertiajs/vue3';
</script>
<template>
<Head title="Dashboard" />
<AuthenticatedLayout>
<template #header>
<h2
class="text-xl font-semibold leading-tight text-textColor-800"
>
Dashboard
</h2>
</template>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div
class="overflow-hidden bg-white shadow-sm sm:rounded-lg"
>
<div class="p-6 text-textColor-900">
You're logged in!
</div>
</div>
</div>
</div>
</AuthenticatedLayout>
</template>

@ -2,18 +2,29 @@
import { Head, Link } from '@inertiajs/vue3'; import { Head, Link } from '@inertiajs/vue3';
import Layout from '@/Layouts/Layout.vue'; import Layout from '@/Layouts/Layout.vue';
const props = defineProps({
services: {
type: Object,
default: []
}
});
</script> </script>
<template> <template>
<Head title="Welcome" /> <Head title="Welcome" />
<Layout> <Layout>
<header class="text-center py-20"> <header class="text-center my-10">
<h1 class="text-4xl font-bold animate-fade-in">Bienvenue sur Minecraft Hosting</h1> <h1 class="text-4xl font-bold fade-in flex justify-center items-center gap-2">
<p class="text-gray-300 max-w-3xl mx-auto mt-4 animate-fade-in">Un service gratuit permettant d'héberger facilement vos serveurs Minecraft dans des conteneurs Docker sécurisés et performants.</p> <img src="/icons/server-icon.svg" alt="Serveur" class="w-12 h-12 invert"> Bienvenue sur Hosting
</h1>
<p class="text-gray-300 max-w-3xl mx-auto mt-4 fade-in">Un service gratuit permettant d'héberger facilement vos serveurs dans des conteneurs Docker sécurisés et performants.</p>
</header> </header>
<section class="max-w-4xl mx-auto bg-gray-800 p-6 rounded-lg shadow-lg animate-slide-up"> <section class="max-w-4xl mx-auto bg-gray-800 p-6 rounded-lg shadow-lg slide-up">
<h2 class="text-2xl font-bold mb-4">Pourquoi choisir notre hébergement ?</h2> <h2 class="text-2xl font-bold mb-4 flex items-center gap-2">
<img src="/icons/security-icon.svg" alt="Sécurité" class="w-6 h-6 invert">Comment fonctionne notre hébergement ?
</h2>
<ul class="list-disc list-inside text-gray-300"> <ul class="list-disc list-inside text-gray-300">
<li>Infrastructure basée sur Docker pour une isolation et une sécurité optimales.</li> <li>Infrastructure basée sur Docker pour une isolation et une sécurité optimales.</li>
<li>Stockage limité à 10 Go par serveur pour éviter toute surcharge.</li> <li>Stockage limité à 10 Go par serveur pour éviter toute surcharge.</li>
@ -23,28 +34,45 @@ import Layout from '@/Layouts/Layout.vue';
</section> </section>
<section class="mt-10 text-center"> <section class="mt-10 text-center">
<h2 class="text-2xl font-bold mb-4 animate-fade-in">Comment ça fonctionne ?</h2> <h2 class="text-2xl font-bold mb-4 fade-in flex justify-center items-center gap-2">
<div class="max-w-4xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-6 animate-slide-up"> <img src="/icons/process-icon.svg" alt="Processus" class="w-7 h-7 invert">Démarche à sur suivre ?
<div class="bg-gray-800 p-6 rounded-lg shadow-lg"> </h2>
<div class="max-w-4xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-6 slide-up">
<div class="bg-gray-800 p-6 rounded-lg shadow-lg flex flex-col items-center">
<img src="/icons/start-icon.svg" alt="Créer" class="w-14 h-14 mb-2 invert">
<h3 class="text-xl font-semibold">1. Créez votre serveur</h3> <h3 class="text-xl font-semibold">1. Créez votre serveur</h3>
<p class="text-gray-300">Remplissez un simple formulaire pour générer votre serveur.</p> <p class="text-gray-300">Remplissez un simple formulaire pour générer votre serveur.</p>
</div> </div>
<div class="bg-gray-800 p-6 rounded-lg shadow-lg"> <div class="bg-gray-800 p-6 rounded-lg shadow-lg flex flex-col items-center">
<img src="/icons/play-icon.svg" alt="Lancer" class="w-14 h-14 mb-2 invert">
<h3 class="text-xl font-semibold">2. Lancez et jouez</h3> <h3 class="text-xl font-semibold">2. Lancez et jouez</h3>
<p class="text-gray-300">Votre serveur est déployé instantanément et prêt à être rejoint.</p> <p class="text-gray-300">Votre serveur est déployé instantanément et prêt à être rejoint.</p>
</div> </div>
<div class="bg-gray-800 p-6 rounded-lg shadow-lg"> <div class="bg-gray-800 p-6 rounded-lg shadow-lg flex flex-col items-center">
<img src="/icons/auto-icon.svg" alt="Auto-gestion" class="w-14 h-14 mb-2 invert">
<h3 class="text-xl font-semibold">3. Auto-gestion</h3> <h3 class="text-xl font-semibold">3. Auto-gestion</h3>
<p class="text-gray-300">Le serveur s'éteint automatiquement après inactivité pour économiser les ressources.</p> <p class="text-gray-300">Le serveur s'éteint automatiquement après inactivité pour économiser les ressources.</p>
</div> </div>
</div> </div>
</section> </section>
<section class="max-w-4xl mx-auto text-center bg-cover bg-center fade-in my-10" style="background-image: url('https://source.unsplash.com/1600x900/?minecraft,game');"> <section class="mt-10 text-center mb-10">
<div class="w-full bg-gray-800 p-10 inline-block rounded-lg slide-up"> <h2 class="text-2xl font-bold mb-4 fade-in flex justify-center items-center gap-2">
<h2 class="text-4xl font-bold">Hébergez votre serveur Minecraft</h2> <img src="/icons/rocket-icon.svg" alt="Démarrer" class="w-7 h-7 invert"> Commencez dès maintenant !
<p class="text-gray-300 mt-4">Des performances optimales pour des parties sans lag. Commencez dès maintenant !</p>
<a href="#offres" class="mt-6 inline-block bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-6 rounded-lg shadow-md scale-hover">Créer un serveur</a> </h2>
<p class="text-gray-300 mt-4 fade-in">Des performances optimales pour des parties sans lag. Commencez dès maintenant !</p>
<Link :href="route('servers.create')" class="mt-6 w-fit mx-auto items-center fade-in flex bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-6 rounded-lg shadow-md scale-hover">
<img src="/icons/arrow-icon.svg" alt="Créer" class="w-5 h-5 rotate-180 invert mr-2 object-cover"> Créer un serveur
</Link>
</section>
<p class="text-center text-2xl font-bold mb-4 fade-in">Nos Services</p>
<section class="flex justify-center mx-auto mb-10 slide-up">
<div v-for="service in props.services" class="relative flex items-center justify-center h-72 max-w-52 overflow-x-hidden bg-black w-full rounded-lg mx-5">
<img :src="service.image" class="object-cover h-full">
<!-- <p class="absolute bottom-0 right-0 left-0 p-1 text-center bg-gray-950/60 font-extrabold text-gray-300 text-2xl">{{ service.name }}</p> -->
</div> </div>
</section> </section>
</Layout> </Layout>

@ -6,14 +6,31 @@ import axios from 'axios';
import Layout from '@/Layouts/Layout.vue'; import Layout from '@/Layouts/Layout.vue';
import InputError from '@/Components/InputError.vue'; import InputError from '@/Components/InputError.vue';
import InputLabel from '@/Components/InputLabel.vue'; import InputLabel from '@/Components/InputLabel.vue';
import { computed } from 'vue';
const props = defineProps({
services: {
type: Object,
default: []
}
});
const form = useForm({ const form = useForm({
name: "", name: "",
port: "25000", service: props.services[0].uuid,
port: "",
});
const formatPort = computed(() => {
let result = "port";
let nb = props.services.find(s => form.service == s.uuid).ports.split("|").length;
for(let i = 1; i < nb; i++) result = result + "|port";
result += ")"
return result;
}); });
const submit = () => { const submit = () => {
form.post("/spawn"); form.post(route("servers.store"));
} }
console.log(); console.log();
@ -24,19 +41,23 @@ console.log();
<Layout> <Layout>
<!-- Création de Serveur --> <!-- Création de Serveur -->
<section class="py-20 px-6 text-center"> <section class="py-20 px-6 text-center">
<h2 class="text-3xl font-bold mb-10 fade-in">Créer Votre Serveur Minecraft Gratuitement</h2> <h2 class="text-3xl font-bold mb-10 fade-in">Créer Votre Serveur Gratuitement</h2>
<p class="text-gray-300 max-w-3xl mx-auto fade-in">Nos serveurs sont isolés via Docker et offrent un stockage limité à 10Go. Pour économiser les ressources, un serveur inactif pendant une période prolongée sera automatiquement arrêté.</p> <p class="text-gray-300 max-w-3xl mx-auto fade-in">Nos serveurs sont isolés via Docker et offrent un stockage limité à 10Go. Pour économiser les ressources, un serveur inactif pendant une période prolongée sera automatiquement arrêté.</p>
<form @submit.prevent="submit" class="max-w-lg mx-auto bg-gray-800 p-8 rounded-lg shadow-lg slide-up mt-6"> <form @submit.prevent="submit" class="max-w-lg mx-auto bg-gray-800 p-8 rounded-lg shadow-lg slide-up mt-6">
<div class="mb-6"> <div class="mb-3">
<InputLabel class="block text-left text-gray-300 mb-2" for="name">Name</InputLabel> <InputLabel class="block text-left text-gray-300 mb-2" for="name">Name</InputLabel>
<TextInput v-model="form.name" type="text" class="w-full p-3 rounded bg-gray-700 text-white" placeholder="Server name"></TextInput> <TextInput v-model="form.name" type="text" class="w-full p-3 rounded bg-gray-700 text-white" placeholder="Server name"></TextInput>
<InputError :message="form.errors.name"></InputError> <InputError :message="form.errors.name" class="text-left mt-1"></InputError>
</div> </div>
<div class="mb-6"> <div class="mb-10">
<InputLabel class="block text-left text-gray-300 mb-2" for="port">Port</InputLabel> <InputLabel class="block text-left text-gray-300 mb-2" for="service">Service</InputLabel>
<TextInput v-model="form.port" type="text" class="w-full p-3 rounded bg-gray-700 text-white" placeholder="Port (ex: 25000)"></TextInput> <select @change="e => form.service = e.target.value"
<InputError :message="form.errors.port"></InputError> class="w-full p-3 rounded bg-gray-700 text-white border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
<option v-for="service in props.services" :value="service.uuid">{{ service.name }}</option>
</select>
</div> </div>
<InputError :message="form.errors.service" class="text-left mt-1"></InputError>
<button type="submit" class="w-full bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-6 rounded-lg shadow-md scale-hover">Créer le Serveur</button> <button type="submit" class="w-full bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-6 rounded-lg shadow-md scale-hover">Créer le Serveur</button>
</form> </form>
</section> </section>

@ -0,0 +1,29 @@
<script setup>
import Layout from '@/Layouts/Layout.vue';
import { Head } from '@inertiajs/vue3';
import ServerElement from './Paritals/ServerElement.vue';
const props = defineProps({
servers: {
type: Array,
default: []
}
});
</script>
<template>
<Head title="Spawn" />
<Layout>
<!-- En-tête -->
<header class="max-w-6xl mx-auto my-10 text-center">
<h1 class="text-3xl font-bold animate-fade-in">Liste des Serveurs</h1>
<p class="text-gray-400 mt-2">Gérez vos serveurs Minecraft, Ark, Rust et plus encore.</p>
</header>
<!-- Liste des serveurs -->
<section class="max-w-6xl mx-auto grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 my-10">
<ServerElement v-for="server in props.servers" :server="server"/>
</section>
</Layout>
</template>

@ -0,0 +1,49 @@
<script setup>
import { Link } from '@inertiajs/vue3';
const props = defineProps({
server: {
type: Object,
required: true
}
})
</script>
<template>
<!-- Carte Serveur -->
<div class="bg-gray-800 rounded-lg shadow-lg p-6 slide-up relative">
<div class="flex justify-between items-center">
<h2 class="text-xl font-semibold flex items-center gap-2">
<img src="/icons/server-icon.svg" alt="Serveur" class="w-6 h-6 rotate-on-hover invert">
Serveur {{ props.server.name }}
</h2>
<span v-if="props.server.status.id < 3" class="px-3 py-1 text-sm font-bold rounded-lg bg-green-500 text-white">{{ props.server.status.title }}</span>
<span v-else class="px-3 py-1 text-sm font-bold rounded-lg bg-red-500 text-white">{{ props.server.status.title }}</span>
</div>
<div class="mt-4 space-y-2 text-sm">
<p><span class="font-medium">Type </span> {{ props.server.service.name }}</p>
<p><span class="font-medium">Dernier démarrage </span> {{ props.server.start ? props.server.start : "aucun" }}</p>
<p class="flex gap-2">
<span class="font-medium">Lien :</span>
<p class="text-green-400 hover:underline">
{{ props.server.ports.length ? "hosting.anulax.ch:" + props.server.ports[0] : "Indisponible" }}
</p>
</p>
</div>
<!-- Actions -->
<div class="mt-4 flex gap-2 w-full justify-end">
<a href="" class="bg-green-500 hover:bg-green-600 text-white font-bold p-2 rounded-lg shadow-lg flex items-center gap-2">
<img src="/icons/start-icon.svg" alt="Start" class="w-5 h-5 invert">
</a>
<a href="#" class="bg-red-500 hover:bg-red-600 text-white font-bold p-2 rounded-lg shadow-lg flex items-center gap-2">
<img src="/icons/stop-icon.svg" alt="Stop" class="w-5 h-5 invert">
</a>
<Link :href="route('servers.show', props.server.uuid)" class="bg-blue-500 hover:bg-blue-600 text-white font-bold p-2 rounded-lg shadow-lg flex items-center gap-2">
<img src="/icons/details-icon.svg" alt="Détails" class="w-5 h-5 invert">
</Link>
</div>
</div>
</template>

@ -0,0 +1,132 @@
<script setup>
import Layout from '@/Layouts/Layout.vue';
import { Head } from '@inertiajs/vue3';
</script>
<template>
<Head title="Spawn" />
<Layout>
<!-- En-tête -->
<header class="my-10 text-center">
<h1 class="text-4xl font-bold flex items-center justify-center gap-2 fade-in">
Dashboard - Détails du Serveur
</h1>
<p class="text-gray-300 mt-4 fade-in">
Gérez et visualisez les informations clés de votre serveur en un coup d'œil.
</p>
</header>
<!-- Cartes d'information -->
<main class="max-w-6xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-6 mb-10 slide-up">
<!-- Carte : Informations Générales -->
<div class="bg-gray-800 rounded-lg shadow-lg p-6">
<h2 class="text-2xl font-semibold border-b border-gray-700 pb-2 mb-4 flex items-center gap-2">
<img src="/icons/server-icon.svg" alt="Général" class="w-6 h-6 rotate-on-hover glow-on-hover invert">
Informations Générales
</h2>
<div class="space-y-3 text-sm">
<div class="flex justify-between">
<span class="font-medium">Nom</span>
<span class="text-green-400 font-bold">Mon Serveur Minecraft</span>
</div>
<div class="flex justify-between">
<span class="font-medium">Type de jeu</span>
<span>Minecraft</span>
</div>
<div class="flex flex-col gap-2">
<div class="flex justify-between items-center mb-1">
<div class="flex items-center gap-2">
<span class="font-medium">Lien d'accès</span>
</div>
<div class="flex items-center gap-2">
<a href="http://hosting.anulax.ch:25005" class="text-green-400 hover:underline">
hosting.anulax.ch:25005
</a>
<button class="bg-blue-500 hover:bg-blue-600 text-white font-bold p-1 rounded-lg shadow-lg glow-on-hover flex items-center">
<img src="/icons/copy-icon.svg" alt="Copier" class="w-5 h-5 invert">
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Carte : Activité -->
<div class="bg-gray-800 rounded-lg shadow-lg p-6">
<h2 class="text-2xl font-semibold border-b border-gray-700 pb-2 mb-4 flex items-center gap-2">
<img src="/icons/stats-icon.svg" alt="Activité" class="w-6 h-6 rotate-on-hover glow-on-hover invert">
Activité
</h2>
<div class="space-y-3 text-sm mb-4">
<div class="flex justify-between">
<span class="font-medium">Statut</span>
<span class="text-green-400 font-bold">Running</span>
</div>
<div class="flex justify-between">
<span class="font-medium">Dernier lancement :</span>
<span class="text-green-400 font-bold">2024-02-15 10:00</span>
</div>
<div class="flex justify-between">
<span class="font-medium">Dernier arrêt :</span>
<span class="text-red-400 font-bold">2024-02-15 09:00</span>
</div>
</div>
<div class="flex gap-3">
<a href="#" class="bg-green-500 hover:bg-green-600 text-white font-bold p-2 rounded-lg shadow-lg glow-on-hover flex items-center gap-2">
<img src="/icons/start-icon.svg" alt="Start" class="w-5 h-5 invert">
</a>
<a href="#" class="bg-red-500 hover:bg-red-600 text-white font-bold p-2 rounded-lg shadow-lg glow-on-hover flex items-center gap-2">
<img src="/icons/stop-icon.svg" alt="Stop" class="w-5 h-5 invert">
</a>
</div>
</div>
<!-- Carte : Hardware -->
<div class="bg-gray-800 rounded-lg shadow-lg p-6">
<h2 class="text-2xl font-semibold border-b border-gray-700 pb-2 mb-4 flex items-center gap-2">
<img src="/icons/hardware-icon.svg" alt="Hardware" class="w-6 h-6 rotate-on-hover glow-on-hover invert">
Hardware
</h2>
<div class="space-y-3 text-sm">
<div class="flex justify-between">
<span class="font-medium">CPU :</span>
<span>Intel Xeon E5</span>
</div>
<div class="flex justify-between">
<span class="font-medium">RAM :</span>
<span>16GB</span>
</div>
<div class="flex justify-between">
<span class="font-medium">Stockage :</span>
<span>10GB SSD</span>
</div>
</div>
</div>
</main>
<!-- Section Actions en haut -->
<section class="max-w-6xl mx-auto mb-6 fade-in">
<div class="flex justify-between items-center bg-gray-800 p-4 rounded-lg shadow-lg">
<div class="flex gap-3">
<button class="bg-blue-500 hover:bg-blue-600 text-white font-bold p-2 rounded-lg shadow-lg glow-on-hover flex items-center">
<img src="/icons/share-icon.svg" alt="Partager" class="w-5 h-5 invert">
</button>
</div>
<!-- Actions de gestion -->
<div class="flex gap-3">
<a href="#" class="bg-blue-500 hover:bg-blue-600 text-white font-bold p-2 rounded-lg shadow-lg glow-on-hover flex items-center gap-2">
<img src="/icons/edit-icon.svg" alt="Edit" class="w-5 h-5 invert">
</a>
<button class="bg-red-500 hover:bg-red-600 text-white font-bold p-2 rounded-lg shadow-lg glow-on-hover flex items-center">
<img src="/icons/public-icon.svg" alt="Rendre public" class="w-5 h-5 invert">
</button>
<a href="#" class="bg-red-500 hover:bg-red-600 text-white font-bold p-2 rounded-lg shadow-lg glow-on-hover flex items-center gap-2">
<img src="/icons/delete-icon.svg" alt="Delete" class="w-5 h-5 invert">
</a>
</div>
</div>
</section>
</Layout>
</template>

@ -15,7 +15,7 @@
@vite(['resources/js/app.js', "resources/js/Pages/{$page['component']}.vue"]) @vite(['resources/js/app.js', "resources/js/Pages/{$page['component']}.vue"])
@inertiaHead @inertiaHead
</head> </head>
<body class="font-roboto antialiased w-screen h-screen overflow-x-hidden bg-gray-600 dark"> <body class="font-roboto antialiased w-screen h-screen overflow-x-hidden bg-gray-900 dark">
@inertia @inertia
</body> </body>
</html> </html>

@ -1,8 +1,26 @@
<?php <?php
use App\Docker\Container;
use Illuminate\Foundation\Inspiring; use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;
Artisan::command('inspire', function () { Artisan::command('inspire', function () {
$this->comment(Inspiring::quote()); $this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote'); })->purpose('Display an inspiring quote');
Artisan::command('exec {id}', function ($id) {
try{
$container = new Container($id);
$exec = $container->exec(["apt install -y iproute2"]);
Log::info(json_encode($exec->inspect(), JSON_PRETTY_PRINT));
$exec->start();
Log::info($container->logs());
$exec = $container->exec(["echo hello"]);
$data = $exec->inspect();
Log::info(json_encode($data, JSON_PRETTY_PRINT));
$exec->start();
} catch (Exception $e) { Log::error(((object)$e)->getResponse()->getBody()); }
})->purpose('Display an inspiring quote');

@ -2,6 +2,8 @@
use App\Docker\Docker; use App\Docker\Docker;
use App\Docker\Container; use App\Docker\Container;
use App\Http\Controllers\ProfileController; use App\Http\Controllers\ProfileController;
use App\Http\Controllers\ServerController;
use App\Models\Service;
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@ -15,7 +17,9 @@
Route::get('/', function () { Route::get('/', function () {
return Inertia::render('Home'); return Inertia::render('Home', [
"services" => Service::all()
]);
})->name("home"); })->name("home");
Route::get("/info", function() { Route::get("/info", function() {
@ -23,36 +27,16 @@
return Inertia::render('Info', [ "config" => $config ]); return Inertia::render('Info', [ "config" => $config ]);
})->name("docker.info"); })->name("docker.info");
Route::get("/spawn", function (Request $request) {
return Inertia::render('Spawn');
})->name("docker.create");
Route::post("/spawn", function (Request $request) {
$request->validate([
"name" => "required|string",
"port" => "required|string"
]);
$container = Container::create($request->name, [
"Hostname" => "mincraft-". $request->name,
"Domainname" => $request->name,
"User" => "root",
"Image" => "minecraft:latest",
"OpenStdin" => true,
"Tty" => true,
"ExposedPorts" => [ "25565/tcp" => (object)[] ],
"HostConfig" => [
"PortBindings" => [ "25565/tcp" => [[ "HostPort" => $request->port ]] ],
]
]);
$container->start();
return redirect("/");
});
Route::get('/dashboard', function () { Route::get('/dashboard', function () {
return Inertia::render('Dashboard'); return Inertia::render('Dashboard');
})->middleware(['auth', 'verified'])->name('dashboard'); })->middleware(['auth', 'verified'])->name('dashboard');
Route::middleware('auth')->group(function () { Route::middleware(['auth'])->group(function () {
Route::get("/servers/create", [ServerController::class, 'create'])->name("servers.create");
Route::post("/servers", [ServerController::class, 'store'])->name("servers.store");
Route::get("/servers", [ServerController::class, 'index'])->name("servers.index");
Route::get("/servers/{id}", [ServerController::class, 'show'])->name("servers.show");
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit'); Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update'); Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy'); Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');

@ -1 +0,0 @@
a:3:{s:6:"_token";s:40:"nwGLpFjKisR3R1Mu3mdHCaXL39V8ByW0CVFN2n2E";s:9:"_previous";a:1:{s:3:"url";s:27:"http://localhost:8000/spawn";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}

11
svg

@ -0,0 +1,11 @@
mkdir -p icons && cd icons
# Télécharger les icônes (vérifie que ces URL correspondent bien aux fichiers SVG)
wget -O server-icon.svg "https://www.svgrepo.com/download/452095/server.svg"
wget -O security-icon.svg "https://www.svgrepo.com/download/488474/security-shield.svg"
wget -O process-icon.svg "https://www.svgrepo.com/download/444524/process.svg"
wget -O create-icon.svg "https://www.svgrepo.com/download/513806/add.svg"
wget -O play-icon.svg "https://www.svgrepo.com/download/488502/play-button.svg"
wget -O auto-icon.svg "https://www.svgrepo.com/download/456246/automation.svg"
wget -O rocket-icon.svg "https://www.svgrepo.com/download/488478/rocket.svg"
wget -O arrow-icon.svg "https://www.svgrepo.com/download/502744/arrow-right.svg"

@ -0,0 +1,27 @@
{
"Hostname": "mincraft-server",
"User": "root",
"Image": "minecraftbedrock:latest",
"OpenStdin": true,
"AttachStdout": false,
"AttachStderr": false,
"Tty": true,
"ExposedPorts": {
"19132/udp": {},
"19133/udp": {}
},
"HostConfig": {
"PortBindings": {
"19132/udp": [
{
"HostPort": 25004
}
],
"19133/udp": [
{
"HostPort": 25005
}
]
}
}
}
Loading…
Cancel
Save