diff --git a/app/Http/Controllers/Dashboard/SettingController.php b/app/Http/Controllers/Dashboard/SettingController.php
index b838e54d..1fb1db0a 100644
--- a/app/Http/Controllers/Dashboard/SettingController.php
+++ b/app/Http/Controllers/Dashboard/SettingController.php
@@ -8,6 +8,7 @@
 use App\Http\Requests\SettingRequest;
 use App\Models\Setting;
 use Illuminate\Http\RedirectResponse;
+use Illuminate\Support\Facades\Storage;
 use Inertia\Response;
 
 class SettingController extends Controller
@@ -21,11 +22,42 @@ public function edit(): Response
 
     public function update(SettingRequest $request): RedirectResponse
     {
-        Setting::query()->first()
-            ->update($request->validated());
+        $settings = Setting::query()->firstOrFail();
+        $settings->fill($request->getData());
+
+        if ($request->file("logo")) {
+            if ($settings->logo) {
+                Storage::disk("public")->delete($settings->logo);
+            }
+            $file = $request->file("logo");
+            $fileName = $file->getClientOriginalName();
+            $path = "/logo";
+
+            $fullPath = Storage::disk("public")->putFileAs($path, $file, $fileName);
+            $settings->logo = $fullPath;
+        }
+
+        $settings->save();
 
         return redirect()
             ->back()
             ->with("success", "Zaktualizowano ustawienia");
     }
+
+    public function removeLogo(): RedirectResponse
+    {
+        $settings = Setting::query()->firstOrFail();
+
+        if ($settings->logo) {
+            $res = Storage::disk("public")->delete($settings->logo);
+            $settings->logo = null;
+            $settings->save();
+
+            return redirect()
+                ->back()
+                ->with("success", "Usunięto logo");
+        }
+
+        abort(404);
+    }
 }
diff --git a/app/Http/Requests/SettingRequest.php b/app/Http/Requests/SettingRequest.php
index 3a4f2232..ae103e17 100644
--- a/app/Http/Requests/SettingRequest.php
+++ b/app/Http/Requests/SettingRequest.php
@@ -16,6 +16,22 @@ public function rules(): array
             "teacher_titles" => ["required", "max:255"],
             "university_name" => ["required", "max:255"],
             "department_name" => ["required", "max:255"],
+            "primary_color" => ["required", "regex:/^#([A-Fa-f0-9]{6})$/"],
+            "secondary_color" => ["required", "regex:/^#([A-Fa-f0-9]{6})$/"],
+            "logo" => ["nullable", "image", "max:1024"],
+        ];
+    }
+
+    public function getData(): array
+    {
+        return [
+            "teacher_name" => $this->input("teacher_name"),
+            "teacher_email" => $this->input("teacher_email"),
+            "teacher_titles" => $this->input("teacher_titles"),
+            "university_name" => $this->input("university_name"),
+            "department_name" => $this->input("department_name"),
+            "primary_color" => $this->input("primary_color"),
+            "secondary_color" => $this->input("secondary_color"),
         ];
     }
 }
diff --git a/app/Models/Setting.php b/app/Models/Setting.php
index ecb6a981..bb4dc614 100644
--- a/app/Models/Setting.php
+++ b/app/Models/Setting.php
@@ -30,5 +30,8 @@ class Setting extends Model
         "teacher_titles",
         "university_name",
         "department_name",
+        "primary_color",
+        "secondary_color",
+        "logo",
     ];
 }
diff --git a/database/factories/SettingFactory.php b/database/factories/SettingFactory.php
index 876e117d..89664ef0 100644
--- a/database/factories/SettingFactory.php
+++ b/database/factories/SettingFactory.php
@@ -16,6 +16,8 @@ public function definition(): array
             "teacher_email" => fake()->email,
             "department_name" => "Zakład Informatyki, Wydział Nauk Technicznych i Ekonomicznych",
             "university_name" => "Collegium Witelona Uczelnia Państwowa",
+            "primary_color" => "#000000",
+            "secondary_color" => "#ffffff",
         ];
     }
 }
