feat: full rootless setup (#165)

* use local devtools configs instead of global ones

* make docker image rootless

* add migration notes

* fix setup command

* fix regress jo
This commit is contained in:
2026-08-14 13:34:42 +03:00
committed by GitHub
parent 695424fa16
commit 3548b434be
36 changed files with 581 additions and 147 deletions
+1 -1
View File
@@ -44,7 +44,7 @@ pacman -Qdtq | pacman -Rscn --noconfirm -
# initial setup command as root # initial setup command as root
[[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080") [[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080")
ahriman -a x86_64 -r "github" service-setup --packager "ahriman bot <ahriman@example.com>" "${WEB_ARGS[@]}" sudo -u ahriman -- ahriman -a x86_64 -r "github" service-setup --packager "ahriman bot <ahriman@example.com>" "${WEB_ARGS[@]}"
# enable services # enable services
systemctl enable ahriman@x86_64-github.timer systemctl enable ahriman@x86_64-github.timer
if [[ -z $MINIMAL_INSTALL ]]; then if [[ -z $MINIMAL_INSTALL ]]; then
+7 -5
View File
@@ -18,8 +18,8 @@ jobs:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
env: env:
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman-web.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman-web.sock
options: --privileged --entrypoint entrypoint-web options: --privileged --user root --entrypoint entrypoint-web
ports: ports:
- 8080 - 8080
volumes: volumes:
@@ -31,8 +31,8 @@ jobs:
AHRIMAN_DEBUG: y AHRIMAN_DEBUG: y
AHRIMAN_OUTPUT: console AHRIMAN_OUTPUT: console
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman-web.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman-web.sock
options: --privileged options: --privileged --user root
volumes: volumes:
- repo:/var/lib/ahriman - repo:/var/lib/ahriman
@@ -40,7 +40,9 @@ jobs:
- run: pacman -Sy - run: pacman -Sy
- name: Init repository - name: Init repository
run: entrypoint help run: |
chown ahriman:ahriman /var/lib/ahriman
sudo -E -u ahriman -- entrypoint help
- name: Print configuration - name: Print configuration
run: | run: |
+15 -1
View File
@@ -7,16 +7,19 @@ usage() {
echo "Usage: $cmd [options] -- [archbuild args]" echo "Usage: $cmd [options] -- [archbuild args]"
echo " -r <repository> Repository name" echo " -r <repository> Repository name"
echo " -a <architecture> Repository architecture" echo " -a <architecture> Repository architecture"
echo " -c <directory> Read devtools pacman configurations from this directory"
exit 1 exit 1
} }
repository= repository=
architecture= architecture=
pacman_config_dir=
while getopts ":r:a:" arg; do while getopts ":r:a:c:" arg; do
case "$arg" in case "$arg" in
r) repository="$OPTARG" ;; r) repository="$OPTARG" ;;
a) architecture="$OPTARG" ;; a) architecture="$OPTARG" ;;
c) pacman_config_dir="$OPTARG" ;;
*) usage ;; *) usage ;;
esac esac
done done
@@ -28,6 +31,17 @@ fi
source "/usr/share/devtools/lib/archroot.sh" source "/usr/share/devtools/lib/archroot.sh"
check_root "SOURCE_DATE_EPOCH,SRCDEST,SRCPKGDEST,PKGDEST,LOGDEST,NPROC,MAKEFLAGS,PACKAGER,GNUPGHOME" "${BASH_SOURCE[0]}" "$@" check_root "SOURCE_DATE_EPOCH,SRCDEST,SRCPKGDEST,PKGDEST,LOGDEST,NPROC,MAKEFLAGS,PACKAGER,GNUPGHOME" "${BASH_SOURCE[0]}" "$@"
# because devtools doesn't allow to read configuration from custom path
# here is a workaround, which uses unshare to bind-mount directory with configuration files
# for specific process
if [[ -n $pacman_config_dir && -z ${AHRIMAN_ARCHBUILD_MOUNTED:-} ]]; then
export AHRIMAN_ARCHBUILD_MOUNTED=1
exec unshare --mount --propagation private bash -e -c '
mount --bind "$0" /usr/share/devtools/pacman.conf.d
exec "$@"
' "$(readlink -f "$pacman_config_dir")" "${BASH_SOURCE[0]}" "$@"
fi
exec bash -c ' exec bash -c '
source "$1" "${@:2}" source "$1" "${@:2}"
' "${repository}-${architecture}-build" "archbuild" "${@:$OPTIND}" ' "${repository}-${architecture}-build" "archbuild" "${@:$OPTIND}"
@@ -1,6 +1,6 @@
[settings] [settings]
; Relative path to directory with configuration files overrides. Overrides will be applied in alphabetic order. ; Relative path to directory with configuration files overrides. Overrides will be applied in alphabetic order.
include = ahriman.ini.d $HOME/.config/ahriman.ini.d include = ahriman.ini.d ${repository:root}/.config/ahriman/ahriman.ini.d
; Relative path to configuration used by logging package. ; Relative path to configuration used by logging package.
logging = ahriman.ini.d/logging.ini logging = ahriman.ini.d/logging.ini
; Perform database migrations on the application start. Do not touch this option unless you know what you are doing. ; Perform database migrations on the application start. Do not touch this option unless you know what you are doing.
@@ -34,6 +34,8 @@ retry_backoff = 1.0
[build] [build]
; List of additional flags passed to archbuild command. ; List of additional flags passed to archbuild command.
;archbuild_flags = ;archbuild_flags =
; Path to local directory with devtools configuration files, which will be bind-mounted for devtools.
devtools_configs = ${repository:root}/.config/ahriman/pacman.conf.d
; Path to build command. ; Path to build command.
devtools_wrapper = ahriman-archbuild devtools_wrapper = ahriman-archbuild
; List of packages to be ignored during automatic updates. ; List of packages to be ignored during automatic updates.
@@ -28,7 +28,7 @@ from urllib.parse import quote_plus as url_encode
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers.handler import Handler, SubParserAction from ahriman.application.handlers.handler import Handler, SubParserAction
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import MissingArchitectureError from ahriman.core.exceptions import InitializeError, MissingArchitectureError
from ahriman.core.utils import enum_values from ahriman.core.utils import enum_values
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
from ahriman.models.sign_settings import SignSettings from ahriman.models.sign_settings import SignSettings
@@ -63,18 +63,20 @@ class Setup(Handler):
if args.architecture is None or args.repository is None: if args.architecture is None or args.repository is None:
raise MissingArchitectureError(args.command) raise MissingArchitectureError(args.command)
Setup.configuration_create_ahriman(args, repository_id, configuration) target_directory = Setup.configuration_create_directory(configuration)
Setup.configuration_create_ahriman(args, repository_id, configuration, target_directory)
configuration.reload() configuration.reload()
application = Application(repository_id, configuration, report=report) application = Application(repository_id, configuration, report=report)
paths = application.repository.paths
# basically we create configuration here as root, but it is ok, because those files are only used for reading repository_server = f"file://{paths.repository}" if args.server is None else args.server
repository_server = f"file://{application.repository.paths.repository}" if args.server is None else args.server target_directory = paths.ensure_exists(configuration.getpath("build", "devtools_configs"))
Setup.configuration_create_devtools( Setup.configuration_create_devtools(repository_id, args.from_configuration, target_directory, args.mirror,
repository_id, args.from_configuration, args.mirror, args.multilib, repository_server) args.multilib, repository_server)
# finish initialization # finish initialization
with application.repository.paths.preserve_owner(): with paths.preserve_owner():
application.repository.repo.init() application.repository.repo.init()
# lazy database sync # lazy database sync
application.repository.pacman.handle # pylint: disable=pointless-statement application.repository.pacman.handle # pylint: disable=pointless-statement
@@ -114,12 +116,12 @@ class Setup(Handler):
parser.add_argument("--web-port", help="port of the web service", type=int) parser.add_argument("--web-port", help="port of the web service", type=int)
parser.add_argument("--web-unix-socket", help="path to unix socket used for interprocess communications", parser.add_argument("--web-unix-socket", help="path to unix socket used for interprocess communications",
type=Path) type=Path)
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True) parser.set_defaults(lock=None, quiet=True, report=False)
return parser return parser
@staticmethod @staticmethod
def configuration_create_ahriman(args: argparse.Namespace, repository_id: RepositoryId, def configuration_create_ahriman(args: argparse.Namespace, repository_id: RepositoryId,
root: Configuration) -> None: root: Configuration, target_directory: Path) -> None:
""" """
create service specific configuration create service specific configuration
@@ -127,6 +129,7 @@ class Setup(Handler):
args(argparse.Namespace): command line args args(argparse.Namespace): command line args
repository_id(RepositoryId): repository unique identifier repository_id(RepositoryId): repository unique identifier
root(Configuration): root configuration instance root(Configuration): root configuration instance
target_directory(Path): path to directory where configuration files will be written
""" """
configuration = Configuration() configuration = Configuration()
@@ -164,15 +167,13 @@ class Setup(Handler):
if args.generate_salt: if args.generate_salt:
configuration.set_option("auth", "salt", User.generate_password(20)) configuration.set_option("auth", "salt", User.generate_password(20))
include_path = next(path for path in root.getpathlist("settings", "include") if os.access(path, os.W_OK)) target = target_directory / f"00-setup-overrides-{repository_id.id}.ini"
(include_path / "00-setup-overrides.ini").unlink(missing_ok=True) # remove old-style configuration
target = include_path / f"00-setup-overrides-{repository_id.id}.ini"
with target.open("w", encoding="utf8") as ahriman_configuration: with target.open("w", encoding="utf8") as ahriman_configuration:
configuration.write(ahriman_configuration) configuration.write(ahriman_configuration)
@staticmethod @staticmethod
def configuration_create_devtools(repository_id: RepositoryId, source: Path, mirror: str | None, def configuration_create_devtools(repository_id: RepositoryId, source: Path, target_directory: Path,
multilib: bool, repository_server: str) -> None: mirror: str | None, multilib: bool, repository_server: str) -> None:
""" """
create configuration for devtools based on ``source`` configuration create configuration for devtools based on ``source`` configuration
@@ -182,6 +183,7 @@ class Setup(Handler):
Args: Args:
repository_id(RepositoryId): repository unique identifier repository_id(RepositoryId): repository unique identifier
source(Path): path to source configuration file source(Path): path to source configuration file
target_directory(Path): path to directory where configuration files will be written
mirror(str | None): link to package server mirror mirror(str | None): link to package server mirror
multilib(bool): add or do not multilib repository to the configuration multilib(bool): add or do not multilib repository to the configuration
repository_server(str): url of the repository repository_server(str): url of the repository
@@ -216,8 +218,32 @@ class Setup(Handler):
configuration.set_option(repository_id.name, "SigLevel", "Never") # we don't care configuration.set_option(repository_id.name, "SigLevel", "Never") # we don't care
configuration.set_option(repository_id.name, "Server", repository_server) configuration.set_option(repository_id.name, "Server", repository_server)
target = source.parent / f"{repository_id.name}-{repository_id.architecture}.conf" target = target_directory / f"{repository_id.name}-{repository_id.architecture}.conf"
with target.open("w", encoding="utf8") as devtools_configuration: with target.open("w", encoding="utf8") as devtools_configuration:
configuration.write(devtools_configuration) configuration.write(devtools_configuration)
@staticmethod
def configuration_create_directory(root: Configuration) -> Path:
"""
create directory for includes
Args:
root(Configuration): root configuration instance
Returns:
Path: path to first writable directory
Raises:
InitializeError: if no writable directories have been found
"""
for include_path in root.include:
try:
directory = root.repository_paths.ensure_exists(include_path)
if os.access(directory, os.W_OK | os.X_OK):
return directory
except OSError:
continue
raise InitializeError("No writable include directory found")
arguments = [_set_service_setup_parser] arguments = [_set_service_setup_parser]
@@ -38,6 +38,7 @@ class Task(LazyLogging):
Attributes: Attributes:
archbuild_flags(list[str]): command flags for archbuild command archbuild_flags(list[str]): command flags for archbuild command
build_command(list[str]): build command build_command(list[str]): build command
devtools_configs(Path): path to local directory with devtools configuration files
include_debug_packages(bool): whether to include debug packages or not include_debug_packages(bool): whether to include debug packages or not
make_flags(str): MAKEFLAGS variable for makepkg command make_flags(str): MAKEFLAGS variable for makepkg command
makechrootpkg_flags(list[str]): command flags for makechrootpkg command makechrootpkg_flags(list[str]): command flags for makechrootpkg command
@@ -64,6 +65,7 @@ class Task(LazyLogging):
self.archbuild_flags = configuration.getlist("build", "archbuild_flags", fallback=[]) self.archbuild_flags = configuration.getlist("build", "archbuild_flags", fallback=[])
self.build_command = configuration.getlist("build", "devtools_wrapper") self.build_command = configuration.getlist("build", "devtools_wrapper")
self.devtools_configs = configuration.getpath("build", "devtools_configs")
self._legacy_build_command = configuration.getlist("build", "build_command", fallback=[]) self._legacy_build_command = configuration.getlist("build", "build_command", fallback=[])
self.include_debug_packages = configuration.getboolean("build", "include_debug_packages", fallback=True) self.include_debug_packages = configuration.getboolean("build", "include_debug_packages", fallback=True)
# even though this option is declared as list, there is no need to read it as list, # even though this option is declared as list, there is no need to read it as list,
@@ -116,7 +118,12 @@ class Task(LazyLogging):
""" """
command = self._legacy_build_command[:] command = self._legacy_build_command[:]
if not command: if not command:
command = self.build_command + ["-r", self.repository_id.name, "-a", self.repository_id.architecture, "--"] command = self.build_command + [
"-r", self.repository_id.name,
"-a", self.repository_id.architecture,
"-c", str(self.devtools_configs),
"--",
]
command.extend(["-r", str(self.paths.chroot)] + self.archbuild_flags) # archbuild flags command.extend(["-r", str(self.paths.chroot)] + self.archbuild_flags) # archbuild flags
command.extend(["--", "-D", str(self.paths.archive)] + self.makechrootpkg_flags) # makechrootpkg flags command.extend(["--", "-D", str(self.paths.archive)] + self.makechrootpkg_flags) # makechrootpkg flags
@@ -108,6 +108,16 @@ class Configuration(configparser.RawConfigParser):
_, repository_id = self.check_loaded() _, repository_id = self.check_loaded()
return repository_id.architecture return repository_id.architecture
@property
def include(self) -> list[Path]:
"""
get full path to include directory
Returns:
list[Path]: paths to directories with configuration includes
"""
return self.getpathlist("settings", "include")
@property @property
def logging_path(self) -> Path: def logging_path(self) -> Path:
""" """
@@ -322,20 +332,11 @@ class Configuration(configparser.RawConfigParser):
self.includes = [] # reset state self.includes = [] # reset state
try: try:
# raw processing to make sure that options are applied correctly include_directories = self.include
include_directories = shlex.split(self.get("settings", "include", raw=True))
except (configparser.NoOptionError, configparser.NoSectionError): except (configparser.NoOptionError, configparser.NoSectionError):
return return
for directory in include_directories: for path in include_directories: # pylint: disable=not-an-iterable
value = self._interpolation.before_get( # type: ignore[attr-defined]
self,
"settings",
"include",
directory,
self._unify_values("settings", None), # type: ignore[attr-defined]
)
path = self._convert_path(value)
if not path.is_dir(): if not path.is_dir():
continue continue
@@ -200,6 +200,13 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"empty": False, "empty": False,
}, },
}, },
"devtools_configs": {
"type": "path",
"coerce": "absolute_path",
"required": True,
"path_exists": True,
"path_type": "dir",
},
"devtools_wrapper": { "devtools_wrapper": {
"type": "list", "type": "list",
"coerce": "list", "coerce": "list",
@@ -103,7 +103,7 @@ class RepositoryPaths(LazyLogging):
Returns: Returns:
Path: path to directory in which build process is run Path: path to directory in which build process is run
""" """
uid, _ = owner(self.root) uid, _ = self.root_owner
return self.chroot / f"{self.repository_id.name}-{self.repository_id.architecture}" / getpwuid(uid).pw_name return self.chroot / f"{self.repository_id.name}-{self.repository_id.architecture}" / getpwuid(uid).pw_name
@property @property
@@ -127,6 +127,16 @@ class RepositoryPaths(LazyLogging):
# for the chroot directory devtools will create own tree, and we don't have to specify architecture here # for the chroot directory devtools will create own tree, and we don't have to specify architecture here
return self.root / "chroot" / self.repository_id.name return self.root / "chroot" / self.repository_id.name
@property
def configs(self) -> Path:
"""
get directory for local configuration files
Returns:
Path: full path to local configuration directory
"""
return self.root / ".config" / "ahriman"
@property @property
def packages(self) -> Path: def packages(self) -> Path:
""" """
@@ -323,6 +333,7 @@ class RepositoryPaths(LazyLogging):
self.archive, self.archive,
self.cache, self.cache,
self.chroot, self.chroot,
self.configs,
self.packages, self.packages,
self.pacman, self.pacman,
self.repository, self.repository,
@@ -1,5 +1,6 @@
import argparse import argparse
import multiprocessing import multiprocessing
import os
import pytest import pytest
from pathlib import Path from pathlib import Path
@@ -11,9 +12,8 @@ from urllib.parse import quote_plus as url_encode
from ahriman.application.handlers.setup import Setup from ahriman.application.handlers.setup import Setup
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite from ahriman.core.database import SQLite
from ahriman.core.exceptions import MissingArchitectureError from ahriman.core.exceptions import InitializeError, MissingArchitectureError
from ahriman.core.repository import Repository from ahriman.core.repository import Repository
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths from ahriman.models.repository_paths import RepositoryPaths
from ahriman.models.sign_settings import SignSettings from ahriman.models.sign_settings import SignSettings
@@ -51,8 +51,11 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
must run command must run command
""" """
args = _default_args(args) args = _default_args(args)
local = Path("local")
mocker.patch("ahriman.core.database.SQLite.load", return_value=database) mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mkdir_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_directory",
return_value=local)
ahriman_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_ahriman") ahriman_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_ahriman")
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_devtools") devtools_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_devtools")
init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init") init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init")
@@ -61,9 +64,16 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
_, repository_id = configuration.check_loaded() _, repository_id = configuration.check_loaded()
Setup.run(args, repository_id, configuration, report=False) Setup.run(args, repository_id, configuration, report=False)
owner_guard_mock.assert_called_once_with() owner_guard_mock.assert_called_once_with()
ahriman_configuration_mock.assert_called_once_with(args, repository_id, configuration) mkdir_mock.assert_called_once_with(configuration)
ahriman_configuration_mock.assert_called_once_with(args, repository_id, configuration, local)
devtools_configuration_mock.assert_called_once_with( devtools_configuration_mock.assert_called_once_with(
repository_id, args.from_configuration, args.mirror, args.multilib, f"file://{repository_paths.repository}") repository_id,
args.from_configuration,
configuration.getpath("build", "devtools_configs"),
args.mirror,
args.multilib,
f"file://{repository_paths.repository}",
)
init_mock.assert_called_once_with() init_mock.assert_called_once_with()
@@ -102,11 +112,17 @@ def test_run_with_server(args: argparse.Namespace, configuration: Configuration,
_, repository_id = configuration.check_loaded() _, repository_id = configuration.check_loaded()
Setup.run(args, repository_id, configuration, report=False) Setup.run(args, repository_id, configuration, report=False)
devtools_configuration_mock.assert_called_once_with( devtools_configuration_mock.assert_called_once_with(
repository_id, args.from_configuration, args.mirror, args.multilib, "server") repository_id,
args.from_configuration,
configuration.getpath("build", "devtools_configs"),
args.mirror,
args.multilib,
"server",
)
def test_configuration_create_ahriman(args: argparse.Namespace, configuration: Configuration, def test_configuration_create_ahriman(args: argparse.Namespace, configuration: Configuration, tmp_path: Path,
repository_paths: RepositoryPaths, mocker: MockerFixture) -> None: mocker: MockerFixture) -> None:
""" """
must create configuration for the service must create configuration for the service
""" """
@@ -114,10 +130,9 @@ def test_configuration_create_ahriman(args: argparse.Namespace, configuration: C
mocker.patch("pathlib.Path.open") mocker.patch("pathlib.Path.open")
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option") set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write") write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
remove_mock = mocker.patch("pathlib.Path.unlink", autospec=True)
_, repository_id = configuration.check_loaded() _, repository_id = configuration.check_loaded()
Setup.configuration_create_ahriman(args, repository_id, configuration) Setup.configuration_create_ahriman(args, repository_id, configuration, tmp_path)
set_option_mock.assert_has_calls([ set_option_mock.assert_has_calls([
MockCall("repository", "name", repository_id.name), MockCall("repository", "name", repository_id.name),
MockCall(Configuration.section_name("build", repository_id.name, repository_id.architecture), MockCall(Configuration.section_name("build", repository_id.name, repository_id.architecture),
@@ -139,15 +154,10 @@ def test_configuration_create_ahriman(args: argparse.Namespace, configuration: C
MockCall("auth", "salt", pytest.helpers.anyvar(str, strict=True)), MockCall("auth", "salt", pytest.helpers.anyvar(str, strict=True)),
]) ])
write_mock.assert_called_once_with(pytest.helpers.anyvar(int)) write_mock.assert_called_once_with(pytest.helpers.anyvar(int))
remove_mock.assert_called_once_with(
next(
path for path in configuration.getpathlist("settings", "include")) /
"00-setup-overrides.ini",
missing_ok=True)
def test_configuration_create_ahriman_no_multilib(args: argparse.Namespace, configuration: Configuration, def test_configuration_create_ahriman_no_multilib(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None: tmp_path: Path, mocker: MockerFixture) -> None:
""" """
must create configuration for the service without multilib repository must create configuration for the service without multilib repository
""" """
@@ -158,14 +168,14 @@ def test_configuration_create_ahriman_no_multilib(args: argparse.Namespace, conf
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option") set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
_, repository_id = configuration.check_loaded() _, repository_id = configuration.check_loaded()
Setup.configuration_create_ahriman(args, repository_id, configuration) Setup.configuration_create_ahriman(args, repository_id, configuration, tmp_path)
set_option_mock.assert_has_calls([ set_option_mock.assert_has_calls([
MockCall(Configuration.section_name("alpm", repository_id.name, repository_id.architecture), "mirror", MockCall(Configuration.section_name("alpm", repository_id.name, repository_id.architecture), "mirror",
args.mirror), args.mirror),
]) # non-strict check called intentionally ]) # non-strict check called intentionally
def test_configuration_create_devtools(args: argparse.Namespace, configuration: Configuration, def test_configuration_create_devtools(args: argparse.Namespace, configuration: Configuration, tmp_path: Path,
mocker: MockerFixture) -> None: mocker: MockerFixture) -> None:
""" """
must create configuration for the devtools must create configuration for the devtools
@@ -177,12 +187,12 @@ def test_configuration_create_devtools(args: argparse.Namespace, configuration:
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write") write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
_, repository_id = configuration.check_loaded() _, repository_id = configuration.check_loaded()
Setup.configuration_create_devtools(repository_id, args.from_configuration, None, args.multilib, "server") Setup.configuration_create_devtools(repository_id, args.from_configuration, tmp_path, None, args.multilib, "server")
add_section_mock.assert_has_calls([MockCall("multilib"), MockCall(repository_id.name)]) add_section_mock.assert_has_calls([MockCall("multilib"), MockCall(repository_id.name)])
write_mock.assert_called_once_with(pytest.helpers.anyvar(int)) write_mock.assert_called_once_with(pytest.helpers.anyvar(int))
def test_configuration_create_devtools_mirror(args: argparse.Namespace, configuration: Configuration, def test_configuration_create_devtools_mirror(args: argparse.Namespace, configuration: Configuration, tmp_path: Path,
mocker: MockerFixture) -> None: mocker: MockerFixture) -> None:
""" """
must create configuration for the devtools with mirror set explicitly must create configuration for the devtools with mirror set explicitly
@@ -202,14 +212,21 @@ def test_configuration_create_devtools_mirror(args: argparse.Namespace, configur
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option") set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
_, repository_id = configuration.check_loaded() _, repository_id = configuration.check_loaded()
Setup.configuration_create_devtools(repository_id, args.from_configuration, args.mirror, args.multilib, "server") Setup.configuration_create_devtools(
repository_id,
args.from_configuration,
tmp_path,
args.mirror,
args.multilib,
"server",
)
get_mock.assert_has_calls([MockCall("core", "Include", fallback=None), MockCall("extra", "Include", fallback=None)]) get_mock.assert_has_calls([MockCall("core", "Include", fallback=None), MockCall("extra", "Include", fallback=None)])
remove_option_mock.assert_called_once_with("core", "Include") remove_option_mock.assert_called_once_with("core", "Include")
set_option_mock.assert_has_calls([MockCall("core", "Server", args.mirror)]) # non-strict check called intentionally set_option_mock.assert_has_calls([MockCall("core", "Server", args.mirror)]) # non-strict check called intentionally
def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, configuration: Configuration, def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None: tmp_path: Path, mocker: MockerFixture) -> None:
""" """
must create configuration for the devtools without multilib must create configuration for the devtools without multilib
""" """
@@ -219,10 +236,33 @@ def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, con
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write") write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
_, repository_id = configuration.check_loaded() _, repository_id = configuration.check_loaded()
Setup.configuration_create_devtools(repository_id, args.from_configuration, args.mirror, False, "server") Setup.configuration_create_devtools(repository_id, args.from_configuration, tmp_path, args.mirror, False, "server")
write_mock.assert_called_once_with(pytest.helpers.anyvar(int)) write_mock.assert_called_once_with(pytest.helpers.anyvar(int))
def test_configuration_create_directory(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must create writable directory for includes
"""
configuration.set_option("settings", "include", f"/path1 /path2 /path3")
mkdir_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.ensure_exists",
side_effect=[OSError, "/path2", "/path3"])
access_mock = mocker.patch("os.access", side_effect=[False, True])
assert Setup.configuration_create_directory(configuration) == "/path3"
mkdir_mock.assert_has_calls([MockCall(Path("/path1")), MockCall(Path("/path2")), MockCall(Path("/path3"))])
access_mock.assert_has_calls([MockCall("/path2", os.W_OK | os.X_OK), MockCall("/path3", os.W_OK | os.X_OK)])
def test_configuration_create_directory_no_writable(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must raise InitializeError if no writable directories found
"""
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.ensure_exists", side_effect=OSError)
with pytest.raises(InitializeError):
Setup.configuration_create_directory(configuration)
def test_disallow_multi_architecture_run() -> None: def test_disallow_multi_architecture_run() -> None:
""" """
must not allow multi architecture run must not allow multi architecture run
@@ -63,7 +63,7 @@ def test_run_default(args: argparse.Namespace, configuration: Configuration) ->
default = Configuration.from_path(Configuration.SYSTEM_CONFIGURATION_PATH, repository_id) default = Configuration.from_path(Configuration.SYSTEM_CONFIGURATION_PATH, repository_id)
# copy autogenerated values # copy autogenerated values
for section, key in (("repository", "root"),): for section, key in (("repository", "root"), ("build", "devtools_configs")):
value = configuration.get(section, key) value = configuration.get(section, key)
default.set_option(section, key, value) default.set_option(section, key, value)
@@ -1488,7 +1488,7 @@ def test_subparsers_service_run_option_repository(parser: argparse.ArgumentParse
def test_subparsers_service_setup(parser: argparse.ArgumentParser) -> None: def test_subparsers_service_setup(parser: argparse.ArgumentParser) -> None:
""" """
service-setup command must imply lock, quiet, report and unsafe service-setup command must imply lock, quiet and report
""" """
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-setup", args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-setup",
"--packager", "ahriman bot <ahriman@example.com>"]) "--packager", "ahriman bot <ahriman@example.com>"])
@@ -1497,7 +1497,6 @@ def test_subparsers_service_setup(parser: argparse.ArgumentParser) -> None:
assert args.quiet assert args.quiet
assert not args.report assert not args.report
assert args.repository == "repo" assert args.repository == "repo"
assert args.unsafe
def test_subparsers_service_setup_option_from_configuration(parser: argparse.ArgumentParser) -> None: def test_subparsers_service_setup_option_from_configuration(parser: argparse.ArgumentParser) -> None:
@@ -54,7 +54,9 @@ def test_build(task_ahriman: Task, mocker: MockerFixture) -> None:
assert task_ahriman.build(local) == [task_ahriman.package.base] assert task_ahriman.build(local) == [task_ahriman.package.base]
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"ahriman-archbuild", "ahriman-archbuild",
"-r", task_ahriman.repository_id.name, "-a", task_ahriman.repository_id.architecture, "-r", task_ahriman.repository_id.name,
"-a", task_ahriman.repository_id.architecture,
"-c", str(task_ahriman.devtools_configs),
"--", "-r", str(task_ahriman.paths.chroot), "--", "-r", str(task_ahriman.paths.chroot),
"--", "-D", str(task_ahriman.paths.archive), "--", "-D", str(task_ahriman.paths.archive),
"--", "--skippgpcheck", "--", "--skippgpcheck",
@@ -81,7 +83,9 @@ def test_build_environment(task_ahriman: Task, mocker: MockerFixture) -> None:
task_ahriman.build(local, **environment, empty=None) task_ahriman.build(local, **environment, empty=None)
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"ahriman-archbuild", "ahriman-archbuild",
"-r", task_ahriman.repository_id.name, "-a", task_ahriman.repository_id.architecture, "-r", task_ahriman.repository_id.name,
"-a", task_ahriman.repository_id.architecture,
"-c", str(task_ahriman.devtools_configs),
"--", "-r", str(task_ahriman.paths.chroot), "--", "-r", str(task_ahriman.paths.chroot),
"--", "-D", str(task_ahriman.paths.archive), "--", "-D", str(task_ahriman.paths.archive),
"--", "--skippgpcheck", "--", "--skippgpcheck",
@@ -106,7 +110,9 @@ def test_build_makeflags(task_ahriman: Task, mocker: MockerFixture) -> None:
task_ahriman.build(local) task_ahriman.build(local)
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"ahriman-archbuild", "ahriman-archbuild",
"-r", task_ahriman.repository_id.name, "-a", task_ahriman.repository_id.architecture, "-r", task_ahriman.repository_id.name,
"-a", task_ahriman.repository_id.architecture,
"-c", str(task_ahriman.devtools_configs),
"--", "-r", str(task_ahriman.paths.chroot), "--", "-r", str(task_ahriman.paths.chroot),
"--", "-D", str(task_ahriman.paths.archive), "--", "-D", str(task_ahriman.paths.archive),
"--", "--skippgpcheck", "--", "--skippgpcheck",
@@ -130,7 +136,9 @@ def test_build_dry_run(task_ahriman: Task, mocker: MockerFixture) -> None:
task_ahriman.build(local, dry_run=True) task_ahriman.build(local, dry_run=True)
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"ahriman-archbuild", "ahriman-archbuild",
"-r", task_ahriman.repository_id.name, "-a", task_ahriman.repository_id.architecture, "-r", task_ahriman.repository_id.name,
"-a", task_ahriman.repository_id.architecture,
"-c", str(task_ahriman.devtools_configs),
"--", "-r", str(task_ahriman.paths.chroot), "--", "-r", str(task_ahriman.paths.chroot),
"--", "-D", str(task_ahriman.paths.archive), "--", "-D", str(task_ahriman.paths.archive),
"--", "--skippgpcheck", "--", "--skippgpcheck",
+2
View File
@@ -0,0 +1,2 @@
[web]
host = $AHRIMAN_HOST
+4 -2
View File
@@ -80,7 +80,6 @@ FROM archlinux:base AS ahriman
# image configuration # image configuration
ENV AHRIMAN_ARCHITECTURE="x86_64" ENV AHRIMAN_ARCHITECTURE="x86_64"
ENV AHRIMAN_DEBUG="" ENV AHRIMAN_DEBUG=""
ENV AHRIMAN_FORCE_ROOT=""
ENV AHRIMAN_HOST="0.0.0.0" ENV AHRIMAN_HOST="0.0.0.0"
ENV AHRIMAN_MULTILIB="yes" ENV AHRIMAN_MULTILIB="yes"
ENV AHRIMAN_OUTPUT="" ENV AHRIMAN_OUTPUT=""
@@ -91,7 +90,6 @@ ENV AHRIMAN_POSTSETUP_COMMAND=""
ENV AHRIMAN_PRESETUP_COMMAND="" ENV AHRIMAN_PRESETUP_COMMAND=""
ENV AHRIMAN_REPOSITORY="aur" ENV AHRIMAN_REPOSITORY="aur"
ENV AHRIMAN_REPOSITORY_SERVER="" ENV AHRIMAN_REPOSITORY_SERVER=""
ENV AHRIMAN_REPOSITORY_ROOT="/var/lib/ahriman/ahriman"
ENV AHRIMAN_UNIX_SOCKET="" ENV AHRIMAN_UNIX_SOCKET=""
ENV AHRIMAN_USER="ahriman" ENV AHRIMAN_USER="ahriman"
ENV AHRIMAN_VALIDATE_CONFIGURATION="yes" ENV AHRIMAN_VALIDATE_CONFIGURATION="yes"
@@ -135,11 +133,15 @@ RUN find "/var/cache/pacman/pkg" "/var/lib/pacman/sync" -type "f,l" -delete && \
VOLUME ["/var/lib/ahriman"] VOLUME ["/var/lib/ahriman"]
# minimal runtime ahriman setup # minimal runtime ahriman setup
RUN systemd-machine-id-setup
COPY "docker/01-docker.ini" "/etc/ahriman.ini.d/01-docker.ini"
## FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container ## FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container
COPY "docker/systemd-nspawn.sh" "/usr/local/bin/systemd-nspawn" COPY "docker/systemd-nspawn.sh" "/usr/local/bin/systemd-nspawn"
## entrypoint setup ## entrypoint setup
COPY "docker/entrypoint.sh" "/usr/local/bin/entrypoint" COPY "docker/entrypoint.sh" "/usr/local/bin/entrypoint"
COPY "docker/entrypoint-web.sh" "/usr/local/bin/entrypoint-web" COPY "docker/entrypoint-web.sh" "/usr/local/bin/entrypoint-web"
USER ahriman
ENTRYPOINT ["entrypoint"] ENTRYPOINT ["entrypoint"]
# default command # default command
CMD ["repo-update", "--refresh"] CMD ["repo-update", "--refresh"]
+6 -1
View File
@@ -2,4 +2,9 @@
# Special workaround for running web service in github actions, must not be usually used in real environment, # Special workaround for running web service in github actions, must not be usually used in real environment,
# consider running web command explicitly instead # consider running web command explicitly instead
exec entrypoint web "$@" if (( EUID == 0 )); then
chown ahriman:ahriman /var/lib/ahriman
exec sudo -E -u ahriman -- entrypoint web "$@"
fi
exec entrypoint web "$@"
+1 -28
View File
@@ -3,30 +3,15 @@
set -e set -e
[ -n "$AHRIMAN_DEBUG" ] && set -x [ -n "$AHRIMAN_DEBUG" ] && set -x
# configuration tune
cat <<EOF > "/etc/ahriman.ini.d/01-docker.ini"
[repository]
root = $AHRIMAN_REPOSITORY_ROOT
[web]
host = $AHRIMAN_HOST
EOF
AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE") AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE")
AHRIMAN_DEFAULT_ARGS+=("--repository" "$AHRIMAN_REPOSITORY") AHRIMAN_DEFAULT_ARGS+=("--repository" "$AHRIMAN_REPOSITORY")
if [ -n "$AHRIMAN_OUTPUT" ]; then if [ -n "$AHRIMAN_OUTPUT" ]; then
AHRIMAN_DEFAULT_ARGS+=("--log-handler" "$AHRIMAN_OUTPUT") AHRIMAN_DEFAULT_ARGS+=("--log-handler" "$AHRIMAN_OUTPUT")
fi fi
# create repository root inside the [[mounted]] directory and set correct ownership
[ -d "$AHRIMAN_REPOSITORY_ROOT" ] || mkdir "$AHRIMAN_REPOSITORY_ROOT"
chown "$AHRIMAN_USER":"$AHRIMAN_USER" "$AHRIMAN_REPOSITORY_ROOT"
# create .gnupg directory which is required for keys # create .gnupg directory which is required for keys
AHRIMAN_GNUPG_HOME="$(getent passwd "$AHRIMAN_USER" | cut -d : -f 6)/.gnupg" AHRIMAN_GNUPG_HOME="$(getent passwd "$AHRIMAN_USER" | cut -d : -f 6)/.gnupg"
[ -d "$AHRIMAN_GNUPG_HOME" ] || mkdir -m700 "$AHRIMAN_GNUPG_HOME" [ -d "$AHRIMAN_GNUPG_HOME" ] || mkdir -m700 "$AHRIMAN_GNUPG_HOME"
chown "$AHRIMAN_USER":"$AHRIMAN_USER" "$AHRIMAN_GNUPG_HOME"
# run built-in setup command # run built-in setup command
AHRIMAN_SETUP_ARGS=("--build-as-user" "$AHRIMAN_USER") AHRIMAN_SETUP_ARGS=("--build-as-user" "$AHRIMAN_USER")
@@ -54,19 +39,7 @@ ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" service-setup "${AHRIMAN_SETUP_ARGS[@]}"
# validate configuration if set # validate configuration if set
[ -n "$AHRIMAN_VALIDATE_CONFIGURATION" ] && ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" service-config-validate --exit-code [ -n "$AHRIMAN_VALIDATE_CONFIGURATION" ] && ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" service-config-validate --exit-code
# create machine-id which is required by build tools
systemd-machine-id-setup &> /dev/null
# special workaround to emulate /bin/bash entrypoint if first argument starts with / # special workaround to emulate /bin/bash entrypoint if first argument starts with /
[[ "$1" =~ ^/.* ]] && exec "$@" [[ "$1" =~ ^/.* ]] && exec "$@"
# if AHRIMAN_FORCE_ROOT is set or command is unsafe we can run without sudo exec ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" "$@"
# otherwise we prepend executable by sudo command
if [ -n "$AHRIMAN_FORCE_ROOT" ]; then
AHRIMAN_EXECUTABLE=("ahriman")
elif ahriman help-commands-unsafe -- "$@" &> /dev/null; then
AHRIMAN_EXECUTABLE=("sudo" "-E" "-u" "$AHRIMAN_USER" "--" "ahriman")
else
AHRIMAN_EXECUTABLE=("ahriman")
fi
exec "${AHRIMAN_EXECUTABLE[@]}" "${AHRIMAN_DEFAULT_ARGS[@]}" "$@"
+1 -1
View File
@@ -116,7 +116,7 @@ Filesystem tree
The application supports two types of trees, one is for the legacy configuration (when there were no explicit repository name configuration available) and another one is the new-style tree. This document describes only new-style tree in order to avoid deprecated structures. The application supports two types of trees, one is for the legacy configuration (when there were no explicit repository name configuration available) and another one is the new-style tree. This document describes only new-style tree in order to avoid deprecated structures.
Having default root as ``/var/lib/ahriman`` (differs from container though), the directory structure is the following: Having default root as ``/var/lib/ahriman``, the directory structure is the following:
.. code-block:: .. code-block::
+12 -8
View File
@@ -22,6 +22,12 @@ In order to make data available outside of container, you would need to mount lo
docker run --privileged -v /path/to/local/repo:/var/lib/ahriman -v /path/to/overrides/overrides.ini:/etc/ahriman.ini.d/10-overrides.ini arcan1s/ahriman:latest docker run --privileged -v /path/to/local/repo:/var/lib/ahriman -v /path/to/overrides/overrides.ini:/etc/ahriman.ini.d/10-overrides.ini arcan1s/ahriman:latest
The volume must have correct rights, e.g.:
.. code-block:: shell
chown 643:643 /path/to/local/repo
The action can be specified during run, e.g.: The action can be specified during run, e.g.:
.. code-block:: shell .. code-block:: shell
@@ -59,19 +65,17 @@ The following environment variables are supported:
* ``AHRIMAN_ARCHITECTURE`` - architecture of the repository, default is ``x86_64``. * ``AHRIMAN_ARCHITECTURE`` - architecture of the repository, default is ``x86_64``.
* ``AHRIMAN_DEBUG`` - if set all commands will be logged to console. * ``AHRIMAN_DEBUG`` - if set all commands will be logged to console.
* ``AHRIMAN_FORCE_ROOT`` - force run ahriman as root instead of guessing by subcommand.
* ``AHRIMAN_HOST`` - host for the web interface, default is ``0.0.0.0``. * ``AHRIMAN_HOST`` - host for the web interface, default is ``0.0.0.0``.
* ``AHRIMAN_MULTILIB`` - if set (default) multilib repository will be used, disabled otherwise. * ``AHRIMAN_MULTILIB`` - if set (default) multilib repository will be used, disabled otherwise.
* ``AHRIMAN_OUTPUT`` - controls logging handler, e.g. ``syslog``, ``console``. The name must be found in logging configuration. Note that if ``syslog`` handler is used you will need to mount ``/dev/log`` inside container because it is not available there. * ``AHRIMAN_OUTPUT`` - controls logging handler, e.g. ``syslog``, ``console``. The name must be found in logging configuration. Note that if ``syslog`` handler is used you will need to mount ``/dev/log`` inside container because it is not available there.
* ``AHRIMAN_PACKAGER`` - packager name from which packages will be built, default is ``ahriman bot <ahriman@example.com>``. * ``AHRIMAN_PACKAGER`` - packager name from which packages will be built, default is ``ahriman bot <ahriman@example.com>``.
* ``AHRIMAN_PACMAN_MIRROR`` - override pacman mirror server if set. * ``AHRIMAN_PACMAN_MIRROR`` - override pacman mirror server if set.
* ``AHRIMAN_PORT`` - HTTP server port if any, default is empty. * ``AHRIMAN_PORT`` - HTTP server port if any, default is empty.
* ``AHRIMAN_POSTSETUP_COMMAND`` - if set, the command which will be called (as root) after the setup command, but before any other actions. * ``AHRIMAN_POSTSETUP_COMMAND`` - if set, the command which will be called after the setup command, but before any other actions.
* ``AHRIMAN_PRESETUP_COMMAND`` - if set, the command which will be called (as root) right before the setup command. * ``AHRIMAN_PRESETUP_COMMAND`` - if set, the command which will be called right before the setup command.
* ``AHRIMAN_REPOSITORY`` - repository name, default is ``aur``. * ``AHRIMAN_REPOSITORY`` - repository name, default is ``aur``.
* ``AHRIMAN_REPOSITORY_SERVER`` - optional override for the repository URL. Useful if you would like to download packages from remote instead of local filesystem. * ``AHRIMAN_REPOSITORY_SERVER`` - optional override for the repository URL. Useful if you would like to download packages from remote instead of local filesystem.
* ``AHRIMAN_REPOSITORY_ROOT`` - repository root. Because of filesystem rights it is required to override default repository root. By default, it uses ``ahriman`` directory inside ahriman's home, which can be passed as mount volume. * ``AHRIMAN_UNIX_SOCKET`` - full path to unix socket which is used by web server, default is empty. Note that more likely you would like to put it inside repository root directory (e.g. ``/var/lib/ahriman/ahriman-web.sock``) or to ``/run/ahriman``.
* ``AHRIMAN_UNIX_SOCKET`` - full path to unix socket which is used by web server, default is empty. Note that more likely you would like to put it inside ``AHRIMAN_REPOSITORY_ROOT`` directory (e.g. ``/var/lib/ahriman/ahriman/ahriman-web.sock``) or to ``/run/ahriman``.
* ``AHRIMAN_USER`` - ahriman user, usually must not be overwritten, default is ``ahriman``. * ``AHRIMAN_USER`` - ahriman user, usually must not be overwritten, default is ``ahriman``.
* ``AHRIMAN_VALIDATE_CONFIGURATION`` - if set (default) validate service configuration. * ``AHRIMAN_VALIDATE_CONFIGURATION`` - if set (default) validate service configuration.
@@ -99,7 +103,7 @@ For that you would need to have web container instance running forever; it can b
.. code-block:: shell .. code-block:: shell
docker run --privileged -p 8080:8080 -e AHRIMAN_PORT=8080 -e AHRIMAN_UNIX_SOCKET=/var/lib/ahriman/ahriman/ahriman-web.sock -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest docker run --privileged -p 8080:8080 -e AHRIMAN_PORT=8080 -e AHRIMAN_UNIX_SOCKET=/var/lib/ahriman/ahriman-web.sock -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
Note about ``AHRIMAN_PORT`` environment variable which is required in order to enable web service. An additional port bind by ``-p 8080:8080`` is required to pass docker port outside of container. Note about ``AHRIMAN_PORT`` environment variable which is required in order to enable web service. An additional port bind by ``-p 8080:8080`` is required to pass docker port outside of container.
@@ -109,7 +113,7 @@ If you are using ``AHRIMAN_UNIX_SOCKET`` variable, for every next container run
.. code-block:: shell .. code-block:: shell
docker run --privileged -e AHRIMAN_UNIX_SOCKET=/var/lib/ahriman/ahriman/ahriman-web.sock -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest docker run --privileged -e AHRIMAN_UNIX_SOCKET=/var/lib/ahriman/ahriman-web.sock -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
Otherwise, you would need to pass ``AHRIMAN_PORT`` and mount container network to the host system (``--net=host``), e.g.: Otherwise, you would need to pass ``AHRIMAN_PORT`` and mount container network to the host system (``--net=host``), e.g.:
@@ -128,7 +132,7 @@ In order to create configuration for additional repositories, the ``AHRIMAN_POST
.. code-block:: shell .. code-block:: shell
docker run --privileged -p 8080:8080 -e AHRIMAN_PORT=8080 -e AHRIMAN_UNIX_SOCKET=/var/lib/ahriman/ahriman/ahriman-web.sock -e AHRIMAN_POSTSETUP_COMMAND="ahriman --architecture x86_64 --repository aur-v2 service-setup --build-as-user ahriman --packager 'ahriman bot <ahriman@example.com>'" -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest docker run --privileged -p 8080:8080 -e AHRIMAN_PORT=8080 -e AHRIMAN_UNIX_SOCKET=/var/lib/ahriman/ahriman-web.sock -e AHRIMAN_POSTSETUP_COMMAND="ahriman --architecture x86_64 --repository aur-v2 service-setup --build-as-user ahriman --packager 'ahriman bot <ahriman@example.com>'" -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
The command above will also create configuration for the repository named ``aur-v2``. The command above will also create configuration for the repository named ``aur-v2``.
+11
View File
@@ -55,6 +55,13 @@ There are two possible ways to achieve same setup, by using docker container. Th
FROM arcan1s/ahriman:latest FROM arcan1s/ahriman:latest
#.
Switch to ``root`` user:
.. code-block:: dockerfile
USER root
#. #.
Init pacman keys. This command is required in order to populate distribution keys: Init pacman keys. This command is required in order to populate distribution keys:
@@ -78,12 +85,16 @@ There are two possible ways to achieve same setup, by using docker container. Th
FROM arcan1s/ahriman:latest FROM arcan1s/ahriman:latest
USER root
RUN pacman-key --init RUN pacman-key --init
RUN pacman --noconfirm -Sy wget RUN pacman --noconfirm -Sy wget
RUN wget https://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.2-any.pkg.tar.zst && pacman --noconfirm -U devtools-20221208-1.2-any.pkg.tar.zst RUN wget https://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.2-any.pkg.tar.zst && pacman --noconfirm -U devtools-20221208-1.2-any.pkg.tar.zst
RUN wget https://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20230705-1.0-any.pkg.tar.zst && pacman --noconfirm -U archlinux32-keyring-20230705-1.0-any.pkg.tar.zst RUN wget https://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20230705-1.0-any.pkg.tar.zst && pacman --noconfirm -U archlinux32-keyring-20230705-1.0-any.pkg.tar.zst
USER ahriman
#. #.
After that you can build you own container, e.g.: After that you can build you own container, e.g.:
+54
View File
@@ -0,0 +1,54 @@
To 2.22.0
---------
This release stores newly generated configuration files in the repository root and changes the docker image to run as the ``ahriman`` user. Existing system-wide configuration files remain supported, so regular installations do not require manual intervention. Docker installations require data migration.
Regular installation
^^^^^^^^^^^^^^^^^^^^
Newly generated ahriman and devtools configuration files are stored below ``/var/lib/ahriman/.config/ahriman`` instead of system-wide configuration directories. Existing configurations continue to work without any changes.
However, it is recommended to migrate to the new configuration schema by doing the following steps:
#.
Stop all ahriman services.
#.
Remove the old generated configuration files. For example, for repository ``aur`` and architecture ``x86_64``:
.. code-block:: shell
sudo rm /etc/ahriman.ini.d/00-setup-overrides-x86_64-aur.ini
sudo rm /usr/share/devtools/pacman.conf.d/aur-x86_64.conf
Repeat this step for every configured repository. Do not remove manually maintained configuration overrides.
#.
Run setup command (i.e. ``ahriman service-setup``) again with the same arguments as used before as the ``ahriman`` user.
#.
Start the services again.
Docker installation
^^^^^^^^^^^^^^^^^^^
The repository root inside the Docker image has changed from ``/var/lib/ahriman/ahriman`` to ``/var/lib/ahriman``. Existing repository contents must therefore be moved one directory level up, and the volume must be owned by the ``ahriman`` user.
#.
Stop all containers using the repository volume and create a backup.
#.
Run a one-off container which mounts the existing volume. Replace ``VOLUME`` with the named volume or bind mount used by the installation:
.. code-block:: shell
docker run --rm --user root --entrypoint bash \
--volume VOLUME:/var/lib/ahriman \
arcan1s/ahriman:latest \
-c 'find /var/lib/ahriman/ahriman -mindepth 1 -maxdepth 1 -exec mv -t /var/lib/ahriman -- {} + && rmdir /var/lib/ahriman/ahriman && chown ahriman:ahriman /var/lib/ahriman'
#.
Update custom configuration and container arguments which refer to ``/var/lib/ahriman/ahriman``. The new path is ``/var/lib/ahriman``.
#.
Start the containers again.
+1
View File
@@ -12,3 +12,4 @@ Upgrades to breakpoints
2.9.0 2.9.0
2.12.0 2.12.0
2.16.0 2.16.0
2.22.0
+28 -5
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -8,9 +25,9 @@ services:
AHRIMAN_OUTPUT: console AHRIMAN_OUTPUT: console
AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD} AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD}
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | sudo -u ahriman ahriman user-add demo -R full AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | ahriman user-add demo -R full
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman.sock
configs: configs:
- source: service - source: service
@@ -22,8 +39,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
healthcheck: healthcheck:
test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info
@@ -37,6 +56,10 @@ services:
ports: ports:
- 8080:80 - 8080:80
depends_on:
backend:
condition: service_healthy
configs: configs:
- source: nginx - source: nginx
target: /etc/nginx/conf.d/default.conf target: /etc/nginx/conf.d/default.conf
@@ -57,7 +80,7 @@ services:
AHRIMAN_DEBUG: yes AHRIMAN_DEBUG: yes
AHRIMAN_OUTPUT: console AHRIMAN_OUTPUT: console
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman.sock
volumes: volumes:
- type: volume - type: volume
+21 -2
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -12,8 +29,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
command: repo-daemon command: repo-daemon
+27 -4
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -8,9 +25,9 @@ services:
AHRIMAN_OUTPUT: console AHRIMAN_OUTPUT: console
AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD} AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD}
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | sudo -u ahriman ahriman user-add demo -R full AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | ahriman user-add demo -R full
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman.sock
configs: configs:
- source: service - source: service
@@ -22,8 +39,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
healthcheck: healthcheck:
test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info
@@ -37,6 +56,10 @@ services:
ports: ports:
- 8080:80 - 8080:80
depends_on:
backend:
condition: service_healthy
configs: configs:
- source: nginx - source: nginx
target: /etc/nginx/conf.d/default.conf target: /etc/nginx/conf.d/default.conf
+28 -5
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -8,9 +25,9 @@ services:
AHRIMAN_OUTPUT: console AHRIMAN_OUTPUT: console
AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD} AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD}
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | sudo -u ahriman ahriman user-add demo -R full AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | ahriman user-add demo -R full
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman.sock
configs: configs:
- source: service - source: service
@@ -22,8 +39,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
healthcheck: healthcheck:
test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info
@@ -37,6 +56,10 @@ services:
ports: ports:
- 8080:80 - 8080:80
depends_on:
backend:
condition: service_healthy
configs: configs:
- source: nginx - source: nginx
target: /etc/nginx/conf.d/default.conf target: /etc/nginx/conf.d/default.conf
@@ -62,7 +85,7 @@ services:
AHRIMAN_OUTPUT: console AHRIMAN_OUTPUT: console
AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD} AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD}
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | sudo -u ahriman ahriman user-add demo -R full AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | ahriman user-add demo -R full
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
AHRIMAN_REPOSITORY_SERVER: http://frontend/repo/$$repo/$$arch AHRIMAN_REPOSITORY_SERVER: http://frontend/repo/$$repo/$$arch
+4
View File
@@ -2,8 +2,12 @@ FROM arcan1s/ahriman:edge
ENV ARCH32_KEYRING_VERSION="20231126-1.0" ENV ARCH32_KEYRING_VERSION="20231126-1.0"
USER root
RUN pacman-key --init RUN pacman-key --init
RUN pacman -Sy --noconfirm wget && \ RUN pacman -Sy --noconfirm wget && \
wget -nv https://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-${ARCH32_KEYRING_VERSION}-any.pkg.tar.zst && \ wget -nv https://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-${ARCH32_KEYRING_VERSION}-any.pkg.tar.zst && \
pacman -U --noconfirm archlinux32-keyring-${ARCH32_KEYRING_VERSION}-any.pkg.tar.zst pacman -U --noconfirm archlinux32-keyring-${ARCH32_KEYRING_VERSION}-any.pkg.tar.zst
USER ahriman
+27 -4
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: ahriman-i686 image: ahriman-i686
build: . build: .
@@ -12,9 +29,9 @@ services:
AHRIMAN_PACMAN_MIRROR: https://de.mirror.archlinux32.org/$$arch/$$repo AHRIMAN_PACMAN_MIRROR: https://de.mirror.archlinux32.org/$$arch/$$repo
AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD} AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD}
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | sudo -u ahriman ahriman user-add demo -R full AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | ahriman user-add demo -R full
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman.sock
configs: configs:
- source: makepkg - source: makepkg
@@ -30,8 +47,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
healthcheck: healthcheck:
test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info
@@ -45,6 +64,10 @@ services:
ports: ports:
- 8080:80 - 8080:80
depends_on:
backend:
condition: service_healthy
configs: configs:
- source: nginx - source: nginx
target: /etc/nginx/conf.d/default.conf target: /etc/nginx/conf.d/default.conf
+21 -2
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -16,8 +33,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
command: repo-report command: repo-report
+27 -4
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -8,10 +25,10 @@ services:
AHRIMAN_OUTPUT: console AHRIMAN_OUTPUT: console
AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD} AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD}
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | sudo -u ahriman ahriman user-add demo -R full AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | ahriman user-add demo -R full
AHRIMAN_PRESETUP_COMMAND: ahriman --architecture x86_64 --repository another-demo service-setup --build-as-user ahriman --packager 'ahriman bot <ahriman@example.com>' AHRIMAN_PRESETUP_COMMAND: ahriman --architecture x86_64 --repository another-demo service-setup --build-as-user ahriman --packager 'ahriman bot <ahriman@example.com>'
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman.sock
configs: configs:
- source: service - source: service
@@ -23,8 +40,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
healthcheck: healthcheck:
test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info
@@ -38,6 +57,10 @@ services:
ports: ports:
- 8080:80 - 8080:80
depends_on:
backend:
condition: service_healthy
configs: configs:
- source: nginx - source: nginx
target: /etc/nginx/conf.d/default.conf target: /etc/nginx/conf.d/default.conf
+27 -4
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -9,9 +26,9 @@ services:
AHRIMAN_OAUTH_CLIENT_SECRET: ${AHRIMAN_OAUTH_CLIENT_SECRET} AHRIMAN_OAUTH_CLIENT_SECRET: ${AHRIMAN_OAUTH_CLIENT_SECRET}
AHRIMAN_OUTPUT: console AHRIMAN_OUTPUT: console
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_POSTSETUP_COMMAND: sudo -u ahriman ahriman user-add ${AHRIMAN_OAUTH_USER} -R full -p "" AHRIMAN_POSTSETUP_COMMAND: ahriman user-add ${AHRIMAN_OAUTH_USER} -R full -p ""
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman.sock
configs: configs:
- source: service - source: service
@@ -21,8 +38,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
healthcheck: healthcheck:
test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info
@@ -36,6 +55,10 @@ services:
ports: ports:
- 8080:80 - 8080:80
depends_on:
backend:
condition: service_healthy
configs: configs:
- source: nginx - source: nginx
target: /etc/nginx/conf.d/default.conf target: /etc/nginx/conf.d/default.conf
+26 -3
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -10,7 +27,7 @@ services:
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_PRESETUP_COMMAND: useradd -d / -G wheel -M demo; (cat /run/secrets/password; echo; cat /run/secrets/password) | passwd demo AHRIMAN_PRESETUP_COMMAND: useradd -d / -G wheel -M demo; (cat /run/secrets/password; echo; cat /run/secrets/password) | passwd demo
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman.sock
configs: configs:
- source: service - source: service
@@ -22,8 +39,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
healthcheck: healthcheck:
test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info
@@ -37,6 +56,10 @@ services:
ports: ports:
- 8080:80 - 8080:80
depends_on:
backend:
condition: service_healthy
configs: configs:
- source: nginx - source: nginx
target: /etc/nginx/conf.d/default.conf target: /etc/nginx/conf.d/default.conf
+21 -2
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -16,8 +33,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
frontend: frontend:
image: nginx image: nginx
+22 -3
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -6,7 +23,7 @@ services:
environment: environment:
AHRIMAN_DEBUG: yes AHRIMAN_DEBUG: yes
AHRIMAN_OUTPUT: console AHRIMAN_OUTPUT: console
AHRIMAN_POSTSETUP_COMMAND: sudo -u ahriman gpg --import /run/secrets/key AHRIMAN_POSTSETUP_COMMAND: gpg --import /run/secrets/key
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
configs: configs:
@@ -19,8 +36,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
command: repo-daemon command: repo-daemon
+27 -4
View File
@@ -1,4 +1,21 @@
services: services:
volume-init:
image: arcan1s/ahriman:edge
user: root
entrypoint: [
"chown",
]
command: [
"ahriman:ahriman",
"/var/lib/ahriman",
]
volumes:
- type: volume
source: repository
target: /var/lib/ahriman
backend: backend:
image: arcan1s/ahriman:edge image: arcan1s/ahriman:edge
privileged: true privileged: true
@@ -8,9 +25,9 @@ services:
AHRIMAN_OUTPUT: console AHRIMAN_OUTPUT: console
AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD} AHRIMAN_PASSWORD: ${AHRIMAN_PASSWORD}
AHRIMAN_PORT: 8080 AHRIMAN_PORT: 8080
AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | sudo -u ahriman ahriman user-add demo -R full AHRIMAN_POSTSETUP_COMMAND: (cat /run/secrets/password; echo; cat /run/secrets/password) | ahriman user-add demo -R full
AHRIMAN_REPOSITORY: ahriman-demo AHRIMAN_REPOSITORY: ahriman-demo
AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman/ahriman.sock AHRIMAN_UNIX_SOCKET: /var/lib/ahriman/ahriman.sock
configs: configs:
- source: service - source: service
@@ -22,8 +39,10 @@ services:
- type: volume - type: volume
source: repository source: repository
target: /var/lib/ahriman target: /var/lib/ahriman
volume:
nocopy: true depends_on:
volume-init:
condition: service_completed_successfully
healthcheck: healthcheck:
test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info test: curl --fail --silent --output /dev/null http://backend:8080/api/v1/info
@@ -37,6 +56,10 @@ services:
ports: ports:
- 8080:80 - 8080:80
depends_on:
backend:
condition: service_healthy
configs: configs:
- source: nginx - source: nginx
target: /etc/nginx/conf.d/default.conf target: /etc/nginx/conf.d/default.conf
+1
View File
@@ -23,6 +23,7 @@ allow_read_only = no
[build] [build]
archbuild_flags = archbuild_flags =
devtools_configs = .
devtools_wrapper = ahriman-archbuild devtools_wrapper = ahriman-archbuild
ignore_packages = ignore_packages =
makechrootpkg_flags = makechrootpkg_flags =