diff --git a/src/ahriman/core/archive/__init__.py b/src/ahriman/core/archive/__init__.py
new file mode 100644
index 00000000..7413eea9
--- /dev/null
+++ b/src/ahriman/core/archive/__init__.py
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2021-2025 ahriman team.
+#
+# This file is part of ahriman
+# (see https://github.com/arcan1s/ahriman).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
diff --git a/src/ahriman/core/archive/archive_trigger.py b/src/ahriman/core/archive/archive_trigger.py
new file mode 100644
index 00000000..14e188ac
--- /dev/null
+++ b/src/ahriman/core/archive/archive_trigger.py
@@ -0,0 +1,65 @@
+#
+# Copyright (c) 2021-2025 ahriman team.
+#
+# This file is part of ahriman
+# (see https://github.com/arcan1s/ahriman).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+from pathlib import Path
+
+from ahriman.core.configuration import Configuration
+from ahriman.core.triggers import Trigger
+from ahriman.models.package import Package
+from ahriman.models.repository_id import RepositoryId
+from ahriman.models.result import Result
+
+
+class ArchiveRotationTrigger(Trigger):
+ """
+ archive repository extension
+
+ Attributes:
+ paths(RepositoryPaths): repository paths instance
+ """
+
+ def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
+ """
+ Args:
+ repository_id(RepositoryId): repository unique identifier
+ configuration(Configuration): configuration instance
+ """
+ Trigger.__init__(self, repository_id, configuration)
+
+ self.paths = configuration.repository_paths
+
+ @property
+ def repos_path(self) -> Path:
+ return self.paths.archive / "repos"
+
+ def on_result(self, result: Result, packages: list[Package]) -> None:
+ """
+ run trigger
+
+ Args:
+ result(Result): build result
+ packages(list[Package]): list of all available packages
+ """
+
+ def on_start(self) -> None:
+ """
+ trigger action which will be called at the start of the application
+ """
+ with self.paths.preserve_owner(self.repos_path):
+ self.repos_path.mkdir(mode=0o755, exist_ok=True)