diff --git a/migrations/Version20230130174431.php b/migrations/Version20230130174431.php
new file mode 100644
index 0000000000000000000000000000000000000000..89a7ec4151e0cf3c427f912678611c79b535cfa8
--- /dev/null
+++ b/migrations/Version20230130174431.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+/**
+ * Auto-generated Migration: Please modify to your needs!
+ */
+final class Version20230130174431 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return '';
+    }
+
+    public function up(Schema $schema): void
+    {
+        // this up() migration is auto-generated, please modify it to your needs
+        $this->addSql('CREATE TABLE redirect (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, redirect_url VARCHAR(255) NOT NULL, is_s3_file TINYINT(1) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
+    }
+
+    public function down(Schema $schema): void
+    {
+        // this down() migration is auto-generated, please modify it to your needs
+        $this->addSql('DROP TABLE redirect');
+    }
+}
diff --git a/src/Controller/Admin/DashboardController.php b/src/Controller/Admin/DashboardController.php
index f6387f3f9694ebd2527236434167b26b256b151d..925e515d31c8489ef9c5305d7c2a6222c057fc37 100644
--- a/src/Controller/Admin/DashboardController.php
+++ b/src/Controller/Admin/DashboardController.php
@@ -5,6 +5,7 @@ namespace App\Controller\Admin;
 use App\Entity\Blog;
 use App\Entity\NTPServer;
 use App\Entity\Page;
+use App\Entity\Redirect;
 use App\Entity\SocialLink;
 use App\Entity\User;
 use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
@@ -35,5 +36,6 @@ class DashboardController extends AbstractDashboardController
         yield MenuItem::linkToCrud('Social Links', 'fas fa-list', SocialLink::class);
         yield MenuItem::linkToCrud('Pages', 'fas fa-list', Page::class);
         yield MenuItem::linkToCrud('NTP Server', 'fas fa-list', NTPServer::class);
+        yield MenuItem::linkToCrud('Redirect', 'fas fa-list', Redirect::class);
     }
 }
diff --git a/src/Controller/Admin/RedirectCrudController.php b/src/Controller/Admin/RedirectCrudController.php
new file mode 100644
index 0000000000000000000000000000000000000000..3b9f0e4a79e5caf84c602421447109ff7d7e3052
--- /dev/null
+++ b/src/Controller/Admin/RedirectCrudController.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Controller\Admin;
+
+use App\Entity\Redirect;
+use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+
+class RedirectCrudController extends AbstractCrudController
+{
+    public static function getEntityFqcn(): string
+    {
+        return Redirect::class;
+    }
+
+    /*
+    public function configureFields(string $pageName): iterable
+    {
+        return [
+            IdField::new('id'),
+            TextField::new('title'),
+            TextEditorField::new('description'),
+        ];
+    }
+    */
+}
diff --git a/src/Controller/PageController.php b/src/Controller/PageController.php
index 52065207fef0dc59984e66ec2451c22cd41a3b0a..a6d2f341cb376dff12cb846f609a8bc2ade6f2cf 100644
--- a/src/Controller/PageController.php
+++ b/src/Controller/PageController.php
@@ -3,7 +3,10 @@
 namespace App\Controller;
 
 use App\Repository\PageRepository;
+use App\Repository\RedirectRepository;
+use App\Service\S3Service;
 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\Routing\Annotation\Route;