diff --git a/database/migrations/2024_08_07_075139_add_fields_to_settings_table.php b/database/migrations/2024_08_07_075139_add_fields_to_settings_table.php
new file mode 100644
index 00000000..edc1f8d4
--- /dev/null
+++ b/database/migrations/2024_08_07_075139_add_fields_to_settings_table.php
@@ -0,0 +1,27 @@
+<?php
+
+declare(strict_types=1);
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class() extends Migration {
+    public function up(): void
+    {
+        Schema::table("settings", function (Blueprint $table): void {
+            $table->string("primary_color")->nullable();
+            $table->string("secondary_color")->nullable();
+            $table->string("logo")->nullable();
+        });
+    }
+
+    public function down(): void
+    {
+        Schema::table("settings", function (Blueprint $table): void {
+            $table->dropColumn("primary_color");
+            $table->dropColumn("secondary_color");
+            $table->dropColumn("logo");
+        });
+    }
+};
diff --git a/environment/dev/app/Dockerfile b/environment/dev/app/Dockerfile
index 1024bc85..a45f0a09 100644
--- a/environment/dev/app/Dockerfile
+++ b/environment/dev/app/Dockerfile
@@ -41,7 +41,9 @@ RUN apt-get update \
     && echo "deb https://nginx.org/packages/mainline/debian bullseye nginx" | tee /etc/apt/sources.list.d/nginx.list \
     && apt-get update && apt-get install --assume-yes \
         nginx=${NGINX_VERSION} \
+        gnupg \
         libzip-dev \
+        libpng-dev \
         libpq-dev \
         supervisor \
         cron \
@@ -49,6 +51,7 @@ RUN apt-get update \
     && docker-php-ext-install \
         zip \
         pdo_pgsql \
+        gd \
     && docker-php-ext-enable \
         redis
 
