From cf96acda929721f65428214407060795d8ea9cf3 Mon Sep 17 00:00:00 2001 From: Djeex Date: Sun, 23 Aug 2026 14:14:54 +0200 Subject: [PATCH 1/3] Run container as non-root via PUID/PGID with a startup entrypoint banner and logs --- Dockerfile | 7 +-- README.md | 4 ++ blocklist_scheduler.py | 2 +- docker-compose.yml | 2 + entrypoint.sh | 105 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 4 deletions(-) create mode 100755 entrypoint.sh diff --git a/Dockerfile b/Dockerfile index d451cea..3400552 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.14.7-alpine AS base ENV TZ=Europe/Paris -RUN apk add --no-cache tzdata curl \ +RUN apk add --no-cache tzdata curl su-exec \ && cp /usr/share/zoneinfo/$TZ /etc/localtime \ && echo $TZ > /etc/timezone @@ -11,7 +11,8 @@ WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt -COPY blocklist_scheduler.py . +COPY blocklist_scheduler.py entrypoint.sh VERSION ./ +RUN chmod +x entrypoint.sh FROM base AS test RUN pip install --no-cache-dir pytest==9.1.1 @@ -19,4 +20,4 @@ COPY tests/ tests/ COPY pytest.ini . FROM base -ENTRYPOINT ["python3", "blocklist_scheduler.py"] +ENTRYPOINT ["./entrypoint.sh"] diff --git a/README.md b/README.md index a9f93a9..8a8415e 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ | Variable | Description | Example | Possible Values | |--------------------------|--------------------------------------------------------------------------|-----------------------------|---------------------------------------------| +| `PUID` | User ID the process runs as (drops root at startup) | `1000` | Any valid numeric UID | +| `PGID` | Group ID the process runs as | `1000` | Any valid numeric GID | | `TZ` | Timezone of the container to correctly schedule updates | `Europe/Paris` | Any valid timezone (e.g., `UTC`, `America/New_York`, etc.) | | `BLOCK_COUNTRIES` | List of country codes for CIDR lists, separated by commas. You can also define an exclude list (all countries except the specified ones) by prefixing each country code with !. Mixing inclusion and exclusion codes is not supported. | including list : `cn,ru,ir`, excluding list : `!cn,!ru,!ir` | ISO 2-letter country codes | | `BLOCKLIST_CRON_TYPE` | Scheduling type: `daily` or `weekly` | `daily` | `daily`, `weekly` | @@ -64,6 +66,8 @@ container_name: adguard-cidre restart: unless-stopped environment: + - PUID=1000 # user id the process runs as, matches ownership of the /adguard mount + - PGID=1000 # group id the process runs as - TZ=Europe/Paris # change to your timezone - BLOCK_COUNTRIES=cn,ru # choose countries listed IP to block. Full lists here https://github.com/vulnebify/cidre/tree/main/output/cidr/ipv4 - BLOCKLIST_CRON_TYPE=daily # daily or weekly diff --git a/blocklist_scheduler.py b/blocklist_scheduler.py index 5129dd8..fe5a839 100644 --- a/blocklist_scheduler.py +++ b/blocklist_scheduler.py @@ -11,7 +11,7 @@ from pathlib import Path logging.basicConfig( level=logging.INFO, - format='[blocklist] %(levelname)s: %(message)s', + format="%(asctime)s [%(levelname)s] %(message)s", stream=sys.stdout, ) diff --git a/docker-compose.yml b/docker-compose.yml index 29766a0..2e317f7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,8 @@ services: container_name: adguard-cidre restart: unless-stopped environment: + - PUID=1000 # user id the process runs as, matches ownership of the /adguard mount + - PGID=1000 # group id the process runs as - TZ=Europe/Paris # change to your timezone - BLOCK_COUNTRIES=cn,ru # choose countries listed IP to block. Full lists here https://github.com/vulnebify/cidre/tree/main/output/cidr/ipv4 - BLOCKLIST_CRON_TYPE=daily # daily or weekly diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..d4b3331 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,105 @@ +#!/bin/sh +set -e + +CYAN="\033[1;36m" +NC="\033[0m" + +log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*"; } +fail() { echo "$(date '+%Y-%m-%d %H:%M:%S') [!] $*" >&2; exit 1; } + +print_banner() { + version=$(cat VERSION 2>/dev/null || echo "unknown") + title="AdGuard CIDRe - Version ${version}" + lines="Source: https://git.djeex.fr/Djeex/adguard-cidre +Mirror: https://github.com/Djeex/adguard-cidre" + + width=${#title} + old_ifs=$IFS + IFS=' +' + for l in $lines; do + [ ${#l} -gt "$width" ] && width=${#l} + done + IFS=$old_ifs + width=$((width + 2)) + + border="" + i=0 + while [ "$i" -lt "$width" ]; do + border="${border}─" + i=$((i + 1)) + done + printf "${CYAN}╭%s╮${NC}\n" "$border" + + total_pad=$((width - ${#title})) + left=$((total_pad / 2)) + right=$((total_pad - left)) + printf "${CYAN}│${NC}%*s%s%*s${CYAN}│${NC}\n" "$left" "" "$title" "$right" "" + + printf "${CYAN}├%s┤${NC}\n" "$border" + + IFS=' +' + for l in $lines; do + printf "${CYAN}│${NC} %-*s${CYAN}│${NC}\n" "$((width - 1))" "$l" + done + IFS=$old_ifs + + printf "${CYAN}╰%s╯${NC}\n" "$border" +} + +print_banner + +PUID=${PUID:-911} +PGID=${PGID:-911} + +case "$PGID" in + ''|*[!0-9]*) fail "PGID '$PGID' is not a valid numeric group id." ;; +esac +case "$PUID" in + ''|*[!0-9]*) fail "PUID '$PUID' is not a valid numeric user id." ;; +esac + +[ -d /adguard ] || fail "/adguard is not mounted — check the volume mapping in docker-compose.yml." + +log "[i] Requested PUID=$PUID, PGID=$PGID" + +log "[~] Checking group for GID $PGID..." +GROUP_NAME=$(getent group "$PGID" | cut -d: -f1 || true) +if [ -z "$GROUP_NAME" ]; then + log "[→] No existing group with GID $PGID, creating 'appgroup'." + addgroup -g "$PGID" appgroup || fail "Failed to create group with GID $PGID (addgroup exited $?)." + GROUP_NAME=appgroup +else + log "[i] Reusing existing group '$GROUP_NAME' (GID $PGID)." +fi +log "[✓] Group ready: $GROUP_NAME" + +log "[~] Checking user for UID $PUID..." +USER_NAME=$(getent passwd "$PUID" | cut -d: -f1 || true) +if [ -z "$USER_NAME" ]; then + log "[→] No existing user with UID $PUID, creating 'appuser'." + adduser -D -u "$PUID" -G "$GROUP_NAME" appuser || fail "Failed to create user with UID $PUID (adduser exited $?)." + USER_NAME=appuser +else + log "[i] Reusing existing user '$USER_NAME' (UID $PUID)." +fi +log "[✓] User ready: $USER_NAME" + +# Grant write access to the shared AdGuard config directory and to the files +# this script manages, without touching anything else AdGuardHome owns in +# there (its own db/certs/stats). AdGuardHome itself runs as root, so this is +# a one-way grant: it keeps full access regardless of what we chown here. +log "[~] Setting ownership of /adguard to $USER_NAME:$GROUP_NAME..." +chown "$USER_NAME:$GROUP_NAME" /adguard || fail "chown on /adguard failed — check that the host directory permissions allow it." +log "[✓] Ownership set on /adguard" + +for f in AdGuardHome.yaml AdGuardHome.yaml.first-start.bak AdGuardHome.yaml.last-update.bak AdGuardHome.yaml.tmp; do + if [ -e "/adguard/$f" ]; then + chown "$USER_NAME:$GROUP_NAME" "/adguard/$f" || fail "chown on /adguard/$f failed." + log "[✓] chown OK: /adguard/$f" + fi +done + +log "[→] Dropping privileges to $USER_NAME:$GROUP_NAME and starting blocklist_scheduler.py" +exec su-exec "$USER_NAME:$GROUP_NAME" python3 blocklist_scheduler.py "$@" -- 2.54.0 From d13f79ed82245f63bd0f92336ac8498c38eb8a17 Mon Sep 17 00:00:00 2001 From: Djeex Date: Sun, 23 Aug 2026 14:11:50 +0200 Subject: [PATCH 2/3] Bump version to 1.5.0 for non-root support --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 347f583..bc80560 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.4.1 +1.5.0 -- 2.54.0 From 620d00134c878848667553988eac9b9997fdc4a5 Mon Sep 17 00:00:00 2001 From: Djeex Date: Sun, 23 Aug 2026 15:11:22 +0200 Subject: [PATCH 3/3] Move environment configuration to a .env file --- .env | 22 ++++++++++++++++++++++ README.md | 9 +++++---- docker-compose.yml | 18 +++++++++--------- 3 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..a8c4f10 --- /dev/null +++ b/.env @@ -0,0 +1,22 @@ +# User/group id the process runs as, matches ownership of the /adguard mount +PUID=1000 +PGID=1000 + +# Timezone of the container +TZ=Europe/Paris + +# Country codes for CIDR lists, comma separated. Prefix with ! to exclude instead of include. +# Full lists here: https://github.com/vulnebify/cidre/tree/main/output/cidr/ipv4 +BLOCK_COUNTRIES=cn,ru + +# Scheduling: daily or weekly +BLOCKLIST_CRON_TYPE=daily +# If weekly, choose the day: mon, tue, wed, thu, fri, sat, sun +BLOCKLIST_CRON_DAY=mon +# Time of day to run the update, 24h HH:MM format +BLOCKLIST_CRON_TIME=06:00 + +# Docker API URL used to restart the AdGuard container (via socket-proxy) +DOCKER_API_URL=http://socket-proxy-adguard:2375 +# Name of the AdGuard Home container to restart +ADGUARD_CONTAINER_NAME=adguardhome diff --git a/README.md b/README.md index 8a8415e..d230913 100644 --- a/README.md +++ b/README.md @@ -125,11 +125,12 @@ git clone https://git.djeex.fr/Djeex/adguard-cidre cd adguard-cidre ``` -2. **Modify docker-compose.yml** +2. **Edit the `.env` file** -- Set `BLOCK_COUNTRIES` environment variable with the countries you want to block. -- Adjust `BLOCKLIST_CRON` variables if you want a different update frequency. -- Bind mount your adguard configuration folder (wich contains `AdGuardHome.yaml`) to `/adguard` +- A `.env` file is included at the repo root with all environment variables (see [Environment Variables](#environment-variables)). Edit values there instead of `docker-compose.yml`. +- Set `BLOCK_COUNTRIES` with the countries you want to block. +- Adjust `BLOCKLIST_CRON_*` variables if you want a different update frequency. +- Bind mount your adguard configuration folder (wich contains `AdGuardHome.yaml`) to `/adguard` in `docker-compose.yml`. - (optionnally) create and edit `manually_blocked_ips.conf` file in your adguard configuration folder to add other IPs you want to block. Only valid IP or CIDR entries will be processed, for exemple : ```bash diff --git a/docker-compose.yml b/docker-compose.yml index 2e317f7..350eb80 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,16 +5,16 @@ services: container_name: adguard-cidre restart: unless-stopped environment: - - PUID=1000 # user id the process runs as, matches ownership of the /adguard mount - - PGID=1000 # group id the process runs as - - TZ=Europe/Paris # change to your timezone - - BLOCK_COUNTRIES=cn,ru # choose countries listed IP to block. Full lists here https://github.com/vulnebify/cidre/tree/main/output/cidr/ipv4 - - BLOCKLIST_CRON_TYPE=daily # daily or weekly + - PUID=${PUID} # user id the process runs as, matches ownership of the /adguard mount + - PGID=${PGID} # group id the process runs as + - TZ=${TZ} # change to your timezone + - BLOCK_COUNTRIES=${BLOCK_COUNTRIES} # choose countries listed IP to block. Full lists here https://github.com/vulnebify/cidre/tree/main/output/cidr/ipv4 + - BLOCKLIST_CRON_TYPE=${BLOCKLIST_CRON_TYPE} # daily or weekly # if weekly, choose the day - # - BLOCKLIST_CRON_DAY=mon - - BLOCKLIST_CRON_TIME=06:00 - - DOCKER_API_URL=http://socket-proxy-adguard:2375 # docker socket proxy - - ADGUARD_CONTAINER_NAME=adguardhome # adguard container name + - BLOCKLIST_CRON_DAY=${BLOCKLIST_CRON_DAY} + - BLOCKLIST_CRON_TIME=${BLOCKLIST_CRON_TIME} + - DOCKER_API_URL=${DOCKER_API_URL} # docker socket proxy + - ADGUARD_CONTAINER_NAME=${ADGUARD_CONTAINER_NAME} # adguard container name volumes: - /path/to/adguard/confdir:/adguard -- 2.54.0