diff --git a/archivebox/config/permissions.py b/archivebox/config/permissions.py index a1136fbb..be28dd57 100644 --- a/archivebox/config/permissions.py +++ b/archivebox/config/permissions.py @@ -1,6 +1,11 @@ __package__ = 'archivebox.config' import os +import pwd +import sys + +from rich import print + from pathlib import Path from contextlib import contextmanager @@ -27,16 +32,29 @@ USER: str = Path('~').expanduser().resolve().name IS_ROOT = RUNNING_AS_UID == 0 IN_DOCKER = os.environ.get('IN_DOCKER', False) in ('1', 'true', 'True', 'TRUE', 'yes') -os.environ.setdefault('PUID', str(DATA_DIR_UID or RUNNING_AS_UID or DEFAULT_PUID)) -os.environ.setdefault('PGID', str(DATA_DIR_GID or RUNNING_AS_GID or DEFAULT_PGID)) +FALLBACK_UID = RUNNING_AS_UID +FALLBACK_GID = RUNNING_AS_GID +if RUNNING_AS_UID == 0: + try: + # if we are running as root it's really hard to figure out what the correct archivebox user should be + # as a last resort instead of setting DATA_DIR ownership to 0:0 (which breaks it for non-root users) + # check if 911:911 archivebox user exists on host system, and use it instead of 0 + import pwd + if pwd.getpwuid(DEFAULT_PUID).pw_name == 'archivebox': + FALLBACK_UID = DEFAULT_PUID + FALLBACK_GID = DEFAULT_PGID + except Exception: + pass + + +os.environ.setdefault('PUID', str(DATA_DIR_UID or EUID or RUNNING_AS_UID or FALLBACK_UID)) +os.environ.setdefault('PGID', str(DATA_DIR_GID or EGID or RUNNING_AS_GID or FALLBACK_GID)) ARCHIVEBOX_USER = int(os.environ['PUID']) ARCHIVEBOX_GROUP = int(os.environ['PGID']) - if not USER: try: # alternative method 1 to get username - import pwd USER = pwd.getpwuid(ARCHIVEBOX_USER).pw_name except Exception: pass @@ -55,6 +73,14 @@ if not USER: USER = os.getlogin() or 'archivebox' except Exception: USER = 'archivebox' + +ARCHIVEBOX_USER_EXISTS = False +try: + pwd.getpwuid(ARCHIVEBOX_USER) + ARCHIVEBOX_USER_EXISTS = True +except Exception: + ARCHIVEBOX_USER_EXISTS = False + ############################################################################################# @@ -64,7 +90,7 @@ def drop_privileges(): # always run archivebox as the user that owns the data dir, never as root if os.getuid() == 0: # drop permissions to the user that owns the data dir / provided PUID - if os.geteuid() != ARCHIVEBOX_USER: + if os.geteuid() != ARCHIVEBOX_USER and ARCHIVEBOX_USER != 0 and ARCHIVEBOX_USER_EXISTS: os.seteuid(ARCHIVEBOX_USER) # try: @@ -77,6 +103,8 @@ def drop_privileges(): # with SudoPermission(uid=0, fallback=True): # os.system(f'chown -R :{ARCHIVEBOX_GROUP} "{PACKAGE_DIR}"') # if we need sudo (e.g. for installing dependencies) code should use SudoPermissions() context manager to regain root + if ARCHIVEBOX_USER == 0 or not ARCHIVEBOX_USER_EXISTS: + print('[yellow]:warning: Running as root is not recommended and may make your [blue]DATA_DIR[/blue] inaccessible to other users on your system.[/yellow]', file=sys.stderr) @contextmanager diff --git a/archivebox/main.py b/archivebox/main.py index a3caea3b..5675f564 100755 --- a/archivebox/main.py +++ b/archivebox/main.py @@ -219,8 +219,8 @@ def version(quiet: bool=False, OUTPUT_IS_REMOTE_FS = CONSTANTS.DATA_LOCATIONS.DATA_DIR.is_mount or CONSTANTS.DATA_LOCATIONS.ARCHIVE_DIR.is_mount DATA_DIR_STAT = CONSTANTS.DATA_DIR.stat() prnt( - f'EUID={os.geteuid()} UID={RUNNING_AS_UID} PUID={ARCHIVEBOX_USER} FS_UID={DATA_DIR_STAT.st_uid}', - f'EGID={os.getegid()} GID={RUNNING_AS_GID} PGID={ARCHIVEBOX_GROUP} FS_GID={DATA_DIR_STAT.st_gid}', + f'EUID={os.geteuid()}:{os.getegid()} UID={RUNNING_AS_UID}:{RUNNING_AS_GID} PUID={ARCHIVEBOX_USER}:{ARCHIVEBOX_GROUP}', + f'FS_UID={DATA_DIR_STAT.st_uid}:{DATA_DIR_STAT.st_gid}', f'FS_PERMS={STORAGE_CONFIG.OUTPUT_PERMISSIONS}', f'FS_ATOMIC={STORAGE_CONFIG.ENFORCE_ATOMIC_WRITES}', f'FS_REMOTE={OUTPUT_IS_REMOTE_FS}', diff --git a/archivebox/vendor/pydantic-pkgr b/archivebox/vendor/pydantic-pkgr index 88892cc7..b1c4fcb3 160000 --- a/archivebox/vendor/pydantic-pkgr +++ b/archivebox/vendor/pydantic-pkgr @@ -1 +1 @@ -Subproject commit 88892cc7b8d8a6424d712b424ebbc1a1be9ce4dc +Subproject commit b1c4fcb349e6d8fa2772e96c80549648cce3d9a9 diff --git a/pyproject.toml b/pyproject.toml index f943e2d2..645e43e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "archivebox" -version = "0.8.5rc9" +version = "0.8.5rc10" requires-python = ">=3.10" description = "Self-hosted internet archiving solution." authors = [{name = "Nick Sweeting", email = "pyproject.toml@archivebox.io"}] @@ -79,7 +79,7 @@ dependencies = [ "base32-crockford==0.3.0", "platformdirs>=4.3.6", # "pocket@git+https://github.com/tapanpandita/pocket.git@v0.3.7", - "pydantic-pkgr>=0.4.8", + "pydantic-pkgr>=0.4.9", ############# Plugin Dependencies ################ "sonic-client>=1.0.0", "yt-dlp>=2024.8.6", # for: media" diff --git a/uv.lock b/uv.lock index 3a97730f..f44fb3dd 100644 --- a/uv.lock +++ b/uv.lock @@ -41,7 +41,7 @@ wheels = [ [[package]] name = "archivebox" -version = "0.8.5rc9" +version = "0.8.5rc10" source = { editable = "." } dependencies = [ { name = "atomicwrites" },