如何设置 Alpine Linux 镜像

来自 Alpine Linux

简介

本文档描述了如何设置 Alpine Linux 镜像,并通过 http 和 rsync 使其可用。

我们将

  • 创建存放镜像的目录
  • 设置一个 cron 任务,每小时与主镜像同步
  • 设置 lighttpd 用于 http 访问
  • 设置 rsync,以便其他镜像可以从您这里 rsync

确保您有足够的磁盘空间。

当前 (2024-12-31) 磁盘使用量 (GB)

edge v3.0 v3.1 v3.2 v3.3 v3.4 v3.5 v3.6 v3.7 v3.8 v3.9 v3.10 v3.11 v3.12 v3.13 v3.14 v3.15 v3.16 v3.17 v3.18 v3.19 v3.20 v3.21 总计
499 17 18 15 21 25 27 45 43 59 73 92 126 148 156 181 194 209 244 298 288 361 400 3538

用于计算大小的脚本

#!/bin/sh

total=0
dest="$(mktemp -d)"

for dir in edge v3.0 v3.1 v3.2 v3.3 v3.4 v3.5 v3.6 v3.7 v3.8 v3.9 v3.10 v3.11 v3.12 v3.13 v3.14 v3.15 v3.16 v3.17 v3.18 v3.19 v3.20 v3.21; do
    old_total="$total"
    src="rsync://rsync.alpinelinux.org/alpine/$dir/"
    size=$(rsync -a -n --stats "$src" "$dest" | grep '^Total file size' | tr -d ',' | awk '{ print $4 }')
    total=$(( old_total + size ))
    echo "$dir: $size" | awk '{ print $1 sprintf("%.1f", $2/1073741824) }'
done

echo "total: $total" | awk '{ print $1 sprintf("%.1f", $2/1073741824) }'
rm -r "$dest"

设置 cron 任务

安装 rsync,它将用于从主镜像同步。

apk add rsync

将以下文件另存为 /etc/periodic/hourly/alpine-mirror

#!/bin/sh

# make sure we never run 2 rsync at the same time
lockfile="/tmp/alpine-mirror.lock"
if [ -z "$flock" ] ; then
  exec env flock=1 flock -n $lockfile "$0" "$@"
fi

src=rsync://rsync.alpinelinux.org/alpine/ 
dest=/var/www/localhost/htdocs/alpine/

# uncomment this to exclude old v2.x branches
#exclude="--exclude v2.*"

mkdir -p "$dest"
/usr/bin/rsync \
        --archive \
        --update \
        --hard-links \
        --delete \
        --delete-after \
        --delay-updates \
        --timeout=600 \
        $exclude \
        "$src" "$dest"

(或使用 此脚本)

使其可执行

chmod +x /etc/periodic/hourly/alpine-mirror

现在它将每小时同步一次。(假设 cron 正在运行)

通过 lighttpd 设置 HTTP 访问

安装 lighttpd 服务器

apk add lighttpd

通过取消注释 /etc/lighttpd/lighttpd.conf 中的以下行来启用目录列表

dir-listing.activate      = "enable"

还要设置 cache-control 以强制缓存每 30 分钟重新验证。取消注释 /etc/lighttpd/lighttpd.conf 中的 mod_setenv

"mod_setenv",

还要将以下行添加到 /etc/lighttpd/lighttpd.conf

setenv.add-response-header += (           
        "Cache-Control" => "must-revalidate"
)

启动 lighttpd 并使其在启动时启动

rc-service lighttpd start rc-update add lighttpd

注意: 您可能希望考虑使用 Darkhttpd 作为 Lighttpd 的替代方案

如果是这样,只需安装、启动和自动启动 Web 服务器:

apk add darkhttpd && rc-service darkhttpd start && rc-update add darkhttpd

Darkhttpd 默认情况下将提供目录列表并从 /var/www/localhost/htdocs/ 提供数据。

请参阅关于 Darkhttpd 的主要文章,以获取更多配置选项

设置 rsyncd

将以下行添加到 /etc/rsyncd.conf

[alpine]
        path = /var/www/localhost/htdocs/alpine
        comment = My Alpine Linux Mirror

可选地在 /etc/conf.d/rsyncd 中设置带宽限制。在此示例中,我们将限制为 500Kbytes/s(约 5Mbit/s)

RSYNC_OPTS="--bwlimit=500"

镜像统计信息

简单的带宽统计信息可以使用 vnstat 生成。

apk add vnstat

编辑 /etc/vnstat.conf 并将接口名称替换为适当的名称。

启动 vnstatd

rc-service vnstatd start

将以下脚本复制到 /etc/periodic/15min/stats 并确保您的 crond 正在运行。请注意 heredoc 应该使用制表符缩进,否则脚本将失败。一个可用的副本可以在这里找到: https://tpaste.us/RrMv

#!/bin/sh

output="/var/www/localhost/htdocs/.stats"
nic="eth0"

