<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alpinelinux.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tetsumaki</id>
	<title>Alpine Linux - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alpinelinux.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tetsumaki"/>
	<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/wiki/Special:Contributions/Tetsumaki"/>
	<updated>2026-04-25T18:31:37Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=16004</id>
		<title>How to setup a Alpine Linux mirror</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=16004"/>
		<updated>2019-06-15T13:24:36Z</updated>

		<summary type="html">&lt;p&gt;Tetsumaki: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This document describes how to set up an Alpine Linux mirror and make it available via http and rsync.&lt;br /&gt;
&lt;br /&gt;
We will:&lt;br /&gt;
* create the dir where we have the mirror&lt;br /&gt;
* set up a cron job to sync with master mirror every hour&lt;br /&gt;
* set up lighttpd for http access&lt;br /&gt;
* set up rsync so other mirrors can rsync from you&lt;br /&gt;
&lt;br /&gt;
Make sure that you have enough disk space.&lt;br /&gt;
&lt;br /&gt;
Current (2019-06-15) disk usage in GB:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!edge&lt;br /&gt;
!v2.4&lt;br /&gt;
!v2.5&lt;br /&gt;
!v2.6&lt;br /&gt;
!v2.7&lt;br /&gt;
!v3.0&lt;br /&gt;
!v3.1&lt;br /&gt;
!v3.2&lt;br /&gt;
!v3.3&lt;br /&gt;
!v3.4&lt;br /&gt;
!v3.5&lt;br /&gt;
!v3.6&lt;br /&gt;
!v3.7&lt;br /&gt;
!v3.8&lt;br /&gt;
!v3.9&lt;br /&gt;
!total&lt;br /&gt;
|-&lt;br /&gt;
|127.7&lt;br /&gt;
|18.9&lt;br /&gt;
|10.4&lt;br /&gt;
|13.0&lt;br /&gt;
|16.6&lt;br /&gt;
|16.5&lt;br /&gt;
|17.5&lt;br /&gt;
|14.5&lt;br /&gt;
|20.4&lt;br /&gt;
|24.3&lt;br /&gt;
|26.8&lt;br /&gt;
|48.3&lt;br /&gt;
|46.8&lt;br /&gt;
|74.0&lt;br /&gt;
|82.3&lt;br /&gt;
|&#039;&#039;&#039;558.2&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Script used to calculate the size:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
&lt;br /&gt;
total=0&lt;br /&gt;
dest=&amp;quot;$(mktemp -d)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
for dir in edge v2.4 v2.5 v2.6 v2.7 v3.0 v3.1 v3.2 v3.3 v3.4 v3.5 v3.6 v3.7 v3.8 v3.9; do&lt;br /&gt;
    old_total=&amp;quot;$total&amp;quot;&lt;br /&gt;
    src=&amp;quot;rsync://rsync.alpinelinux.org/alpine/$dir/&amp;quot;&lt;br /&gt;
    size=`rsync -a -n --stats &amp;quot;$src&amp;quot; &amp;quot;$dest&amp;quot; | grep &#039;^Total file size&#039; | tr -d &#039;,&#039; | awk &#039;{ print $4 }&#039;`&lt;br /&gt;
    total=$((&amp;quot;$old_total&amp;quot; + &amp;quot;$size&amp;quot;))&lt;br /&gt;
    echo &amp;quot;$dir: $size&amp;quot; | awk &#039;{ print $1 sprintf(&amp;quot;%.1f&amp;quot;, $2/1073741824) }&#039;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;total: $total&amp;quot; | awk &#039;{ print $1 sprintf(&amp;quot;%.1f&amp;quot;, $2/1073741824) }&#039;&lt;br /&gt;
rm -r &amp;quot;$dest&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting up the cron job ==&lt;br /&gt;
Install rsync which will be used to sync from the master mirror.&lt;br /&gt;
{{Cmd|apk add rsync}}&lt;br /&gt;
&lt;br /&gt;
Save the following file as &#039;&#039;/etc/periodic/hourly/alpine-mirror&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
# make sure we never run 2 rsync at the same time&lt;br /&gt;
lockfile=&amp;quot;/tmp/alpine-mirror.lock&amp;quot;&lt;br /&gt;
if [ -z &amp;quot;$flock&amp;quot; ] ; then&lt;br /&gt;
  exec env flock=1 flock -n $lockfile &amp;quot;$0&amp;quot; &amp;quot;$@&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
