diff --git a/app/Actions/Projects/CreateProject.php b/app/Actions/Projects/CreateProject.php
index 839f1202..45c4137e 100644
--- a/app/Actions/Projects/CreateProject.php
+++ b/app/Actions/Projects/CreateProject.php
@@ -10,10 +10,13 @@ class CreateProject
 {
     public function create(User $user, array $input): Project
     {
+        if (isset($input['name'])) {
+            $input['name'] = strtolower($input['name']);
+        }
+
         $this->validate($user, $input);
 
         $project = new Project([
-            'user_id' => $user->id,
             'name' => $input['name'],
         ]);
 
@@ -29,7 +32,7 @@ private function validate(User $user, array $input): void
                 'required',
                 'string',
                 'max:255',
-                'unique:projects,name,NULL,id,user_id,'.$user->id,
+                'unique:projects,name',
             ],
         ])->validate();
     }
diff --git a/app/Actions/User/CreateUser.php b/app/Actions/User/CreateUser.php
new file mode 100644
index 00000000..516de094
--- /dev/null
+++ b/app/Actions/User/CreateUser.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace App\Actions\User;
+
+use App\Enums\UserRole;
+use App\Models\User;
+use Illuminate\Support\Facades\Validator;
+use Illuminate\Validation\Rule;
+
+class CreateUser
+{
+    public function create(array $input): User
+    {
+        $this->validate($input);
+
+        /** @var User $user */
+        $user = User::query()->create([
+            'name' => $input['name'],
+            'email' => $input['email'],
+            'role' => $input['role'],
+            'password' => bcrypt($input['password']),
+            'timezone' => 'UTC',
+        ]);
+
+        return $user;
+    }
+
+    private function validate(array $input): void
+    {
+        Validator::make($input, [
+            'name' => 'required|string|max:255',
+            'email' => 'required|email|unique:users,email',
+            'password' => 'required|string|min:8',
+            'role' => [
+                'required',
+                Rule::in([UserRole::ADMIN, UserRole::USER]),
+            ],
+        ])->validate();
+    }
+}
diff --git a/app/Actions/User/UpdateUser.php b/app/Actions/User/UpdateUser.php
new file mode 100644
index 00000000..70fc0c5f
--- /dev/null
+++ b/app/Actions/User/UpdateUser.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace App\Actions\User;
+
+use App\Enums\UserRole;
+use App\Models\User;
+use Illuminate\Support\Facades\Validator;
+use Illuminate\Validation\Rule;
+
+class UpdateUser
+{
+    public function update(User $user, array $input): void
+    {
+        $this->validate($user, $input);
+
+        $user->name = $input['name'];
+        $user->email = $input['email'];
+        $user->timezone = $input['timezone'];
+        $user->role = $input['role'];
+
+        if (isset($input['password']) && $input['password'] !== null) {
+            $user->password = bcrypt($input['password']);
+        }
+
+        $user->save();
+    }
+
+    private function validate(User $user, array $input): void
+    {
+        Validator::make($input, [
+            'name' => ['required', 'string', 'max:255'],
+            'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
+            'timezone' => [
+                'required',
+                Rule::in(timezone_identifiers_list()),
+            ],
+            'role' => [
+                'required',
+                Rule::in([UserRole::ADMIN, UserRole::USER]),
+                function ($attribute, $value, $fail) use ($user) {
+                    if ($user->is(auth()->user()) && $value !== $user->role) {
+                        $fail('You cannot change your own role');
+                    }
+                },
+            ],
+        ])->validate();
+    }
+}
diff --git a/app/Console/Commands/CreateUserCommand.php b/app/Console/Commands/CreateUserCommand.php
index 187431b0..c3bd6eea 100644
--- a/app/Console/Commands/CreateUserCommand.php
+++ b/app/Console/Commands/CreateUserCommand.php
@@ -7,7 +7,7 @@
 
 class CreateUserCommand extends Command
 {
-    protected $signature = 'user:create {name} {email} {password}';
+    protected $signature = 'user:create {name} {email} {password} {--role=admin}';
 
     protected $description = 'Create a new user';
 
@@ -25,6 +25,7 @@ public function handle(): void
             'name' => $this->argument('name'),
             'email' => $this->argument('email'),
             'password' => bcrypt($this->argument('password')),
+            'role' => $this->option('role'),
         ]);
 
         $this->info('User created!');
