From 09a9735962ed1d17b394fed449fa2b25fbdfac54 Mon Sep 17 00:00:00 2001 From: Saeed Vaziry <61919774+saeedvaziry@users.noreply.github.com> Date: Tue, 10 Jun 2025 00:14:05 +0200 Subject: [PATCH] reverse proxy basics (#609) --- app/Actions/Site/CreateSite.php | 10 ++++ app/Http/Controllers/SearchController.php | 30 ++++++++++++ resources/js/components/app-command.tsx | 5 +- resources/js/components/ui/sheet.tsx | 2 +- .../js/pages/sites/components/create-site.tsx | 11 +++++ .../services/webserver/caddy/vhost.blade.php | 28 ++++++----- .../services/webserver/nginx/vhost.blade.php | 48 +++++++++++-------- 7 files changed, 101 insertions(+), 33 deletions(-) create mode 100644 app/Http/Controllers/SearchController.php diff --git a/app/Actions/Site/CreateSite.php b/app/Actions/Site/CreateSite.php index 60bafe43..dd294baf 100755 --- a/app/Actions/Site/CreateSite.php +++ b/app/Actions/Site/CreateSite.php @@ -13,6 +13,7 @@ use App\Notifications\SiteInstallationSucceed; use App\ValidationRules\DomainRule; use Exception; +use Illuminate\Database\Query\Builder; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\Rule; @@ -38,6 +39,7 @@ public function create(Server $server, array $input): Site 'type' => $input['type'], 'domain' => $input['domain'], 'aliases' => $input['aliases'] ?? [], + 'port' => $input['port'] ?? null, 'user' => $user, 'path' => '/home/'.$user.'/'.$input['domain'], 'status' => SiteStatus::INSTALLING, @@ -132,6 +134,14 @@ public static function rules(Server $server, array $input): array Rule::unique('sites', 'user')->where('server_id', $server->id), Rule::notIn($server->getSshUsers()), ], + 'port' => [ + 'nullable', + 'integer', + 'min:1', + 'max:65535', + Rule::unique('sites', 'port') + ->where(fn (Builder $query) => $query->where('server_id', $server->id)), + ], ]; return array_merge($rules, self::typeRules($server, $input)); diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php new file mode 100644 index 00000000..02c48264 --- /dev/null +++ b/app/Http/Controllers/SearchController.php @@ -0,0 +1,30 @@ +validate($request, [ + 'query' => 'required|string|min:3', + ]); + + $query = $request->input('query'); + + $results = [ + 'data' => [], // Replace with actual search results + ]; + + return response()->json($results); + } +} diff --git a/resources/js/components/app-command.tsx b/resources/js/components/app-command.tsx index b6678063..e942e564 100644 --- a/resources/js/components/app-command.tsx +++ b/resources/js/components/app-command.tsx @@ -2,6 +2,7 @@ import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, C import { useEffect, useState } from 'react'; import { Button } from '@/components/ui/button'; import { CommandIcon, SearchIcon } from 'lucide-react'; +import CreateServer from '@/pages/servers/components/create-server'; export default function AppCommand() { const [open, setOpen] = useState(false); @@ -33,7 +34,9 @@ export default function AppCommand() { No results found. - Create server + + Create server + Create project diff --git a/resources/js/components/ui/sheet.tsx b/resources/js/components/ui/sheet.tsx index 764b7409..3987b558 100644 --- a/resources/js/components/ui/sheet.tsx +++ b/resources/js/components/ui/sheet.tsx @@ -47,7 +47,7 @@ function SheetContent({ { @@ -154,6 +156,15 @@ export default function CreateSite({ server, children }: { server?: Server; chil + + + form.setData('port', e.target.value)} placeholder="3000" /> +

+ This port will be used for reverse proxying the site. It should be unique across all sites on the server. +

+ +
+ {page.props.configs.site_types_custom_fields[form.data.type].map((config) => getFormField(config))} diff --git a/resources/views/ssh/services/webserver/caddy/vhost.blade.php b/resources/views/ssh/services/webserver/caddy/vhost.blade.php index 665ea30e..677573c6 100755 --- a/resources/views/ssh/services/webserver/caddy/vhost.blade.php +++ b/resources/views/ssh/services/webserver/caddy/vhost.blade.php @@ -8,17 +8,21 @@ import access_log {{ $site->domain }} import compression import security_headers - @if ($site->type()->language() === 'php') - root * {{ $site->getWebDirectoryPath() }} - @php - $phpSocket = "unix//var/run/php/php{$site->php_version}-fpm.sock"; - if ($site->isIsolated()) { - $phpSocket = "unix//run/php/php{$site->php_version}-fpm-{$site->user}.sock"; - } - @endphp - try_files {path} {path}/ /index.php?{query} - php_fastcgi {{ $phpSocket }} - file_server + @if ($site->port) + reverse_proxy 127.0.0.1:{{ $site->port }} + @else + @if ($site->type()->language() === 'php') + root * {{ $site->getWebDirectoryPath() }} + @php + $phpSocket = "unix//var/run/php/php{$site->php_version}-fpm.sock"; + if ($site->isIsolated()) { + $phpSocket = "unix//run/php/php{$site->php_version}-fpm-{$site->user}.sock"; + } + @endphp + try_files {path} {path}/ /index.php?{query} + php_fastcgi {{ $phpSocket }} + file_server + @endif @endif @if ($site->type === \App\Enums\SiteType::LOAD_BALANCER) reverse_proxy { @@ -44,4 +48,4 @@ } @endif @include('ssh.services.webserver.caddy.redirects', ['site' => $site]) -} \ No newline at end of file +} diff --git a/resources/views/ssh/services/webserver/nginx/vhost.blade.php b/resources/views/ssh/services/webserver/nginx/vhost.blade.php index 0f54a652..77e7ac1f 100755 --- a/resources/views/ssh/services/webserver/nginx/vhost.blade.php +++ b/resources/views/ssh/services/webserver/nginx/vhost.blade.php @@ -51,31 +51,41 @@ charset utf-8; - @if ($site->type()->language() === 'php') - @php - $phpSocket = "unix:/var/run/php/php{$site->php_version}-fpm.sock"; - if ($site->isIsolated()) { - $phpSocket = "unix:/run/php/php{$site->php_version}-fpm-{$site->user}.sock"; - } - @endphp + @if ($site->port) location / { - try_files $uri $uri/ /index.php?$query_string; - } - location ~ \.php$ { - fastcgi_pass {{ $phpSocket }}; - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - include fastcgi_params; - fastcgi_hide_header X-Powered-By; + proxy_pass http://127.0.0.1:{{ $site->port }}; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; } + @else + @if ($site->type()->language() === 'php') + @php + $phpSocket = "unix:/var/run/php/php{$site->php_version}-fpm.sock"; + if ($site->isIsolated()) { + $phpSocket = "unix:/run/php/php{$site->php_version}-fpm-{$site->user}.sock"; + } + @endphp + location / { + try_files $uri $uri/ /index.php?$query_string; + } + location ~ \.php$ { + fastcgi_pass {{ $phpSocket }}; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + include fastcgi_params; + fastcgi_hide_header X-Powered-By; + } + @endif @endif @if ($site->type === \App\Enums\SiteType::LOAD_BALANCER) location / { - proxy_pass http://{{ $backendName }}$request_uri; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://{{ $backendName }}$request_uri; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; } @endif