generate_index() {
    cat <<-EOF
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="cache-control" content=no-cache">
        <meta http-equiv="refresh" content="3000">
        <title>Alpine Linux mirror statistics</title>
    </head>
    <body>
        <table border="0">
            <tr><td><img src="summary.png" alt="summary"></td><td><img src="hours.png" alt="hours"></td></tr>
            <tr><td rowspan="2"><img src="days.png" alt="days"></td><td><img src="top10.png" alt="top10"></td></tr>
            <tr><td><img src="months.png" alt="months"></td></tr>
        </table>
    </body>
    </html>
    EOF
}

if  [ ! -f "$output"/index.html ]; then
    mkdir -p $output
    generate_index > "$output"/index.html
fi

for type in hours days months top10 summary hsummary vsummary; do
    vnstati --${type} -i $nic -o $output/${type}.png
done

从 mqtt 更新镜像

如果您希望您的镜像与我们的主镜像相比真正是最新的,您可以订阅 Alpine Linux 消息服务器 "msg.alpinelinux.org" 并检查上传消息。添加 mqtt-exec 以便能够在发送特定主题时执行进程。

apk add mqtt-exec

mqtt-exec 支持多次运行,因此我们需要设置一个特定的配置。

ln -s mqtt-exec /etc/init.d/mqtt-exec.sync-mirror

ln -s mqtt-exec /etc/conf.d/mqtt-exec.sync-mirror

编辑 /etc/conf.d/mqtt-exec.sync-mirror

mqtt_topics="rsync/rsync.alpinelinux.org/#"
exec_user="buildozer"
exec_command="/usr/local/bin/sync-mirror"

将以下文件复制到 /usr/local/bin/sync-mirror 并使其可执行(不要忘记更新变量)。

#!/bin/sh

src="rsync://rsync.alpinelinux.org/alpine/"
dest="/var/www/localhost/htdocs/alpine/"
lock="/tmp/sync-mirror.lock"
topic="$1"
dir="$2"

[ -z "$flock" ] && exec env flock=1 flock $lock $0 "$@"

if [ -n "$dir" ] && [ -d "$dest/${dir%/*}" ]; then
    logger "Syncing directory: $dir"
    src="${src}${dir%/}/"
    dest="${dest}${dir%/}/"
else
    logger "Syncing all directories"
fi

/usr/bin/rsync \
    --archive \
    --update \
    --verbose \
    --progress \
    --timeout=600 \
    --delay-updates \
    --delete-after \
    "$src" \
    "$dest"

最后启动 mqtt-exec 并使其监听 msg.alpinelinux.org

rc-service mqtt-exec.sync-mirror start

为了确保您不会遗漏任何软件包(以防 MQTT 订阅出现问题),您可以定期同步所有目录,方法是将脚本添加到 cron。

ln -s /usr/local/bin/sync-mirror /etc/periodic/hourly/sync-mirror

现在查看您的 syslog,它应该会告诉您何时更新本地镜像中的目录。

使用 nginx 的部分镜像

对于私有镜像,仅同步最新版本或 Alpine 的某些架构以节省空间可能是有意义的,但是如果您确实将旧的 Alpine 版本指向您的镜像,他们仍然应该能够安装软件包。我们可以通过使用 nginx 来服务镜像内容并将所有 404 错误请求重定向到公共镜像来实现这一点。

假设您选择仅镜像 v3.13 及更高版本的 Alpine 版本。如果客户端向您的镜像请求 v3.10,则应重定向到另一个镜像。

您的 nginx 配置服务器块应该如下所示

server {
        listen 80;
        server_name alpine.mydomain.local;
        root /data/alpine;          # point to where your alpine mirror is located. make sure nginx is allowed to read it
        autoindex on;               # Enable indexing

        error_page 404 = @alpinemirror;

        location @alpinemirror
        {
          return 302 http://dl-cdn.alpinelinux.org/alpine$request_uri;
        }
}

相应的同步脚本可能如下所示

#!/bin/sh

# make sure we never run 2 rsync at the same time
lockfile="/tmp/alpine-mirror.lock"
if [ -z "$flock" ] ; then
  exec env flock=1 flock -n $lockfile "$0" "$@"
  fi

  src=rsync://rsync.alpinelinux.org/alpine/
  dest=/data/alpine/

  exclude="--exclude v2.* --exclude v3.0 --exclude v3.1 --exclude v3.2 --exclude v3.3 --exclude v3.4 --exclude v3.5 --exclude v3.6 --exclude v3.7 --exclude v3.8 --exclude v3.9 --exclude v3.10 --exclude v3.11 --exclude v3.12"

  mkdir -p "$dest"
  /usr/bin/rsync -vvv \
  --archive \
  --update \
  --hard-links \
  --delete \
  --delete-after \
  --delete-excluded \
  --delay-updates \
  --timeout=600 \
  $exclude \
  "$src" "$dest"