diff --git a/environment/dev/app/nginx.conf b/environment/dev/app/nginx.conf
index 0350a9f7..ddeabbe3 100644
--- a/environment/dev/app/nginx.conf
+++ b/environment/dev/app/nginx.conf
@@ -26,6 +26,8 @@ http {
         listen 80 default;
         server_name keating-nginx;
 
+        client_max_body_size 20M;
+
         access_log /dev/stdout;
         error_log /dev/stderr;
 
diff --git a/environment/dev/app/php.ini b/environment/dev/app/php.ini
index 8ffeea58..1d16a3ee 100644
--- a/environment/dev/app/php.ini
+++ b/environment/dev/app/php.ini
@@ -1,5 +1,7 @@
 [PHP]
 memory_limit = 256M
+upload_max_filesize = 20m
+post_max_size = 20m
 
 [xdebug]
 xdebug.client_host=xdebug://gateway
diff --git a/resources/js/Pages/Dashboard/Setting/Edit.vue b/resources/js/Pages/Dashboard/Setting/Edit.vue
index bebafa1e..0666a819 100644
--- a/resources/js/Pages/Dashboard/Setting/Edit.vue
+++ b/resources/js/Pages/Dashboard/Setting/Edit.vue
@@ -9,6 +9,9 @@ import { useForm } from '@inertiajs/inertia-vue3'
 import FormError from '@/Shared/Forms/FormError.vue'
 import ManagementHeader from '@/Shared/Components/ManagementHeader.vue'
 import ManagementHeaderItem from '@/Shared/Components/ManagementHeaderItem.vue'
+import ColorInput from '../../../Shared/Forms/ColorInput.vue'
+import { ref } from 'vue'
+import { Method } from '@inertiajs/inertia'
 
 const props = defineProps({
   settings: Object,
@@ -20,10 +23,29 @@ const form = useForm({
   teacher_titles: props.settings.teacher_titles,
   university_name: props.settings.university_name,
   department_name: props.settings.department_name,
+  primary_color: props.settings.primary_color,
+  secondary_color: props.settings.secondary_color,
+  logo: null,
 })
 
+const imageUrl = ref('')
+
 function updateSettings() {
-  form.patch('/dashboard/settings')
+  form.post('/dashboard/settings')
+}
+
+function onFileSelected(event) {
+  const file = event.target?.files[0]
+
+  if (file.size > 1024 * 1024) {
+    form.errors.logo = 'Plik nie może być większy niż 1MB'
+
+    return
+  }
+
+  form.logo = file
+  imageUrl.value = URL.createObjectURL(event.target?.files[0])
+  form.errors.logo = ''
 }
 </script>
 
@@ -40,7 +62,7 @@ function updateSettings() {
           </ManagementHeaderItem>
         </template>
       </ManagementHeader>
-      <form class="grid grid-cols-2" @submit.prevent="updateSettings">
+      <form class="grid grid-cols-2" enctype="multipart/form-data" @submit.prevent="updateSettings">
         <Section>
           <div class="flex flex-col justify-between gap-4">
             <FormGroup>
@@ -78,6 +100,55 @@ function updateSettings() {
               <TextInput id="department_name" v-model="form.department_name" :error="form.errors.department_name" autocomplete="off" />
               <FormError :error="form.errors.department_name" />
             </FormGroup>
+            <FormGroup>
+              <FormLabel for="primary_color">
+                Kolor główny
+              </FormLabel>
+              <ColorInput id="primary_color" v-model="form.primary_color" :error="form.errors.primary_color" autocomplete="off" />
+              <FormError :error="form.errors.primary_color" />
+            </FormGroup>
+            <FormGroup>
+              <FormLabel for="secondary_color">
+                Kolor dodatkowy
+              </FormLabel>
+              <ColorInput id="secondary_color" v-model="form.secondary_color" :error="form.errors.secondary_color" autocomplete="off" />
+              <FormError :error="form.errors.secondary_color" />
+            </FormGroup>
+            <FormGroup>
+              <FormLabel for="title">
+                Logo
+              </FormLabel>
+              <input
+                class="border-brand-light-gray text-brand-black hover:border-brand-black focus:border-brand-black !mb-px block w-full border-0 border-b p-2 text-sm font-medium hover:!mb-px hover:border-b-2 focus:!mb-px focus:border-b-2 focus:ring-0 focus:ring-offset-0"
+                type="file" max="1" @input="onFileSelected"
+              >
+              <FormError :error="form.errors.logo" class="mt-2" />
+            </FormGroup>
+            <FormGroup v-if="settings.logo || imageUrl">
+              <div v-if="settings.logo && !imageUrl">
+                <FormLabel class="mb-3 flex justify-between">
+                  Aktualne logo
+                  <InertiaLink
+                    href="/dashboard/settings/remove-logo"
+                    :method="Method.DELETE"
+                    class="text-sm text-red-500 hover:text-red-700"
+                    @click="form.logo = ''"
+                  >
+                    Usuń
+                  </InertiaLink>
+                </FormLabel>
+                <img :alt="'alt text'"
+                     :src="`/storage/${settings.logo}`"
+                     class="m-auto shadow-lg"
+                >
+              </div>
+              <div v-else>
+                <FormLabel class="mb-3">
+                  Przesłane logo
+                </FormLabel>
+                <img :src="imageUrl" alt="Image preview" class="m-auto shadow-lg">
+              </div>
+            </FormGroup>
             <div class="mt-4 flex justify-end">
               <SubmitButton>
                 Zapisz
diff --git a/resources/js/Pages/Public/Home.vue b/resources/js/Pages/Public/Home.vue
index 94dc2d04..526b6ab1 100644
--- a/resources/js/Pages/Public/Home.vue
+++ b/resources/js/Pages/Public/Home.vue
@@ -24,7 +24,7 @@ defineProps({
   <PublicLayout>
     <div v-if="sectionSettings.banner_enabled" class="relative isolate bg-white pt-14">
       <BackgroundGrid />
-      <img src="/cwup.png" alt="" class="absolute right-0 hidden w-[50%] opacity-10 lg:mt-16 lg:block xl:mt-10 2xl:mt-0">
+      <img src="/cwup.png" alt="" class="absolute right-0 hidden w-1/2 opacity-10 lg:mt-16 lg:block xl:mt-10 2xl:mt-0">
       <div class="mx-auto max-w-7xl px-6 py-24 sm:py-32 lg:flex lg:items-center lg:gap-x-10 lg:px-8 lg:py-32">
         <div class="mx-auto max-w-7xl text-center lg:mx-0 lg:flex-auto">
           <h1 class="mx-auto mt-10 max-w-4xl text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">
diff --git a/resources/js/Pages/Public/Login.vue b/resources/js/Pages/Public/Login.vue
index eb831e0b..cb2f8c7d 100644
--- a/resources/js/Pages/Public/Login.vue
+++ b/resources/js/Pages/Public/Login.vue
@@ -22,7 +22,7 @@ function attemptLogin() {
   <PublicLayout>
     <div class="relative isolate bg-white pt-14">
       <BackgroundGrid />
-      <img src="/cwup.png" alt="" class="absolute right-0 z-0 hidden w-[50%] opacity-10 lg:mt-16 lg:block xl:mt-10 2xl:mt-0">
+      <img src="/cwup.png" alt="" class="absolute right-0 z-0 hidden w-1/2 opacity-10 lg:mt-16 lg:block xl:mt-10 2xl:mt-0">
       <div class="mx-auto max-w-7xl px-6 py-24 sm:py-32 lg:flex lg:items-center lg:gap-x-10 lg:px-8 lg:py-40">
         <div class="mx-auto max-w-7xl text-center lg:mx-0 lg:flex-auto">
           <img :src="universityLogo" :alt="university" class="mx-auto w-[360px]">
diff --git a/resources/js/Shared/Forms/ColorInput.vue b/resources/js/Shared/Forms/ColorInput.vue
new file mode 100644
index 00000000..eb4f74a5
--- /dev/null
+++ b/resources/js/Shared/Forms/ColorInput.vue
@@ -0,0 +1,32 @@
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+  modelValue: {
+    type: [String, Number, null],
+    default: null,
+  },
+  error: {
+    type: String,
+    default: null,
+  },
+})
+const emit = defineEmits(['update:modelValue'])
+const value = computed({
+  get: () => props.modelValue,
+  set: (value) => {
+    emit('update:modelValue', value)
+  },
+})
+</script>
+
+<template>
+  <input v-bind="$attrs" v-model="value"
+         type="color"
+         :class="[props.error
+                    ? 'text-red-900 ring-red-300 placeholder:text-red-300'
+                    : 'text-gray-900 shadow-sm ring-gray-300 placeholder:text-gray-400',
+                  'block h-10 w-14 cursor-pointer rounded-lg border border-gray-200 bg-white p-1 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-700 dark:bg-neutral-900'
+         ]"
+  >
+</template>
diff --git a/routes/web.php b/routes/web.php
index 782d1530..c21b994d 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -124,7 +124,8 @@
     });
     Route::controller(SettingController::class)->group(function (): void {
         Route::get("/settings", "edit")->name("settings.edit");
-        Route::patch("/settings", "update")->name("settings.update");
+        Route::post("/settings", "update")->name("settings.update");
+        Route::delete("/settings/remove-logo", "removeLogo")->name("settings.remove.logo");
     });
     Route::controller(SectionController::class)->group(function (): void {
         Route::get("/sections", "show")->name("sections.show");
diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php
index 940210ce..0a01957c 100644
--- a/tests/Feature/ExampleTest.php
+++ b/tests/Feature/ExampleTest.php
@@ -10,6 +10,13 @@
 
 class ExampleTest extends TestCase
 {
+    protected function tearDown(): void
+    {
+        Setting::query()->delete();
+
+        parent::tearDown();
+    }
+
     public function testTheApplicationReturnsASuccessfulResponse(): void
     {
         Setting::factory()->create();
diff --git a/tests/Feature/SettingsTest.php b/tests/Feature/SettingsTest.php
index f86add0b..f252b8cd 100644
--- a/tests/Feature/SettingsTest.php
+++ b/tests/Feature/SettingsTest.php
@@ -2,11 +2,13 @@
 
 declare(strict_types=1);
 
-namespace Feature;
+namespace Tests\Feature;
 
 use App\Models\Setting;
 use App\Models\User;
 use Illuminate\Foundation\Testing\RefreshDatabase;
+use Illuminate\Http\UploadedFile;
+use Illuminate\Support\Facades\Storage;
 use Illuminate\Support\Str;
 use Tests\TestCase;
 
@@ -25,6 +27,8 @@ protected function setUp(): void
             "teacher_titles" => "dr inż.",
             "university_name" => "CWUP",
             "department_name" => "IT department",
+            "primary_color" => "#000000",
+            "secondary_color" => "#ffffff",
         ]);
         $this->actingAs($this->user);
     }
@@ -37,14 +41,19 @@ public function testSettingsCanBeUpdated(): void
             "teacher_titles" => "dr inż.",
             "university_name" => "CWUP",
             "department_name" => "IT department",
+            "primary_color" => "#000000",
+            "secondary_color" => "#ffffff",
+            "logo" => null,
         ]);
 
-        $this->patch("/dashboard/settings", [
+        $this->post("/dashboard/settings", [
             "teacher_name" => "John Doe",
             "teacher_email" => "john.doe@exmple.com",
             "teacher_titles" => "dr",
             "university_name" => "SWPS",
             "department_name" => "Psychology department",
+            "primary_color" => "#11ffff",
+            "secondary_color" => "#110000",
         ])->assertSessionHasNoErrors();
 
         $this->assertDatabaseHas("settings", [
@@ -53,6 +62,9 @@ public function testSettingsCanBeUpdated(): void
             "teacher_titles" => "dr",
             "university_name" => "SWPS",
             "department_name" => "Psychology department",
+            "primary_color" => "#11ffff",
+            "secondary_color" => "#110000",
+            "logo" => null,
         ]);
     }
 
@@ -64,14 +76,19 @@ public function testSettingsCannotBeUpdatedWithInvalidData(): void
             "teacher_titles" => "dr inż.",
             "university_name" => "CWUP",
             "department_name" => "IT department",
+            "primary_color" => "#000000",
+            "secondary_color" => "#ffffff",
+            "logo" => null,
         ]);
 
-        $this->patch("/dashboard/settings", [
+        $this->post("/dashboard/settings", [
             "teacher_name" => Str::random(256),
             "teacher_email" => "john.doe",
             "teacher_titles" => Str::random(256),
             "university_name" => Str::random(256),
             "department_name" => Str::random(256),
+            "primary_color" => "000000",
+            "secondary_color" => "ffffff",
         ])->assertSessionHasErrors()
             ->assertInvalid([
                 "teacher_name",
@@ -79,6 +96,8 @@ public function testSettingsCannotBeUpdatedWithInvalidData(): void
                 "teacher_titles",
                 "university_name",
                 "department_name",
+                "primary_color",
+                "secondary_color",
             ]);
 
         $this->assertDatabaseHas("settings", [
@@ -87,6 +106,9 @@ public function testSettingsCannotBeUpdatedWithInvalidData(): void
             "teacher_titles" => "dr inż.",
             "university_name" => "CWUP",
             "department_name" => "IT department",
+            "primary_color" => "#000000",
+            "secondary_color" => "#ffffff",
+            "logo" => null,
         ]);
     }
 
@@ -98,14 +120,19 @@ public function testSettingsCannotBeUpdatedWithEmptyData(): void
             "teacher_titles" => "dr inż.",
             "university_name" => "CWUP",
             "department_name" => "IT department",
+            "primary_color" => "#000000",
+            "secondary_color" => "#ffffff",
+            "logo" => null,
         ]);
 