diff --git a/app/Enums/UserRole.php b/app/Enums/UserRole.php
new file mode 100644
index 00000000..57fc7ebc
--- /dev/null
+++ b/app/Enums/UserRole.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace App\Enums;
+
+final class UserRole
+{
+    const USER = 'user';
+
+    const ADMIN = 'admin';
+}
diff --git a/app/Http/Controllers/ApplicationController.php b/app/Http/Controllers/ApplicationController.php
index 47ce228e..91548601 100644
--- a/app/Http/Controllers/ApplicationController.php
+++ b/app/Http/Controllers/ApplicationController.php
@@ -22,6 +22,8 @@ class ApplicationController extends Controller
 {
     public function deploy(Server $server, Site $site): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         try {
             app(Deploy::class)->run($site);
 
@@ -41,11 +43,15 @@ public function deploy(Server $server, Site $site): HtmxResponse
 
     public function showDeploymentLog(Server $server, Site $site, Deployment $deployment): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         return back()->with('content', $deployment->log?->getContent());
     }
 
     public function updateDeploymentScript(Server $server, Site $site, Request $request): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(UpdateDeploymentScript::class)->update($site, $request->input());
 
         Toast::success('Deployment script updated!');
@@ -55,6 +61,8 @@ public function updateDeploymentScript(Server $server, Site $site, Request $requ
 
     public function updateBranch(Server $server, Site $site, Request $request): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(UpdateBranch::class)->update($site, $request->input());
 
         Toast::success('Branch updated!');
@@ -64,11 +72,15 @@ public function updateBranch(Server $server, Site $site, Request $request): Redi
 
     public function getEnv(Server $server, Site $site): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         return back()->with('env', $site->getEnv());
     }
 
     public function updateEnv(Server $server, Site $site, Request $request): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(UpdateEnv::class)->update($site, $request->input());
 
         Toast::success('Env updated!');
@@ -78,6 +90,8 @@ public function updateEnv(Server $server, Site $site, Request $request): Redirec
 
     public function enableAutoDeployment(Server $server, Site $site): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         if (! $site->isAutoDeployment()) {
             try {
                 $site->enableAutoDeployment();
@@ -101,6 +115,8 @@ public function enableAutoDeployment(Server $server, Site $site): HtmxResponse
 
     public function disableAutoDeployment(Server $server, Site $site): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         if ($site->isAutoDeployment()) {
             try {
                 $site->disableAutoDeployment();
diff --git a/app/Http/Controllers/ConsoleController.php b/app/Http/Controllers/ConsoleController.php
index 51639f18..6905858d 100644
--- a/app/Http/Controllers/ConsoleController.php
+++ b/app/Http/Controllers/ConsoleController.php
@@ -11,6 +11,8 @@ class ConsoleController extends Controller
 {
     public function index(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('console.index', [
             'server' => $server,
         ]);
@@ -18,6 +20,8 @@ public function index(Server $server): View
 
     public function run(Server $server, Request $request)
     {
+        $this->authorize('manage', $server);
+
         $this->validate($request, [
             'user' => [
                 'required',
diff --git a/app/Http/Controllers/CronjobController.php b/app/Http/Controllers/CronjobController.php
index 2c55c3c7..e958d050 100644
--- a/app/Http/Controllers/CronjobController.php
+++ b/app/Http/Controllers/CronjobController.php
@@ -16,6 +16,8 @@ class CronjobController extends Controller
 {
     public function index(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('cronjobs.index', [
             'server' => $server,
             'cronjobs' => $server->cronJobs,
@@ -24,6 +26,8 @@ public function index(Server $server): View
 
     public function store(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(CreateCronJob::class)->create($server, $request->input());
 
         Toast::success('Cronjob created successfully.');
@@ -33,6 +37,8 @@ public function store(Server $server, Request $request): HtmxResponse
 
     public function destroy(Server $server, CronJob $cronJob): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(DeleteCronJob::class)->delete($server, $cronJob);
 
         Toast::success('Cronjob deleted successfully.');
diff --git a/app/Http/Controllers/DatabaseBackupController.php b/app/Http/Controllers/DatabaseBackupController.php
index 7ab6367d..770cbb28 100644
--- a/app/Http/Controllers/DatabaseBackupController.php
+++ b/app/Http/Controllers/DatabaseBackupController.php
@@ -18,6 +18,8 @@ class DatabaseBackupController extends Controller
 {
     public function show(Server $server, Backup $backup): View
     {
+        $this->authorize('manage', $server);
+
         return view('databases.backups', [
             'server' => $server,
             'databases' => $server->databases,
@@ -28,6 +30,8 @@ public function show(Server $server, Backup $backup): View
 
     public function run(Server $server, Backup $backup): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(RunBackup::class)->run($backup);
 
         Toast::success('Backup is running.');
@@ -37,6 +41,8 @@ public function run(Server $server, Backup $backup): RedirectResponse
 
     public function store(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(CreateBackup::class)->create('database', $server, $request->input());
 
         Toast::success('Backup created successfully.');
@@ -46,6 +52,8 @@ public function store(Server $server, Request $request): HtmxResponse
 
     public function destroy(Server $server, Backup $backup): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $backup->delete();
 
         Toast::success('Backup deleted successfully.');
@@ -55,6 +63,8 @@ public function destroy(Server $server, Backup $backup): RedirectResponse
 
     public function restore(Server $server, Backup $backup, BackupFile $backupFile, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(RestoreBackup::class)->restore($backupFile, $request->input());
 
         Toast::success('Backup restored successfully.');
@@ -64,6 +74,8 @@ public function restore(Server $server, Backup $backup, BackupFile $backupFile,
 
     public function destroyFile(Server $server, Backup $backup, BackupFile $backupFile): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $backupFile->delete();
 
         Toast::success('Backup file deleted successfully.');
diff --git a/app/Http/Controllers/DatabaseController.php b/app/Http/Controllers/DatabaseController.php
index dafd84ff..4b5c9460 100644
--- a/app/Http/Controllers/DatabaseController.php
+++ b/app/Http/Controllers/DatabaseController.php
@@ -17,6 +17,8 @@ class DatabaseController extends Controller
 {
     public function index(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('databases.index', [
             'server' => $server,
             'databases' => $server->databases,
@@ -27,6 +29,8 @@ public function index(Server $server): View
 
     public function store(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         $database = app(CreateDatabase::class)->create($server, $request->input());
 
         if ($request->input('user')) {
@@ -40,6 +44,8 @@ public function store(Server $server, Request $request): HtmxResponse
 
     public function destroy(Server $server, Database $database): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(DeleteDatabase::class)->delete($server, $database);
 
         Toast::success('Database deleted successfully.');
diff --git a/app/Http/Controllers/DatabaseUserController.php b/app/Http/Controllers/DatabaseUserController.php
index 945a908a..939dffda 100644
--- a/app/Http/Controllers/DatabaseUserController.php
+++ b/app/Http/Controllers/DatabaseUserController.php
@@ -16,6 +16,8 @@ class DatabaseUserController extends Controller
 {
     public function store(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         $database = app(CreateDatabaseUser::class)->create($server, $request->input());
 
         if ($request->input('user')) {
@@ -29,6 +31,8 @@ public function store(Server $server, Request $request): HtmxResponse
 
     public function destroy(Server $server, DatabaseUser $databaseUser): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(DeleteDatabaseUser::class)->delete($server, $databaseUser);
 
         Toast::success('User deleted successfully.');
@@ -38,6 +42,8 @@ public function destroy(Server $server, DatabaseUser $databaseUser): RedirectRes
 
     public function password(Server $server, DatabaseUser $databaseUser): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         return back()->with([
             'password' => $databaseUser->password,
         ]);
@@ -45,6 +51,8 @@ public function password(Server $server, DatabaseUser $databaseUser): RedirectRe
 
     public function link(Server $server, DatabaseUser $databaseUser, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(LinkUser::class)->link($databaseUser, $request->input());
 
         Toast::success('Database linked successfully.');
diff --git a/app/Http/Controllers/FirewallController.php b/app/Http/Controllers/FirewallController.php
index 218bb85f..d52fecc2 100644
--- a/app/Http/Controllers/FirewallController.php
+++ b/app/Http/Controllers/FirewallController.php
@@ -16,6 +16,8 @@ class FirewallController extends Controller
 {
     public function index(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('firewall.index', [
             'server' => $server,
             'rules' => $server->firewallRules,
@@ -24,6 +26,8 @@ public function index(Server $server): View
 
     public function store(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(CreateRule::class)->create($server, $request->input());
 
         Toast::success('Firewall rule created!');
@@ -33,6 +37,8 @@ public function store(Server $server, Request $request): HtmxResponse
 
     public function destroy(Server $server, FirewallRule $firewallRule): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(DeleteRule::class)->delete($server, $firewallRule);
 
         Toast::success('Firewall rule deleted!');
diff --git a/app/Http/Controllers/MetricController.php b/app/Http/Controllers/MetricController.php
index 6d83190c..060f96ca 100644
--- a/app/Http/Controllers/MetricController.php
+++ b/app/Http/Controllers/MetricController.php
@@ -15,6 +15,8 @@ class MetricController extends Controller
 {
     public function index(Server $server, Request $request): View|RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $this->checkIfMonitoringServiceInstalled($server);
 
         return view('metrics.index', [
@@ -26,6 +28,8 @@ public function index(Server $server, Request $request): View|RedirectResponse
 
     public function settings(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         $this->checkIfMonitoringServiceInstalled($server);
 
         app(UpdateMetricSettings::class)->update($server, $request->input());
@@ -37,6 +41,8 @@ public function settings(Server $server, Request $request): HtmxResponse
 
     private function checkIfMonitoringServiceInstalled(Server $server): void
     {
+        $this->authorize('manage', $server);
+
         if (! $server->monitoring()) {
             abort(404, 'Monitoring service is not installed on this server');
         }
diff --git a/app/Http/Controllers/PHPController.php b/app/Http/Controllers/PHPController.php
index 492ed973..07bf6db0 100644
--- a/app/Http/Controllers/PHPController.php
+++ b/app/Http/Controllers/PHPController.php
@@ -20,6 +20,8 @@ class PHPController extends Controller
 {
     public function index(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('php.index', [
             'server' => $server,
             'phps' => $server->services()->where('type', 'php')->get(),
@@ -29,6 +31,8 @@ public function index(Server $server): View
 
     public function install(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         try {
             app(InstallNewPHP::class)->install($server, $request->input());
 
@@ -42,6 +46,8 @@ public function install(Server $server, Request $request): HtmxResponse
 
     public function installExtension(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(InstallPHPExtension::class)->install($server, $request->input());
 
         Toast::success('PHP extension is being installed! Check the logs');
@@ -51,6 +57,8 @@ public function installExtension(Server $server, Request $request): HtmxResponse
 
     public function defaultCli(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(ChangeDefaultCli::class)->change($server, $request->input());
 
         Toast::success('Default PHP CLI is being changed!');
@@ -60,6 +68,8 @@ public function defaultCli(Server $server, Request $request): HtmxResponse
 
     public function getIni(Server $server, Request $request): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $ini = app(GetPHPIni::class)->getIni($server, $request->input());
 
         return back()->with('ini', $ini);
@@ -67,6 +77,8 @@ public function getIni(Server $server, Request $request): RedirectResponse
 
     public function updateIni(Server $server, Request $request): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(UpdatePHPIni::class)->update($server, $request->input());
 
         Toast::success('PHP ini updated!');
@@ -78,6 +90,8 @@ public function updateIni(Server $server, Request $request): RedirectResponse
 
     public function uninstall(Server $server, Request $request): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(UninstallPHP::class)->uninstall($server, $request->input());
 
         Toast::success('PHP is being uninstalled!');
diff --git a/app/Http/Controllers/Settings/ProfileController.php b/app/Http/Controllers/ProfileController.php
similarity index 87%
rename from app/Http/Controllers/Settings/ProfileController.php
rename to app/Http/Controllers/ProfileController.php
index 4476c6a3..cd49a353 100644
--- a/app/Http/Controllers/Settings/ProfileController.php
+++ b/app/Http/Controllers/ProfileController.php
@@ -1,11 +1,10 @@
 <?php
 
-namespace App\Http\Controllers\Settings;
+namespace App\Http\Controllers;
 
 use App\Actions\User\UpdateUserPassword;
 use App\Actions\User\UpdateUserProfileInformation;
 use App\Facades\Toast;
-use App\Http\Controllers\Controller;
 use Illuminate\Contracts\View\View;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
@@ -14,7 +13,7 @@ class ProfileController extends Controller
 {
     public function index(): View
     {
-        return view('settings.profile.index');
+        return view('profile.index');
     }
 
     public function info(Request $request): RedirectResponse
diff --git a/app/Http/Controllers/QueueController.php b/app/Http/Controllers/QueueController.php
index 3009aeea..c37a64aa 100644
--- a/app/Http/Controllers/QueueController.php
+++ b/app/Http/Controllers/QueueController.php
@@ -19,6 +19,8 @@ class QueueController extends Controller
 {
     public function index(Server $server, Site $site): View
     {
+        $this->authorize('manage', $server);
+
         return view('queues.index', [
             'server' => $server,
             'site' => $site,
@@ -28,6 +30,8 @@ public function index(Server $server, Site $site): View
 
     public function store(Server $server, Site $site, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(CreateQueue::class)->create($site, $request->input());
 
         Toast::success('Queue is being created.');
@@ -37,6 +41,8 @@ public function store(Server $server, Site $site, Request $request): HtmxRespons
 
     public function action(Server $server, Site $site, Queue $queue, string $action): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(ManageQueue::class)->{$action}($queue);
 
         Toast::success('Queue is about to '.$action);
@@ -46,6 +52,8 @@ public function action(Server $server, Site $site, Queue $queue, string $action)
 
     public function destroy(Server $server, Site $site, Queue $queue): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(DeleteQueue::class)->delete($queue);
 
         Toast::success('Queue is being deleted.');
@@ -55,6 +63,8 @@ public function destroy(Server $server, Site $site, Queue $queue): RedirectRespo
 
     public function logs(Server $server, Site $site, Queue $queue): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         return back()->with('content', app(GetQueueLogs::class)->getLogs($queue));
     }
 }
diff --git a/app/Http/Controllers/SSHKeyController.php b/app/Http/Controllers/SSHKeyController.php
index 4d7f0f5e..c576ebde 100644
--- a/app/Http/Controllers/SSHKeyController.php
+++ b/app/Http/Controllers/SSHKeyController.php
@@ -17,6 +17,8 @@ class SSHKeyController extends Controller
 {
     public function index(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('server-ssh-keys.index', [
             'server' => $server,
             'keys' => $server->sshKeys,
@@ -25,6 +27,8 @@ public function index(Server $server): View
 
     public function store(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         /** @var \App\Models\SshKey $key */
         $key = app(CreateSshKey::class)->create(
             $request->user(),
@@ -38,6 +42,8 @@ public function store(Server $server, Request $request): HtmxResponse
 
     public function destroy(Server $server, SshKey $sshKey): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(DeleteKeyFromServer::class)->delete($server, $sshKey);
 
         Toast::success('SSH Key has been deleted.');
@@ -47,6 +53,8 @@ public function destroy(Server $server, SshKey $sshKey): RedirectResponse
 
     public function deploy(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(DeployKeyToServer::class)->deploy(
             $request->user(),
             $server,
diff --git a/app/Http/Controllers/SSLController.php b/app/Http/Controllers/SSLController.php
index 18d7d526..8523aada 100644
--- a/app/Http/Controllers/SSLController.php
+++ b/app/Http/Controllers/SSLController.php
@@ -17,6 +17,8 @@ class SSLController extends Controller
 {
     public function index(Server $server, Site $site): View
     {
+        $this->authorize('manage', $server);
+
         return view('ssls.index', [
             'server' => $server,
             'site' => $site,
@@ -26,6 +28,8 @@ public function index(Server $server, Site $site): View
 
     public function store(Server $server, Site $site, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(CreateSSL::class)->create($site, $request->input());
 
         Toast::success('SSL certificate is being created.');
@@ -35,6 +39,8 @@ public function store(Server $server, Site $site, Request $request): HtmxRespons
 
     public function destroy(Server $server, Site $site, Ssl $ssl): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(DeleteSSL::class)->delete($ssl);
 
         Toast::success('SSL certificate has been deleted.');
diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php
index 712d8e7d..0c23e4be 100644
--- a/app/Http/Controllers/SearchController.php
+++ b/app/Http/Controllers/SearchController.php
@@ -4,6 +4,7 @@
 
 use App\Models\Server;
 use App\Models\Site;
+use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 
@@ -23,10 +24,22 @@ public function search(Request $request): JsonResponse
                 $query->where('name', 'like', '%'.$request->input('q').'%')
                     ->orWhere('ip', 'like', '%'.$request->input('q').'%');
             })
+            ->whereHas('project', function (Builder $projectQuery) {
+                $projectQuery->whereHas('users', function (Builder $userQuery) {
+                    $userQuery->where('user_id', auth()->user()->id);
+                });
+            })
             ->get();
 
         $sites = Site::query()
             ->where('domain', 'like', '%'.$request->input('q').'%')
+            ->whereHas('server', function (Builder $serverQuery) {
+                $serverQuery->whereHas('project', function (Builder $projectQuery) {
+                    $projectQuery->whereHas('users', function (Builder $userQuery) {
+                        $userQuery->where('user_id', auth()->user()->id);
+                    });
+                });
+            })
             ->get();
 
         $result = [];
diff --git a/app/Http/Controllers/ServerController.php b/app/Http/Controllers/ServerController.php
index 0e6e67f1..f6bc4aa7 100644
--- a/app/Http/Controllers/ServerController.php
+++ b/app/Http/Controllers/ServerController.php
@@ -19,6 +19,9 @@ public function index(): View
     {
         /** @var User $user */
         $user = auth()->user();
+
+        $this->authorize('viewAny', [Server::class, $user->currentProject]);
+
         $servers = $user->currentProject->servers()->orderByDesc('created_at')->get();
 
         return view('servers.index', compact('servers'));
@@ -26,6 +29,11 @@ public function index(): View
 
     public function create(Request $request): View
     {
+        /** @var User $user */
+        $user = auth()->user();
+
+        $this->authorize('create', [Server::class, $user->currentProject]);
+
         $provider = $request->query('provider', old('provider', \App\Enums\ServerProvider::CUSTOM));
         $serverProviders = ServerProvider::query()->where('provider', $provider)->get();
 
@@ -40,8 +48,13 @@ public function create(Request $request): View
      */
     public function store(Request $request): HtmxResponse
     {
+        /** @var User $user */
+        $user = auth()->user();
+
+        $this->authorize('create', [Server::class, $user->currentProject]);
+
         $server = app(CreateServer::class)->create(
-            $request->user(),
+            $user,
             $request->input()
         );
 
@@ -52,6 +65,8 @@ public function store(Request $request): HtmxResponse
 
     public function show(Server $server): View
     {
+        $this->authorize('view', $server);
+
         return view('servers.show', [
             'server' => $server,
         ]);
@@ -59,6 +74,8 @@ public function show(Server $server): View
 
     public function delete(Server $server): RedirectResponse
     {
+        $this->authorize('delete', $server);
+
         $server->delete();
 
         Toast::success('Server deleted successfully.');
diff --git a/app/Http/Controllers/ServerLogController.php b/app/Http/Controllers/ServerLogController.php
index 933c3936..00c6764b 100644
--- a/app/Http/Controllers/ServerLogController.php
+++ b/app/Http/Controllers/ServerLogController.php
@@ -14,6 +14,8 @@ class ServerLogController extends Controller
 {
     public function index(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('server-logs.index', [
             'server' => $server,
             'pageTitle' => __('Vito Logs'),
@@ -22,6 +24,8 @@ public function index(Server $server): View
 
     public function show(Server $server, ServerLog $serverLog): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         if ($server->id != $serverLog->server_id) {
             abort(404);
         }
@@ -33,6 +37,8 @@ public function show(Server $server, ServerLog $serverLog): RedirectResponse
 
     public function remote(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('server-logs.remote-logs', [
             'server' => $server,
             'remote' => true,
@@ -42,6 +48,8 @@ public function remote(Server $server): View
 
     public function store(Server $server, Request $request): \App\Helpers\HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(CreateServerLog::class)->create($server, $request->input());
 
         Toast::success('Log added successfully.');
@@ -51,6 +59,8 @@ public function store(Server $server, Request $request): \App\Helpers\HtmxRespon
 
     public function destroy(Server $server, ServerLog $serverLog): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $serverLog->delete();
 
         Toast::success('Remote log deleted successfully.');
diff --git a/app/Http/Controllers/ServerSettingController.php b/app/Http/Controllers/ServerSettingController.php
index 15f689eb..a89ae604 100644
--- a/app/Http/Controllers/ServerSettingController.php
+++ b/app/Http/Controllers/ServerSettingController.php
@@ -15,11 +15,15 @@ class ServerSettingController extends Controller
 {
     public function index(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('server-settings.index', compact('server'));
     }
 
     public function checkConnection(Server $server): RedirectResponse|HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         $oldStatus = $server->status;
 
         $server = $server->checkConnection();
@@ -41,6 +45,8 @@ public function checkConnection(Server $server): RedirectResponse|HtmxResponse
 
     public function reboot(Server $server): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(RebootServer::class)->reboot($server);
 
         Toast::info('Server is rebooting.');
@@ -50,6 +56,8 @@ public function reboot(Server $server): HtmxResponse
 
     public function edit(Request $request, Server $server): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(EditServer::class)->edit($server, $request->input());
 
         Toast::success('Server updated.');
diff --git a/app/Http/Controllers/ServiceController.php b/app/Http/Controllers/ServiceController.php
index df4967bf..3d9f03d1 100644
--- a/app/Http/Controllers/ServiceController.php
+++ b/app/Http/Controllers/ServiceController.php
@@ -16,6 +16,8 @@ class ServiceController extends Controller
 {
     public function index(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('services.index', [
             'server' => $server,
             'services' => $server->services,
@@ -24,6 +26,8 @@ public function index(Server $server): View
 
     public function start(Server $server, Service $service): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $service->start();
 
         Toast::success('Service is being started!');
@@ -33,6 +37,8 @@ public function start(Server $server, Service $service): RedirectResponse
 
     public function stop(Server $server, Service $service): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $service->stop();
 
         Toast::success('Service is being stopped!');
@@ -42,6 +48,8 @@ public function stop(Server $server, Service $service): RedirectResponse
 
     public function restart(Server $server, Service $service): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $service->restart();
 
         Toast::success('Service is being restarted!');
@@ -51,6 +59,8 @@ public function restart(Server $server, Service $service): RedirectResponse
 
     public function enable(Server $server, Service $service): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $service->enable();
 
         Toast::success('Service is being enabled!');
@@ -60,6 +70,8 @@ public function enable(Server $server, Service $service): RedirectResponse
 
     public function disable(Server $server, Service $service): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $service->disable();
 
         Toast::success('Service is being disabled!');
@@ -69,6 +81,8 @@ public function disable(Server $server, Service $service): RedirectResponse
 
     public function install(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(Install::class)->install($server, $request->input());
 
         Toast::success('Service is being installed!');
@@ -78,6 +92,8 @@ public function install(Server $server, Request $request): HtmxResponse
 
     public function uninstall(Server $server, Service $service): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         app(Uninstall::class)->uninstall($service);
 
         Toast::success('Service is being uninstalled!');
diff --git a/app/Http/Controllers/Settings/NotificationChannelController.php b/app/Http/Controllers/Settings/NotificationChannelController.php
index 88e12238..c007c4f4 100644
--- a/app/Http/Controllers/Settings/NotificationChannelController.php
+++ b/app/Http/Controllers/Settings/NotificationChannelController.php
@@ -29,7 +29,7 @@ public function add(Request $request): HtmxResponse
 
         Toast::success('Channel added successfully');
 
-        return htmx()->redirect(route('notification-channels'));
+        return htmx()->redirect(route('settings.notification-channels'));
     }
 
     public function delete(int $id): RedirectResponse
@@ -40,6 +40,6 @@ public function delete(int $id): RedirectResponse
 
         Toast::success('Channel deleted successfully');
 
-        return redirect()->route('notification-channels');
+        return redirect()->route('settings.notification-channels');
     }
 }
diff --git a/app/Http/Controllers/Settings/ProjectController.php b/app/Http/Controllers/Settings/ProjectController.php
index 3d1f5c25..eb8cc904 100644
--- a/app/Http/Controllers/Settings/ProjectController.php
+++ b/app/Http/Controllers/Settings/ProjectController.php
@@ -20,7 +20,7 @@ class ProjectController extends Controller
     public function index(): View
     {
         return view('settings.projects.index', [
-            'projects' => auth()->user()->projects,
+            'projects' => Project::all(),
         ]);
     }
 
@@ -30,7 +30,7 @@ public function create(Request $request): HtmxResponse
 
         Toast::success('Project created.');
 
-        return htmx()->redirect(route('projects'));
+        return htmx()->redirect(route('settings.projects'));
     }
 
     public function update(Request $request, Project $project): HtmxResponse
@@ -42,7 +42,7 @@ public function update(Request $request, Project $project): HtmxResponse
 
         Toast::success('Project updated.');
 
-        return htmx()->redirect(route('projects'));
+        return htmx()->redirect(route('settings.projects'));
     }
 
     public function delete(Project $project): RedirectResponse
@@ -74,6 +74,8 @@ public function switch($projectId): RedirectResponse
         /** @var Project $project */
         $project = $user->projects()->findOrFail($projectId);
 
+        $this->authorize('view', $project);
+
         $user->current_project_id = $project->id;
         $user->save();
 
diff --git a/app/Http/Controllers/Settings/SSHKeyController.php b/app/Http/Controllers/Settings/SSHKeyController.php
index 5fc14959..181b827a 100644
--- a/app/Http/Controllers/Settings/SSHKeyController.php
+++ b/app/Http/Controllers/Settings/SSHKeyController.php
@@ -29,7 +29,7 @@ public function add(Request $request): HtmxResponse
 
         Toast::success('SSH Key added');
 
-        return htmx()->redirect(route('ssh-keys'));
+        return htmx()->redirect(route('settings.ssh-keys'));
     }
 
     public function delete(int $id): RedirectResponse
@@ -40,6 +40,6 @@ public function delete(int $id): RedirectResponse
 
         Toast::success('SSH Key deleted');
 
-        return redirect()->route('ssh-keys');
+        return redirect()->route('settings.ssh-keys');
     }
 }
diff --git a/app/Http/Controllers/Settings/ServerProviderController.php b/app/Http/Controllers/Settings/ServerProviderController.php
index bae20923..9f738a56 100644
--- a/app/Http/Controllers/Settings/ServerProviderController.php
+++ b/app/Http/Controllers/Settings/ServerProviderController.php
@@ -30,7 +30,7 @@ public function connect(Request $request): HtmxResponse
 
         Toast::success('Server provider connected.');
 
-        return htmx()->redirect(route('server-providers'));
+        return htmx()->redirect(route('settings.server-providers'));
     }
 
     public function delete(ServerProvider $serverProvider): RedirectResponse
diff --git a/app/Http/Controllers/Settings/SourceControlController.php b/app/Http/Controllers/Settings/SourceControlController.php
index f3bb097a..019b20fb 100644
--- a/app/Http/Controllers/Settings/SourceControlController.php
+++ b/app/Http/Controllers/Settings/SourceControlController.php
@@ -29,7 +29,7 @@ public function connect(Request $request): HtmxResponse
 
         Toast::success('Source control connected.');
 
-        return htmx()->redirect(route('source-controls'));
+        return htmx()->redirect(route('settings.source-controls'));
     }
 
     public function delete(SourceControl $sourceControl): RedirectResponse
@@ -44,6 +44,6 @@ public function delete(SourceControl $sourceControl): RedirectResponse
 
         Toast::success('Source control deleted.');
 
-        return redirect()->route('source-controls');
+        return redirect()->route('settings.source-controls');
     }
 }
diff --git a/app/Http/Controllers/Settings/StorageProviderController.php b/app/Http/Controllers/Settings/StorageProviderController.php
index 939c56b9..fc5b12b9 100644
--- a/app/Http/Controllers/Settings/StorageProviderController.php
+++ b/app/Http/Controllers/Settings/StorageProviderController.php
@@ -30,7 +30,7 @@ public function connect(Request $request): HtmxResponse
 
         Toast::success('Storage provider connected.');
 
-        return htmx()->redirect(route('storage-providers'));
+        return htmx()->redirect(route('settings.storage-providers'));
     }
 
     public function delete(StorageProvider $storageProvider): RedirectResponse
diff --git a/app/Http/Controllers/Settings/UserController.php b/app/Http/Controllers/Settings/UserController.php
new file mode 100644
index 00000000..9d407733
--- /dev/null
+++ b/app/Http/Controllers/Settings/UserController.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace App\Http\Controllers\Settings;
+
+use App\Actions\User\CreateUser;
+use App\Actions\User\UpdateUser;
+use App\Facades\Toast;
+use App\Helpers\HtmxResponse;
+use App\Http\Controllers\Controller;
+use App\Models\User;
+use Illuminate\Contracts\View\View;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Request;
+use Illuminate\Validation\Rule;
+
+class UserController extends Controller
+{
+    public function index(): View
+    {
+        $users = User::query()->paginate(20);
+
+        return view('settings.users.index', compact('users'));
+    }
+
+    public function store(Request $request): HtmxResponse
+    {
+        $user = app(CreateUser::class)->create($request->input());
+
+        return htmx()->redirect(route('settings.users.show', $user));
+    }
+
+    public function show(User $user): View
+    {
+        return view('settings.users.show', [
+            'user' => $user,
+        ]);
+    }
+
+    public function update(User $user, Request $request): RedirectResponse
+    {
+        app(UpdateUser::class)->update($user, $request->input());
+
+        Toast::success('User updated successfully');
+
+        return back();
+    }
+
+    public function updateProjects(User $user, Request $request): HtmxResponse
+    {
+        $this->validate($request, [
+            'projects.*' => [
+                'required',
+                Rule::exists('projects', 'id'),
+            ],
+        ]);
+
+        $user->projects()->sync($request->projects);
+
+        Toast::success('Projects updated successfully');
+
+        return htmx()->redirect(route('settings.users.show', $user));
+    }
+
+    public function destroy(User $user): RedirectResponse
+    {
+        if ($user->is(request()->user())) {
+            Toast::error('You cannot delete your own account');
+
+            return back();
+        }
+
+        $user->delete();
+
+        Toast::success('User deleted successfully');
+
+        return redirect()->route('settings.users.index');
+    }
+}
diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php
index 1ad175dc..f99862ce 100644
--- a/app/Http/Controllers/SiteController.php
+++ b/app/Http/Controllers/SiteController.php
@@ -19,6 +19,8 @@ class SiteController extends Controller
 {
     public function index(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('sites.index', [
             'server' => $server,
             'sites' => $server->sites()->orderByDesc('id')->get(),
@@ -27,6 +29,8 @@ public function index(Server $server): View
 
     public function store(Server $server, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         $site = app(CreateSite::class)->create($server, $request->input());
 
         Toast::success('Site created');
@@ -36,6 +40,8 @@ public function store(Server $server, Request $request): HtmxResponse
 
     public function create(Server $server): View
     {
+        $this->authorize('manage', $server);
+
         return view('sites.create', [
             'server' => $server,
             'type' => old('type', request()->query('type', SiteType::LARAVEL)),
@@ -45,6 +51,8 @@ public function create(Server $server): View
 
     public function show(Server $server, Site $site, Request $request): View|RedirectResponse|HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         if (in_array($site->status, [SiteStatus::INSTALLING, SiteStatus::INSTALLATION_FAILED])) {
             if ($request->hasHeader('HX-Request')) {
                 return htmx()->redirect(route('servers.sites.installing', [$server, $site]));
@@ -61,6 +69,8 @@ public function show(Server $server, Site $site, Request $request): View|Redirec
 
     public function installing(Server $server, Site $site, Request $request): View|RedirectResponse|HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         if (! in_array($site->status, [SiteStatus::INSTALLING, SiteStatus::INSTALLATION_FAILED])) {
             if ($request->hasHeader('HX-Request')) {
                 return htmx()->redirect(route('servers.sites.show', [$server, $site]));
@@ -77,6 +87,8 @@ public function installing(Server $server, Site $site, Request $request): View|R
 
     public function destroy(Server $server, Site $site): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         app(DeleteSite::class)->delete($site);
 
         Toast::success('Site is being deleted');
diff --git a/app/Http/Controllers/SiteLogController.php b/app/Http/Controllers/SiteLogController.php
index 79c89b00..2975a996 100644
--- a/app/Http/Controllers/SiteLogController.php
+++ b/app/Http/Controllers/SiteLogController.php
@@ -10,6 +10,8 @@ class SiteLogController extends Controller
 {
     public function index(Server $server, Site $site): View
     {
+        $this->authorize('manage', $server);
+
         return view('site-logs.index', [
             'server' => $server,
             'site' => $site,
diff --git a/app/Http/Controllers/SiteSettingController.php b/app/Http/Controllers/SiteSettingController.php
index b45170e4..a17ac4d0 100644
--- a/app/Http/Controllers/SiteSettingController.php
+++ b/app/Http/Controllers/SiteSettingController.php
@@ -18,6 +18,8 @@ class SiteSettingController extends Controller
 {
     public function index(Server $server, Site $site): View
     {
+        $this->authorize('manage', $server);
+
         return view('site-settings.index', [
             'server' => $server,
             'site' => $site,
@@ -26,6 +28,8 @@ public function index(Server $server, Site $site): View
 
     public function getVhost(Server $server, Site $site): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         /** @var Webserver $handler */
         $handler = $server->webserver()->handler();
 
@@ -34,6 +38,8 @@ public function getVhost(Server $server, Site $site): RedirectResponse
 
     public function updateVhost(Server $server, Site $site, Request $request): RedirectResponse
     {
+        $this->authorize('manage', $server);
+
         $this->validate($request, [
             'vhost' => 'required|string',
         ]);
@@ -53,6 +59,8 @@ public function updateVhost(Server $server, Site $site, Request $request): Redir
 
     public function updatePHPVersion(Server $server, Site $site, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         $this->validate($request, [
             'version' => [
                 'required',
@@ -73,6 +81,8 @@ public function updatePHPVersion(Server $server, Site $site, Request $request):
 
     public function updateSourceControl(Server $server, Site $site, Request $request): HtmxResponse
     {
+        $this->authorize('manage', $server);
+
         $site = app(UpdateSourceControl::class)->update($site, $request->input());
 
         Toast::success('Source control updated successfully!');
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index f0394daa..a1731197 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -68,5 +68,6 @@ class Kernel extends HttpKernel
         'server-is-ready' => ServerIsReadyMiddleware::class,
         'handle-ssh-errors' => HandleSSHErrors::class,
         'select-current-project' => SelectCurrentProject::class,
+        'is-admin' => \App\Http\Middleware\IsAdmin::class,
     ];
 }
diff --git a/app/Http/Middleware/IsAdmin.php b/app/Http/Middleware/IsAdmin.php
new file mode 100644
index 00000000..c5b4697e
--- /dev/null
+++ b/app/Http/Middleware/IsAdmin.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Enums\UserRole;
+use Closure;
+use Illuminate\Http\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+class IsAdmin
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
+     */
+    public function handle(Request $request, Closure $next): Response
+    {
+        if (auth()->user()->role !== UserRole::ADMIN) {
+            abort(403, 'You are not authorized to access this page.');
+        }
+
+        return $next($request);
+    }
+}
diff --git a/app/Models/Project.php b/app/Models/Project.php
index 1985d125..d354817b 100644
--- a/app/Models/Project.php
+++ b/app/Models/Project.php
@@ -7,6 +7,7 @@
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 use Illuminate\Database\Eloquent\Relations\HasMany;
 
 /**
@@ -53,4 +54,9 @@ public function notificationChannels(): HasMany
     {
         return $this->hasMany(NotificationChannel::class);
     }
+
+    public function users(): BelongsToMany
+    {
+        return $this->belongsToMany(User::class, 'user_project')->withTimestamps();
+    }
 }
diff --git a/app/Models/User.php b/app/Models/User.php
index 55aea29c..efe30c1a 100755
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -2,7 +2,9 @@
 
 namespace App\Models;
 
+use App\Enums\UserRole;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 use Illuminate\Database\Eloquent\Relations\HasMany;
 use Illuminate\Database\Eloquent\Relations\HasOne;
 use Illuminate\Foundation\Auth\User as Authenticatable;
@@ -30,6 +32,7 @@
  * @property int $current_project_id
  * @property Project $currentProject
  * @property Collection<Project> $projects
+ * @property string $role
  */
 class User extends Authenticatable
 {
@@ -43,6 +46,7 @@ class User extends Authenticatable
         'password',
         'timezone',
         'current_project_id',
+        'role',
     ];
 
     protected $hidden = [
@@ -60,7 +64,9 @@ public static function boot(): void
         parent::boot();
 
         static::created(function (User $user) {
-            $user->createDefaultProject();
+            if (Project::count() === 0) {
+                $user->createDefaultProject();
+            }
         });
     }
 
@@ -117,9 +123,9 @@ public function connectedSourceControls(): array
         return $connectedSourceControls;
     }
 
-    public function projects(): HasMany
+    public function projects(): BelongsToMany
     {
-        return $this->hasMany(Project::class);
+        return $this->belongsToMany(Project::class, 'user_project')->withTimestamps();
     }
 
     public function currentProject(): HasOne
@@ -138,9 +144,10 @@ public function createDefaultProject(): Project
 
         if (! $project) {
             $project = new Project();
-            $project->user_id = $this->id;
-            $project->name = 'Default';
+            $project->name = 'default';
             $project->save();
+
+            $project->users()->attach($this->id);
         }
 
         $this->current_project_id = $project->id;
@@ -148,4 +155,9 @@ public function createDefaultProject(): Project
 
         return $project;
     }
+
+    public function isAdmin(): bool
+    {
+        return $this->role === UserRole::ADMIN;
+    }
 }
diff --git a/app/NotificationChannels/Discord.php b/app/NotificationChannels/Discord.php
index 3655adf6..ce283fd8 100644
--- a/app/NotificationChannels/Discord.php
+++ b/app/NotificationChannels/Discord.php
@@ -35,7 +35,7 @@ public function connect(): bool
             __('Congratulations! 🎉'),
             __("You've connected your Discord to :app", ['app' => config('app.name')])."\n".
             __('Manage your notification channels')."\n".
-            route('notification-channels')
+            route('settings.notification-channels')
         );
 
         if (! $connect) {
diff --git a/app/NotificationChannels/Slack.php b/app/NotificationChannels/Slack.php
index b4a68ffb..3bc28cd3 100644
--- a/app/NotificationChannels/Slack.php
+++ b/app/NotificationChannels/Slack.php
@@ -35,7 +35,7 @@ public function connect(): bool
             __('Congratulations! 🎉'),
             __("You've connected your Slack to :app", ['app' => config('app.name')])."\n".
             __('Manage your notification channels')."\n".
-            route('notification-channels')
+            route('settings.notification-channels')
         );
 
         if (! $connect) {
diff --git a/app/Policies/ProjectPolicy.php b/app/Policies/ProjectPolicy.php
new file mode 100644
index 00000000..7c062da9
--- /dev/null
+++ b/app/Policies/ProjectPolicy.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Policies;
+
+use App\Enums\UserRole;
+use App\Models\Project;
+use App\Models\User;
+
+class ProjectPolicy
+{
+    public function viewAny(User $user): bool
+    {
+        return $user->role === UserRole::ADMIN;
+    }
+
+    public function view(User $user, Project $project): bool
+    {
+        return $user->role === UserRole::ADMIN || $project->users->contains($user);
+    }
+
+    public function create(User $user): bool
+    {
+        return $user->role === UserRole::ADMIN;
+    }
+
+    public function update(User $user, Project $project): bool
+    {
+        return $user->role === UserRole::ADMIN;
+    }
+
+    public function delete(User $user, Project $project): bool
+    {
+        return $user->role === UserRole::ADMIN;
+    }
+}
diff --git a/app/Policies/ServerPolicy.php b/app/Policies/ServerPolicy.php
new file mode 100644
index 00000000..2f9eec2d
--- /dev/null
+++ b/app/Policies/ServerPolicy.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace App\Policies;
+
+use App\Enums\UserRole;
+use App\Models\Project;
+use App\Models\Server;
+use App\Models\User;
+
+class ServerPolicy
+{
+    public function viewAny(User $user, Project $project): bool
+    {
+        return $user->role === UserRole::ADMIN || $project->users->contains($user);
+    }
+
+    public function view(User $user, Server $server): bool
+    {
+        return $user->role === UserRole::ADMIN || $server->project->users->contains($user);
+    }
+
+    public function create(User $user, Project $project): bool
+    {
+        return $user->role === UserRole::ADMIN || $project->users->contains($user);
+    }
+
+    public function update(User $user, Server $server): bool
+    {
+        return $user->role === UserRole::ADMIN || $server->project->users->contains($user);
+    }
+
+    public function delete(User $user, Server $server): bool
+    {
+        return $user->role === UserRole::ADMIN || $server->project->users->contains($user);
+    }
+
+    public function manage(User $user, Server $server): bool
+    {
+        return $user->role === UserRole::ADMIN || $server->project->users->contains($user);
+    }
+}
diff --git a/app/View/Components/ProfileLayout.php b/app/View/Components/SettingsLayout.php
similarity index 66%
rename from app/View/Components/ProfileLayout.php
rename to app/View/Components/SettingsLayout.php
index b4f6c0e1..3cc54421 100644
--- a/app/View/Components/ProfileLayout.php
+++ b/app/View/Components/SettingsLayout.php
@@ -5,10 +5,10 @@
 use Illuminate\Contracts\View\View;
 use Illuminate\View\Component;
 
-class ProfileLayout extends Component
+class SettingsLayout extends Component
 {
     public function render(): View
     {
-        return view('layouts.profile');
+        return view('layouts.settings');
     }
 }
diff --git a/database/factories/ProjectFactory.php b/database/factories/ProjectFactory.php
index d99018a5..239a96a0 100644
--- a/database/factories/ProjectFactory.php
+++ b/database/factories/ProjectFactory.php
@@ -16,7 +16,6 @@ class ProjectFactory extends Factory
     public function definition(): array
     {
         return [
-            'user_id' => $this->faker->randomNumber(),
             'name' => $this->faker->name(),
             'created_at' => Carbon::now(),
             'updated_at' => Carbon::now(),
diff --git a/database/factories/ServerFactory.php b/database/factories/ServerFactory.php
index 72193273..7bc05112 100755
--- a/database/factories/ServerFactory.php
+++ b/database/factories/ServerFactory.php
@@ -7,7 +7,6 @@
 use App\Enums\ServerStatus;
 use App\Enums\ServerType;
 use App\Models\Server;
-use App\Models\User;
 use Illuminate\Database\Eloquent\Factories\Factory;
 
 class ServerFactory extends Factory
@@ -16,11 +15,7 @@ class ServerFactory extends Factory
 
     public function definition(): array
     {
-        /** @var User $user */
-        $user = User::factory()->create();
-
         return [
-            'user_id' => $user->id,
             'name' => $this->faker->name(),
             'ssh_user' => 'vito',
             'ip' => $this->faker->ipv4(),
diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php
index d2022098..26cb238e 100755
--- a/database/factories/UserFactory.php
+++ b/database/factories/UserFactory.php
@@ -2,6 +2,7 @@
 
 namespace Database\Factories;
 
+use App\Enums\UserRole;
 use App\Models\User;
 use Illuminate\Database\Eloquent\Factories\Factory;
 use Illuminate\Support\Str;
@@ -18,6 +19,7 @@ public function definition(): array
             'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
             'remember_token' => Str::random(10),
             'timezone' => 'UTC',
+            'role' => UserRole::ADMIN,
         ];
     }
 }
diff --git a/database/migrations/2023_08_13_095440_update_storage_providers_table.php b/database/migrations/2023_08_13_095440_update_storage_providers_table.php
index 200140ed..b5dc1ff5 100644
--- a/database/migrations/2023_08_13_095440_update_storage_providers_table.php
+++ b/database/migrations/2023_08_13_095440_update_storage_providers_table.php
@@ -9,15 +9,13 @@
     public function up(): void
     {
         Schema::table('storage_providers', function (Blueprint $table) {
-            $table->dropColumn('token');
-            $table->dropColumn('refresh_token');
-            $table->dropColumn('token_expires_at');
-            $table->dropColumn('label');
-            $table->dropColumn('connected');
             $table->unsignedBigInteger('user_id')->after('id');
             $table->string('profile')->after('user_id');
             $table->longText('credentials')->nullable()->after('provider');
         });
+        Schema::table('storage_providers', function (Blueprint $table) {
+            $table->dropColumn(['token', 'refresh_token', 'token_expires_at', 'label', 'connected']);
+        });
     }
 
     public function down(): void
@@ -27,9 +25,9 @@ public function down(): void
             $table->string('refresh_token')->nullable();
             $table->string('token_expires_at')->nullable();
             $table->string('label')->nullable();
-            $table->dropColumn('user_id');
-            $table->dropColumn('profile');
-            $table->dropColumn('credentials');
+        });
+        Schema::table('storage_providers', function (Blueprint $table) {
+            $table->dropColumn(['user_id', 'profile', 'credentials']);
         });
     }
 };
diff --git a/database/migrations/2024_04_24_213204_add_role_to_users_table.php b/database/migrations/2024_04_24_213204_add_role_to_users_table.php
new file mode 100644
index 00000000..2fdde00c
--- /dev/null
+++ b/database/migrations/2024_04_24_213204_add_role_to_users_table.php
@@ -0,0 +1,31 @@
+<?php
+
+use App\Enums\UserRole;
+use App\Models\User;
+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::table('users', function (Blueprint $table) {
+            $table->string('role')->default(UserRole::USER);
+        });
+        User::query()->update(['role' => UserRole::ADMIN]);
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('users', function (Blueprint $table) {
+            $table->dropColumn('role');
+        });
+    }
+};
diff --git a/database/migrations/2024_04_26_122230_create_user_project_table.php b/database/migrations/2024_04_26_122230_create_user_project_table.php
new file mode 100644
index 00000000..60820d98
--- /dev/null
+++ b/database/migrations/2024_04_26_122230_create_user_project_table.php
@@ -0,0 +1,38 @@
+<?php
+
+use App\Models\Project;
+use App\Models\User;
+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('user_project', function (Blueprint $table) {
+            $table->id();
+            $table->unsignedBigInteger('user_id');
+            $table->unsignedBigInteger('project_id');
+            $table->timestamps();
+        });
+        Project::all()->each(function (Project $project) {
+            $project->users()->attach($project->user_id);
+        });
+        User::all()->each(function (User $user) {
+            $user->current_project_id = $user->projects()->first()?->id;
+            $user->save();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('user_project');
+    }
+};
diff --git a/database/migrations/2024_04_26_123326_drop_user_id_from_projects_table.php b/database/migrations/2024_04_26_123326_drop_user_id_from_projects_table.php
new file mode 100644
index 00000000..5c6c1730
--- /dev/null
+++ b/database/migrations/2024_04_26_123326_drop_user_id_from_projects_table.php
@@ -0,0 +1,28 @@
+<?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::table('projects', function (Blueprint $table) {
+            $table->dropColumn('user_id');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('projects', function (Blueprint $table) {
+            $table->bigInteger('user_id')->nullable();
+        });
+    }
+};
diff --git a/resources/views/components/dropdown.blade.php b/resources/views/components/dropdown.blade.php
index dbd0f62e..84bca4c0 100644
--- a/resources/views/components/dropdown.blade.php
+++ b/resources/views/components/dropdown.blade.php
@@ -1,4 +1,11 @@
-@props(["open" => false, "align" => "right", "width" => "48", "contentClasses" => "list-none divide-y divide-gray-100 rounded-md border border-gray-200 bg-white py-1 text-base dark:divide-gray-600 dark:border-gray-600 dark:bg-gray-700"])
+@props([
+    "open" => false,
+    "align" => "right",
+    "width" => "48",
+    "contentClasses" => "list-none divide-y divide-gray-100 rounded-md border border-gray-200 bg-white py-1 text-base dark:divide-gray-600 dark:border-gray-600 dark:bg-gray-700",
+    "search" => false,
+    "searchUrl" => "",
+])
 
 @php
     switch ($align) {
@@ -42,6 +49,28 @@ class="{{ $width }} {{ $alignmentClasses }} absolute z-50 mt-2 rounded-md"
         @click="open = false"
     >
         <div class="{{ $contentClasses }} rounded-md">
+            @if ($search)
+                <div class="p-2">
+                    <input
+                        type="text"
+                        x-ref="search"
+                        x-model="search"
+                        x-on:keydown.window.prevent.enter="open = false"
+                        x-on:keydown.window.prevent.escape="open = false"
+                        x-on:keydown.window.prevent.arrow-up="
+                            open = true
+                            $refs.search.focus()
+                        "
+                        x-on:keydown.window.prevent.arrow-down="
+                            open = true
+                            $refs.search.focus()
+                        "
+                        class="w-full rounded-md border border-gray-200 p-2"
+                        placeholder="Search..."
+                    />
+                </div>
+            @endif
+
             {{ $content }}
         </div>
     </div>
diff --git a/resources/views/components/heroicons/o-arrow-left-circle.blade.php b/resources/views/components/heroicons/o-arrow-left-circle.blade.php
new file mode 100644
index 00000000..a9da3c4f
--- /dev/null
+++ b/resources/views/components/heroicons/o-arrow-left-circle.blade.php
@@ -0,0 +1,14 @@
+<svg
+    xmlns="http://www.w3.org/2000/svg"
+    fill="none"
+    viewBox="0 0 24 24"
+    stroke-width="1.5"
+    stroke="currentColor"
+    {{ $attributes }}
+>
+    <path
+        stroke-linecap="round"
+        stroke-linejoin="round"
+        d="m11.25 9-3 3m0 0 3 3m-3-3h7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
+    />
+</svg>
diff --git a/resources/views/components/heroicons/o-user-group.blade.php b/resources/views/components/heroicons/o-user-group.blade.php
new file mode 100644
index 00000000..87da1551
--- /dev/null
+++ b/resources/views/components/heroicons/o-user-group.blade.php
@@ -0,0 +1,14 @@
+<svg
+    xmlns="http://www.w3.org/2000/svg"
+    fill="none"
+    viewBox="0 0 24 24"
+    stroke-width="1.5"
+    stroke="currentColor"
+    {{ $attributes }}
+>
+    <path
+        stroke-linecap="round"
+        stroke-linejoin="round"
+        d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z"
+    />
+</svg>
diff --git a/resources/views/components/heroicons/o-x-mark.blade.php b/resources/views/components/heroicons/o-x-mark.blade.php
new file mode 100644
index 00000000..11d6f99f
--- /dev/null
+++ b/resources/views/components/heroicons/o-x-mark.blade.php
@@ -0,0 +1,10 @@
+<svg
+    xmlns="http://www.w3.org/2000/svg"
+    fill="none"
+    viewBox="0 0 24 24"
+    stroke-width="1.5"
+    stroke="currentColor"
+    {{ $attributes }}
+>
+    <path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
+</svg>
diff --git a/resources/views/components/select2.blade.php b/resources/views/components/select2.blade.php
new file mode 100644
index 00000000..e69de29b
diff --git a/resources/views/components/status.blade.php b/resources/views/components/status.blade.php
index 2ef5f143..70f363de 100644
--- a/resources/views/components/status.blade.php
+++ b/resources/views/components/status.blade.php
@@ -4,11 +4,11 @@
 
 @php
     $class = [
-        "success" => "rounded-full bg-green-50 px-2 py-1 text-xs uppercase text-green-500 dark:bg-green-500 dark:bg-opacity-10",
-        "danger" => "rounded-full bg-red-50 px-2 py-1 text-xs uppercase text-red-500 dark:bg-red-500 dark:bg-opacity-10",
-        "warning" => "rounded-full bg-yellow-50 px-2 py-1 text-xs uppercase text-yellow-500 dark:bg-yellow-500 dark:bg-opacity-10",
-        "disabled" => "rounded-full bg-gray-50 px-2 py-1 text-xs uppercase text-gray-500 dark:bg-gray-500 dark:bg-opacity-30 dark:text-gray-400",
-        "info" => "rounded-full bg-primary-50 px-2 py-1 text-xs uppercase text-primary-500 dark:bg-primary-500 dark:bg-opacity-10",
+        "success" => "rounded-md border border-green-300 bg-green-50 px-2 py-1 text-xs uppercase text-green-500 dark:border-green-600 dark:bg-green-500 dark:bg-opacity-10",
+        "danger" => "rounded-md border border-red-300 bg-red-50 px-2 py-1 text-xs uppercase text-red-500 dark:border-red-600 dark:bg-red-500 dark:bg-opacity-10",
+        "warning" => "rounded-md border border-yellow-300 bg-yellow-50 px-2 py-1 text-xs uppercase text-yellow-500 dark:border-yellow-600 dark:bg-yellow-500 dark:bg-opacity-10",
+        "disabled" => "rounded-md border border-gray-300 bg-gray-50 px-2 py-1 text-xs uppercase text-gray-500 dark:border-gray-600 dark:bg-gray-500 dark:bg-opacity-30 dark:text-gray-400",
+        "info" => "rounded-md border border-primary-300 bg-primary-50 px-2 py-1 text-xs uppercase text-primary-500 dark:border-primary-600 dark:bg-primary-500 dark:bg-opacity-10",
     ];
 @endphp
 
diff --git a/resources/views/components/user-dropdown.blade.php b/resources/views/components/user-dropdown.blade.php
index e78559f2..a50c5fd1 100644
--- a/resources/views/components/user-dropdown.blade.php
+++ b/resources/views/components/user-dropdown.blade.php
@@ -9,22 +9,22 @@
             <x-dropdown-link :href="route('profile')">
                 {{ __("Profile") }}
             </x-dropdown-link>
-            <x-dropdown-link :href="route('projects')">
+            <x-dropdown-link :href="route('settings.projects')">
                 {{ __("Projects") }}
             </x-dropdown-link>
-            <x-dropdown-link :href="route('server-providers')">
+            <x-dropdown-link :href="route('settings.server-providers')">
                 {{ __("Server Providers") }}
             </x-dropdown-link>
-            <x-dropdown-link :href="route('source-controls')">
+            <x-dropdown-link :href="route('settings.source-controls')">
                 {{ __("Source Controls") }}
             </x-dropdown-link>
-            <x-dropdown-link :href="route('storage-providers')">
+            <x-dropdown-link :href="route('settings.storage-providers')">
                 {{ __("Storage Providers") }}
             </x-dropdown-link>
-            <x-dropdown-link :href="route('notification-channels')">
+            <x-dropdown-link :href="route('settings.notification-channels')">
                 {{ __("Notification Channels") }}
             </x-dropdown-link>
-            <x-dropdown-link :href="route('ssh-keys')">
+            <x-dropdown-link :href="route('settings.ssh-keys')">
                 {{ __("SSH Keys") }}
             </x-dropdown-link>
             <!-- Authentication -->
diff --git a/resources/views/databases/partials/create-backup-modal.blade.php b/resources/views/databases/partials/create-backup-modal.blade.php
index 45e148a8..6fc1782a 100644
--- a/resources/views/databases/partials/create-backup-modal.blade.php
+++ b/resources/views/databases/partials/create-backup-modal.blade.php
@@ -41,7 +41,7 @@ class="p-6"
                         </option>
                     @endforeach
                 </x-select-input>
-                <x-secondary-button :href="route('storage-providers')" class="ml-2 flex-none">
+                <x-secondary-button :href="route('settings.storage-providers')" class="ml-2 flex-none">
                     Connect
                 </x-secondary-button>
             </div>
diff --git a/resources/views/layouts/navigation.blade.php b/resources/views/layouts/navigation.blade.php
index 779fff63..9044f47e 100644
--- a/resources/views/layouts/navigation.blade.php
+++ b/resources/views/layouts/navigation.blade.php
@@ -3,7 +3,7 @@ class="fixed top-0 z-50 flex h-[64px] w-full items-center border-b border-gray-2
 >
     <div class="w-full">
         <div class="flex items-center justify-between">
-            <div class="flex items-center justify-start">
+            <div class="flex flex-none items-center justify-start">
                 <div
                     class="flex items-center justify-start border-r border-gray-200 px-3 py-3 dark:border-gray-700 md:w-64"
                 >
@@ -17,7 +17,7 @@ class="inline-flex items-center rounded-md p-2 text-sm text-gray-500 hover:bg-gr
                         <span class="sr-only">Open sidebar</span>
                         <x-heroicon name="o-bars-3-center-left" class="h-6 w-6" />
                     </button>
-                    <a href="/" class="ms-2 flex md:me-24">
+                    <a href="/" class="ms-2 flex flex-none md:me-24">
                         <div class="relative flex items-center justify-start text-3xl font-extrabold">
                             <x-application-logo class="h-9 w-9 rounded-md" />
                             <span class="ml-1 hidden md:block">Deploy</span>
@@ -70,9 +70,11 @@ class="flex rounded-full p-1 text-sm focus:ring-2 focus:ring-gray-300 dark:focus
                             {{ __("Profile") }}
                         </x-dropdown-link>
 
-                        <x-dropdown-link :href="route('projects')">
-                            {{ __("Projects") }}
-                        </x-dropdown-link>
+                        @if (auth()->user()->isAdmin())
+                            <x-dropdown-link :href="route('settings.projects')">
+                                {{ __("Projects") }}
+                            </x-dropdown-link>
+                        @endif
 
                         <!-- Authentication -->
                         <form method="POST" action="{{ route("logout") }}">
diff --git a/resources/views/layouts/partials/project-select.blade.php b/resources/views/layouts/partials/project-select.blade.php
index 8e1aebb6..42298f6a 100644
--- a/resources/views/layouts/partials/project-select.blade.php
+++ b/resources/views/layouts/partials/project-select.blade.php
@@ -5,7 +5,14 @@
                 <div
                     class="flex h-10 w-max items-center rounded-md border border-gray-200 bg-gray-100 px-4 py-2 pr-7 text-sm text-gray-900 focus:ring-4 focus:ring-gray-300 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300 dark:focus:ring-gray-600"
                 >
-                    {{ auth()->user()->currentProject?->name ?? __("Select Project") }}
+                    <x-heroicon name="o-inbox-stack" class="mr-2 h-4 w-4 lg:hidden" />
+                    <span class="hidden lg:block">
+                        @if (auth()->user()->currentProject &&auth()->user()->can("view", auth()->user()->currentProject))
+                            {{ auth()->user()->currentProject->name }}
+                        @else
+                            {{ __("Select Project") }}
+                        @endif
+                    </span>
                     <button type="button" class="absolute inset-y-0 right-0 flex items-center pr-2">
                         <x-heroicon name="o-chevron-down" class="h-4 w-4 text-gray-400" />
                     </button>
@@ -14,8 +21,8 @@ class="flex h-10 w-max items-center rounded-md border border-gray-200 bg-gray-10
         </x-slot>
         <x-slot:content>
             @foreach (auth()->user()->projects as $project)
-                <x-dropdown-link class="relative" :href="route('projects.switch', ['project' => $project])">
-                    <span class="block truncate">{{ ucfirst($project->name) }}</span>
+                <x-dropdown-link class="relative" :href="route('settings.projects.switch', ['project' => $project])">
+                    <span class="block truncate">{{ $project->name }}</span>
                     @if ($project->id == auth()->user()->current_project_id)
                         <span class="absolute inset-y-0 right-0 flex items-center pr-3 text-primary-600">
                             <x-heroicon name="o-check" class="h-5 w-5" />
@@ -24,12 +31,14 @@ class="flex h-10 w-max items-center rounded-md border border-gray-200 bg-gray-10
                 </x-dropdown-link>
             @endforeach
 
-            <x-dropdown-link href="{{ route('projects') }}">
-                {{ __("Projects List") }}
-            </x-dropdown-link>
-            <x-dropdown-link href="{{ route('projects', ['create' => 'open']) }}">
-                {{ __("Create a Project") }}
-            </x-dropdown-link>
+            @if (auth()->user()->isAdmin())
+                <x-dropdown-link href="{{ route('settings.projects') }}">
+                    {{ __("Projects List") }}
+                </x-dropdown-link>
+                <x-dropdown-link href="{{ route('settings.projects', ['create' => 'open']) }}">
+                    {{ __("Create a Project") }}
+                </x-dropdown-link>
+            @endif
         </x-slot>
     </x-dropdown>
 </div>
diff --git a/resources/views/layouts/partials/server-select.blade.php b/resources/views/layouts/partials/server-select.blade.php
index 3087f784..6ab99e4b 100644
--- a/resources/views/layouts/partials/server-select.blade.php
+++ b/resources/views/layouts/partials/server-select.blade.php
@@ -1,35 +1,37 @@
-<div data-tooltip="Servers" class="cursor-pointer">
-    <x-dropdown width="full">
-        <x-slot:trigger>
-            <div>
-                <div
-                    class="block w-full rounded-md border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-primary-500 focus:ring-primary-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-primary-500 dark:focus:ring-primary-500"
-                >
-                    {{ isset($server) ? $server->name : "Select Server" }}
+@if (auth()->user()->currentProject &&auth()->user()->can("view", auth()->user()->currentProject))
+    <div data-tooltip="Servers" class="cursor-pointer">
+        <x-dropdown width="full">
+            <x-slot:trigger>
+                <div>
+                    <div
+                        class="block w-full rounded-md border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-primary-500 focus:ring-primary-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-primary-500 dark:focus:ring-primary-500"
+                    >
+                        {{ isset($server) ? $server->name : "Select Server" }}
+                    </div>
+                    <button type="button" class="absolute inset-y-0 right-0 flex items-center pr-2">
+                        <x-heroicon name="o-chevron-down" class="h-4 w-4 text-gray-400" />
+                    </button>
                 </div>
-                <button type="button" class="absolute inset-y-0 right-0 flex items-center pr-2">
-                    <x-heroicon name="o-chevron-down" class="h-4 w-4 text-gray-400" />
-                </button>
-            </div>
-        </x-slot>
-        <x-slot:content>
-            @foreach (auth()->user()->currentProject->servers as $s)
-                <x-dropdown-link class="relative" :href="route('servers.show', ['server' => $s])">
-                    <span class="block truncate">{{ ucfirst($s->name) }}</span>
-                    @if (isset($server) && $server->id == $s->id)
-                        <span class="absolute inset-y-0 right-0 flex items-center pr-3 text-primary-600">
-                            <x-heroicon name="o-check" class="h-5 w-5" />
-                        </span>
-                    @endif
-                </x-dropdown-link>
-            @endforeach
+            </x-slot>
+            <x-slot:content>
+                @foreach (auth()->user()->currentProject->servers as $s)
+                    <x-dropdown-link class="relative" :href="route('servers.show', ['server' => $s])">
+                        <span class="block truncate">{{ ucfirst($s->name) }}</span>
+                        @if (isset($server) && $server->id == $s->id)
+                            <span class="absolute inset-y-0 right-0 flex items-center pr-3 text-primary-600">
+                                <x-heroicon name="o-check" class="h-5 w-5" />
+                            </span>
+                        @endif
+                    </x-dropdown-link>
+                @endforeach
 
-            <x-dropdown-link href="{{ route('servers') }}">
-                {{ __("Servers List") }}
-            </x-dropdown-link>
-            <x-dropdown-link href="{{ route('servers.create') }}">
-                {{ __("Create a Server") }}
-            </x-dropdown-link>
-        </x-slot>
-    </x-dropdown>
-</div>
+                <x-dropdown-link href="{{ route('servers') }}">
+                    {{ __("Servers List") }}
+                </x-dropdown-link>
+                <x-dropdown-link href="{{ route('servers.create') }}">
+                    {{ __("Create a Server") }}
+                </x-dropdown-link>
+            </x-slot>
+        </x-dropdown>
+    </div>
+@endif
diff --git a/resources/views/layouts/partials/site-select.blade.php b/resources/views/layouts/partials/site-select.blade.php
deleted file mode 100644
index 83a24103..00000000
--- a/resources/views/layouts/partials/site-select.blade.php
+++ /dev/null
@@ -1,124 +0,0 @@
-<div x-data="siteCombobox()">
-    <div class="relative">
-        <div
-            @click="open = !open"
-            class="text-md flex h-10 w-full cursor-pointer items-center rounded-md bg-gray-200 px-4 py-3 pr-10 leading-5 focus:ring-1 focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-100"
-            x-text="selected.domain ?? 'Select Site'"
-        ></div>
-        <button type="button" @click="open = !open" class="absolute inset-y-0 right-0 flex items-center pr-2">
-            <svg
-                xmlns="http://www.w3.org/2000/svg"
-                viewBox="0 0 20 20"
-                fill="currentColor"
-                aria-hidden="true"
-                class="h-5 w-5 text-gray-400"
-            >
-                <path
-                    fill-rule="evenodd"
-                    d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z"
-                    clip-rule="evenodd"
-                ></path>
-            </svg>
-        </button>
-        <div
-            x-show="open"
-            @click.away="open = false"
-            class="absolute mt-1 w-full overflow-auto rounded-md bg-white pb-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-gray-700 sm:text-sm"
-        >
-            <div class="relative p-2">
-                <input
-                    x-model="query"
-                    @input="filterSitesAndOpen"
-                    placeholder="Filter"
-                    class="dark:focus:ring-800 w-full rounded-md bg-gray-200 py-2 pl-3 pr-10 text-sm leading-5 focus:ring-1 focus:ring-gray-400 dark:bg-gray-800 dark:text-gray-100"
-                />
-            </div>
-            <div class="relative max-h-[350px] overflow-y-auto">
-                <template x-for="(site, index) in filteredSites" :key="index">
-                    <div
-                        @click="selectSite(site); open = false"
-                        :class="site.id === selected.id ? 'cursor-default bg-primary-600 text-white' : 'cursor-pointer'"
-                        class="relative select-none px-4 py-2 text-gray-700 hover:bg-primary-600 hover:text-white dark:text-white"
-                    >
-                        <span class="block truncate" x-text="site.domain"></span>
-                        <template x-if="site.id === selected.id">
-                            <span class="absolute inset-y-0 right-0 flex items-center pr-3 text-white">
-                                <svg
-                                    xmlns="http://www.w3.org/2000/svg"
-                                    viewBox="0 0 20 20"
-                                    fill="currentColor"
-                                    aria-hidden="true"
-                                    class="h-5 w-5"
-                                >
-                                    <path
-                                        fill-rule="evenodd"
-                                        d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
-                                        clip-rule="evenodd"
-                                    ></path>
-                                </svg>
-                            </span>
-                        </template>
-                    </div>
-                </template>
-            </div>
-            <div
-                x-show="filteredSites.length === 0"
-                class="relative block cursor-default select-none truncate px-4 py-2 text-gray-700 dark:text-white"
-            >
-                No sites found!
-            </div>
-            <div class="py-1">
-                <hr class="border-gray-300 dark:border-gray-600" />
-            </div>
-            <div>
-                <a
-                    href="{{ route("servers.sites", ["server" => $server]) }}"
-                    class="@if(request()->routeIs('sites')) cursor-default bg-primary-600 text-white @else cursor-pointer @endif relative block select-none px-4 py-2 text-gray-700 hover:bg-primary-600 hover:text-white dark:text-white"
-                >
-                    <span class="block truncate">Sites List</span>
-                </a>
-            </div>
-            <div>
-                <a
-                    href="{{ route("servers.sites.create", ["server" => $server]) }}"
-                    class="@if(request()->routeIs('sites.create')) cursor-default bg-primary-600 text-white @else cursor-pointer @endif relative block select-none px-4 py-2 text-gray-700 hover:bg-primary-600 hover:text-white dark:text-white"
-                >
-                    <span class="block truncate">Create a Site</span>
-                </a>
-            </div>
-        </div>
-    </div>
-</div>
-
-<script>
-    function siteCombobox() {
-        const sites = @json(\App\Models\Site::query()->where('server_id', $server->id)->select('id', 'domain')->get());
-        return {
-            open: false,
-            query: '',
-            sites: sites,
-            selected: @if(isset($site)) @json($site->only('id', 'domain')) @else {} @endif,
-            filteredSites: sites,
-            selectSite(site) {
-                if (this.selected.id !== site.id) {
-                    this.selected = site;
-                    window.location.href = '{{ url('/servers') }}/' + '{{ $server->id }}/sites/' + site.id
-                }
-            },
-            filterSitesAndOpen() {
-                if (this.query === '') {
-                    this.filteredSites = this.sites;
-                    this.open = false;
-                } else {
-                    this.filteredSites = this.sites.filter((site) =>
-                        site.domain
-                            .toLowerCase()
-                            .replace(/\s+/g, '')
-                            .includes(this.query.toLowerCase().replace(/\s+/g, ''))
-                    );
-                    this.open = true;
-                }
-            },
-        };
-    }
-</script>
diff --git a/resources/views/layouts/profile.blade.php b/resources/views/layouts/settings.blade.php
similarity index 100%
rename from resources/views/layouts/profile.blade.php
rename to resources/views/layouts/settings.blade.php
diff --git a/resources/views/layouts/sidebar.blade.php b/resources/views/layouts/sidebar.blade.php
index 398c27d0..56f4c508 100644
--- a/resources/views/layouts/sidebar.blade.php
+++ b/resources/views/layouts/sidebar.blade.php
@@ -143,7 +143,7 @@ class="fixed left-0 top-0 z-40 h-screen w-64 -translate-x-full border-r border-g
                     >
                         <x-heroicon name="o-wrench-screwdriver" class="h-6 w-6" />
                         <span class="ml-2">
-                            {{ __("Settings") }}
+                            {{ __("Server Settings") }}
                         </span>
                     </x-sidebar-link>
                 </li>
@@ -168,45 +168,72 @@ class="fixed left-0 top-0 z-40 h-screen w-64 -translate-x-full border-r border-g
                     <span class="ml-2">Profile</span>
                 </x-sidebar-link>
             </li>
-            <li>
-                <x-sidebar-link :href="route('projects')" :active="request()->routeIs('projects')">
-                    <x-heroicon name="o-inbox-stack" class="h-6 w-6" />
-                    <span class="ml-2">Projects</span>
-                </x-sidebar-link>
-            </li>
-            <li>
-                <x-sidebar-link :href="route('server-providers')" :active="request()->routeIs('server-providers')">
-                    <x-heroicon name="o-server-stack" class="h-6 w-6" />
-                    <span class="ml-2">Server Providers</span>
-                </x-sidebar-link>
-            </li>
-            <li>
-                <x-sidebar-link :href="route('source-controls')" :active="request()->routeIs('source-controls')">
-                    <x-heroicon name="o-code-bracket" class="h-6 w-6" />
-                    <span class="ml-2">Source Controls</span>
-                </x-sidebar-link>
-            </li>
-            <li>
-                <x-sidebar-link :href="route('storage-providers')" :active="request()->routeIs('storage-providers')">
-                    <x-heroicon name="o-circle-stack" class="h-6 w-6" />
-                    <span class="ml-2">Storage Providers</span>
-                </x-sidebar-link>
-            </li>
-            <li>
-                <x-sidebar-link
-                    :href="route('notification-channels')"
-                    :active="request()->routeIs('notification-channels')"
-                >
-                    <x-heroicon name="o-bell" class="h-6 w-6" />
-                    <span class="ml-2">Notification Channels</span>
-                </x-sidebar-link>
-            </li>
-            <li>
-                <x-sidebar-link :href="route('ssh-keys')" :active="request()->routeIs('ssh-keys')">
-                    <x-heroicon name="o-key" class="h-6 w-6" />
-                    <span class="ml-2">SSH Keys</span>
-                </x-sidebar-link>
-            </li>
+
+            @if (auth()->user()->isAdmin())
+                <li>
+                    <x-sidebar-link
+                        :href="route('settings.users.index')"
+                        :active="request()->routeIs('settings.users*')"
+                    >
+                        <x-heroicon name="o-user-group" class="h-6 w-6" />
+                        <span class="ml-2">Users</span>
+                    </x-sidebar-link>
+                </li>
+                <li>
+                    <x-sidebar-link
+                        :href="route('settings.projects')"
+                        :active="request()->routeIs('settings.projects')"
+                    >
+                        <x-heroicon name="o-inbox-stack" class="h-6 w-6" />
+                        <span class="ml-2">Projects</span>
+                    </x-sidebar-link>
+                </li>
+                <li>
+                    <x-sidebar-link
+                        :href="route('settings.server-providers')"
+                        :active="request()->routeIs('settings.server-providers')"
+                    >
+                        <x-heroicon name="o-server-stack" class="h-6 w-6" />
+                        <span class="ml-2">Server Providers</span>
+                    </x-sidebar-link>
+                </li>
+                <li>
+                    <x-sidebar-link
+                        :href="route('settings.source-controls')"
+                        :active="request()->routeIs('settings.source-controls')"
+                    >
+                        <x-heroicon name="o-code-bracket" class="h-6 w-6" />
+                        <span class="ml-2">Source Controls</span>
+                    </x-sidebar-link>
+                </li>
+                <li>
+                    <x-sidebar-link
+                        :href="route('settings.storage-providers')"
+                        :active="request()->routeIs('settings.storage-providers')"
+                    >
+                        <x-heroicon name="o-circle-stack" class="h-6 w-6" />
+                        <span class="ml-2">Storage Providers</span>
+                    </x-sidebar-link>
+                </li>
+                <li>
+                    <x-sidebar-link
+                        :href="route('settings.notification-channels')"
+                        :active="request()->routeIs('settings.notification-channels')"
+                    >
+                        <x-heroicon name="o-bell" class="h-6 w-6" />
+                        <span class="ml-2">Notification Channels</span>
+                    </x-sidebar-link>
+                </li>
+                <li>
+                    <x-sidebar-link
+                        :href="route('settings.ssh-keys')"
+                        :active="request()->routeIs('settings.ssh-keys')"
+                    >
+                        <x-heroicon name="o-key" class="h-6 w-6" />
+                        <span class="ml-2">SSH Keys</span>
+                    </x-sidebar-link>
+                </li>
+            @endif
         </ul>
     </div>
 </aside>
diff --git a/resources/views/profile/index.blade.php b/resources/views/profile/index.blade.php
new file mode 100644
index 00000000..ae0e0f24
--- /dev/null
+++ b/resources/views/profile/index.blade.php
@@ -0,0 +1,9 @@
+<x-settings-layout>
+    <x-slot name="pageTitle">{{ __("Profile") }}</x-slot>
+
+    @include("profile.partials.update-profile-information")
+
+    @include("profile.partials.update-password")
+
+    @include("profile.partials.two-factor-authentication")
+</x-settings-layout>
diff --git a/resources/views/profile/partials/two-factor-authentication.blade.php b/resources/views/profile/partials/two-factor-authentication.blade.php
new file mode 100644
index 00000000..1d44665b
--- /dev/null
+++ b/resources/views/profile/partials/two-factor-authentication.blade.php
@@ -0,0 +1,78 @@
+<x-card>
+    <x-slot name="title">
+        {{ __("Two Factor Authentication") }}
+    </x-slot>
+
+    <x-slot name="description">
+        {{ __("Here you can activate 2FA to secure your account") }}
+    </x-slot>
+
+    <div id="two-factor">
+        @if (! auth()->user()->two_factor_secret)
+            {{-- Enable 2FA --}}
+            <form
+                hx-post="{{ route("two-factor.enable") }}"
+                hx-target="#two-factor"
+                hx-select="#two-factor"
+                hx-swap="outerHTML"
+            >
+                @csrf
+
+                <x-primary-button type="submit">
+                    {{ __("Enable Two-Factor") }}
+                </x-primary-button>
+            </form>
+        @else
+            {{-- Disable 2FA --}}
+            <form
+                hx-post="{{ route("two-factor.disable") }}"
+                hx-target="#two-factor"
+                hx-select="#two-factor"
+                hx-swap="outerHTML"
+            >
+                @csrf
+                @method("DELETE")
+
+                <x-danger-button type="submit">
+                    {{ __("Disable Two-Factor") }}
+                </x-danger-button>
+            </form>
+
+            @if (session("status") == "two-factor-authentication-enabled")
+                <div class="mt-5">
+                    {{ __('Two factor authentication is now enabled. Scan the following QR code using your phone\'s authenticator application.') }}
+                </div>
+
+                <div class="mt-5">
+                    {!! auth()->user()->twoFactorQrCodeSvg() !!}
+                </div>
+            @endif
+
+            {{-- Show 2FA Recovery Codes --}}
+            <div class="mt-5">
+                {{ __("Store these recovery codes in a secure password manager. They can be used to recover access to your account if your two factor authentication device is lost.") }}
+            </div>
+
+            <div class="mt-5 rounded-md border border-gray-100 p-2 dark:border-gray-700">
+                @foreach (json_decode(decrypt(auth()->user()->two_factor_recovery_codes), true) as $code)
+                    <div class="mt-2">{{ $code }}</div>
+                @endforeach
+            </div>
+
+            {{-- Regenerate 2FA Recovery Codes --}}
+            <form
+                class="mt-5"
+                hx-post="{{ route("two-factor.recovery-codes") }}"
+                hx-target="#two-factor"
+                hx-select="#two-factor"
+                hx-swap="outerHTML"
+            >
+                @csrf
+
+                <x-primary-button type="submit">
+                    {{ __("Regenerate Recovery Codes") }}
+                </x-primary-button>
+            </form>
+        @endif
+    </div>
+</x-card>
diff --git a/resources/views/settings/profile/partials/update-password.blade.php b/resources/views/profile/partials/update-password.blade.php
similarity index 100%
rename from resources/views/settings/profile/partials/update-password.blade.php
rename to resources/views/profile/partials/update-password.blade.php
diff --git a/resources/views/settings/profile/partials/update-profile-information.blade.php b/resources/views/profile/partials/update-profile-information.blade.php
similarity index 100%
rename from resources/views/settings/profile/partials/update-profile-information.blade.php
rename to resources/views/profile/partials/update-profile-information.blade.php
diff --git a/resources/views/servers/partials/create-server.blade.php b/resources/views/servers/partials/create-server.blade.php
index c32b8379..5921bf1e 100644
--- a/resources/views/servers/partials/create-server.blade.php
+++ b/resources/views/servers/partials/create-server.blade.php
@@ -70,7 +70,7 @@ class="mt-6 space-y-6"
                             @endforeach
                         </x-select-input>
                         <x-secondary-button
-                            :href="route('server-providers', ['provider' => $provider])"
+                            :href="route('settings.server-providers', ['provider' => $provider])"
                             class="ml-2 flex-none"
                         >
                             {{ __("Connect") }}
diff --git a/resources/views/settings/notification-channels/index.blade.php b/resources/views/settings/notification-channels/index.blade.php
index 3b27ab88..e09d74bc 100644
--- a/resources/views/settings/notification-channels/index.blade.php
+++ b/resources/views/settings/notification-channels/index.blade.php
@@ -1,5 +1,5 @@
-<x-profile-layout>
+<x-settings-layout>
     <x-slot name="pageTitle">{{ __("Notification Channels") }}</x-slot>
 
     @include("settings.notification-channels.partials.channels-list")
-</x-profile-layout>
+</x-settings-layout>
diff --git a/resources/views/settings/notification-channels/partials/add-channel.blade.php b/resources/views/settings/notification-channels/partials/add-channel.blade.php
index a137befd..ab413c3c 100644
--- a/resources/views/settings/notification-channels/partials/add-channel.blade.php
+++ b/resources/views/settings/notification-channels/partials/add-channel.blade.php
@@ -10,7 +10,7 @@
 
         <form
             id="add-channel-form"
-            hx-post="{{ route("notification-channels.add") }}"
+            hx-post="{{ route("settings.notification-channels.add") }}"
             hx-swap="outerHTML"
             hx-select="#add-channel-form"
             hx-ext="disable-element"
diff --git a/resources/views/settings/notification-channels/partials/channels-list.blade.php b/resources/views/settings/notification-channels/partials/channels-list.blade.php
index 74d995a8..db1b363a 100644
--- a/resources/views/settings/notification-channels/partials/channels-list.blade.php
+++ b/resources/views/settings/notification-channels/partials/channels-list.blade.php
@@ -24,7 +24,7 @@
                     <div class="flex items-center">
                         <div class="inline">
                             <x-icon-button
-                                x-on:click="deleteAction = '{{ route('notification-channels.delete', $channel->id) }}'; $dispatch('open-modal', 'delete-channel')"
+                                x-on:click="deleteAction = '{{ route('settings.notification-channels.delete', $channel->id) }}'; $dispatch('open-modal', 'delete-channel')"
                             >
                                 <x-heroicon name="o-trash" class="h-5 w-5" />
                             </x-icon-button>
diff --git a/resources/views/settings/profile/index.blade.php b/resources/views/settings/profile/index.blade.php
deleted file mode 100644
index 141d25ff..00000000
--- a/resources/views/settings/profile/index.blade.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<x-profile-layout>
-    <x-slot name="pageTitle">{{ __("Profile") }}</x-slot>
-
-    @include("settings.profile.partials.update-profile-information")
-
-    @include("settings.profile.partials.update-password")
-
-    @include("settings.profile.partials.two-factor-authentication")
-</x-profile-layout>
diff --git a/resources/views/settings/profile/partials/two-factor-authentication.blade.php b/resources/views/settings/profile/partials/two-factor-authentication.blade.php
deleted file mode 100644
index 6ad8d890..00000000
--- a/resources/views/settings/profile/partials/two-factor-authentication.blade.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<x-card>
-    <x-slot name="title">
-        {{ __("Two Factor Authentication") }}
-    </x-slot>
-
-    <x-slot name="description">
-        {{ __("Here you can activate 2FA to secure your account") }}
-    </x-slot>
-
-    @if (! auth()->user()->two_factor_secret)
-        {{-- Enable 2FA --}}
-        <form method="POST" action="{{ route("two-factor.enable") }}">
-            @csrf
-
-            <x-primary-button type="submit">
-                {{ __("Enable Two-Factor") }}
-            </x-primary-button>
-        </form>
-    @else
-        {{-- Disable 2FA --}}
-        <form method="POST" action="{{ route("two-factor.disable") }}">
-            @csrf
-            @method("DELETE")
-
-            <x-danger-button type="submit">
-                {{ __("Disable Two-Factor") }}
-            </x-danger-button>
-        </form>
-
-        @if (session("status") == "two-factor-authentication-enabled")
-            <div class="mt-5">
-                {{ __('Two factor authentication is now enabled. Scan the following QR code using your phone\'s authenticator application.') }}
-            </div>
-
-            <div class="mt-5">
-                {!! auth()->user()->twoFactorQrCodeSvg() !!}
-            </div>
-        @endif
-
-        {{-- Show 2FA Recovery Codes --}}
-        <div class="mt-5">
-            {{ __("Store these recovery codes in a secure password manager. They can be used to recover access to your account if your two factor authentication device is lost.") }}
-        </div>
-
-        <div class="mt-5 rounded-md border border-gray-100 p-2 dark:border-gray-700">
-            @foreach (json_decode(decrypt(auth()->user()->two_factor_recovery_codes), true) as $code)
-                <div class="mt-2">{{ $code }}</div>
-            @endforeach
-        </div>
-
-        {{-- Regenerate 2FA Recovery Codes --}}
-        <form class="mt-5" method="POST" action="{{ route("two-factor.recovery-codes") }}">
-            @csrf
-
-            <x-primary-button type="submit">
-                {{ __("Regenerate Recovery Codes") }}
-            </x-primary-button>
-        </form>
-    @endif
-</x-card>
diff --git a/resources/views/settings/projects/index.blade.php b/resources/views/settings/projects/index.blade.php
index 694dc05d..bdc4c95a 100644
--- a/resources/views/settings/projects/index.blade.php
+++ b/resources/views/settings/projects/index.blade.php
@@ -1,5 +1,5 @@
-<x-profile-layout>
+<x-settings-layout>
     <x-slot name="pageTitle">{{ __("Projects") }}</x-slot>
 
     @include("settings.projects.partials.projects-list")
-</x-profile-layout>
+</x-settings-layout>
diff --git a/resources/views/settings/projects/partials/create-project.blade.php b/resources/views/settings/projects/partials/create-project.blade.php
index 465bc446..1d0b11f4 100644
--- a/resources/views/settings/projects/partials/create-project.blade.php
+++ b/resources/views/settings/projects/partials/create-project.blade.php
@@ -6,7 +6,7 @@
     <x-modal name="create-project" :show="request()->has('create')">
         <form
             id="create-project-form"
-            hx-post="{{ route("projects.create") }}"
+            hx-post="{{ route("settings.projects.create") }}"
             hx-swap="outerHTML"
             hx-select="#create-project-form"
             hx-ext="disable-element"
diff --git a/resources/views/settings/projects/partials/edit-project.blade.php b/resources/views/settings/projects/partials/edit-project.blade.php
index 8e573359..051e24d7 100644
--- a/resources/views/settings/projects/partials/edit-project.blade.php
+++ b/resources/views/settings/projects/partials/edit-project.blade.php
@@ -6,7 +6,7 @@
     <x-modal name="edit-project-{{ $project->id }}">
         <form
             id="edit-project-form-{{ $project->id }}"
-            hx-post="{{ route("projects.update", $project) }}"
+            hx-post="{{ route("settings.projects.update", $project) }}"
             hx-swap="outerHTML"
             hx-select="#edit-project-form-{{ $project->id }}"
             hx-ext="disable-element"
diff --git a/resources/views/settings/projects/partials/projects-list.blade.php b/resources/views/settings/projects/partials/projects-list.blade.php
index 4b3646e6..31b36d6a 100644
--- a/resources/views/settings/projects/partials/projects-list.blade.php
+++ b/resources/views/settings/projects/partials/projects-list.blade.php
@@ -27,7 +27,7 @@
                 <div class="flex items-center">
                     @include("settings.projects.partials.edit-project", ["project" => $project])
                     <x-icon-button
-                        x-on:click="deleteAction = '{{ route('projects.delete', $project) }}'; $dispatch('open-modal', 'delete-project')"
+                        x-on:click="deleteAction = '{{ route('settings.projects.delete', $project) }}'; $dispatch('open-modal', 'delete-project')"
                     >
                         <x-heroicon name="o-trash" class="h-5 w-5" />
                     </x-icon-button>
diff --git a/resources/views/settings/server-providers/index.blade.php b/resources/views/settings/server-providers/index.blade.php
index 3050e1e5..6c0e6457 100644
--- a/resources/views/settings/server-providers/index.blade.php
+++ b/resources/views/settings/server-providers/index.blade.php
@@ -1,5 +1,5 @@
-<x-profile-layout>
+<x-settings-layout>
     <x-slot name="pageTitle">{{ __("Storage Providers") }}</x-slot>
 
     @include("settings.server-providers.partials.providers-list")
-</x-profile-layout>
+</x-settings-layout>
diff --git a/resources/views/settings/server-providers/partials/connect-provider.blade.php b/resources/views/settings/server-providers/partials/connect-provider.blade.php
index f52f3abf..012d6168 100644
--- a/resources/views/settings/server-providers/partials/connect-provider.blade.php
+++ b/resources/views/settings/server-providers/partials/connect-provider.blade.php
@@ -10,7 +10,7 @@
 
         <form
             id="connect-provider-form"
-            hx-post="{{ route("server-providers.connect") }}"
+            hx-post="{{ route("settings.server-providers.connect") }}"
             hx-swap="outerHTML"
             hx-select="#connect-provider-form"
             hx-ext="disable-element"
diff --git a/resources/views/settings/server-providers/partials/providers-list.blade.php b/resources/views/settings/server-providers/partials/providers-list.blade.php
index 09ca8478..d02d3de9 100644
--- a/resources/views/settings/server-providers/partials/providers-list.blade.php
+++ b/resources/views/settings/server-providers/partials/providers-list.blade.php
@@ -26,7 +26,7 @@ class="h-10 w-10"
                     <div class="flex items-center">
                         <div class="inline">
                             <x-icon-button
-                                x-on:click="deleteAction = '{{ route('server-providers.delete', $provider->id) }}'; $dispatch('open-modal', 'delete-provider')"
+                                x-on:click="deleteAction = '{{ route('settings.server-providers.delete', $provider->id) }}'; $dispatch('open-modal', 'delete-provider')"
                             >
                                 <x-heroicon name="o-trash" class="h-5 w-5" />
                             </x-icon-button>
diff --git a/resources/views/settings/source-controls/index.blade.php b/resources/views/settings/source-controls/index.blade.php
index 609a3872..c4c4d688 100644
--- a/resources/views/settings/source-controls/index.blade.php
+++ b/resources/views/settings/source-controls/index.blade.php
@@ -1,5 +1,5 @@
-<x-profile-layout>
+<x-settings-layout>
     <x-slot name="pageTitle">{{ __("Source Controls") }}</x-slot>
 
     @include("settings.source-controls.partials.source-controls-list")
-</x-profile-layout>
+</x-settings-layout>
diff --git a/resources/views/settings/source-controls/partials/connect.blade.php b/resources/views/settings/source-controls/partials/connect.blade.php
index b1280e59..edbea6f9 100644
--- a/resources/views/settings/source-controls/partials/connect.blade.php
+++ b/resources/views/settings/source-controls/partials/connect.blade.php
@@ -10,7 +10,7 @@
 
         <form
             id="connect-source-control-form"
-            hx-post="{{ route("source-controls.connect") }}"
+            hx-post="{{ route("settings.source-controls.connect") }}"
             hx-swap="outerHTML"
             hx-select="#connect-source-control-form"
             hx-ext="disable-element"
diff --git a/resources/views/settings/source-controls/partials/source-controls-list.blade.php b/resources/views/settings/source-controls/partials/source-controls-list.blade.php
index 8453102d..2c2a9e9f 100644
--- a/resources/views/settings/source-controls/partials/source-controls-list.blade.php
+++ b/resources/views/settings/source-controls/partials/source-controls-list.blade.php
@@ -22,7 +22,7 @@
                     <div class="flex items-center">
                         <div class="inline">
                             <x-icon-button
-                                x-on:click="deleteAction = '{{ route('source-controls.delete', $sourceControl->id) }}'; $dispatch('open-modal', 'delete-source-control')"
+                                x-on:click="deleteAction = '{{ route('settings.source-controls.delete', $sourceControl->id) }}'; $dispatch('open-modal', 'delete-source-control')"
                             >
                                 <x-heroicon name="o-trash" class="h-5 w-5" />
                             </x-icon-button>
diff --git a/resources/views/settings/ssh-keys/index.blade.php b/resources/views/settings/ssh-keys/index.blade.php
index 4add01ed..e21a1a90 100644
--- a/resources/views/settings/ssh-keys/index.blade.php
+++ b/resources/views/settings/ssh-keys/index.blade.php
@@ -1,5 +1,5 @@
-<x-profile-layout>
+<x-settings-layout>
     <x-slot name="pageTitle">{{ __("SSH Keys") }}</x-slot>
 
     @include("settings.ssh-keys.partials.keys-list")
-</x-profile-layout>
+</x-settings-layout>
diff --git a/resources/views/settings/ssh-keys/partials/add-key.blade.php b/resources/views/settings/ssh-keys/partials/add-key.blade.php
index 04050897..54a4d76c 100644
--- a/resources/views/settings/ssh-keys/partials/add-key.blade.php
+++ b/resources/views/settings/ssh-keys/partials/add-key.blade.php
@@ -6,7 +6,7 @@
     <x-modal name="add-key">
         <form
             id="add-ssh-key-form"
-            hx-post="{{ route("ssh-keys.add") }}"
+            hx-post="{{ route("settings.ssh-keys.add") }}"
             hx-swap="outerHTML"
             hx-select="#add-ssh-key-form"
             hx-ext="disable-element"
diff --git a/resources/views/settings/ssh-keys/partials/keys-list.blade.php b/resources/views/settings/ssh-keys/partials/keys-list.blade.php
index c162c69f..fb51041b 100644
--- a/resources/views/settings/ssh-keys/partials/keys-list.blade.php
+++ b/resources/views/settings/ssh-keys/partials/keys-list.blade.php
@@ -21,7 +21,7 @@
                     <div class="flex items-center">
                         <div class="inline">
                             <x-icon-button
-                                x-on:click="deleteAction = '{{ route('ssh-keys.delete', $key->id) }}'; $dispatch('open-modal', 'delete-ssh-key')"
+                                x-on:click="deleteAction = '{{ route('settings.ssh-keys.delete', $key->id) }}'; $dispatch('open-modal', 'delete-ssh-key')"
                             >
                                 <x-heroicon name="o-trash" class="h-5 w-5" />
                             </x-icon-button>
diff --git a/resources/views/settings/storage-providers/index.blade.php b/resources/views/settings/storage-providers/index.blade.php
index 1c4024fb..1be9a73c 100644
--- a/resources/views/settings/storage-providers/index.blade.php
+++ b/resources/views/settings/storage-providers/index.blade.php
@@ -1,5 +1,5 @@
-<x-profile-layout>
+<x-settings-layout>
     <x-slot name="pageTitle">{{ __("Storage Providers") }}</x-slot>
 
     @include("settings.storage-providers.partials.providers-list")
-</x-profile-layout>
+</x-settings-layout>
diff --git a/resources/views/settings/storage-providers/partials/connect-provider.blade.php b/resources/views/settings/storage-providers/partials/connect-provider.blade.php
index 81241c10..346c0cb0 100644
--- a/resources/views/settings/storage-providers/partials/connect-provider.blade.php
+++ b/resources/views/settings/storage-providers/partials/connect-provider.blade.php
@@ -10,7 +10,7 @@
 
         <form
             id="connect-storage-provider-form"
-            hx-post="{{ route("storage-providers.connect") }}"
+            hx-post="{{ route("settings.storage-providers.connect") }}"
             hx-swap="outerHTML"
             hx-select="#connect-storage-provider-form"
             hx-ext="disable-element"
diff --git a/resources/views/settings/storage-providers/partials/providers-list.blade.php b/resources/views/settings/storage-providers/partials/providers-list.blade.php
index bb83a17c..acb6d462 100644
--- a/resources/views/settings/storage-providers/partials/providers-list.blade.php
+++ b/resources/views/settings/storage-providers/partials/providers-list.blade.php
@@ -43,7 +43,7 @@ class="h-10 w-10"
                     <div class="flex items-center">
                         <div class="inline">
                             <x-icon-button
-                                x-on:click="deleteAction = '{{ route('storage-providers.delete', $provider->id) }}'; $dispatch('open-modal', 'delete-provider')"
+                                x-on:click="deleteAction = '{{ route('settings.storage-providers.delete', $provider->id) }}'; $dispatch('open-modal', 'delete-provider')"
                             >
                                 <x-heroicon name="o-trash" class="h-5 w-5" />
                             </x-icon-button>
diff --git a/resources/views/settings/users/index.blade.php b/resources/views/settings/users/index.blade.php
new file mode 100644
index 00000000..7593c275
--- /dev/null
+++ b/resources/views/settings/users/index.blade.php
@@ -0,0 +1,61 @@
+<x-settings-layout>
+    <x-slot name="pageTitle">Users</x-slot>
+
+    <x-container>
+        <x-card-header>
+            <x-slot name="title">Users</x-slot>
+            <x-slot name="description">Here you can manage users</x-slot>
+            <x-slot name="aside">
+                @include("settings.users.partials.create-user")
+            </x-slot>
+        </x-card-header>
+        <div class="space-y-3" x-data="{ deleteAction: '' }">
+            <x-table>
+                <x-thead>
+                    <x-tr>
+                        <x-th>ID</x-th>
+                        <x-th>Name</x-th>
+                        <x-th>Email</x-th>
+                        <x-th>Role</x-th>
+                        <x-th></x-th>
+                    </x-tr>
+                </x-thead>
+                <x-tbody>
+                    @foreach ($users as $user)
+                        <x-tr>
+                            <x-td>{{ $user->id }}</x-td>
+                            <x-td>{{ $user->name }}</x-td>
+                            <x-td>{{ $user->email }}</x-td>
+                            <x-td>
+                                <div class="inline-flex">
+                                    @if ($user->role === \App\Enums\UserRole::ADMIN)
+                                        <x-status status="success">ADMIN</x-status>
+                                    @else
+                                        <x-status status="info">USER</x-status>
+                                    @endif
+                                </div>
+                            </x-td>
+                            <x-td class="text-right">
+                                <x-icon-button
+                                    x-on:click="deleteAction = '{{ route('settings.users.delete', ['user' => $user]) }}'; $dispatch('open-modal', 'delete-user')"
+                                >
+                                    <x-heroicon name="o-trash" class="h-5 w-5" />
+                                </x-icon-button>
+                                <x-icon-button :href="route('settings.users.show', ['user' => $user])">
+                                    <x-heroicon name="o-cog-6-tooth" class="h-5 w-5" />
+                                </x-icon-button>
+                            </x-td>
+                        </x-tr>
+                    @endforeach
+                </x-tbody>
+            </x-table>
+            <x-confirmation-modal
+                name="delete-user"
+                :title="__('Confirm')"
+                :description="__('Are you sure that you want to delete this user?')"
+                method="delete"
+                x-bind:action="deleteAction"
+            />
+        </div>
+    </x-container>
+</x-settings-layout>
diff --git a/resources/views/settings/users/partials/create-user.blade.php b/resources/views/settings/users/partials/create-user.blade.php
new file mode 100644
index 00000000..1a9e15c4
--- /dev/null
+++ b/resources/views/settings/users/partials/create-user.blade.php
@@ -0,0 +1,69 @@
+<div>
+    <x-primary-button x-data="" x-on:click.prevent="$dispatch('open-modal', 'create-user')">New User</x-primary-button>
+
+    <x-modal name="create-user">
+        <form
+            id="create-user-form"
+            hx-post="{{ route("settings.users.store") }}"
+            hx-swap="outerHTML"
+            hx-select="#create-user-form"
+            hx-ext="disable-element"
+            hx-disable-element="#btn-create-user"
+            class="p-6"
+        >
+            @csrf
+            <h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">Create New User</h2>
+
+            <div class="mt-6">
+                <x-input-label for="name" value="Name" />
+                <x-text-input value="{{ old('name') }}" id="name" name="name" type="text" class="mt-1 w-full" />
+                @error("name")
+                    <x-input-error class="mt-2" :messages="$message" />
+                @enderror
+            </div>
+
+            <div class="mt-6">
+                <x-input-label for="email" value="Email" />
+                <x-text-input value="{{ old('email') }}" id="email" name="email" type="text" class="mt-1 w-full" />
+                @error("email")
+                    <x-input-error class="mt-2" :messages="$message" />
+                @enderror
+            </div>
+
+            <div class="mt-6">
+                <x-input-label for="password" value="Password" />
+                <x-text-input id="password" name="password" type="password" class="mt-1 w-full" />
+                @error("password")
+                    <x-input-error class="mt-2" :messages="$message" />
+                @enderror
+            </div>
+
+            <div class="mt-6">
+                <x-input-label for="role" value="Role" />
+                <x-select-input id="role" name="role" class="mt-1 w-full">
+                    <option
+                        value="{{ \App\Enums\UserRole::USER }}"
+                        @if(old('role') === \App\Enums\UserRole::USER) selected @endif
+                    >
+                        User
+                    </option>
+                    <option
+                        value="{{ \App\Enums\UserRole::ADMIN }}"
+                        @if(old('role') === \App\Enums\UserRole::ADMIN) selected @endif
+                    >
+                        Admin
+                    </option>
+                </x-select-input>
+                @error("role")
+                    <x-input-error class="mt-2" :messages="$message" />
+                @enderror
+            </div>
+
+            <div class="mt-6 flex justify-end">
+                <x-secondary-button type="button" x-on:click="$dispatch('close')">Cancel</x-secondary-button>
+
+                <x-primary-button id="btn-create-project" class="ml-3">Create</x-primary-button>
+            </div>
+        </form>
+    </x-modal>
+</div>
diff --git a/resources/views/settings/users/partials/update-projects.blade.php b/resources/views/settings/users/partials/update-projects.blade.php
new file mode 100644
index 00000000..e3aa0f04
--- /dev/null
+++ b/resources/views/settings/users/partials/update-projects.blade.php
@@ -0,0 +1,120 @@
+<x-card>
+    <x-slot name="title">Projects</x-slot>
+
+    <x-slot name="description">Manage the projects that the user is in</x-slot>
+
+    <x-slot name="aside">
+        <x-secondary-button :href="route('settings.users.index')">Back to Users</x-secondary-button>
+    </x-slot>
+
+    <form
+        id="update-projects"
+        hx-post="{{ route("settings.users.update-projects", ["user" => $user]) }}"
+        hx-swap="outerHTML"
+        hx-select="#update-projects"
+        hx-trigger="submit"
+        hx-ext="disable-element"
+        hx-disable-element="#btn-save-projects"
+        class="mt-6"
+    >
+        @csrf
+
+        <script>
+            let projects = @json($user->projects);
+        </script>
+
+        <div
+            class="space-y-6"
+            x-data="{
+                q: '',
+                projects: projects,
+                search() {
+                    htmx.ajax('GET', '{{ request()->getUri() }}?q=' + this.q, {
+                        target: '#projects-list',
+                        swap: 'outerHTML',
+                        select: '#projects-list',
+                    }).then(() => {
+                        document.getElementById('q').focus()
+                    })
+                },
+                addProject(project) {
+                    if (this.projects.find((p) => p.id === project.id)) {
+                        return
+                    }
+
+                    this.projects.push(project)
+                    this.q = ''
+                },
+                removeProject(id) {
+                    this.projects = this.projects.filter((project) => project.id !== id)
+                },
+            }"
+        >
+            <div>
+                <x-input-label value="Projects" />
+
+                <div class="mt-1">
+                    <template x-for="project in projects">
+                        <div class="mr-1 inline-flex">
+                            <x-status status="info" class="flex items-center">
+                                <span x-text="project.name"></span>
+                                <x-heroicon
+                                    name="o-x-mark"
+                                    class="ml-1 h-4 w-4 cursor-pointer"
+                                    x-on:click="removeProject(project.id)"
+                                />
+                                <input type="hidden" name="projects[]" x-bind:value="project.id" />
+                            </x-status>
+                        </div>
+                    </template>
+                </div>
+            </div>
+
+            <div>
+                <x-input-label value="Add new Project" />
+
+                @php
+                    $projects = \App\Models\Project::query()
+                        ->where(function ($query) {
+                            if (request()->has("q")) {
+                                $query->where("name", "like", "%" . request("q") . "%");
+                            }
+                        })
+                        ->take(5)
+                        ->get();
+                @endphp
+
+                <x-dropdown width="full">
+                    <x-slot name="trigger">
+                        <x-text-input
+                            id="q"
+                            name="q"
+                            x-model="q"
+                            type="text"
+                            class="mt-1 w-full"
+                            placeholder="Search for projects..."
+                            autocomplete="off"
+                            x-on:input.debounce.500ms="search"
+                        />
+                    </x-slot>
+                    <x-slot name="content">
+                        <div id="projects-list">
+                            @foreach ($projects as $project)
+                                <x-dropdown-link
+                                    class="cursor-pointer"
+                                    x-on:click="addProject({ id: {{ $project->id }}, name: '{{ $project->name }}' })"
+                                >
+                                    {{ $project->name }}
+                                </x-dropdown-link>
+                            @endforeach
+                        </div>
+                    </x-slot>
+                </x-dropdown>
+            </div>
+        </div>
+    </form>
+
+    <x-slot name="actions">
+        <x-primary-button id="btn-save-projects" form="update-projects">Save</x-primary-button>
+    </x-slot>
+</x-card>
diff --git a/resources/views/settings/users/partials/update-user-info.blade.php b/resources/views/settings/users/partials/update-user-info.blade.php
new file mode 100644
index 00000000..eb4e1c50
--- /dev/null
+++ b/resources/views/settings/users/partials/update-user-info.blade.php
@@ -0,0 +1,99 @@
+<x-card>
+    <x-slot name="title">User Info</x-slot>
+
+    <x-slot name="description">You can update user's info here</x-slot>
+
+    <form
+        id="update-user-info"
+        hx-post="{{ route("settings.users.update", ["user" => $user]) }}"
+        hx-swap="outerHTML"
+        hx-select="#update-user-info"
+        hx-trigger="submit"
+        hx-ext="disable-element"
+        hx-disable-element="#btn-save-info"
+        class="mt-6 space-y-6"
+    >
+        @csrf
+        <div>
+            <x-input-label for="name" value="Name" />
+            <x-text-input
+                id="name"
+                name="name"
+                type="text"
+                value="{{ old('name', $user->name) }}"
+                class="mt-1 block w-full"
+                required
+                autocomplete="name"
+            />
+            @error("name")
+                <x-input-error class="mt-2" :messages="$message" />
+            @enderror
+        </div>
+
+        <div>
+            <x-input-label for="email" value="Email" />
+            <x-text-input
+                id="email"
+                name="email"
+                type="email"
+                value="{{ old('email', $user->email) }}"
+                class="mt-1 block w-full"
+                required
+                autocomplete="email"
+            />
+            @error("email")
+                <x-input-error class="mt-2" :messages="$message" />
+            @enderror
+        </div>
+
+        <div>
+            <x-input-label for="timezone" value="Timezone" />
+            <x-select-input id="timezone" name="timezone" class="mt-1 block w-full" required>
+                @foreach (timezone_identifiers_list() as $timezone)
+                    <option
+                        value="{{ $timezone }}"
+                        @if(old('timezone', $user->timezone) == $timezone) selected @endif
+                    >
+                        {{ $timezone }}
+                    </option>
+                @endforeach
+            </x-select-input>
+            @error("timezone")
+                <x-input-error class="mt-2" :messages="$message" />
+            @enderror
+        </div>
+
+        <div>
+            <x-input-label for="role" value="Role" />
+            <x-select-input id="role" name="role" class="mt-1 w-full">
+                <option
+                    value="{{ \App\Enums\UserRole::USER }}"
+                    @if(old('role', $user->role) === \App\Enums\UserRole::USER) selected @endif
+                >
+                    User
+                </option>
+                <option
+                    value="{{ \App\Enums\UserRole::ADMIN }}"
+                    @if(old('role', $user->role) === \App\Enums\UserRole::ADMIN) selected @endif
+                >
+                    Admin
+                </option>
+            </x-select-input>
+            @error("role")
+                <x-input-error class="mt-2" :messages="$message" />
+            @enderror
+        </div>
+
+        <div>
+            <x-input-label for="password" value="New Password" />
+            <x-text-input id="password" name="password" type="password" class="mt-1 w-full" />
+            @error("password")
+                <x-input-error class="mt-2" :messages="$message" />
+            @enderror
+        </div>
+    </form>
+
+    <x-slot name="actions">
+        <x-primary-button id="btn-save-info" form="update-user-info">Save</x-primary-button>
+    </x-slot>
+</x-card>
diff --git a/resources/views/settings/users/partials/update-user-password.blade.php b/resources/views/settings/users/partials/update-user-password.blade.php
new file mode 100644
index 00000000..b1b80e9c
--- /dev/null
+++ b/resources/views/settings/users/partials/update-user-password.blade.php
@@ -0,0 +1,69 @@
+<x-card>
+    <x-slot name="title">
+        {{ __("Update Password") }}
+    </x-slot>
+
+    <x-slot name="description">
+        {{ __("Ensure your account is using a long, random password to stay secure.") }}
+    </x-slot>
+
+    <form
+        id="update-password"
+        class="mt-6 space-y-6"
+        hx-post="{{ route("profile.password") }}"
+        hx-swap="outerHTML"
+        hx-select="#update-password"
+        hx-trigger="submit"
+        hx-ext="disable-element"
+        hx-disable-element="#btn-save-password"
+    >
+        @csrf
+
+        <div>
+            <x-input-label for="current_password" :value="__('Current Password')" />
+            <x-text-input
+                id="current_password"
+                name="current_password"
+                type="password"
+                class="mt-1 block w-full"
+                autocomplete="current-password"
+            />
+            @error("current_password")
+                <x-input-error class="mt-2" :messages="$message" />
+            @enderror
+        </div>
+
+        <div>
+            <x-input-label for="password" :value="__('New Password')" />
+            <x-text-input
+                id="password"
+                name="password"
+                type="password"
+                class="mt-1 block w-full"
+                autocomplete="new-password"
+            />
+            @error("password")
+                <x-input-error class="mt-2" :messages="$message" />
+            @enderror
+        </div>
+
+        <div>
+            <x-input-label for="password_confirmation" :value="__('Confirm Password')" />
+            <x-text-input
+                id="password_confirmation"
+                name="password_confirmation"
+                type="password"
+                class="mt-1 block w-full"
+                autocomplete="new-password"
+            />
+            @error("password_confirmation")
+                <x-input-error class="mt-2" :messages="$message" />
+            @enderror
+        </div>
+    </form>
+    <x-slot name="actions">
+        <x-primary-button id="btn-save-password" form="update-password">
+            {{ __("Save") }}
+        </x-primary-button>
+    </x-slot>
+</x-card>
diff --git a/resources/views/settings/users/show.blade.php b/resources/views/settings/users/show.blade.php
new file mode 100644
index 00000000..bb995adc
--- /dev/null
+++ b/resources/views/settings/users/show.blade.php
@@ -0,0 +1,9 @@
+<x-settings-layout>
+    <x-slot name="pageTitle">Users</x-slot>
+
+    <x-container>
+        @include("settings.users.partials.update-projects")
+
+        @include("settings.users.partials.update-user-info")
+    </x-container>
+</x-settings-layout>
diff --git a/resources/views/sites/partials/create/fields/source-control.blade.php b/resources/views/sites/partials/create/fields/source-control.blade.php
index 7bbb8443..515d557d 100644
--- a/resources/views/sites/partials/create/fields/source-control.blade.php
+++ b/resources/views/sites/partials/create/fields/source-control.blade.php
@@ -13,7 +13,10 @@
                 </option>
             @endforeach
         </x-select-input>
-        <x-secondary-button :href="route('source-controls', ['redirect' => request()->url()])" class="ml-2 flex-none">
+        <x-secondary-button
+            :href="route('settings.source-controls', ['redirect' => request()->url()])"
+            class="ml-2 flex-none"
+        >
             {{ __("Connect") }}
         </x-secondary-button>
     </div>
diff --git a/routes/settings.php b/routes/settings.php
index b548e61c..7b700480 100644
--- a/routes/settings.php
+++ b/routes/settings.php
@@ -1,66 +1,62 @@
 <?php
 
 use App\Http\Controllers\Settings\NotificationChannelController;
-use App\Http\Controllers\Settings\ProfileController;
 use App\Http\Controllers\Settings\ProjectController;
 use App\Http\Controllers\Settings\ServerProviderController;
 use App\Http\Controllers\Settings\SourceControlController;
 use App\Http\Controllers\Settings\SSHKeyController;
 use App\Http\Controllers\Settings\StorageProviderController;
+use App\Http\Controllers\Settings\UserController;
 use Illuminate\Support\Facades\Route;
 
-// profile
-Route::prefix('settings/profile')->group(function () {
-    Route::get('/', [ProfileController::class, 'index'])->name('profile');
-    Route::post('info', [ProfileController::class, 'info'])->name('profile.info');
-    Route::post('password', [ProfileController::class, 'password'])->name('profile.password');
+Route::prefix('settings/users')->group(function () {
+    Route::get('/', [UserController::class, 'index'])->name('settings.users.index');
+    Route::post('/', [UserController::class, 'store'])->name('settings.users.store');
+    Route::get('/{user}', [UserController::class, 'show'])->name('settings.users.show');
+    Route::post('/{user}', [UserController::class, 'update'])->name('settings.users.update');
+    Route::post('/{user}/projects', [UserController::class, 'updateProjects'])->name('settings.users.update-projects');
+    Route::delete('/{user}', [UserController::class, 'destroy'])->name('settings.users.delete');
 });
 
-// profile
+// projects
 Route::prefix('settings/projects')->group(function () {
-    Route::get('/', [ProjectController::class, 'index'])->name('projects');
-    Route::post('create', [ProjectController::class, 'create'])->name('projects.create');
-    Route::post('update/{project}', [ProjectController::class, 'update'])->name('projects.update');
-    Route::delete('delete/{project}', [ProjectController::class, 'delete'])->name('projects.delete');
-    Route::get('switch/{project}', [ProjectController::class, 'switch'])->name('projects.switch');
+    Route::get('/', [ProjectController::class, 'index'])->name('settings.projects');
+    Route::post('create', [ProjectController::class, 'create'])->name('settings.projects.create');
+    Route::post('update/{project}', [ProjectController::class, 'update'])->name('settings.projects.update');
+    Route::delete('delete/{project}', [ProjectController::class, 'delete'])->name('settings.projects.delete');
 });
 
 // server-providers
 Route::prefix('settings/server-providers')->group(function () {
-    Route::get('/', [ServerProviderController::class, 'index'])->name('server-providers');
-    Route::post('connect', [ServerProviderController::class, 'connect'])->name('server-providers.connect');
-    Route::delete('delete/{serverProvider}', [ServerProviderController::class, 'delete'])
-        ->name('server-providers.delete');
+    Route::get('/', [ServerProviderController::class, 'index'])->name('settings.server-providers');
+    Route::post('connect', [ServerProviderController::class, 'connect'])->name('settings.server-providers.connect');
+    Route::delete('delete/{serverProvider}', [ServerProviderController::class, 'delete'])->name('settings.server-providers.delete');
 });
 
 // source-controls
 Route::prefix('settings/source-controls')->group(function () {
-    Route::get('/', [SourceControlController::class, 'index'])->name('source-controls');
-    Route::post('connect', [SourceControlController::class, 'connect'])->name('source-controls.connect');
-    Route::delete('delete/{sourceControl}', [SourceControlController::class, 'delete'])
-        ->name('source-controls.delete');
+    Route::get('/', [SourceControlController::class, 'index'])->name('settings.source-controls');
+    Route::post('connect', [SourceControlController::class, 'connect'])->name('settings.source-controls.connect');
+    Route::delete('delete/{sourceControl}', [SourceControlController::class, 'delete'])->name('settings.source-controls.delete');
 });
 
 // storage-providers
 Route::prefix('settings/storage-providers')->group(function () {
-    Route::get('/', [StorageProviderController::class, 'index'])->name('storage-providers');
-    Route::post('connect', [StorageProviderController::class, 'connect'])->name('storage-providers.connect');
-    Route::delete('delete/{storageProvider}', [StorageProviderController::class, 'delete'])
-        ->name('storage-providers.delete');
+    Route::get('/', [StorageProviderController::class, 'index'])->name('settings.storage-providers');
+    Route::post('connect', [StorageProviderController::class, 'connect'])->name('settings.storage-providers.connect');
+    Route::delete('delete/{storageProvider}', [StorageProviderController::class, 'delete'])->name('settings.storage-providers.delete');
 });
 
 // notification-channels
 Route::prefix('settings/notification-channels')->group(function () {
-    Route::get('/', [NotificationChannelController::class, 'index'])->name('notification-channels');
-    Route::post('add', [NotificationChannelController::class, 'add'])
-        ->name('notification-channels.add');
-    Route::delete('delete/{id}', [NotificationChannelController::class, 'delete'])
-        ->name('notification-channels.delete');
+    Route::get('/', [NotificationChannelController::class, 'index'])->name('settings.notification-channels');
+    Route::post('add', [NotificationChannelController::class, 'add'])->name('settings.notification-channels.add');
+    Route::delete('delete/{id}', [NotificationChannelController::class, 'delete'])->name('settings.notification-channels.delete');
 });
 
 // ssh-keys
 Route::prefix('settings/ssh-keys')->group(function () {
-    Route::get('/', [SSHKeyController::class, 'index'])->name('ssh-keys');
-    Route::post('add', [SshKeyController::class, 'add'])->name('ssh-keys.add');
-    Route::delete('delete/{id}', [SshKeyController::class, 'delete'])->name('ssh-keys.delete');
+    Route::get('/', [SSHKeyController::class, 'index'])->name('settings.ssh-keys');
+    Route::post('add', [SshKeyController::class, 'add'])->name('settings.ssh-keys.add');
+    Route::delete('delete/{id}', [SshKeyController::class, 'delete'])->name('settings.ssh-keys.delete');
 });
diff --git a/routes/web.php b/routes/web.php
index 7c056061..7326a48f 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -1,6 +1,8 @@
 <?php
 
+use App\Http\Controllers\ProfileController;
 use App\Http\Controllers\SearchController;
+use App\Http\Controllers\Settings\ProjectController;
 use Illuminate\Support\Facades\Route;
 
 Route::get('/', function () {
@@ -8,7 +10,19 @@
 });
 
 Route::middleware('auth')->group(function () {
-    require __DIR__.'/settings.php';
+    // profile
+    Route::prefix('profile')->group(function () {
+        Route::get('/', [ProfileController::class, 'index'])->name('profile');
+        Route::post('info', [ProfileController::class, 'info'])->name('profile.info');
+        Route::post('password', [ProfileController::class, 'password'])->name('profile.password');
+    });
+
+    // switch project
+    Route::get('settings/projects/switch/{project}', [ProjectController::class, 'switch'])->name('settings.projects.switch');
+
+    Route::middleware('is-admin')->group(function () {
+        require __DIR__.'/settings.php';
+    });
 
     Route::prefix('/servers')->group(function () {
         require __DIR__.'/server.php';
diff --git a/tests/Feature/NotificationChannelsTest.php b/tests/Feature/NotificationChannelsTest.php
index 18c8c982..28f7e5b6 100644
--- a/tests/Feature/NotificationChannelsTest.php
+++ b/tests/Feature/NotificationChannelsTest.php
@@ -17,7 +17,7 @@ public function test_add_email_channel(): void
     {
         $this->actingAs($this->user);
 
-        $this->post(route('notification-channels.add'), [
+        $this->post(route('settings.notification-channels.add'), [
             'provider' => NotificationChannel::EMAIL,
             'email' => 'email@example.com',
             'label' => 'Email',
@@ -40,7 +40,7 @@ public function test_cannot_add_email_channel(): void
 
         $this->actingAs($this->user);
 
-        $this->post(route('notification-channels.add'), [
+        $this->post(route('settings.notification-channels.add'), [
             'provider' => NotificationChannel::EMAIL,
             'email' => 'email@example.com',
             'label' => 'Email',
@@ -61,7 +61,7 @@ public function test_add_slack_channel(): void
 
         Http::fake();
 
-        $this->post(route('notification-channels.add'), [
+        $this->post(route('settings.notification-channels.add'), [
             'provider' => NotificationChannel::SLACK,
             'webhook_url' => 'https://hooks.slack.com/services/123/token',
             'label' => 'Slack',
@@ -84,7 +84,7 @@ public function test_cannot_add_slack_channel(): void
             'slack.com/*' => Http::response(['ok' => false], 401),
         ]);
 
-        $this->post(route('notification-channels.add'), [
+        $this->post(route('settings.notification-channels.add'), [
             'provider' => NotificationChannel::SLACK,
             'webhook_url' => 'https://hooks.slack.com/services/123/token',
             'label' => 'Slack',
@@ -104,7 +104,7 @@ public function test_add_discord_channel(): void
 
         Http::fake();
 
-        $this->post(route('notification-channels.add'), [
+        $this->post(route('settings.notification-channels.add'), [
             'provider' => NotificationChannel::DISCORD,
             'webhook_url' => 'https://discord.com/api/webhooks/123/token',
             'label' => 'Discord',
@@ -127,7 +127,7 @@ public function test_cannot_add_discord_channel(): void
             'discord.com/*' => Http::response(['ok' => false], 401),
         ]);
 
-        $this->post(route('notification-channels.add'), [
+        $this->post(route('settings.notification-channels.add'), [
             'provider' => NotificationChannel::DISCORD,
             'webhook_url' => 'https://discord.com/api/webhooks/123/token',
             'label' => 'Discord',
@@ -147,7 +147,7 @@ public function test_add_telegram_channel(): void
 
         Http::fake();
 
-        $this->post(route('notification-channels.add'), [
+        $this->post(route('settings.notification-channels.add'), [
             'provider' => NotificationChannel::TELEGRAM,
             'bot_token' => 'token',
             'chat_id' => '123',
@@ -172,7 +172,7 @@ public function test_cannot_add_telegram_channel(): void
             'api.telegram.org/*' => Http::response(['ok' => false], 401),
         ]);
 
-        $this->post(route('notification-channels.add'), [
+        $this->post(route('settings.notification-channels.add'), [
             'provider' => NotificationChannel::TELEGRAM,
             'bot_token' => 'token',
             'chat_id' => '123',
@@ -193,7 +193,7 @@ public function test_see_channels_list(): void
 
         $channel = \App\Models\NotificationChannel::factory()->create();
 
-        $this->get(route('notification-channels'))
+        $this->get(route('settings.notification-channels'))
             ->assertSuccessful()
             ->assertSee($channel->provider);
     }
@@ -204,7 +204,7 @@ public function test_delete_channel(): void
 
         $channel = \App\Models\NotificationChannel::factory()->create();
 
-        $this->delete(route('notification-channels.delete', $channel->id))
+        $this->delete(route('settings.notification-channels.delete', $channel->id))
             ->assertSessionDoesntHaveErrors();
 
         $this->assertDatabaseMissing('notification_channels', [
diff --git a/tests/Feature/ProjectsTest.php b/tests/Feature/ProjectsTest.php
index 6b60d3e6..aa375684 100644
--- a/tests/Feature/ProjectsTest.php
+++ b/tests/Feature/ProjectsTest.php
@@ -14,7 +14,7 @@ public function test_create_project(): void
     {
         $this->actingAs($this->user);
 
-        $this->post(route('projects.create'), [
+        $this->post(route('settings.projects.create'), [
             'name' => 'test',
         ])->assertSessionDoesntHaveErrors();
 
@@ -27,11 +27,11 @@ public function test_see_projects_list(): void
     {
         $this->actingAs($this->user);
 
-        $project = Project::factory()->create([
-            'user_id' => $this->user->id,
-        ]);
+        $project = Project::factory()->create();
 
-        $this->get(route('projects'))
+        $this->user->projects()->attach($project);
+
+        $this->get(route('settings.projects'))
             ->assertSuccessful()
             ->assertSee($project->name);
     }
@@ -40,11 +40,11 @@ public function test_delete_project(): void
     {
         $this->actingAs($this->user);
 
-        $project = Project::factory()->create([
-            'user_id' => $this->user->id,
-        ]);
+        $project = Project::factory()->create();
 
-        $this->delete(route('projects.delete', $project))
+        $this->user->projects()->attach($project);
+
+        $this->delete(route('settings.projects.delete', $project))
             ->assertSessionDoesntHaveErrors();
 
         $this->assertDatabaseMissing('projects', [
@@ -56,11 +56,11 @@ public function test_edit_project(): void
     {
         $this->actingAs($this->user);
 
-        $project = Project::factory()->create([
-            'user_id' => $this->user->id,
-        ]);
+        $project = Project::factory()->create();
 
-        $this->post(route('projects.update', $project), [
+        $this->user->projects()->attach($project);
+
+        $this->post(route('settings.projects.update', $project), [
             'name' => 'new-name',
         ])->assertSessionDoesntHaveErrors();
 
@@ -74,7 +74,7 @@ public function test_cannot_delete_last_project(): void
     {
         $this->actingAs($this->user);
 
-        $this->delete(route('projects.delete', [
+        $this->delete(route('settings.projects.delete', [
             'project' => $this->user->currentProject,
         ]))
             ->assertSessionDoesntHaveErrors()
diff --git a/tests/Feature/ServerProvidersTest.php b/tests/Feature/ServerProvidersTest.php
index 85b5b75e..0f99abdc 100644
--- a/tests/Feature/ServerProvidersTest.php
+++ b/tests/Feature/ServerProvidersTest.php
@@ -27,7 +27,7 @@ public function test_connect_provider(string $provider, array $input): void
             ],
             $input
         );
-        $this->post(route('server-providers.connect'), $data)->assertSessionDoesntHaveErrors();
+        $this->post(route('settings.server-providers.connect'), $data)->assertSessionDoesntHaveErrors();
 
         $this->assertDatabaseHas('server_providers', [
             'provider' => $provider,
@@ -53,7 +53,7 @@ public function test_cannot_connect_to_provider(string $provider, array $input):
             ],
             $input
         );
-        $this->post(route('server-providers.connect'), $data)->assertSessionHasErrors();
+        $this->post(route('settings.server-providers.connect'), $data)->assertSessionHasErrors();
 
         $this->assertDatabaseMissing('server_providers', [
             'provider' => $provider,
@@ -69,7 +69,7 @@ public function test_see_providers_list(): void
             'user_id' => $this->user->id,
         ]);
 
-        $this->get(route('server-providers'))
+        $this->get(route('settings.server-providers'))
             ->assertSuccessful()
             ->assertSee($provider->profile);
     }
@@ -86,7 +86,7 @@ public function test_delete_provider(string $provider): void
             'provider' => $provider,
         ]);
 
-        $this->delete(route('server-providers.delete', $provider))
+        $this->delete(route('settings.server-providers.delete', $provider))
             ->assertSessionDoesntHaveErrors();
 
         $this->assertDatabaseMissing('server_providers', [
@@ -110,7 +110,7 @@ public function test_cannot_delete_provider(string $provider): void
             'provider_id' => $provider->id,
         ]);
 
-        $this->delete(route('server-providers.delete', $provider))
+        $this->delete(route('settings.server-providers.delete', $provider))
             ->assertSessionDoesntHaveErrors()
             ->assertSessionHas('toast.type', 'error')
             ->assertSessionHas('toast.message', 'This server provider is being used by a server.');
diff --git a/tests/Feature/SourceControlsTest.php b/tests/Feature/SourceControlsTest.php
index cca5f088..067263ad 100644
--- a/tests/Feature/SourceControlsTest.php
+++ b/tests/Feature/SourceControlsTest.php
@@ -28,7 +28,7 @@ public function test_connect_provider(string $provider, ?string $customUrl, arra
         if ($customUrl !== null) {
             $input['url'] = $customUrl;
         }
-        $this->post(route('source-controls.connect'), $input)
+        $this->post(route('settings.source-controls.connect'), $input)
             ->assertSessionDoesntHaveErrors();
 
         $this->assertDatabaseHas('source_controls', [
@@ -50,7 +50,7 @@ public function test_delete_provider(string $provider): void
             'profile' => 'test',
         ]);
 
-        $this->delete(route('source-controls.delete', $sourceControl->id))
+        $this->delete(route('settings.source-controls.delete', $sourceControl->id))
             ->assertSessionDoesntHaveErrors();
 
         $this->assertDatabaseMissing('source_controls', [
@@ -75,7 +75,7 @@ public function test_cannot_delete_provider(string $provider): void
             'source_control_id' => $sourceControl->id,
         ]);
 
-        $this->delete(route('source-controls.delete', $sourceControl->id))
+        $this->delete(route('settings.source-controls.delete', $sourceControl->id))
             ->assertSessionDoesntHaveErrors()
             ->assertSessionHas('toast.type', 'error')
             ->assertSessionHas('toast.message', 'This source control is being used by a site.');
diff --git a/tests/Feature/SshKeysTest.php b/tests/Feature/SshKeysTest.php
index 154d542c..81b1fd66 100644
--- a/tests/Feature/SshKeysTest.php
+++ b/tests/Feature/SshKeysTest.php
@@ -14,7 +14,7 @@ public function test_create_ssh_key(): void
     {
         $this->actingAs($this->user);
 
-        $this->post(route('ssh-keys.add'), [
+        $this->post(route('settings.ssh-keys.add'), [
             'name' => 'test',
             'public_key' => 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q== test@test.local',
         ])->assertSessionDoesntHaveErrors();
@@ -28,7 +28,7 @@ public function test_get_public_keys_list(): void
             'user_id' => $this->user->id,
         ]);
 
-        $this->get(route('ssh-keys'))
+        $this->get(route('settings.ssh-keys'))
             ->assertSuccessful()
             ->assertSee($key->name);
     }
@@ -41,7 +41,7 @@ public function test_delete_key(): void
             'user_id' => $this->user->id,
         ]);
 
-        $this->delete(route('ssh-keys.delete', $key->id))
+        $this->delete(route('settings.ssh-keys.delete', $key->id))
             ->assertSessionDoesntHaveErrors();
 
         $this->assertDatabaseMissing('ssh_keys', [
diff --git a/tests/Feature/StorageProvidersTest.php b/tests/Feature/StorageProvidersTest.php
index a4577f93..2b4d687a 100644
--- a/tests/Feature/StorageProvidersTest.php
+++ b/tests/Feature/StorageProvidersTest.php
@@ -19,7 +19,7 @@ public function test_connect_dropbox(): void
 
         Http::fake();
 
-        $this->post(route('storage-providers.connect'), [
+        $this->post(route('settings.storage-providers.connect'), [
             'provider' => StorageProvider::DROPBOX,
             'name' => 'profile',
             'token' => 'token',
@@ -40,7 +40,7 @@ public function test_see_providers_list(): void
             'provider' => StorageProvider::DROPBOX,
         ]);
 
-        $this->get(route('storage-providers'))
+        $this->get(route('settings.storage-providers'))
             ->assertSuccessful()
             ->assertSee($provider->profile);
     }
@@ -53,7 +53,7 @@ public function test_delete_provider(): void
             'user_id' => $this->user->id,
         ]);
 
-        $this->delete(route('storage-providers.delete', $provider->id))
+        $this->delete(route('settings.storage-providers.delete', $provider->id))
             ->assertSessionDoesntHaveErrors();
 
         $this->assertDatabaseMissing('storage_providers', [
@@ -79,7 +79,7 @@ public function test_cannot_delete_provider(): void
             'storage_id' => $provider->id,
         ]);
 
-        $this->delete(route('storage-providers.delete', $provider->id))
+        $this->delete(route('settings.storage-providers.delete', $provider->id))
             ->assertSessionDoesntHaveErrors()
             ->assertSessionHas('toast.type', 'error')
             ->assertSessionHas('toast.message', 'This storage provider is being used by a backup.');
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 0a64bb33..1fb04ef6 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -5,6 +5,7 @@
 use App\Enums\Database;
 use App\Enums\NotificationChannel;
 use App\Enums\ServiceStatus;
+use App\Enums\UserRole;
 use App\Enums\Webserver;
 use App\Models\Server;
 use App\Models\Site;
@@ -30,7 +31,9 @@ public function setUp(): void
         config()->set('queue.connections.ssh.driver', 'sync');
         config()->set('filesystems.disks.key-pairs.root', storage_path('app/key-pairs-test'));
 
-        $this->user = User::factory()->create();
+        $this->user = User::factory()->create([
+            'role' => UserRole::ADMIN,
+        ]);
         $this->user->createDefaultProject();
 
         \App\Models\NotificationChannel::factory()->create([
diff --git a/tests/Unit/Commands/CreateUserCommandTest.php b/tests/Unit/Commands/CreateUserCommandTest.php
index 45e0664d..2979e5f9 100644
--- a/tests/Unit/Commands/CreateUserCommandTest.php
+++ b/tests/Unit/Commands/CreateUserCommandTest.php
@@ -2,6 +2,7 @@
 
 namespace Tests\Unit\Commands;
 
+use App\Models\Project;
 use App\Models\User;
 use Illuminate\Foundation\Testing\RefreshDatabase;
 use Tests\TestCase;
@@ -27,7 +28,36 @@ public function test_create_user(): void
         $user = User::query()->where('email', 'john@doe.com')->first();
 
         $this->assertDatabaseHas('projects', [
+            'name' => 'default',
+        ]);
+    }
+
+    public function test_create_user_and_project(): void
+    {
+        Project::query()->delete();
+        User::query()->delete();
+
+        $this->artisan('user:create', [
+            'name' => 'John Doe',
+            'email' => 'john@doe.com',
+            'password' => 'password',
+        ])->expectsOutput('User created!');
+
+        $this->assertDatabaseHas('users', [
+            'name' => 'John Doe',
+            'email' => 'john@doe.com',
+        ]);
+
+        /** @var User $user */
+        $user = User::query()->where('email', 'john@doe.com')->first();
+
+        $this->assertDatabaseHas('projects', [
+            'name' => 'default',
+        ]);
+
+        $this->assertDatabaseHas('user_project', [
             'user_id' => $user->id,
+            'project_id' => $user->refresh()->current_project_id,
         ]);
     }