@@ -11,14 +14,26 @@ use Symfony\Component\Routing\Annotation\Route;
 class PageController extends AbstractController
 {
     #[Route('/{all}', requirements: ['all' => '.*'], methods: ['GET'], priority: -1)]
-    public function renderPage(Request $request, PageRepository $pageRepository): Response
-    {
+    public function renderPage(
+        Request $request,
+        PageRepository $pageRepository,
+        RedirectRepository $redirectRepository,
+        S3Service $s3Service
+    ): Response {
         $page = $pageRepository->getPageFromURL($request->getPathInfo());
-        if (!$page) {
-            throw $this->createNotFoundException();
+        if ($page) {
+            return $this->render('pages/page.html.twig', [
+                'page' => $page
+            ]);
         }
-        return $this->render('pages/page.html.twig', [
-            'page' => $page
-        ]);
+        $redirect = $redirectRepository->getRedirectFromURL($request->getPathInfo());
+        if ($redirect) {
+            $url = $redirect->getRedirectURL();
+            if ($redirect->isIsS3File()) {
+                $url = $s3Service->generateSignedUrl('download/' . $url);
+            }
+            return new RedirectResponse($url);
+        }
+        throw $this->createNotFoundException();
     }
 }
diff --git a/src/Entity/Redirect.php b/src/Entity/Redirect.php
new file mode 100644
index 0000000000000000000000000000000000000000..c03c49327d44397e5f3e4cdcf368fc1b669589be
--- /dev/null
+++ b/src/Entity/Redirect.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace App\Entity;
+
+use App\Repository\RedirectRepository;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ORM\Entity(repositoryClass: RedirectRepository::class)]
+class Redirect
+{
+    #[ORM\Id]
+    #[ORM\GeneratedValue]
+    #[ORM\Column]
+    private ?int $id = null;
+
+    #[ORM\Column(length: 255)]
+    private ?string $name = null;
+
+    #[ORM\Column(length: 255)]
+    private ?string $redirectURL = null;
+
+    #[ORM\Column]
+    private ?bool $isS3File = null;
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function getName(): ?string
+    {
+        return $this->name;
+    }
+
+    public function setName(string $name): self
+    {
+        $this->name = $name;
+
+        return $this;
+    }
+
+    public function getRedirectURL(): ?string
+    {
+        return $this->redirectURL;
+    }
+
+    public function setRedirectURL(string $redirectURL): self
+    {
+        $this->redirectURL = $redirectURL;
+
+        return $this;
+    }
+
+    public function isIsS3File(): ?bool
+    {
+        return $this->isS3File;
+    }
+
+    public function setIsS3File(bool $isS3File): self
+    {
+        $this->isS3File = $isS3File;
+
+        return $this;
+    }
+}
diff --git a/src/Repository/RedirectRepository.php b/src/Repository/RedirectRepository.php
new file mode 100644
index 0000000000000000000000000000000000000000..3cfff1ba4fb7ebe0480a0b78a5af64feaa437dc2
--- /dev/null
+++ b/src/Repository/RedirectRepository.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Repository;
+
+use App\Entity\Redirect;
+use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Doctrine\Persistence\ManagerRegistry;
+
+/**
+ * @extends ServiceEntityRepository<Redirect>
+ *
+ * @method Redirect|null find($id, $lockMode = null, $lockVersion = null)
+ * @method Redirect|null findOneBy(array $criteria, array $orderBy = null)
+ * @method Redirect[]    findAll()
+ * @method Redirect[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
+ */
+class RedirectRepository extends ServiceEntityRepository
+{
+    public function __construct(ManagerRegistry $registry)
+    {
+        parent::__construct($registry, Redirect::class);
+    }
+
+    public function save(Redirect $entity, bool $flush = false): void
+    {
+        $this->getEntityManager()->persist($entity);
+
+        if ($flush) {
+            $this->getEntityManager()->flush();
+        }
+    }
+
+    public function remove(Redirect $entity, bool $flush = false): void
+    {
+        $this->getEntityManager()->remove($entity);
+
+        if ($flush) {
+            $this->getEntityManager()->flush();
+        }
+    }
+
+    public function getRedirectFromURL(string $url): Redirect|null
+    {
+        return $this->createQueryBuilder('r')
+            ->where('r.name = :path')
+            ->setParameter('path', $url)
+            ->getQuery()
+            ->getOneOrNullResult();
+    }
+//    /**
+//     * @return Redirect[] Returns an array of Redirect objects
+//     */
+//    public function findByExampleField($value): array
+//    {
+//        return $this->createQueryBuilder('r')
+//            ->andWhere('r.exampleField = :val')
+//            ->setParameter('val', $value)
+//            ->orderBy('r.id', 'ASC')
+//            ->setMaxResults(10)
+//            ->getQuery()
+//            ->getResult()
+//        ;
+//    }
+
+//    public function findOneBySomeField($value): ?Redirect
+//    {
+//        return $this->createQueryBuilder('r')
+//            ->andWhere('r.exampleField = :val')
+//            ->setParameter('val', $value)
+//            ->getQuery()
+//            ->getOneOrNullResult()
+//        ;
+//    }
+}