src=rsync://rsync.alpinelinux.org/alpine/ &lt;br /&gt;
dest=/var/www/localhost/htdocs/alpine/&lt;br /&gt;
&lt;br /&gt;
# uncomment this to exclude old v2.x branches&lt;br /&gt;
#exclude=&amp;quot;--exclude v2.*&amp;quot;&lt;br /&gt;
&lt;br /&gt;
mkdir -p &amp;quot;$dest&amp;quot;&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
        --archive \&lt;br /&gt;
        --update \&lt;br /&gt;
        --hard-links \&lt;br /&gt;
        --delete \&lt;br /&gt;
        --delete-after \&lt;br /&gt;
        --delay-updates \&lt;br /&gt;
        --timeout=600 \&lt;br /&gt;
        $exclude \&lt;br /&gt;
        &amp;quot;$src&amp;quot; &amp;quot;$dest&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(or use [https://gist.github.com/jirutka/288c6fff7c0b8a835d143686207316be this script])&lt;br /&gt;
&lt;br /&gt;
Make it executable:&lt;br /&gt;
{{Cmd|&amp;lt;nowiki&amp;gt;chmod +x /etc/periodic/hourly/alpine-mirror&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now it will sync every hour. (given cron runs)&lt;br /&gt;
&lt;br /&gt;
== Setting up HTTP access via lighttpd ==&lt;br /&gt;
&lt;br /&gt;
Install the lighttpd server&lt;br /&gt;
{{Cmd|apk add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
Enable dir listings by uncommenting the following line in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 dir-listing.activate      = &amp;quot;enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Also set cache-control to force cache revalidate every 30 mins. Uncomment mod_setenv in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 &amp;quot;mod_setenv&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
Add also the following lines to &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 setenv.add-response-header += (           &lt;br /&gt;
         &amp;quot;Cache-Control&amp;quot; =&amp;gt; &amp;quot;must-revalidate&amp;quot;&lt;br /&gt;
 )&lt;br /&gt;
&lt;br /&gt;
Start lighttpd and make it start at boot:&lt;br /&gt;
{{Cmd|rc-service lighttpd start&lt;br /&gt;
rc-update add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
{{Note|You may wish to consider [[Darkhttpd]] as an alternative to [[Lighttpd]]&lt;br /&gt;
&lt;br /&gt;
If so, simply install, start and auto-start the webserver:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add darkhttpd &amp;amp;&amp;amp; rc-service darkhttpd start &amp;amp;&amp;amp; rc-update add darkhttpd}}&lt;br /&gt;
&lt;br /&gt;
Darkhttpd will, by default, offer directory listings and serve data from /var/www/localhost/htdocs/ &lt;br /&gt;
&lt;br /&gt;
See the main article on [[Darkhttpd]] for more configuration options}}&lt;br /&gt;
&lt;br /&gt;
== Setting up rsyncd ==&lt;br /&gt;
Add the following lines to &#039;&#039;/etc/rsyncd.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[alpine]&lt;br /&gt;
        path = /var/www/localhost/htdocs/alpine&lt;br /&gt;
        comment = My Alpine Linux Mirror&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally set a bandwidth limit in &#039;&#039;/etc/conf.d/rsyncd&#039;&#039;. In this example we limit to 500Kbytes/s (approx 5Mbit/s)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
RSYNC_OPTS=&amp;quot;--bwlimit=500&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mirror statistics ==&lt;br /&gt;
&lt;br /&gt;
Simple bandwidth statistics can be generated with vnstat.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add vnstat}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/vnstat.conf and replace the interface name with the appropriate one.&lt;br /&gt;
&lt;br /&gt;
Start vnstatd&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/vnstatd start }}&lt;br /&gt;
&lt;br /&gt;
copy the following script to /etc/periodic/15min/stats and make sure your crond is running.&lt;br /&gt;
please not that heredoc should be tab indented or the script will fail. A working copy can be found here: http://tpaste.us/RrMv&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
output=&amp;quot;/var/www/localhost/htdocs/.stats&amp;quot;&lt;br /&gt;
nic=&amp;quot;eth0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
generate_index() {&lt;br /&gt;
    cat &amp;lt;&amp;lt;-EOF&lt;br /&gt;
    &amp;lt;!doctype html&amp;gt;&lt;br /&gt;
    &amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;&lt;br /&gt;
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;cache-control&amp;quot; content=no-cache&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;3000&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;title&amp;gt;Alpine Linux mirror statistics&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;&lt;br /&gt;
        &amp;lt;table border=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;summary.png&amp;quot; alt=&amp;quot;summary&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;hours.png&amp;quot; alt=&amp;quot;hours&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td rowspan=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;days.png&amp;quot; alt=&amp;quot;days&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;top10.png&amp;quot; alt=&amp;quot;top10&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;months.png&amp;quot; alt=&amp;quot;months&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
        &amp;lt;/table&amp;gt;&lt;br /&gt;
    &amp;lt;/body&amp;gt;&lt;br /&gt;
    &amp;lt;/html&amp;gt;&lt;br /&gt;
    EOF&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if  [ ! -f &amp;quot;$output&amp;quot;/index.html ]; then&lt;br /&gt;
    mkdir -p $output&lt;br /&gt;
    generate_index &amp;gt; &amp;quot;$output&amp;quot;/index.html&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
for type in hours days months top10 summary hsummary vsummary; do&lt;br /&gt;
    vnstati --${type} -i $nic -o $output/${type}.png&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Update mirror from mqtt ==&lt;br /&gt;
&lt;br /&gt;
If you want your mirror to be really uptodate compared to our master mirror you can subscribe to Alpine Linux message server &amp;quot;msg.alpinelinux.org&amp;quot; and check for upload messages.&lt;br /&gt;
Add mqtt-exec to be able to execute processes when specific topics are being send.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| apk add mqtt-exec}}&lt;br /&gt;
&lt;br /&gt;
mqtt-exec supports running multiple time so we need to setup a specific config.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/init.d/mqtt-exec /etc/init.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/conf.d/mqtt-exec /etc/conf.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/conf.d/mqtt-exec.sync-mirror&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt_topics=&amp;quot;rsync/rsync.alpinelinux.org/#&amp;quot;&lt;br /&gt;
exec_user=&amp;quot;buildozer&amp;quot;&lt;br /&gt;
exec_command=&amp;quot;/usr/local/bin/sync-mirror&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the following file to /usr/local/bin/sync-mirror and make it executable (dont forget to update the variables).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
src=&amp;quot;rsync://rsync.alpinelinux.org/alpine/&amp;quot;&lt;br /&gt;
dest=&amp;quot;/var/www/localhost/htdocs/alpine/&amp;quot;&lt;br /&gt;
lock=&amp;quot;/tmp/sync-mirror.lock&amp;quot;&lt;br /&gt;
topic=&amp;quot;$1&amp;quot;&lt;br /&gt;
dir=&amp;quot;$2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[ -z &amp;quot;$flock&amp;quot; ] &amp;amp;&amp;amp; exec env flock=1 flock $lock $0 &amp;quot;$@&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ -n &amp;quot;$dir&amp;quot; ] &amp;amp;&amp;amp; [ -d &amp;quot;$dest/${dir%/*}&amp;quot; ]; then&lt;br /&gt;
    logger &amp;quot;Syncing directory: $dir&amp;quot;&lt;br /&gt;
    src=&amp;quot;${src}${dir%/}/&amp;quot;&lt;br /&gt;
    dest=&amp;quot;${dest}${dir%/}/&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
    logger &amp;quot;Syncing all directories&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
    --archive \&lt;br /&gt;
    --update \&lt;br /&gt;
    --verbose \&lt;br /&gt;
    --progress \&lt;br /&gt;
    --timeout=600 \&lt;br /&gt;
    --delay-updates \&lt;br /&gt;
    --delete-after \&lt;br /&gt;
    &amp;quot;$src&amp;quot; \&lt;br /&gt;
    &amp;quot;$dest&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally start mqtt-exec and let it listen on msg.alpinelinux.org&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/mqtt-exec.sync-mirror start}}&lt;br /&gt;
&lt;br /&gt;
To make sure you are not missing any packages (in case something goes wrong with MQTT subscription) you can periodically sync all directories by adding the script to cron.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|ln -s /usr/local/bin/sync-mirror /etc/periodic/hourly/sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
Now watch your syslog as it should tell you when it will update directories in your local mirror.&lt;br /&gt;
&lt;br /&gt;
[[Category:Server]]&lt;br /&gt;
[[Category:Package Manager]]&lt;/div&gt;</summary>
		<author><name>Tetsumaki</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=15680</id>
		<title>How to setup a Alpine Linux mirror</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=15680"/>
		<updated>2019-01-24T21:01:46Z</updated>

		<summary type="html">&lt;p&gt;Tetsumaki: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This document describes how to set up an Alpine Linux mirror and make it available via http and rsync.&lt;br /&gt;
&lt;br /&gt;
We will:&lt;br /&gt;
* create the dir where we have the mirror&lt;br /&gt;
* set up a cron job to sync with master mirror every hour&lt;br /&gt;
* set up lighttpd for http access&lt;br /&gt;
* set up rsync so other mirrors can rsync from you&lt;br /&gt;
&lt;br /&gt;
Make sure that you have enough disk space.&lt;br /&gt;
&lt;br /&gt;
Current (2019-01-24) disk usage in GB:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!edge&lt;br /&gt;
!v2.4&lt;br /&gt;
!v2.5&lt;br /&gt;
!v2.6&lt;br /&gt;
!v2.7&lt;br /&gt;
!v3.0&lt;br /&gt;
!v3.1&lt;br /&gt;
!v3.2&lt;br /&gt;
!v3.3&lt;br /&gt;
!v3.4&lt;br /&gt;
!v3.5&lt;br /&gt;
!v3.6&lt;br /&gt;
!v3.7&lt;br /&gt;
!v3.8&lt;br /&gt;
!v3.9&lt;br /&gt;
!total&lt;br /&gt;
|-&lt;br /&gt;
|98.1&lt;br /&gt;
|18.9&lt;br /&gt;
|10.4&lt;br /&gt;
|13.0&lt;br /&gt;
|16.6&lt;br /&gt;
|16.5&lt;br /&gt;
|17.5&lt;br /&gt;
|14.5&lt;br /&gt;
|20.4&lt;br /&gt;
|24.3&lt;br /&gt;
|33.8&lt;br /&gt;
|45.6&lt;br /&gt;
|43.8&lt;br /&gt;
|69.3&lt;br /&gt;
|66.8&lt;br /&gt;
|&#039;&#039;&#039;525.4&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Script used to calculate the size:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
&lt;br /&gt;
total=0&lt;br /&gt;
dest=&amp;quot;$(mktemp -d)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
for dir in edge v2.4 v2.5 v2.6 v2.7 v3.0 v3.1 v3.2 v3.3 v3.4 v3.5 v3.6 v3.7 v3.8; do&lt;br /&gt;
    old_total=&amp;quot;$total&amp;quot;&lt;br /&gt;
    src=&amp;quot;rsync://rsync.alpinelinux.org/alpine/$dir/&amp;quot;&lt;br /&gt;
    size=`rsync -a -n --stats &amp;quot;$src&amp;quot; &amp;quot;$dest&amp;quot; | grep &#039;^Total file size&#039; | tr -d &#039;,&#039; | awk &#039;{ print $4 }&#039;`&lt;br /&gt;
    total=$((&amp;quot;$old_total&amp;quot; + &amp;quot;$size&amp;quot;))&lt;br /&gt;
    echo &amp;quot;$dir: $size&amp;quot; | awk &#039;{ print $1 sprintf(&amp;quot;%.1f&amp;quot;, $2/1073741824) }&#039;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;total: $total&amp;quot; | awk &#039;{ print $1 sprintf(&amp;quot;%.1f&amp;quot;, $2/1073741824) }&#039;&lt;br /&gt;
rm -r &amp;quot;$dest&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting up the cron job ==&lt;br /&gt;
Install rsync which will be used to sync from the master mirror.&lt;br /&gt;
{{Cmd|apk add rsync}}&lt;br /&gt;
&lt;br /&gt;
Save the following file as &#039;&#039;/etc/periodic/hourly/alpine-mirror&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
# make sure we never run 2 rsync at the same time&lt;br /&gt;
lockfile=&amp;quot;/tmp/alpine-mirror.lock&amp;quot;&lt;br /&gt;
if [ -z &amp;quot;$flock&amp;quot; ] ; then&lt;br /&gt;
  exec env flock=1 flock -n $lockfile &amp;quot;$0&amp;quot; &amp;quot;$@&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
src=rsync://rsync.alpinelinux.org/alpine/ &lt;br /&gt;
dest=/var/www/localhost/htdocs/alpine/&lt;br /&gt;
&lt;br /&gt;
# uncomment this to exclude old v2.x branches&lt;br /&gt;
#exclude=&amp;quot;--exclude v2.*&amp;quot;&lt;br /&gt;
&lt;br /&gt;
mkdir -p &amp;quot;$dest&amp;quot;&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
        --archive \&lt;br /&gt;
        --update \&lt;br /&gt;
        --hard-links \&lt;br /&gt;
        --delete \&lt;br /&gt;
        --delete-after \&lt;br /&gt;
        --delay-updates \&lt;br /&gt;
        --timeout=600 \&lt;br /&gt;
        $exclude \&lt;br /&gt;
        &amp;quot;$src&amp;quot; &amp;quot;$dest&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(or use [https://gist.github.com/jirutka/288c6fff7c0b8a835d143686207316be this script])&lt;br /&gt;
&lt;br /&gt;
Make it executable:&lt;br /&gt;
{{Cmd|&amp;lt;nowiki&amp;gt;chmod +x /etc/periodic/hourly/alpine-mirror&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now it will sync every hour. (given cron runs)&lt;br /&gt;
&lt;br /&gt;
== Setting up HTTP access via lighttpd ==&lt;br /&gt;
&lt;br /&gt;
Install the lighttpd server&lt;br /&gt;
{{Cmd|apk add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
Enable dir listings by uncommenting the following line in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 dir-listing.activate      = &amp;quot;enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Also set cache-control to force cache revalidate every 30 mins. Uncomment mod_setenv in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 &amp;quot;mod_setenv&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
Add also the following lines to &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 setenv.add-response-header += (           &lt;br /&gt;
         &amp;quot;Cache-Control&amp;quot; =&amp;gt; &amp;quot;must-revalidate&amp;quot;&lt;br /&gt;
 )&lt;br /&gt;
&lt;br /&gt;
Start lighttpd and make it start at boot:&lt;br /&gt;
{{Cmd|rc-service lighttpd start&lt;br /&gt;
rc-update add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
{{Note|You may wish to consider [[Darkhttpd]] as an alternative to [[Lighttpd]]&lt;br /&gt;
&lt;br /&gt;
If so, simply install, start and auto-start the webserver:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add darkhttpd &amp;amp;&amp;amp; rc-service darkhttpd start &amp;amp;&amp;amp; rc-update add darkhttpd}}&lt;br /&gt;
&lt;br /&gt;
Darkhttpd will, by default, offer directory listings and serve data from /var/www/localhost/htdocs/ &lt;br /&gt;
&lt;br /&gt;
See the main article on [[Darkhttpd]] for more configuration options}}&lt;br /&gt;
&lt;br /&gt;
== Setting up rsyncd ==&lt;br /&gt;
Add the following lines to &#039;&#039;/etc/rsyncd.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[alpine]&lt;br /&gt;
        path = /var/www/localhost/htdocs/alpine&lt;br /&gt;
        comment = My Alpine Linux Mirror&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally set a bandwidth limit in &#039;&#039;/etc/conf.d/rsyncd&#039;&#039;. In this example we limit to 500Kbytes/s (approx 5Mbit/s)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
RSYNC_OPTS=&amp;quot;--bwlimit=500&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mirror statistics ==&lt;br /&gt;
&lt;br /&gt;
Simple bandwidth statistics can be generated with vnstat.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add vnstat}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/vnstat.conf and replace the interface name with the appropriate one.&lt;br /&gt;
&lt;br /&gt;
Start vnstatd&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/vnstatd start }}&lt;br /&gt;
&lt;br /&gt;
copy the following script to /etc/periodic/15min/stats and make sure your crond is running.&lt;br /&gt;
please not that heredoc should be tab indented or the script will fail. A working copy can be found here: http://tpaste.us/RrMv&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
output=&amp;quot;/var/www/localhost/htdocs/.stats&amp;quot;&lt;br /&gt;
nic=&amp;quot;eth0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
generate_index() {&lt;br /&gt;
    cat &amp;lt;&amp;lt;-EOF&lt;br /&gt;
    &amp;lt;!doctype html&amp;gt;&lt;br /&gt;
    &amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;&lt;br /&gt;
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;cache-control&amp;quot; content=no-cache&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;3000&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;title&amp;gt;Alpine Linux mirror statistics&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;&lt;br /&gt;
        &amp;lt;table border=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;summary.png&amp;quot; alt=&amp;quot;summary&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;hours.png&amp;quot; alt=&amp;quot;hours&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td rowspan=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;days.png&amp;quot; alt=&amp;quot;days&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;top10.png&amp;quot; alt=&amp;quot;top10&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;months.png&amp;quot; alt=&amp;quot;months&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
        &amp;lt;/table&amp;gt;&lt;br /&gt;
    &amp;lt;/body&amp;gt;&lt;br /&gt;
    &amp;lt;/html&amp;gt;&lt;br /&gt;
    EOF&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if  [ ! -f &amp;quot;$output&amp;quot;/index.html ]; then&lt;br /&gt;
    mkdir -p $output&lt;br /&gt;
    generate_index &amp;gt; &amp;quot;$output&amp;quot;/index.html&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
for type in hours days months top10 summary hsummary vsummary; do&lt;br /&gt;
    vnstati --${type} -i $nic -o $output/${type}.png&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Update mirror from mqtt ==&lt;br /&gt;
&lt;br /&gt;
If you want your mirror to be really uptodate compared to our master mirror you can subscribe to Alpine Linux message server &amp;quot;msg.alpinelinux.org&amp;quot; and check for upload messages.&lt;br /&gt;
Add mqtt-exec to be able to execute processes when specific topics are being send.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| apk add mqtt-exec}}&lt;br /&gt;
&lt;br /&gt;
mqtt-exec supports running multiple time so we need to setup a specific config.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/init.d/mqtt-exec /etc/init.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/conf.d/mqtt-exec /etc/conf.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/conf.d/mqtt-exec.sync-mirror&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt_topics=&amp;quot;rsync/rsync.alpinelinux.org/#&amp;quot;&lt;br /&gt;
exec_user=&amp;quot;buildozer&amp;quot;&lt;br /&gt;
exec_command=&amp;quot;/usr/local/bin/sync-mirror&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the following file to /usr/local/bin/sync-mirror and make it executable (dont forget to update the variables).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
src=&amp;quot;rsync://rsync.alpinelinux.org/alpine/&amp;quot;&lt;br /&gt;
dest=&amp;quot;/var/www/localhost/htdocs/alpine/&amp;quot;&lt;br /&gt;
lock=&amp;quot;/tmp/sync-mirror.lock&amp;quot;&lt;br /&gt;
topic=&amp;quot;$1&amp;quot;&lt;br /&gt;
dir=&amp;quot;$2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[ -z &amp;quot;$flock&amp;quot; ] &amp;amp;&amp;amp; exec env flock=1 flock $lock $0 &amp;quot;$@&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ -n &amp;quot;$dir&amp;quot; ] &amp;amp;&amp;amp; [ -d &amp;quot;$dest/${dir%/*}&amp;quot; ]; then&lt;br /&gt;
    logger &amp;quot;Syncing directory: $dir&amp;quot;&lt;br /&gt;
    src=&amp;quot;${src}${dir%/}/&amp;quot;&lt;br /&gt;
    dest=&amp;quot;${dest}${dir%/}/&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
    logger &amp;quot;Syncing all directories&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
    --archive \&lt;br /&gt;
    --update \&lt;br /&gt;
    --verbose \&lt;br /&gt;
    --progress \&lt;br /&gt;
    --timeout=600 \&lt;br /&gt;
    --delay-updates \&lt;br /&gt;
    --delete-after \&lt;br /&gt;
    &amp;quot;$src&amp;quot; \&lt;br /&gt;
    &amp;quot;$dest&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally start mqtt-exec and let it listen on msg.alpinelinux.org&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/mqtt-exec.sync-mirror start}}&lt;br /&gt;
&lt;br /&gt;
To make sure you are not missing any packages (in case something goes wrong with MQTT subscription) you can periodically sync all directories by adding the script to cron.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|ln -s /usr/local/bin/sync-mirror /etc/periodic/hourly/sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
Now watch your syslog as it should tell you when it will update directories in your local mirror.&lt;br /&gt;
&lt;br /&gt;
[[Category:Server]]&lt;br /&gt;
[[Category:Package Manager]]&lt;/div&gt;</summary>
		<author><name>Tetsumaki</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=15679</id>
		<title>How to setup a Alpine Linux mirror</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=15679"/>
		<updated>2019-01-24T20:59:54Z</updated>

		<summary type="html">&lt;p&gt;Tetsumaki: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This document describes how to set up an Alpine Linux mirror and make it available via http and rsync.&lt;br /&gt;
&lt;br /&gt;
We will:&lt;br /&gt;
* create the dir where we have the mirror&lt;br /&gt;
* set up a cron job to sync with master mirror every hour&lt;br /&gt;
* set up lighttpd for http access&lt;br /&gt;
* set up rsync so other mirrors can rsync from you&lt;br /&gt;
&lt;br /&gt;
Make sure that you have enough disk space.&lt;br /&gt;
&lt;br /&gt;
Current (2018-08-11) disk usage in GB:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!edge&lt;br /&gt;
!v2.4&lt;br /&gt;
!v2.5&lt;br /&gt;
!v2.6&lt;br /&gt;
!v2.7&lt;br /&gt;
!v3.0&lt;br /&gt;
!v3.1&lt;br /&gt;
!v3.2&lt;br /&gt;
!v3.3&lt;br /&gt;
!v3.4&lt;br /&gt;
!v3.5&lt;br /&gt;
!v3.6&lt;br /&gt;
!v3.7&lt;br /&gt;
!v3.8&lt;br /&gt;
!v3.9&lt;br /&gt;
!total&lt;br /&gt;
|-&lt;br /&gt;
|98.1&lt;br /&gt;
|18.9&lt;br /&gt;
|10.4&lt;br /&gt;
|13.0&lt;br /&gt;
|16.6&lt;br /&gt;
|16.5&lt;br /&gt;
|17.5&lt;br /&gt;
|14.5&lt;br /&gt;
|20.4&lt;br /&gt;
|24.3&lt;br /&gt;
|33.8&lt;br /&gt;
|45.6&lt;br /&gt;
|43.8&lt;br /&gt;
|69.3&lt;br /&gt;
|66.8&lt;br /&gt;
|&#039;&#039;&#039;525.4&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Script used to calculate the size:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
total=0&lt;br /&gt;
dest=&amp;quot;$(mktemp -d)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
for dir in edge v2.4 v2.5 v2.6 v2.7 v3.0 v3.1 v3.2 v3.3 v3.4 v3.5 v3.6 v3.7 v3.8; do&lt;br /&gt;
    old_total=&amp;quot;$total&amp;quot;&lt;br /&gt;
    src=&amp;quot;rsync://rsync.alpinelinux.org/alpine/$dir/&amp;quot;&lt;br /&gt;
    size=`rsync -a -n --stats &amp;quot;$src&amp;quot; &amp;quot;$dest&amp;quot; | grep &#039;^Total file size&#039; | tr -d &#039;,&#039; | awk &#039;{ print $4 }&#039;`&lt;br /&gt;
    total=$((&amp;quot;$old_total&amp;quot; + &amp;quot;$size&amp;quot;))&lt;br /&gt;
    echo &amp;quot;$dir: $size&amp;quot; | awk &#039;{ print $1 sprintf(&amp;quot;%.1f&amp;quot;, $2/1073741824) }&#039;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;total: $total&amp;quot; | awk &#039;{ print $1 sprintf(&amp;quot;%.1f&amp;quot;, $2/1073741824) }&#039;&lt;br /&gt;
rm -r &amp;quot;$dest&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting up the cron job ==&lt;br /&gt;
Install rsync which will be used to sync from the master mirror.&lt;br /&gt;
{{Cmd|apk add rsync}}&lt;br /&gt;
&lt;br /&gt;
Save the following file as &#039;&#039;/etc/periodic/hourly/alpine-mirror&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
# make sure we never run 2 rsync at the same time&lt;br /&gt;
lockfile=&amp;quot;/tmp/alpine-mirror.lock&amp;quot;&lt;br /&gt;
if [ -z &amp;quot;$flock&amp;quot; ] ; then&lt;br /&gt;
  exec env flock=1 flock -n $lockfile &amp;quot;$0&amp;quot; &amp;quot;$@&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
src=rsync://rsync.alpinelinux.org/alpine/ &lt;br /&gt;
dest=/var/www/localhost/htdocs/alpine/&lt;br /&gt;
&lt;br /&gt;
# uncomment this to exclude old v2.x branches&lt;br /&gt;
#exclude=&amp;quot;--exclude v2.*&amp;quot;&lt;br /&gt;
&lt;br /&gt;
mkdir -p &amp;quot;$dest&amp;quot;&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
        --archive \&lt;br /&gt;
        --update \&lt;br /&gt;
        --hard-links \&lt;br /&gt;
        --delete \&lt;br /&gt;
        --delete-after \&lt;br /&gt;
        --delay-updates \&lt;br /&gt;
        --timeout=600 \&lt;br /&gt;
        $exclude \&lt;br /&gt;
        &amp;quot;$src&amp;quot; &amp;quot;$dest&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(or use [https://gist.github.com/jirutka/288c6fff7c0b8a835d143686207316be this script])&lt;br /&gt;
&lt;br /&gt;
Make it executable:&lt;br /&gt;
{{Cmd|&amp;lt;nowiki&amp;gt;chmod +x /etc/periodic/hourly/alpine-mirror&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now it will sync every hour. (given cron runs)&lt;br /&gt;
&lt;br /&gt;
== Setting up HTTP access via lighttpd ==&lt;br /&gt;
&lt;br /&gt;
Install the lighttpd server&lt;br /&gt;
{{Cmd|apk add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
Enable dir listings by uncommenting the following line in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 dir-listing.activate      = &amp;quot;enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Also set cache-control to force cache revalidate every 30 mins. Uncomment mod_setenv in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 &amp;quot;mod_setenv&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
Add also the following lines to &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 setenv.add-response-header += (           &lt;br /&gt;
         &amp;quot;Cache-Control&amp;quot; =&amp;gt; &amp;quot;must-revalidate&amp;quot;&lt;br /&gt;
 )&lt;br /&gt;
&lt;br /&gt;
Start lighttpd and make it start at boot:&lt;br /&gt;
{{Cmd|rc-service lighttpd start&lt;br /&gt;
rc-update add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
{{Note|You may wish to consider [[Darkhttpd]] as an alternative to [[Lighttpd]]&lt;br /&gt;
&lt;br /&gt;
If so, simply install, start and auto-start the webserver:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add darkhttpd &amp;amp;&amp;amp; rc-service darkhttpd start &amp;amp;&amp;amp; rc-update add darkhttpd}}&lt;br /&gt;
&lt;br /&gt;
Darkhttpd will, by default, offer directory listings and serve data from /var/www/localhost/htdocs/ &lt;br /&gt;
&lt;br /&gt;
See the main article on [[Darkhttpd]] for more configuration options}}&lt;br /&gt;
&lt;br /&gt;
== Setting up rsyncd ==&lt;br /&gt;
Add the following lines to &#039;&#039;/etc/rsyncd.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[alpine]&lt;br /&gt;
        path = /var/www/localhost/htdocs/alpine&lt;br /&gt;
        comment = My Alpine Linux Mirror&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally set a bandwidth limit in &#039;&#039;/etc/conf.d/rsyncd&#039;&#039;. In this example we limit to 500Kbytes/s (approx 5Mbit/s)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
RSYNC_OPTS=&amp;quot;--bwlimit=500&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mirror statistics ==&lt;br /&gt;
&lt;br /&gt;
Simple bandwidth statistics can be generated with vnstat.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add vnstat}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/vnstat.conf and replace the interface name with the appropriate one.&lt;br /&gt;
&lt;br /&gt;
Start vnstatd&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/vnstatd start }}&lt;br /&gt;
&lt;br /&gt;
copy the following script to /etc/periodic/15min/stats and make sure your crond is running.&lt;br /&gt;
please not that heredoc should be tab indented or the script will fail. A working copy can be found here: http://tpaste.us/RrMv&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
output=&amp;quot;/var/www/localhost/htdocs/.stats&amp;quot;&lt;br /&gt;
nic=&amp;quot;eth0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
generate_index() {&lt;br /&gt;
    cat &amp;lt;&amp;lt;-EOF&lt;br /&gt;
    &amp;lt;!doctype html&amp;gt;&lt;br /&gt;
    &amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;&lt;br /&gt;
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;cache-control&amp;quot; content=no-cache&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;3000&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;title&amp;gt;Alpine Linux mirror statistics&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;&lt;br /&gt;
        &amp;lt;table border=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;summary.png&amp;quot; alt=&amp;quot;summary&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;hours.png&amp;quot; alt=&amp;quot;hours&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td rowspan=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;days.png&amp;quot; alt=&amp;quot;days&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;top10.png&amp;quot; alt=&amp;quot;top10&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;months.png&amp;quot; alt=&amp;quot;months&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
        &amp;lt;/table&amp;gt;&lt;br /&gt;
    &amp;lt;/body&amp;gt;&lt;br /&gt;
    &amp;lt;/html&amp;gt;&lt;br /&gt;
    EOF&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if  [ ! -f &amp;quot;$output&amp;quot;/index.html ]; then&lt;br /&gt;
    mkdir -p $output&lt;br /&gt;
    generate_index &amp;gt; &amp;quot;$output&amp;quot;/index.html&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
for type in hours days months top10 summary hsummary vsummary; do&lt;br /&gt;
    vnstati --${type} -i $nic -o $output/${type}.png&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Update mirror from mqtt ==&lt;br /&gt;
&lt;br /&gt;
If you want your mirror to be really uptodate compared to our master mirror you can subscribe to Alpine Linux message server &amp;quot;msg.alpinelinux.org&amp;quot; and check for upload messages.&lt;br /&gt;
Add mqtt-exec to be able to execute processes when specific topics are being send.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| apk add mqtt-exec}}&lt;br /&gt;
&lt;br /&gt;
mqtt-exec supports running multiple time so we need to setup a specific config.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/init.d/mqtt-exec /etc/init.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/conf.d/mqtt-exec /etc/conf.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/conf.d/mqtt-exec.sync-mirror&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt_topics=&amp;quot;rsync/rsync.alpinelinux.org/#&amp;quot;&lt;br /&gt;
exec_user=&amp;quot;buildozer&amp;quot;&lt;br /&gt;
exec_command=&amp;quot;/usr/local/bin/sync-mirror&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the following file to /usr/local/bin/sync-mirror and make it executable (dont forget to update the variables).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
src=&amp;quot;rsync://rsync.alpinelinux.org/alpine/&amp;quot;&lt;br /&gt;
dest=&amp;quot;/var/www/localhost/htdocs/alpine/&amp;quot;&lt;br /&gt;
lock=&amp;quot;/tmp/sync-mirror.lock&amp;quot;&lt;br /&gt;
topic=&amp;quot;$1&amp;quot;&lt;br /&gt;
dir=&amp;quot;$2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[ -z &amp;quot;$flock&amp;quot; ] &amp;amp;&amp;amp; exec env flock=1 flock $lock $0 &amp;quot;$@&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ -n &amp;quot;$dir&amp;quot; ] &amp;amp;&amp;amp; [ -d &amp;quot;$dest/${dir%/*}&amp;quot; ]; then&lt;br /&gt;
    logger &amp;quot;Syncing directory: $dir&amp;quot;&lt;br /&gt;
    src=&amp;quot;${src}${dir%/}/&amp;quot;&lt;br /&gt;
    dest=&amp;quot;${dest}${dir%/}/&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
    logger &amp;quot;Syncing all directories&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
    --archive \&lt;br /&gt;
    --update \&lt;br /&gt;
    --verbose \&lt;br /&gt;
    --progress \&lt;br /&gt;
    --timeout=600 \&lt;br /&gt;
    --delay-updates \&lt;br /&gt;
    --delete-after \&lt;br /&gt;
    &amp;quot;$src&amp;quot; \&lt;br /&gt;
    &amp;quot;$dest&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally start mqtt-exec and let it listen on msg.alpinelinux.org&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/mqtt-exec.sync-mirror start}}&lt;br /&gt;
&lt;br /&gt;
To make sure you are not missing any packages (in case something goes wrong with MQTT subscription) you can periodically sync all directories by adding the script to cron.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|ln -s /usr/local/bin/sync-mirror /etc/periodic/hourly/sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
Now watch your syslog as it should tell you when it will update directories in your local mirror.&lt;br /&gt;
&lt;br /&gt;
[[Category:Server]]&lt;br /&gt;
[[Category:Package Manager]]&lt;/div&gt;</summary>
		<author><name>Tetsumaki</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=15434</id>
		<title>How to setup a Alpine Linux mirror</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=15434"/>
		<updated>2018-08-11T19:21:53Z</updated>

		<summary type="html">&lt;p&gt;Tetsumaki: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This document describes how to set up an Alpine Linux mirror and make it available via http and rsync.&lt;br /&gt;
&lt;br /&gt;
We will:&lt;br /&gt;
* create the dir where we have the mirror&lt;br /&gt;
* set up a cron job to sync with master mirror every hour&lt;br /&gt;
* set up lighttpd for http access&lt;br /&gt;
* set up rsync so other mirrors can rsync from you&lt;br /&gt;
&lt;br /&gt;
Make sure that you have enough disk space.&lt;br /&gt;
&lt;br /&gt;
Current (2018-08-11) disk usage in GB:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!edge&lt;br /&gt;
!v2.4&lt;br /&gt;
!v2.5&lt;br /&gt;
!v2.6&lt;br /&gt;
!v2.7&lt;br /&gt;
!v3.0&lt;br /&gt;
!v3.1&lt;br /&gt;
!v3.2&lt;br /&gt;
!v3.3&lt;br /&gt;
!v3.4&lt;br /&gt;
!v3.5&lt;br /&gt;
!v3.6&lt;br /&gt;
!v3.7&lt;br /&gt;
!v3.8&lt;br /&gt;
!total&lt;br /&gt;
|-&lt;br /&gt;
|98.1&lt;br /&gt;
|18.9&lt;br /&gt;
|10.4&lt;br /&gt;
|13.0&lt;br /&gt;
|16.6&lt;br /&gt;
|16.5&lt;br /&gt;
|17.5&lt;br /&gt;
|14.5&lt;br /&gt;
|20.4&lt;br /&gt;
|24.3&lt;br /&gt;
|25.7&lt;br /&gt;
|40.2&lt;br /&gt;
|38.1&lt;br /&gt;
|64.8&lt;br /&gt;
|&#039;&#039;&#039;419.1&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Script used to calculate the size:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
total=0&lt;br /&gt;
dest=&amp;quot;$(mktemp -d)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
for dir in edge v2.4 v2.5 v2.6 v2.7 v3.0 v3.1 v3.2 v3.3 v3.4 v3.5 v3.6 v3.7 v3.8; do&lt;br /&gt;
    old_total=&amp;quot;$total&amp;quot;&lt;br /&gt;
    src=&amp;quot;rsync://rsync.alpinelinux.org/alpine/$dir/&amp;quot;&lt;br /&gt;
    size=`rsync -a -n --stats &amp;quot;$src&amp;quot; &amp;quot;$dest&amp;quot; | grep &#039;^Total file size&#039; | tr -d &#039;,&#039; | awk &#039;{ print $4 }&#039;`&lt;br /&gt;
    total=$((&amp;quot;$old_total&amp;quot; + &amp;quot;$size&amp;quot;))&lt;br /&gt;
    echo &amp;quot;$dir: $size&amp;quot; | awk &#039;{ print $1 sprintf(&amp;quot;%.1f&amp;quot;, $2/1073741824) }&#039;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;total: $total&amp;quot; | awk &#039;{ print $1 sprintf(&amp;quot;%.1f&amp;quot;, $2/1073741824) }&#039;&lt;br /&gt;
rm -r &amp;quot;$dest&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting up the cron job ==&lt;br /&gt;
Install rsync which will be used to sync from the master mirror.&lt;br /&gt;
{{Cmd|apk add rsync}}&lt;br /&gt;
&lt;br /&gt;
Save the following file as &#039;&#039;/etc/periodic/hourly/alpine-mirror&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
# make sure we never run 2 rsync at the same time&lt;br /&gt;
lockfile=&amp;quot;/tmp/alpine-mirror.lock&amp;quot;&lt;br /&gt;
if [ -z &amp;quot;$flock&amp;quot; ] ; then&lt;br /&gt;
  exec env flock=1 flock -n $lockfile &amp;quot;$0&amp;quot; &amp;quot;$@&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
src=rsync://rsync.alpinelinux.org/alpine/ &lt;br /&gt;
dest=/var/www/localhost/htdocs/alpine/&lt;br /&gt;
&lt;br /&gt;
# uncomment this to exclude old v2.x branches&lt;br /&gt;
#exclude=&amp;quot;--exclude v2.*&amp;quot;&lt;br /&gt;
&lt;br /&gt;
mkdir -p &amp;quot;$dest&amp;quot;&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
        --archive \&lt;br /&gt;
        --update \&lt;br /&gt;
        --hard-links \&lt;br /&gt;
        --delete \&lt;br /&gt;
        --delete-after \&lt;br /&gt;
        --delay-updates \&lt;br /&gt;
        --timeout=600 \&lt;br /&gt;
        $exclude \&lt;br /&gt;
        &amp;quot;$src&amp;quot; &amp;quot;$dest&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(or use [https://gist.github.com/jirutka/288c6fff7c0b8a835d143686207316be this script])&lt;br /&gt;
&lt;br /&gt;
Make it executable:&lt;br /&gt;
{{Cmd|&amp;lt;nowiki&amp;gt;chmod +x /etc/periodic/hourly/alpine-mirror&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now it will sync every hour. (given cron runs)&lt;br /&gt;
&lt;br /&gt;
== Setting up HTTP access via lighttpd ==&lt;br /&gt;
&lt;br /&gt;
Install the lighttpd server&lt;br /&gt;
{{Cmd|apk add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
Enable dir listings by uncommenting the following line in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 dir-listing.activate      = &amp;quot;enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Also set cache-control to force cache revalidate every 30 mins. Uncomment mod_setenv in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 &amp;quot;mod_setenv&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
Add also the following lines to &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 setenv.add-response-header += (           &lt;br /&gt;
         &amp;quot;Cache-Control&amp;quot; =&amp;gt; &amp;quot;must-revalidate&amp;quot;&lt;br /&gt;
 )&lt;br /&gt;
&lt;br /&gt;
Start lighttpd and make it start at boot:&lt;br /&gt;
{{Cmd|rc-service lighttpd start&lt;br /&gt;
rc-update add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
{{Note|You may wish to consider [[Darkhttpd]] as an alternative to [[Lighttpd]]&lt;br /&gt;
&lt;br /&gt;
If so, simply install, start and auto-start the webserver:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add darkhttpd &amp;amp;&amp;amp; rc-service darkhttpd start &amp;amp;&amp;amp; rc-update add darkhttpd}}&lt;br /&gt;
&lt;br /&gt;
Darkhttpd will, by default, offer directory listings and serve data from /var/www/localhost/htdocs/ &lt;br /&gt;
&lt;br /&gt;
See the main article on [[Darkhttpd]] for more configuration options}}&lt;br /&gt;
&lt;br /&gt;
== Setting up rsyncd ==&lt;br /&gt;
Add the following lines to &#039;&#039;/etc/rsyncd.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[alpine]&lt;br /&gt;
        path = /var/www/localhost/htdocs/alpine&lt;br /&gt;
        comment = My Alpine Linux Mirror&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally set a bandwidth limit in &#039;&#039;/etc/conf.d/rsyncd&#039;&#039;. In this example we limit to 500Kbytes/s (approx 5Mbit/s)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
RSYNC_OPTS=&amp;quot;--bwlimit=500&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mirror statistics ==&lt;br /&gt;
&lt;br /&gt;
Simple bandwidth statistics can be generated with vnstat.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add vnstat}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/vnstat.conf and replace the interface name with the appropriate one.&lt;br /&gt;
&lt;br /&gt;
Start vnstatd&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/vnstatd start }}&lt;br /&gt;
&lt;br /&gt;
copy the following script to /etc/periodic/15min/stats and make sure your crond is running.&lt;br /&gt;
please not that heredoc should be tab indented or the script will fail. A working copy can be found here: http://tpaste.us/RrMv&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
output=&amp;quot;/var/www/localhost/htdocs/.stats&amp;quot;&lt;br /&gt;
nic=&amp;quot;eth0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
generate_index() {&lt;br /&gt;
    cat &amp;lt;&amp;lt;-EOF&lt;br /&gt;
    &amp;lt;!doctype html&amp;gt;&lt;br /&gt;
    &amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;&lt;br /&gt;
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;cache-control&amp;quot; content=no-cache&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;3000&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;title&amp;gt;Alpine Linux mirror statistics&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;&lt;br /&gt;
        &amp;lt;table border=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;summary.png&amp;quot; alt=&amp;quot;summary&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;hours.png&amp;quot; alt=&amp;quot;hours&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td rowspan=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;days.png&amp;quot; alt=&amp;quot;days&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;top10.png&amp;quot; alt=&amp;quot;top10&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;months.png&amp;quot; alt=&amp;quot;months&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
        &amp;lt;/table&amp;gt;&lt;br /&gt;
    &amp;lt;/body&amp;gt;&lt;br /&gt;
    &amp;lt;/html&amp;gt;&lt;br /&gt;
    EOF&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if  [ ! -f &amp;quot;$output&amp;quot;/index.html ]; then&lt;br /&gt;
    mkdir -p $output&lt;br /&gt;
    generate_index &amp;gt; &amp;quot;$output&amp;quot;/index.html&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
for type in hours days months top10 summary hsummary vsummary; do&lt;br /&gt;
    vnstati --${type} -i $nic -o $output/${type}.png&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Update mirror from mqtt ==&lt;br /&gt;
&lt;br /&gt;
If you want your mirror to be really uptodate compared to our master mirror you can subscribe to Alpine Linux message server &amp;quot;msg.alpinelinux.org&amp;quot; and check for upload messages.&lt;br /&gt;
Add mqtt-exec to be able to execute processes when specific topics are being send.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| apk add mqtt-exec}}&lt;br /&gt;
&lt;br /&gt;
mqtt-exec supports running multiple time so we need to setup a specific config.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/init.d/mqtt-exec /etc/init.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/conf.d/mqtt-exec /etc/conf.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/conf.d/mqtt-exec.sync-mirror&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt_topics=&amp;quot;rsync/rsync.alpinelinux.org/#&amp;quot;&lt;br /&gt;
exec_user=&amp;quot;buildozer&amp;quot;&lt;br /&gt;
exec_command=&amp;quot;/usr/local/bin/sync-mirror&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the following file to /usr/local/bin/sync-mirror and make it executable (dont forget to update the variables).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
src=&amp;quot;rsync://rsync.alpinelinux.org/alpine/&amp;quot;&lt;br /&gt;
dest=&amp;quot;/var/www/localhost/htdocs/alpine/&amp;quot;&lt;br /&gt;
lock=&amp;quot;/tmp/sync-mirror.lock&amp;quot;&lt;br /&gt;
topic=&amp;quot;$1&amp;quot;&lt;br /&gt;
dir=&amp;quot;$2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[ -z &amp;quot;$flock&amp;quot; ] &amp;amp;&amp;amp; exec env flock=1 flock $lock $0 &amp;quot;$@&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ -n &amp;quot;$dir&amp;quot; ] &amp;amp;&amp;amp; [ -d &amp;quot;$dest/${dir%/*}&amp;quot; ]; then&lt;br /&gt;
    logger &amp;quot;Syncing directory: $dir&amp;quot;&lt;br /&gt;
    src=&amp;quot;${src}${dir%/}/&amp;quot;&lt;br /&gt;
    dest=&amp;quot;${dest}${dir%/}/&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
    logger &amp;quot;Syncing all directories&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
    --archive \&lt;br /&gt;
    --update \&lt;br /&gt;
    --verbose \&lt;br /&gt;
    --progress \&lt;br /&gt;
    --timeout=600 \&lt;br /&gt;
    --delay-updates \&lt;br /&gt;
    --delete-after \&lt;br /&gt;
    &amp;quot;$src&amp;quot; \&lt;br /&gt;
    &amp;quot;$dest&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally start mqtt-exec and let it listen on msg.alpinelinux.org&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/mqtt-exec.sync-mirror start}}&lt;br /&gt;
&lt;br /&gt;
To make sure you are not missing any packages (in case something goes wrong with MQTT subscription) you can periodically sync all directories by adding the script to cron.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|ln -s /usr/local/bin/sync-mirror /etc/periodic/hourly/sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
Now watch your syslog as it should tell you when it will update directories in your local mirror.&lt;br /&gt;
&lt;br /&gt;
[[Category:Server]]&lt;br /&gt;
[[Category:Package Manager]]&lt;/div&gt;</summary>
		<author><name>Tetsumaki</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=15433</id>
		<title>How to setup a Alpine Linux mirror</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=15433"/>
		<updated>2018-08-11T18:53:31Z</updated>

		<summary type="html">&lt;p&gt;Tetsumaki: /* Setting up the cron job */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This document describes how to set up an Alpine Linux mirror and make it available via http and rsync.&lt;br /&gt;
&lt;br /&gt;
We will:&lt;br /&gt;
* create the dir where we have the mirror&lt;br /&gt;
* set up a cron job to sync with master mirror every hour&lt;br /&gt;
* set up lighttpd for http access&lt;br /&gt;
* set up rsync so other mirrors can rsync from you&lt;br /&gt;
&lt;br /&gt;
Make sure that you have enough disk space; each v3.x branch has around 20 GiB.&lt;br /&gt;
&lt;br /&gt;
Current (2018-01-03) disk usage:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!edge&lt;br /&gt;
!v2.4&lt;br /&gt;
!v2.5&lt;br /&gt;
!v2.6&lt;br /&gt;
!v2.7&lt;br /&gt;
!v3.0&lt;br /&gt;
!v3.1&lt;br /&gt;
!v3.2&lt;br /&gt;
!v3.3&lt;br /&gt;
!v3.4&lt;br /&gt;
!v3.5&lt;br /&gt;
!v3.6&lt;br /&gt;
!v3.7&lt;br /&gt;
!Total&lt;br /&gt;
|-&lt;br /&gt;
|71.3G        &lt;br /&gt;
|18.8G   &lt;br /&gt;
|10.4G   &lt;br /&gt;
|13.0G   &lt;br /&gt;
|16.5G   &lt;br /&gt;
|16.5G   &lt;br /&gt;
|17.5G   &lt;br /&gt;
|14.5G   &lt;br /&gt;
|19.0G   &lt;br /&gt;
|23.2G   &lt;br /&gt;
|32.5G   &lt;br /&gt;
|34.4G&lt;br /&gt;
|71.3G&lt;br /&gt;
|&#039;&#039;&#039;358.9G&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Setting up the cron job ==&lt;br /&gt;
Install rsync which will be used to sync from the master mirror.&lt;br /&gt;
{{Cmd|apk add rsync}}&lt;br /&gt;
&lt;br /&gt;
Save the following file as &#039;&#039;/etc/periodic/hourly/alpine-mirror&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
# make sure we never run 2 rsync at the same time&lt;br /&gt;
lockfile=&amp;quot;/tmp/alpine-mirror.lock&amp;quot;&lt;br /&gt;
if [ -z &amp;quot;$flock&amp;quot; ] ; then&lt;br /&gt;
  exec env flock=1 flock -n $lockfile &amp;quot;$0&amp;quot; &amp;quot;$@&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
src=rsync://rsync.alpinelinux.org/alpine/ &lt;br /&gt;
dest=/var/www/localhost/htdocs/alpine/&lt;br /&gt;
&lt;br /&gt;
# uncomment this to exclude old v2.x branches&lt;br /&gt;
#exclude=&amp;quot;--exclude v2.*&amp;quot;&lt;br /&gt;
&lt;br /&gt;
mkdir -p &amp;quot;$dest&amp;quot;&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
        --archive \&lt;br /&gt;
        --update \&lt;br /&gt;
        --hard-links \&lt;br /&gt;
        --delete \&lt;br /&gt;
        --delete-after \&lt;br /&gt;
        --delay-updates \&lt;br /&gt;
        --timeout=600 \&lt;br /&gt;
        $exclude \&lt;br /&gt;
        &amp;quot;$src&amp;quot; &amp;quot;$dest&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(or use [https://gist.github.com/jirutka/288c6fff7c0b8a835d143686207316be this script])&lt;br /&gt;
&lt;br /&gt;
Make it executable:&lt;br /&gt;
{{Cmd|&amp;lt;nowiki&amp;gt;chmod +x /etc/periodic/hourly/alpine-mirror&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now it will sync every hour. (given cron runs)&lt;br /&gt;
&lt;br /&gt;
== Setting up HTTP access via lighttpd ==&lt;br /&gt;
&lt;br /&gt;
Install the lighttpd server&lt;br /&gt;
{{Cmd|apk add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
Enable dir listings by uncommenting the following line in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 dir-listing.activate      = &amp;quot;enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Also set cache-control to force cache revalidate every 30 mins. Uncomment mod_setenv in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 &amp;quot;mod_setenv&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
Add also the following lines to &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 setenv.add-response-header += (           &lt;br /&gt;
         &amp;quot;Cache-Control&amp;quot; =&amp;gt; &amp;quot;must-revalidate&amp;quot;&lt;br /&gt;
 )&lt;br /&gt;
&lt;br /&gt;
Start lighttpd and make it start at boot:&lt;br /&gt;
{{Cmd|rc-service lighttpd start&lt;br /&gt;
rc-update add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
{{Note|You may wish to consider [[Darkhttpd]] as an alternative to [[Lighttpd]]&lt;br /&gt;
&lt;br /&gt;
If so, simply install, start and auto-start the webserver:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add darkhttpd &amp;amp;&amp;amp; rc-service darkhttpd start &amp;amp;&amp;amp; rc-update add darkhttpd}}&lt;br /&gt;
&lt;br /&gt;
Darkhttpd will, by default, offer directory listings and serve data from /var/www/localhost/htdocs/ &lt;br /&gt;
&lt;br /&gt;
See the main article on [[Darkhttpd]] for more configuration options}}&lt;br /&gt;
&lt;br /&gt;
== Setting up rsyncd ==&lt;br /&gt;
Add the following lines to &#039;&#039;/etc/rsyncd.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[alpine]&lt;br /&gt;
        path = /var/www/localhost/htdocs/alpine&lt;br /&gt;
        comment = My Alpine Linux Mirror&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally set a bandwidth limit in &#039;&#039;/etc/conf.d/rsyncd&#039;&#039;. In this example we limit to 500Kbytes/s (approx 5Mbit/s)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
RSYNC_OPTS=&amp;quot;--bwlimit=500&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mirror statistics ==&lt;br /&gt;
&lt;br /&gt;
Simple bandwidth statistics can be generated with vnstat.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add vnstat}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/vnstat.conf and replace the interface name with the appropriate one.&lt;br /&gt;
&lt;br /&gt;
Start vnstatd&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/vnstatd start }}&lt;br /&gt;
&lt;br /&gt;
copy the following script to /etc/periodic/15min/stats and make sure your crond is running.&lt;br /&gt;
please not that heredoc should be tab indented or the script will fail. A working copy can be found here: http://tpaste.us/RrMv&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
output=&amp;quot;/var/www/localhost/htdocs/.stats&amp;quot;&lt;br /&gt;
nic=&amp;quot;eth0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
generate_index() {&lt;br /&gt;
    cat &amp;lt;&amp;lt;-EOF&lt;br /&gt;
    &amp;lt;!doctype html&amp;gt;&lt;br /&gt;
    &amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;&lt;br /&gt;
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;cache-control&amp;quot; content=no-cache&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;3000&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;title&amp;gt;Alpine Linux mirror statistics&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;&lt;br /&gt;
        &amp;lt;table border=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;summary.png&amp;quot; alt=&amp;quot;summary&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;hours.png&amp;quot; alt=&amp;quot;hours&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td rowspan=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;days.png&amp;quot; alt=&amp;quot;days&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;top10.png&amp;quot; alt=&amp;quot;top10&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;months.png&amp;quot; alt=&amp;quot;months&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
        &amp;lt;/table&amp;gt;&lt;br /&gt;
    &amp;lt;/body&amp;gt;&lt;br /&gt;
    &amp;lt;/html&amp;gt;&lt;br /&gt;
    EOF&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if  [ ! -f &amp;quot;$output&amp;quot;/index.html ]; then&lt;br /&gt;
    mkdir -p $output&lt;br /&gt;
    generate_index &amp;gt; &amp;quot;$output&amp;quot;/index.html&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
for type in hours days months top10 summary hsummary vsummary; do&lt;br /&gt;
    vnstati --${type} -i $nic -o $output/${type}.png&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Update mirror from mqtt ==&lt;br /&gt;
&lt;br /&gt;
If you want your mirror to be really uptodate compared to our master mirror you can subscribe to Alpine Linux message server &amp;quot;msg.alpinelinux.org&amp;quot; and check for upload messages.&lt;br /&gt;
Add mqtt-exec to be able to execute processes when specific topics are being send.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| apk add mqtt-exec}}&lt;br /&gt;
&lt;br /&gt;
mqtt-exec supports running multiple time so we need to setup a specific config.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/init.d/mqtt-exec /etc/init.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/conf.d/mqtt-exec /etc/conf.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/conf.d/mqtt-exec.sync-mirror&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt_topics=&amp;quot;rsync/rsync.alpinelinux.org/#&amp;quot;&lt;br /&gt;
exec_user=&amp;quot;buildozer&amp;quot;&lt;br /&gt;
exec_command=&amp;quot;/usr/local/bin/sync-mirror&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the following file to /usr/local/bin/sync-mirror and make it executable (dont forget to update the variables).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
src=&amp;quot;rsync://rsync.alpinelinux.org/alpine/&amp;quot;&lt;br /&gt;
dest=&amp;quot;/var/www/localhost/htdocs/alpine/&amp;quot;&lt;br /&gt;
lock=&amp;quot;/tmp/sync-mirror.lock&amp;quot;&lt;br /&gt;
topic=&amp;quot;$1&amp;quot;&lt;br /&gt;
dir=&amp;quot;$2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[ -z &amp;quot;$flock&amp;quot; ] &amp;amp;&amp;amp; exec env flock=1 flock $lock $0 &amp;quot;$@&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ -n &amp;quot;$dir&amp;quot; ] &amp;amp;&amp;amp; [ -d &amp;quot;$dest/${dir%/*}&amp;quot; ]; then&lt;br /&gt;
    logger &amp;quot;Syncing directory: $dir&amp;quot;&lt;br /&gt;
    src=&amp;quot;${src}${dir%/}/&amp;quot;&lt;br /&gt;
    dest=&amp;quot;${dest}${dir%/}/&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
    logger &amp;quot;Syncing all directories&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
    --archive \&lt;br /&gt;
    --update \&lt;br /&gt;
    --verbose \&lt;br /&gt;
    --progress \&lt;br /&gt;
    --timeout=600 \&lt;br /&gt;
    --delay-updates \&lt;br /&gt;
    --delete-after \&lt;br /&gt;
    &amp;quot;$src&amp;quot; \&lt;br /&gt;
    &amp;quot;$dest&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally start mqtt-exec and let it listen on msg.alpinelinux.org&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/mqtt-exec.sync-mirror start}}&lt;br /&gt;
&lt;br /&gt;
To make sure you are not missing any packages (in case something goes wrong with MQTT subscription) you can periodically sync all directories by adding the script to cron.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|ln -s /usr/local/bin/sync-mirror /etc/periodic/hourly/sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
Now watch your syslog as it should tell you when it will update directories in your local mirror.&lt;br /&gt;
&lt;br /&gt;
[[Category:Server]]&lt;br /&gt;
[[Category:Package Manager]]&lt;/div&gt;</summary>
		<author><name>Tetsumaki</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=15432</id>
		<title>How to setup a Alpine Linux mirror</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=15432"/>
		<updated>2018-08-11T18:44:21Z</updated>

		<summary type="html">&lt;p&gt;Tetsumaki: /* Mirror statistics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This document describes how to set up an Alpine Linux mirror and make it available via http and rsync.&lt;br /&gt;
&lt;br /&gt;
We will:&lt;br /&gt;
* create the dir where we have the mirror&lt;br /&gt;
* set up a cron job to sync with master mirror every hour&lt;br /&gt;
* set up lighttpd for http access&lt;br /&gt;
* set up rsync so other mirrors can rsync from you&lt;br /&gt;
&lt;br /&gt;
Make sure that you have enough disk space; each v3.x branch has around 20 GiB.&lt;br /&gt;
&lt;br /&gt;
Current (2018-01-03) disk usage:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!edge&lt;br /&gt;
!v2.4&lt;br /&gt;
!v2.5&lt;br /&gt;
!v2.6&lt;br /&gt;
!v2.7&lt;br /&gt;
!v3.0&lt;br /&gt;
!v3.1&lt;br /&gt;
!v3.2&lt;br /&gt;
!v3.3&lt;br /&gt;
!v3.4&lt;br /&gt;
!v3.5&lt;br /&gt;
!v3.6&lt;br /&gt;
!v3.7&lt;br /&gt;
!Total&lt;br /&gt;
|-&lt;br /&gt;
|71.3G        &lt;br /&gt;
|18.8G   &lt;br /&gt;
|10.4G   &lt;br /&gt;
|13.0G   &lt;br /&gt;
|16.5G   &lt;br /&gt;
|16.5G   &lt;br /&gt;
|17.5G   &lt;br /&gt;
|14.5G   &lt;br /&gt;
|19.0G   &lt;br /&gt;
|23.2G   &lt;br /&gt;
|32.5G   &lt;br /&gt;
|34.4G&lt;br /&gt;
|71.3G&lt;br /&gt;
|&#039;&#039;&#039;358.9G&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Setting up the cron job ==&lt;br /&gt;
Install rsync which will be used to sync from the master mirror.&lt;br /&gt;
{{Cmd|apk add rsync}}&lt;br /&gt;
&lt;br /&gt;
Save the following file as &#039;&#039;/etc/periodic/hourly/alpine-mirror&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
# make sure we never run 2 rsync at the same time&lt;br /&gt;
lockfile=&amp;quot;/tmp/alpine-mirror.lock&amp;quot;&lt;br /&gt;
if [ -z &amp;quot;$flock&amp;quot; ] ; then&lt;br /&gt;
  exec env flock=1 flock -n $lockfile &amp;quot;$0&amp;quot; &amp;quot;$@&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
src=rsync://rsync.alpinelinux.org/alpine/ &lt;br /&gt;
dest=/var/www/localhost/htdocs/alpine/&lt;br /&gt;
&lt;br /&gt;
# uncomment this to exclude old v2.x branches&lt;br /&gt;
#exclude=&amp;quot;--exclude v2.*&amp;quot;&lt;br /&gt;
&lt;br /&gt;
mkdir -p &amp;quot;$dest&amp;quot;&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
        --archive \&lt;br /&gt;
        --update \&lt;br /&gt;
        --hard-links \&lt;br /&gt;
        --delete \&lt;br /&gt;
        --delete-after \&lt;br /&gt;
        --delay-updates \&lt;br /&gt;
        --timeout=600 \&lt;br /&gt;
        $exclude \&lt;br /&gt;
        &amp;quot;$src&amp;quot; &amp;quot;$dest&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(or use [https://gist.github.com/jirutka/288c6fff7c0b8a835d143686207316be this script])&lt;br /&gt;
&lt;br /&gt;
Make it executable:&lt;br /&gt;
{{Cmd|&amp;lt;nowiki&amp;gt;chmod +x /etc/periodic/hourly/alpine-mirror&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now it will sync every hour. (given cron runs)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting up HTTP access via lighttpd ==&lt;br /&gt;
&lt;br /&gt;
Install the lighttpd server&lt;br /&gt;
{{Cmd|apk add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
Enable dir listings by uncommenting the following line in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 dir-listing.activate      = &amp;quot;enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Also set cache-control to force cache revalidate every 30 mins. Uncomment mod_setenv in &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 &amp;quot;mod_setenv&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
Add also the following lines to &#039;&#039;/etc/lighttpd/lighttpd.conf&#039;&#039;:&lt;br /&gt;
 setenv.add-response-header += (           &lt;br /&gt;
         &amp;quot;Cache-Control&amp;quot; =&amp;gt; &amp;quot;must-revalidate&amp;quot;&lt;br /&gt;
 )&lt;br /&gt;
&lt;br /&gt;
Start lighttpd and make it start at boot:&lt;br /&gt;
{{Cmd|rc-service lighttpd start&lt;br /&gt;
rc-update add lighttpd}}&lt;br /&gt;
&lt;br /&gt;
{{Note|You may wish to consider [[Darkhttpd]] as an alternative to [[Lighttpd]]&lt;br /&gt;
&lt;br /&gt;
If so, simply install, start and auto-start the webserver:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add darkhttpd &amp;amp;&amp;amp; rc-service darkhttpd start &amp;amp;&amp;amp; rc-update add darkhttpd}}&lt;br /&gt;
&lt;br /&gt;
Darkhttpd will, by default, offer directory listings and serve data from /var/www/localhost/htdocs/ &lt;br /&gt;
&lt;br /&gt;
See the main article on [[Darkhttpd]] for more configuration options}}&lt;br /&gt;
&lt;br /&gt;
== Setting up rsyncd ==&lt;br /&gt;
Add the following lines to &#039;&#039;/etc/rsyncd.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[alpine]&lt;br /&gt;
        path = /var/www/localhost/htdocs/alpine&lt;br /&gt;
        comment = My Alpine Linux Mirror&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally set a bandwidth limit in &#039;&#039;/etc/conf.d/rsyncd&#039;&#039;. In this example we limit to 500Kbytes/s (approx 5Mbit/s)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
RSYNC_OPTS=&amp;quot;--bwlimit=500&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mirror statistics ==&lt;br /&gt;
&lt;br /&gt;
Simple bandwidth statistics can be generated with vnstat.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add vnstat}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/vnstat.conf and replace the interface name with the appropriate one.&lt;br /&gt;
&lt;br /&gt;
Start vnstatd&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/vnstatd start }}&lt;br /&gt;
&lt;br /&gt;
copy the following script to /etc/periodic/15min/stats and make sure your crond is running.&lt;br /&gt;
please not that heredoc should be tab indented or the script will fail. A working copy can be found here: http://tpaste.us/RrMv&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env sh&lt;br /&gt;
&lt;br /&gt;
output=&amp;quot;/var/www/localhost/htdocs/.stats&amp;quot;&lt;br /&gt;
nic=&amp;quot;eth0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
generate_index() {&lt;br /&gt;
    cat &amp;lt;&amp;lt;-EOF&lt;br /&gt;
    &amp;lt;!doctype html&amp;gt;&lt;br /&gt;
    &amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;&lt;br /&gt;
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;cache-control&amp;quot; content=no-cache&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;3000&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;title&amp;gt;Alpine Linux mirror statistics&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;&lt;br /&gt;
        &amp;lt;table border=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;summary.png&amp;quot; alt=&amp;quot;summary&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;hours.png&amp;quot; alt=&amp;quot;hours&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td rowspan=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;days.png&amp;quot; alt=&amp;quot;days&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;top10.png&amp;quot; alt=&amp;quot;top10&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
            &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;months.png&amp;quot; alt=&amp;quot;months&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
        &amp;lt;/table&amp;gt;&lt;br /&gt;
    &amp;lt;/body&amp;gt;&lt;br /&gt;
    &amp;lt;/html&amp;gt;&lt;br /&gt;
    EOF&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if  [ ! -f &amp;quot;$output&amp;quot;/index.html ]; then&lt;br /&gt;
    mkdir -p $output&lt;br /&gt;
    generate_index &amp;gt; &amp;quot;$output&amp;quot;/index.html&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
for type in hours days months top10 summary hsummary vsummary; do&lt;br /&gt;
    vnstati --${type} -i $nic -o $output/${type}.png&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Update mirror from mqtt ==&lt;br /&gt;
&lt;br /&gt;
If you want your mirror to be really uptodate compared to our master mirror you can subscribe to Alpine Linux message server &amp;quot;msg.alpinelinux.org&amp;quot; and check for upload messages.&lt;br /&gt;
Add mqtt-exec to be able to execute processes when specific topics are being send.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| apk add mqtt-exec}}&lt;br /&gt;
&lt;br /&gt;
mqtt-exec supports running multiple time so we need to setup a specific config.&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/init.d/mqtt-exec /etc/init.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s /etc/conf.d/mqtt-exec /etc/conf.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
edit /etc/conf.d/mqtt-exec.sync-mirror&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt_topics=&amp;quot;rsync/rsync.alpinelinux.org/#&amp;quot;&lt;br /&gt;
exec_user=&amp;quot;buildozer&amp;quot;&lt;br /&gt;
exec_command=&amp;quot;/usr/local/bin/sync-mirror&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Copy the following file to /usr/local/bin/sync-mirror and make it executable (dont forget to update the variables).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
src=&amp;quot;rsync://rsync.alpinelinux.org/alpine/&amp;quot;&lt;br /&gt;
dest=&amp;quot;/var/www/localhost/htdocs/alpine/&amp;quot;&lt;br /&gt;
lock=&amp;quot;/tmp/sync-mirror.lock&amp;quot;&lt;br /&gt;
topic=&amp;quot;$1&amp;quot;&lt;br /&gt;
dir=&amp;quot;$2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[ -z &amp;quot;$flock&amp;quot; ] &amp;amp;&amp;amp; exec env flock=1 flock $lock $0 &amp;quot;$@&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ -n &amp;quot;$dir&amp;quot; ] &amp;amp;&amp;amp; [ -d &amp;quot;$dest/${dir%/*}&amp;quot; ]; then&lt;br /&gt;
    logger &amp;quot;Syncing directory: $dir&amp;quot;&lt;br /&gt;
    src=&amp;quot;${src}${dir%/}/&amp;quot;&lt;br /&gt;
    dest=&amp;quot;${dest}${dir%/}/&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
    logger &amp;quot;Syncing all directories&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
/usr/bin/rsync \&lt;br /&gt;
    --archive \&lt;br /&gt;
    --update \&lt;br /&gt;
    --verbose \&lt;br /&gt;
    --progress \&lt;br /&gt;
    --timeout=600 \&lt;br /&gt;
    --delay-updates \&lt;br /&gt;
    --delete-after \&lt;br /&gt;
    &amp;quot;$src&amp;quot; \&lt;br /&gt;
    &amp;quot;$dest&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally start mqtt-exec and let it listen on msg.alpinelinux.org&lt;br /&gt;
&lt;br /&gt;
{{Cmd|/etc/init.d/mqtt-exec.sync-mirror start}}&lt;br /&gt;
&lt;br /&gt;
To make sure you are not missing any packages (in case something goes wrong with MQTT subscription) you can periodically sync all directories by adding the script to cron.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|ln -s /usr/local/bin/sync-mirror /etc/periodic/hourly/sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
Now watch your syslog as it should tell you when it will update directories in your local mirror.&lt;br /&gt;
&lt;br /&gt;
[[Category:Server]]&lt;br /&gt;
[[Category:Package Manager]]&lt;/div&gt;</summary>
		<author><name>Tetsumaki</name></author>
	</entry>
</feed>