-        $this->patch("/dashboard/settings", [
+        $this->post("/dashboard/settings", [
             "teacher_name" => "",
             "teacher_email" => "",
             "teacher_titles" => "",
             "university_name" => "",
             "department_name" => "",
+            "primary_color" => "",
+            "secondary_color" => "",
         ])->assertSessionHasErrors()
             ->assertInvalid([
                 "teacher_name",
@@ -113,6 +140,8 @@ public function testSettingsCannotBeUpdatedWithEmptyData(): void
                 "teacher_titles",
                 "university_name",
                 "department_name",
+                "primary_color",
+                "secondary_color",
             ]);
 
         $this->assertDatabaseHas("settings", [
@@ -121,6 +150,104 @@ public function testSettingsCannotBeUpdatedWithEmptyData(): void
             "teacher_titles" => "dr inż.",
             "university_name" => "CWUP",
             "department_name" => "IT department",
+            "primary_color" => "#000000",
+            "secondary_color" => "#ffffff",
+            "logo" => null,
+        ]);
+    }
+
+    public function testLogoCanBeUploadedAndRemoved(): void
+    {
+        Storage::fake("public");
+        $this->assertDatabaseHas("settings", [
+            "teacher_name" => "Ty Doe",
+            "teacher_email" => "ty.doe@exmple.com",
+            "teacher_titles" => "dr inż.",
+            "university_name" => "CWUP",
+            "department_name" => "IT department",
+            "primary_color" => "#000000",
+            "secondary_color" => "#ffffff",
+            "logo" => null,
+        ]);
+        $logo = UploadedFile::fake()->image("logo.png");
+
+        $this->post("/dashboard/settings", [
+            "teacher_name" => "John Doe",
+            "teacher_email" => "john.doe@exmple.com",
+            "teacher_titles" => "dr",
+            "university_name" => "SWPS",
+            "department_name" => "Psychology department",
+            "primary_color" => "#11ffff",
+            "secondary_color" => "#110000",
+            "logo" => $logo,
+        ])->assertSessionHasNoErrors();
+
+        $this->assertDatabaseHas("settings", [
+            "teacher_name" => "John Doe",
+            "teacher_email" => "john.doe@exmple.com",
+            "teacher_titles" => "dr",
+            "university_name" => "SWPS",
+            "department_name" => "Psychology department",
+            "primary_color" => "#11ffff",
+            "secondary_color" => "#110000",
+            "logo" => "logo/logo.png",
+        ]);
+
+        Storage::disk("public")->assertExists("logo/logo.png");
+
+        $this->delete("/dashboard/settings/remove-logo")->assertSessionHasNoErrors();
+
+        $this->assertDatabaseHas("settings", [
+            "teacher_name" => "John Doe",
+            "teacher_email" => "john.doe@exmple.com",
+            "teacher_titles" => "dr",
+            "university_name" => "SWPS",
+            "department_name" => "Psychology department",
+            "primary_color" => "#11ffff",
+            "secondary_color" => "#110000",
+            "logo" => null,
+        ]);
+
+        Storage::disk("public")->assertMissing("logo/logo.png");
+    }
+
+    public function testSettingsCannotBeUpdatedWithTooBigLogoFile(): void
+    {
+        $this->assertDatabaseHas("settings", [
+            "teacher_name" => "Ty Doe",
+            "teacher_email" => "ty.doe@exmple.com",
+            "teacher_titles" => "dr inż.",
+            "university_name" => "CWUP",
+            "department_name" => "IT department",
+            "primary_color" => "#000000",
+            "secondary_color" => "#ffffff",
+            "logo" => null,
+        ]);
+        $logo = UploadedFile::fake()->image("logo.png")->size(2049);
+
+        $this->post("/dashboard/settings", [
+            "teacher_name" => "John Doe",
+            "teacher_email" => "john.doe@exmple.com",
+            "teacher_titles" => "dr",
+            "university_name" => "SWPS",
+            "department_name" => "Psychology department",
+            "primary_color" => "#11ffff",
+            "secondary_color" => "#110000",
+            "logo" => $logo,
+        ])->assertSessionHasErrors()
+            ->assertInvalid([
+                "logo",
+            ]);
+
+        $this->assertDatabaseHas("settings", [
+            "teacher_name" => "Ty Doe",
+            "teacher_email" => "ty.doe@exmple.com",
+            "teacher_titles" => "dr inż.",
+            "university_name" => "CWUP",
+            "department_name" => "IT department",
+            "primary_color" => "#000000",
+            "secondary_color" => "#ffffff",
+            "logo" => null,
         ]);
     }
 }