<?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=Ikke</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=Ikke"/>
	<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/wiki/Special:Contributions/Ikke"/>
	<updated>2026-05-01T02:57:29Z</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=32151</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=32151"/>
		<updated>2026-03-09T21:37:00Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Update mirror stats, split table in 2&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 (2026-03-09) disk usage in GB:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!edge&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;
!v3.10&lt;br /&gt;
!v3.11&lt;br /&gt;
!v3.12&lt;br /&gt;
!v3.13&lt;br /&gt;
!v3.14&lt;br /&gt;
!v3.15&lt;br /&gt;
!v3.16&lt;br /&gt;
|-&lt;br /&gt;
|594&lt;br /&gt;
|17&lt;br /&gt;
|18&lt;br /&gt;
|15&lt;br /&gt;
|20&lt;br /&gt;
|24&lt;br /&gt;
|27&lt;br /&gt;
|44&lt;br /&gt;
|43&lt;br /&gt;
|59&lt;br /&gt;
|73&lt;br /&gt;
|91&lt;br /&gt;
|126&lt;br /&gt;
|148&lt;br /&gt;
|156&lt;br /&gt;
|181&lt;br /&gt;
|194&lt;br /&gt;
|209&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!v3.17&lt;br /&gt;
!v3.18&lt;br /&gt;
!v3.19&lt;br /&gt;
!v3.20&lt;br /&gt;
!v3.21&lt;br /&gt;
!v3.22&lt;br /&gt;
!v3.23&lt;br /&gt;
!total&lt;br /&gt;
|-&lt;br /&gt;
|240&lt;br /&gt;
|290&lt;br /&gt;
|313&lt;br /&gt;
|480&lt;br /&gt;
|477&lt;br /&gt;
|451&lt;br /&gt;
|509&lt;br /&gt;
|&#039;&#039;&#039;4798&#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;
#!/bin/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 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 v3.22 v3.23; 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=$(( old_total + size ))&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;
#!/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;
== 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|rc-service 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: https://tpaste.us/RrMv&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/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 mqtt-exec /etc/init.d/mqtt-exec.sync-mirror}}&lt;br /&gt;
&lt;br /&gt;
{{Cmd| ln -s 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|rc-service 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;
== Partial mirror using nginx ==&lt;br /&gt;
&lt;br /&gt;
For a private mirror it might make sense to sync only the newest versions or some architectures of Alpine to save space, but if you &#039;&#039;do&#039;&#039; point an old Alpine version to your mirror they should still be able to install packages. We can achieve this by using nginx to serve the mirrored content and redirect all requests with 404 errors to a public mirror.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s assume you chose to only mirror Alpine versions up from v3.13. If a client asks your mirror for v.3.10 it should redirect to another mirror.&lt;br /&gt;
&lt;br /&gt;
Your nginx config server block should look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server {&lt;br /&gt;
        listen 80;&lt;br /&gt;
        server_name alpine.mydomain.local;&lt;br /&gt;
        root /data/alpine;          # point to where your alpine mirror is located. make sure nginx is allowed to read it&lt;br /&gt;
        autoindex on;               # Enable indexing&lt;br /&gt;
&lt;br /&gt;
        error_page 404 = @alpinemirror;&lt;br /&gt;
&lt;br /&gt;
        location @alpinemirror&lt;br /&gt;
        {&lt;br /&gt;
          return 302 http://dl-cdn.alpinelinux.org/alpine$request_uri;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The corresponding sync script could look something like this:&lt;br /&gt;
&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=/data/alpine/&lt;br /&gt;
&lt;br /&gt;
  exclude=&amp;quot;--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&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  mkdir -p &amp;quot;$dest&amp;quot;&lt;br /&gt;
  /usr/bin/rsync -vvv \&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;
  --delete-excluded \&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Server]]&lt;br /&gt;
[[Category:Package Manager]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Draft_Release_Notes_for_Alpine_3.24.0&amp;diff=32054</id>
		<title>Draft Release Notes for Alpine 3.24.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Draft_Release_Notes_for_Alpine_3.24.0&amp;diff=32054"/>
		<updated>2026-02-15T14:29:24Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As always, make sure to read [[Upgrading Alpine to a new major release]] when upgrading to a new release.&lt;br /&gt;
&lt;br /&gt;
If you experience any issues with the upgrade, please let us know and file an issue in our repositories.&lt;br /&gt;
&lt;br /&gt;
{{Note|Alpine 3.24 is WIP, see https://gitlab.alpinelinux.org/groups/alpine/-/milestones/27 for important changes. For the latest release 3.23, look at [[Release Notes for Alpine 3.23.0]].}}&lt;br /&gt;
&lt;br /&gt;
== Important changes ==&lt;br /&gt;
&lt;br /&gt;
=== /usr merge ===&lt;br /&gt;
&lt;br /&gt;
New installations can opt-in to being /usr-merged, by setting the &amp;lt;code&amp;gt;BOOTSTRAP_USR_MERGED&amp;lt;/code&amp;gt; environment variable to &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; before running &amp;lt;code&amp;gt;setup-disk&amp;lt;/code&amp;gt;. Manual migration is also possible by installing the &amp;lt;code&amp;gt;merge-usr&amp;lt;/code&amp;gt; package and running its binary as root. For more details see the [https://alpinelinux.org/posts/2025-10-01-usr-merge.html official announcement].&lt;br /&gt;
&lt;br /&gt;
== Significant changes ==&lt;br /&gt;
&lt;br /&gt;
=== GTK+ 3.0 moved to community ===&lt;br /&gt;
&lt;br /&gt;
{{Note|TODO}}&lt;br /&gt;
&lt;br /&gt;
=== gdk-pixbuf uses glycin/glycin loaders got split ===&lt;br /&gt;
&lt;br /&gt;
{{Note|TODO}}&lt;br /&gt;
&lt;br /&gt;
=== Python setuptools 82.0.0 removed pkg_resources === &lt;br /&gt;
&lt;br /&gt;
py3-setuptools has been upgraded to 82.0.0, [https://setuptools.pypa.io/en/latest/history.html#v82-0-0 which removed pkg_resources]. Any project that still depends on it will no longer work and should migrate to its successors.&lt;br /&gt;
&lt;br /&gt;
== Note-worthy updates ==&lt;br /&gt;
&lt;br /&gt;
As always, many packages were upgraded. Make sure to read the individual release notes of the projects you use.&lt;br /&gt;
&lt;br /&gt;
* BIRD TODO&lt;br /&gt;
* busybox TODO&lt;br /&gt;
* Deno TODO&lt;br /&gt;
* ffmpeg TODO&lt;br /&gt;
* GCC TODO&lt;br /&gt;
* GNOME TODO&lt;br /&gt;
* Go TODO&lt;br /&gt;
* ISC BIND TODO&lt;br /&gt;
* ISC Kea TODO&lt;br /&gt;
* KDE Plasma TODO&lt;br /&gt;
* Linux TODO&lt;br /&gt;
* LLVM TODO&lt;br /&gt;
* LXQt TODO&lt;br /&gt;
* .NET TODO&lt;br /&gt;
* nginx TODO&lt;br /&gt;
* NodeJS TODO (LTS)&lt;br /&gt;
* OpenJDK TODO&lt;br /&gt;
* PHP TODO&lt;br /&gt;
* Qt TODO&lt;br /&gt;
* Ruby TODO&lt;br /&gt;
* Rust TODO&lt;br /&gt;
* wlroots TODO&lt;br /&gt;
* zigbee2mqtt TODO&lt;br /&gt;
&lt;br /&gt;
=== COSMIC 1 ===&lt;br /&gt;
&lt;br /&gt;
This release makes the COSMIC desktop available in community as {{pkg|cosmic*}} including {{pkg|xdg-desktop-portal-cosmic*}}.&lt;br /&gt;
&lt;br /&gt;
=== qemu-binfmt service deprecated ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;qemu-binfmt&amp;lt;/code&amp;gt; service from the package &amp;lt;code&amp;gt;qemu-openrc&amp;lt;/code&amp;gt; is deprecated, in favor of &amp;lt;code&amp;gt;binfmt.d&amp;lt;/code&amp;gt; config files from user mode qemu packages (eg. &amp;lt;code&amp;gt;qemu-aarch64 qemu-x86_64&amp;lt;/code&amp;gt;) combined with the &amp;lt;code&amp;gt;binfmt&amp;lt;/code&amp;gt; service.&lt;br /&gt;
&lt;br /&gt;
If you are using &amp;lt;code&amp;gt;qemu-binfmt&amp;lt;/code&amp;gt;, run:&lt;br /&gt;
{{Cmd|# rc-update del qemu-binfmt &amp;amp;&amp;amp; rc-update add binfmt}}&lt;br /&gt;
&lt;br /&gt;
Contrary to the behavior of &amp;lt;code&amp;gt;qemu-binfmt&amp;lt;/code&amp;gt;, the new default configuration prevents setuid programs from granting privileges. If you need to execute setuid programs via qemu:&lt;br /&gt;
&lt;br /&gt;
* make sure you understand the implications: with this configuration, any user with execute access to any foreign-architecture setuid binary can execute arbitrary code with the privileges of that binary&lt;br /&gt;
* if you accept the risks, copy &amp;lt;code&amp;gt;/usr/lib/binfmt.d/qemu-*.conf&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/etc/binfmt.d&amp;lt;/code&amp;gt;, edit to add the &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; flag, and restart binfmt.&lt;br /&gt;
&lt;br /&gt;
See [https://docs.kernel.org/admin-guide/binfmt-misc.html Kernel admin guide - binfmt] for more information about the &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;credentials&amp;lt;/code&amp;gt;) flag.&lt;br /&gt;
&lt;br /&gt;
== Significant removals ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== {{Pkg|binutils-gold}} removed ===&lt;br /&gt;
&lt;br /&gt;
{{Note|TODO: not done yet and maybe not in 3.24}}&lt;br /&gt;
&lt;br /&gt;
The gold linker got deprecated by upstream on February 2025 and in Alpine v3.24 we removed it from our repositories.&lt;br /&gt;
&lt;br /&gt;
Previously this has been hold because of Go&#039;s use of the gold linker for ARM architectures, but these days the default ld linker works as expected.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== py3-six ===&lt;br /&gt;
&lt;br /&gt;
{{Note|TODO https://gitlab.alpinelinux.org/alpine/aports/-/work_items/17822}}&lt;br /&gt;
&lt;br /&gt;
=== More GTK 2 removals ===&lt;br /&gt;
&lt;br /&gt;
{{Note|TODO}}&lt;br /&gt;
&lt;br /&gt;
=== More Qt5 removals ===&lt;br /&gt;
&lt;br /&gt;
{{Note|TODO}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;[[Release Notes for Alpine 3.23.0|← Previous page: Release Notes for Alpine 3.23.0]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:News]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Dynamic_Multipoint_VPN_(DMVPN)&amp;diff=30765</id>
		<title>Dynamic Multipoint VPN (DMVPN)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Dynamic_Multipoint_VPN_(DMVPN)&amp;diff=30765"/>
		<updated>2025-08-21T12:42:31Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Mark page as obsolete / outdated&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Obsolete|Information is outdated. See https://gitlab.alpinelinux.org/alpine/dmvpn-tools}}&lt;br /&gt;
&lt;br /&gt;
{{TOC right}}&lt;br /&gt;
&lt;br /&gt;
https://alpinelinux.org/about under &#039;&#039;&#039;Why the Name Alpine?&#039;&#039;&#039; states:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The first open-source implementation of Cisco&#039;s DMVPN, called OpenNHRP, was written for Alpine Linux.&#039;&#039;[https://web.archive.org/web/20110508001131/https://alpinelinux.org/about]&lt;br /&gt;
&lt;br /&gt;
So the aim of this document is to be the reference Linux DMVPN setup, with all the networking services needed for the clients that will use the DMVPN (DNS, firewall, etc.).  [[Small Office Services]] offers additional services such as DHCP for clients, http proxying, and a basic SIP telephone system.&lt;br /&gt;
&lt;br /&gt;
= Terminology =&lt;br /&gt;
;NBMA: &#039;&#039;Non-Broadcast Multi-Access&#039;&#039; network as described in [https://datatracker.ietf.org/doc/html/rfc2332 RFC 2332]&lt;br /&gt;
&lt;br /&gt;
;Hub: the &#039;&#039;Next Hop Server&#039;&#039; (NHS) performing the Next Hop Resolution Protocol service within the NBMA cloud.&lt;br /&gt;
&lt;br /&gt;
;Spoke: the &#039;&#039;Next Hop Resolution Protocol Client&#039;&#039; (NHC) which initiates NHRP requests of various types in order to obtain access to the NHRP service.&lt;br /&gt;
&lt;br /&gt;
{{Tip|At the time of this writing the recommended Alpine version for building a DMVPN should be at minimum 2.4.11. Don&#039;t use 2.5.x, or 2.6.0 since the kernel has in-tunnel IP fragmentation issues. Alpine 3.0 has also a Musl issue in getprotobyname(). Alpine 2.7.x has been thoroughly tested and 3.0.3 hasn&#039;t shown any issue so far.}}&lt;br /&gt;
&lt;br /&gt;
{{Note|This document assumes that all Alpine installations are run in [[Installation#Basics|diskless mode]] and that the configuration is saved on USB key}}&lt;br /&gt;
&lt;br /&gt;
= Hardware =&lt;br /&gt;
If you need gigabits throughput you should go for a processor with [https://www.intel.com/content/www/us/en/developer/articles/technical/advanced-encryption-standard-instructions-aes-ni.html AES-NI] and [https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sha-extensions.html SHA Extensions].&lt;br /&gt;
&lt;br /&gt;
= Extract Certificates =&lt;br /&gt;
We will use certificates for DMVPN and for OpenVPN (RoadWarrior clients). If you are in need to generate your own certificates, please see [[Generating_SSL_certs_with_ACF]]. You should use a separate machine for this purpose. If you downloaded the certificates on a Windows machine, you may use [https://winscp.net/eng/download.php WinSCP] to copy them on the DMVPN box.&lt;br /&gt;
&lt;br /&gt;
Here are the general purpose instruction for extracting certificates from pfx files:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|openssl pkcs12 -in cert.pfx -cacerts -nokeys -out cacert.pem&lt;br /&gt;
openssl pkcs12 -in cert.pfx -nocerts -nodes -out serverkey.pem&lt;br /&gt;
openssl pkcs12 -in cert.pfx -nokeys -clcerts -out cert.pem&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Set appropriate permission for your certificate files:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|chmod 600 *.pem *.pfx}}&lt;br /&gt;
&lt;br /&gt;
= Spoke Node =&lt;br /&gt;
A local spoke node network has support for multiple ISP connections, along with redundant layer 2 switches.  At least one 802.1q capable switch is required, and a second is optional for redundancy purposes.  The typical spoke node network looks like:&lt;br /&gt;
&lt;br /&gt;
[[File:DMVPN-Spoke.png]]&lt;br /&gt;
&lt;br /&gt;
== Boot Alpine USB == &lt;br /&gt;
Follow the instructions on [[Create_a_Bootable_USB]] about how to create a bootable USB.&lt;br /&gt;
&lt;br /&gt;
== Alpine Setup ==&lt;br /&gt;
We will setup the network interfaces as follows:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;Interface&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;Description&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;Subnet&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bond0.3&lt;br /&gt;
|Management&lt;br /&gt;
|10.1.0.129/26&lt;br /&gt;
|-&lt;br /&gt;
|bond0.101&lt;br /&gt;
|LAN&lt;br /&gt;
|10.1.0.0/25&lt;br /&gt;
|-&lt;br /&gt;
|bond0.256&lt;br /&gt;
|Internet from ISP1&lt;br /&gt;
|Allocated from ISP&lt;br /&gt;
|-&lt;br /&gt;
|bond0.257&lt;br /&gt;
|Internet from ISP2&lt;br /&gt;
|Allocated from ISP&lt;br /&gt;
|-&lt;br /&gt;
|bond0.620&lt;br /&gt;
|Transit between wifi proxy and dmvpn spoke node&lt;br /&gt;
|10.1.0.252/30&lt;br /&gt;
|-&lt;br /&gt;
|bond0.701&lt;br /&gt;
|WiFi clients (no access to DMVPN network)&lt;br /&gt;
|172.17.48.0/24&lt;br /&gt;
|-&lt;br /&gt;
|bond0.1101&lt;br /&gt;
|Voice&lt;br /&gt;
|10.2.0.0/24&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Cmd|setup-alpine}}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;You will be prompted something like this...&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;Suggestion on what you could enter...&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Select keyboard layout [none]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Type an appropriate layout for you&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Select variant:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Type an appropriate layout for you (if prompted)&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Enter system hostname (short form, e.g. &#039;foo&#039;) [localhost]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Enter the hostname, e.g.&#039;&#039; &#039;&#039;&#039;vpnc&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Available interfaces are: eth0&amp;lt;br&amp;gt;Enter &#039;?&#039; for help on bridges, bonding and vlans.&amp;lt;br&amp;gt;Which one do you want to initialize? (or &#039;?&#039; done&#039;)&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Enter&#039;&#039; &#039;&#039;&#039;bond0.101&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Available bond slaves are: eth0 eth1&amp;lt;br&amp;gt;Which slave(s) do you want to add to bond0? (or &#039;done&#039;) [eth0]&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;&#039;eth0 eth1&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;IP address for bond0? (or &#039;dhcp&#039;, &#039;none&#039;, &#039;?&#039;) [none]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Press Enter confirming &#039;none&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;IP address for bond0.101? (or &#039;dhcp&#039;, &#039;none&#039;, &#039;?&#039;) [dhcp]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Enter the IP address of your LAN interface, e.g.&#039;&#039; &#039;&#039;&#039;10.1.0.1&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Netmask? [255.255.255.0]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Press Enter confirming &#039;255.255.255.0&#039; or type another appropriate subnet mask&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Gateway? (or &#039;none&#039;) [none]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Press Enter confirming &#039;none&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Do you want to do any manual network configuration? [no]&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;&#039;yes&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;Make a copy of the bond0.101 configuration for bond0.620, bond0.701, bond0.1101, bond0.256 and bond0.257 (optional) interfaces.&amp;lt;br&amp;gt;Don&#039;t forget to add a gateway and a metric value for ISP interfaces when multiple gateways are set.&amp;lt;br&amp;gt;Save and close the file (:wq)&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;DNS domain name? (e.g. &#039;bar.com&#039;) []:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Enter the domain name of your intranet, e.g.,&#039;&#039; &#039;&#039;&#039;example.net&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;DNS nameservers(s)? []:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;&#039;8.8.8.8 8.8.4.4&#039;&#039;&#039; (we will change them later)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Changing password for root&amp;lt;br&amp;gt;New password:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Enter a secure password for the console&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Retype password:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Retype the above password&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Which timezone are you in? (&#039;?&#039; for list) [UTC]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Press Enter confirming &#039;UTC&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;HTTP/FTP proxy URL? (e.g. &#039;&amp;lt;nowiki&amp;gt;http://proxy:8080&amp;lt;/nowiki&amp;gt;&#039;, or &#039;none&#039;) [none]&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Press Enter confirming &#039;none&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Enter mirror number (1-9) or URL to add (or r/f/e/done) [f]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Select a mirror close to you and press Enter&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Which SSH server? (&#039;openssh&#039;, &#039;dropbear&#039; or &#039;none&#039;) [openssh]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Press Enter confirming &#039;openssh&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Which NTP client to run? (&#039;openntpd&#039;, &#039;chrony&#039; or &#039;none&#039;) [chrony]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Press Enter confirming &#039;chrony&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Which disk(s) would you like to use? (or &#039;?&#039; for help or &#039;none&#039;) [none]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Press Enter confirming &#039;none&#039; or type &#039;none&#039; if needed&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Enter where to store configs (&#039;floppy&#039;, &#039;usb&#039; or &#039;none&#039;) [usb]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Press Enter confirming &#039;usb&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;Enter apk cache directory (or &#039;?&#039; or &#039;none&#039;) [/media/usb/cache]:&amp;lt;/code&amp;gt;&lt;br /&gt;
|&#039;&#039;Press Enter confirming &#039;/media/usb/cache&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Networking ==&lt;br /&gt;
Update the networking configuration.&lt;br /&gt;
&lt;br /&gt;
With your favorite editor open &amp;lt;code&amp;gt;/etc/network/interfaces&amp;lt;/code&amp;gt; and add interfaces:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/network/interfaces|&lt;br /&gt;
     ...&lt;br /&gt;
&lt;br /&gt;
auto bond0.101&lt;br /&gt;
iface bond0.101 inet static&lt;br /&gt;
        address 10.1.0.1&lt;br /&gt;
        netmask 255.255.255.192&lt;br /&gt;
&lt;br /&gt;
auto bond0.620&lt;br /&gt;
iface bond0.620 inet static&lt;br /&gt;
        address 10.1.0.253&lt;br /&gt;
        netmask 255.255.255.252&lt;br /&gt;
&lt;br /&gt;
auto bond0.701&lt;br /&gt;
iface bond0.101 inet static&lt;br /&gt;
        address 172.17.48.1&lt;br /&gt;
        netmask 255.255.255.0&lt;br /&gt;
&lt;br /&gt;
auto bond0.1101&lt;br /&gt;
iface bond0.101 inet static&lt;br /&gt;
        address 10.2.0.1&lt;br /&gt;
        netmask 255.255.255.0&lt;br /&gt;
&lt;br /&gt;
auto bond0.256&lt;br /&gt;
iface bond0.256 inet static&lt;br /&gt;
        address &amp;lt;%ISP1_IP_ADDRESS%&amp;gt;&lt;br /&gt;
        netmask &amp;lt;%ISP1_NETMASK%&amp;gt;&lt;br /&gt;
&lt;br /&gt;
auto bond0.257&lt;br /&gt;
iface bond0.257 inet static&lt;br /&gt;
        address &amp;lt;%ISP2_IP_ADDRESS%&amp;gt;&lt;br /&gt;
        netmask &amp;lt;%ISP2_NETMASK%&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Bonding ==&lt;br /&gt;
Update the bonding configuration.&lt;br /&gt;
&lt;br /&gt;
With your favorite editor open &amp;lt;code&amp;gt;/etc/network/interfaces&amp;lt;/code&amp;gt; and add &amp;lt;code&amp;gt;bond-mode&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bond-miimon&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bond-updelay&amp;lt;/code&amp;gt; parameters to the &amp;lt;code&amp;gt;bond0&amp;lt;/code&amp;gt; stanza:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/network/interfaces|&lt;br /&gt;
auto bond0&lt;br /&gt;
iface bond0 inet manual&lt;br /&gt;
     bond-slaves eth0 eth1&lt;br /&gt;
     bond-mode balance-tlb&lt;br /&gt;
     bond-miimon 100&lt;br /&gt;
     bond-updelay 500&lt;br /&gt;
     ...&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Bring up the new bonding settings:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|ifdown bond0&lt;br /&gt;
ifup bond0}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Physically install ==&lt;br /&gt;
At this point, you&#039;re ready to connect the VPN Spoke Node to the network if you haven&#039;t already done so.  Please set up an 802.1q capable switch with the VLANs listed in AlpineSetup section.  Once done, tag all of the VLANs on one port.  Connect that port to &amp;lt;code&amp;gt;eth0&amp;lt;/code&amp;gt;.  Then, connect your first ISP&#039;s CPE to a switchport with VLAN 256 untagged.&lt;br /&gt;
&lt;br /&gt;
== SSH ==&lt;br /&gt;
Remove password authentication and DNS reverse lookup:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|sed -i &amp;quot;s/.PasswordAuthentication yes/PasswordAuthentication no/&amp;quot; /etc/ssh/sshd_config&lt;br /&gt;
sed -i &amp;quot;s/.UseDNS yes/UseDNS no/&amp;quot; /etc/ssh/sshd_config}}&lt;br /&gt;
&lt;br /&gt;
Restart ssh:&lt;br /&gt;
{{Cmd|rc-service sshd restart}}&lt;br /&gt;
&lt;br /&gt;
== NTP server ==&lt;br /&gt;
In order to have attached devices syncing their time agains this host, we need to do some modifications to chrony config.&amp;lt;BR&amp;gt;&lt;br /&gt;
Add &#039;&amp;lt;code&amp;gt;allow all&amp;lt;/code&amp;gt;&#039; to the end of the &#039;&amp;lt;code&amp;gt;/etc/chrony/chrony.conf&amp;lt;/code&amp;gt;&#039; so the file looks something like this:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/chrony/chrony.conf|&lt;br /&gt;
server pool.ntp.org &lt;br /&gt;
initstepslew 10 pool.ntp.org&lt;br /&gt;
commandkey 10&lt;br /&gt;
keyfile /etc/chrony/chrony.keys&lt;br /&gt;
driftfile /etc/chrony/chrony.drift&lt;br /&gt;
allow all&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Restart chronyd for the changes to take effect&lt;br /&gt;
 {{cmd|rc-service chronyd restart}}&lt;br /&gt;
&lt;br /&gt;
== Recursive DNS  ==&lt;br /&gt;
Install package(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add -U unbound}}&lt;br /&gt;
&lt;br /&gt;
With your favorite editor open &amp;lt;code&amp;gt;/etc/unbound/unbound.conf&amp;lt;/code&amp;gt; and add the following configuration.  If you have a domain that you want unbound to resolve but is internal to your network only, the stub-zone stanza is present:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/unbound/unbound.conf|&lt;br /&gt;
server:&lt;br /&gt;
        verbosity: 1&lt;br /&gt;
        interface: 10.1.0.1&lt;br /&gt;
        do-ip4: yes&lt;br /&gt;
        do-ip6: no&lt;br /&gt;
        do-udp: yes&lt;br /&gt;
        do-tcp: yes&lt;br /&gt;
        do-daemonize: yes&lt;br /&gt;
        access-control: 10.1.0.0/16 allow&lt;br /&gt;
        access-control: 127.0.0.0/8 allow&lt;br /&gt;
&lt;br /&gt;
do-not-query-localhost: no&lt;br /&gt;
&lt;br /&gt;
root-hints: &amp;quot;/etc/unbound/root.hints&amp;quot;&lt;br /&gt;
&lt;br /&gt;
stub-zone:&lt;br /&gt;
	name: &amp;quot;location1.example.net&amp;quot;&lt;br /&gt;
	stub-addr: 10.1.0.2&lt;br /&gt;
&lt;br /&gt;
stub-zone:&lt;br /&gt;
        name: &amp;quot;example.net&amp;quot;&lt;br /&gt;
        stub-addr: 172.16.255.1&lt;br /&gt;
        stub-addr: 172.16.255.2&lt;br /&gt;
        stub-addr: 172.16.255.3&lt;br /&gt;
        stub-addr: 172.16.255.4&lt;br /&gt;
        stub-addr: 172.16.255.5&lt;br /&gt;
        stub-addr: 172.16.255.7&lt;br /&gt;
&lt;br /&gt;
stub-zone:&lt;br /&gt;
        name: &amp;quot;example2.net&amp;quot;&lt;br /&gt;
        stub-addr: 172.16.255.1&lt;br /&gt;
        stub-addr: 172.16.255.2&lt;br /&gt;
        stub-addr: 172.16.255.3&lt;br /&gt;
        stub-addr: 172.16.255.4&lt;br /&gt;
        stub-addr: 172.16.255.5&lt;br /&gt;
        stub-addr: 172.16.255.7&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Start unbound and start using unbound on this host:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|rc-service unbound start&lt;br /&gt;
rc-update add unbound&lt;br /&gt;
echo nameserver 10.1.0.1 &amp;gt; /etc/resolv.conf}}&lt;br /&gt;
&lt;br /&gt;
== GRE Tunnel ==&lt;br /&gt;
With your favorite editor open &amp;lt;code&amp;gt;/etc/network/interfaces&amp;lt;/code&amp;gt; and add the following:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/network/interfaces|&amp;lt;nowiki&amp;gt;&lt;br /&gt;
auto gre1&lt;br /&gt;
iface gre1 inet static&lt;br /&gt;
      pre-up ip tunnel add $IFACE mode gre ttl 64 tos inherit key 12.34.56.78 || true&lt;br /&gt;
      address 172.16.1.1&lt;br /&gt;
      netmask 255.255.0.0&lt;br /&gt;
      post-down ip tunnel del $IFACE || true&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Bring up the new &amp;lt;code&amp;gt;gre1&amp;lt;/code&amp;gt; interface:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|ifup gre1}}&lt;br /&gt;
&lt;br /&gt;
== IPSEC ==&lt;br /&gt;
Install package(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add ipsec-tools}}&lt;br /&gt;
&lt;br /&gt;
With your favorite editor create &amp;lt;code&amp;gt;/etc/ipsec.conf&amp;lt;/code&amp;gt; and set the content to the following:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/ipsec.conf|&lt;br /&gt;
spdflush;&lt;br /&gt;
spdadd 0.0.0.0/0 0.0.0.0/0 gre -P out	ipsec esp/transport//require;&lt;br /&gt;
spdadd 0.0.0.0/0 0.0.0.0/0 gre -P in 	ipsec esp/transport//require;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Create missing directory:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|mkdir /etc/racoon/}}&lt;br /&gt;
&lt;br /&gt;
Extract your pfx into &amp;lt;code&amp;gt;/etc/racoon&amp;lt;/code&amp;gt;, using the filenames &#039;&#039;&#039;&amp;lt;code&amp;gt;ca.pem&amp;lt;/code&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;&amp;lt;code&amp;gt;cert.pem&amp;lt;/code&amp;gt;&#039;&#039;&#039;, and &#039;&#039;&#039;&amp;lt;code&amp;gt;key.pem&amp;lt;/code&amp;gt;&#039;&#039;&#039; (see [[Dynamic_Multipoint_VPN_%28DMVPN%29#Extract_Certificates|instructions above]] for command).&lt;br /&gt;
&lt;br /&gt;
With your favorite editor create &amp;lt;code&amp;gt;/etc/racoon/racoon.conf&amp;lt;/code&amp;gt; and set the content to the following:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/racoon/racoon.conf|&lt;br /&gt;
path certificate &amp;quot;/etc/racoon/&amp;quot;;&lt;br /&gt;
remote anonymous {&lt;br /&gt;
	exchange_mode main;&lt;br /&gt;
	lifetime time 2 hour;&lt;br /&gt;
	certificate_type x509 &amp;quot;/etc/racoon/cert.pem&amp;quot; &amp;quot;/etc/racoon/key.pem&amp;quot;;&lt;br /&gt;
	ca_type x509 &amp;quot;/etc/racoon/ca.pem&amp;quot;;&lt;br /&gt;
	my_identifier asn1dn;&lt;br /&gt;
	nat_traversal on;&lt;br /&gt;
        script &amp;quot;/etc/opennhrp/racoon-ph1dead.sh&amp;quot; phase1_dead;&lt;br /&gt;
	dpd_delay 120;&lt;br /&gt;
	proposal {&lt;br /&gt;
		encryption_algorithm aes 256;&lt;br /&gt;
		hash_algorithm sha1;&lt;br /&gt;
		authentication_method rsasig;&lt;br /&gt;
		dh_group modp4096;&lt;br /&gt;
	}&lt;br /&gt;
	proposal {&lt;br /&gt;
		encryption_algorithm aes 256;&lt;br /&gt;
		hash_algorithm sha1;&lt;br /&gt;
		authentication_method rsasig;&lt;br /&gt;
		dh_group 2;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sainfo anonymous {&lt;br /&gt;
	pfs_group 2;&lt;br /&gt;
	lifetime time 2 hour;&lt;br /&gt;
	encryption_algorithm aes 256;&lt;br /&gt;
	authentication_algorithm hmac_sha1;&lt;br /&gt;
	compression_algorithm deflate;&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Edit &amp;lt;code&amp;gt;/etc/conf.d/racoon&amp;lt;/code&amp;gt; and unset &amp;lt;code&amp;gt;RACOON_PSK_FILE&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/conf.d/racoon|&lt;br /&gt;
...&lt;br /&gt;
RACOON_PSK_FILE{{=}}&lt;br /&gt;
...&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Start service(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|rc-service racoon start&lt;br /&gt;
rc-update add racoon}}&lt;br /&gt;
&lt;br /&gt;
== Next Hop Resolution Protocol (NHRP) ==&lt;br /&gt;
Install package(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add opennhrp}}&lt;br /&gt;
&lt;br /&gt;
With your favorite editor open &amp;lt;code&amp;gt;/etc/opennhrp/opennhrp.conf&amp;lt;/code&amp;gt; and change the content to the following:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/opennhrp/opennhrp.conf|&lt;br /&gt;
interface gre1&lt;br /&gt;
	dynamic-map 172.16.0.0/16 hub.example.com&lt;br /&gt;
	shortcut&lt;br /&gt;
	redirect&lt;br /&gt;
	non-caching&lt;br /&gt;
&lt;br /&gt;
interface bond0.8&lt;br /&gt;
	shortcut-destination&lt;br /&gt;
&lt;br /&gt;
interface bond0.64&lt;br /&gt;
	shortcut-destination&lt;br /&gt;
&lt;br /&gt;
interface bond0.620&lt;br /&gt;
	shortcut-destination&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
You must have a DNS A record &#039;&#039;&amp;lt;code&amp;gt;hub.example.com&amp;lt;/code&amp;gt;&#039;&#039; for each hub node IP address.&lt;br /&gt;
&lt;br /&gt;
With your favorite editor open &amp;lt;code&amp;gt;/etc/opennhrp/opennhrp-script&amp;lt;/code&amp;gt; and change the content to the following:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/opennhrp/opennhrp-script|&amp;lt;nowiki&amp;gt;#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
MYAS=$(sed -n &#039;s/router bgp \(\d*\)/\1/p&#039; &amp;lt; /etc/quagga/bgpd.conf)&lt;br /&gt;
&lt;br /&gt;
case $1 in&lt;br /&gt;
interface-up)&lt;br /&gt;
    echo &amp;quot;Interface $NHRP_INTERFACE is up&amp;quot;&lt;br /&gt;
    if [ &amp;quot;$NHRP_INTERFACE&amp;quot; = &amp;quot;gre1&amp;quot; ]; then&lt;br /&gt;
        ip route flush proto 42 dev $NHRP_INTERFACE&lt;br /&gt;
        ip neigh flush dev $NHRP_INTERFACE&lt;br /&gt;
&lt;br /&gt;
        vtysh -d bgpd \&lt;br /&gt;
            -c &amp;quot;configure terminal&amp;quot; \&lt;br /&gt;
            -c &amp;quot;router bgp $MYAS&amp;quot; \&lt;br /&gt;
            -c &amp;quot;no neighbor core&amp;quot; \&lt;br /&gt;
            -c &amp;quot;neighbor core peer-group&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
    ;;&lt;br /&gt;
peer-register)&lt;br /&gt;
    ;;&lt;br /&gt;
peer-up)&lt;br /&gt;
    if [ -n &amp;quot;$NHRP_DESTMTU&amp;quot; ]; then&lt;br /&gt;
        ARGS=`ip route get $NHRP_DESTNBMA from $NHRP_SRCNBMA | head -1`&lt;br /&gt;
        ip route add $ARGS proto 42 mtu $NHRP_DESTMTU&lt;br /&gt;
    fi&lt;br /&gt;
    echo &amp;quot;Create link from $NHRP_SRCADDR ($NHRP_SRCNBMA) to $NHRP_DESTADDR ($NHRP_DESTNBMA)&amp;quot;&lt;br /&gt;
    racoonctl establish-sa -w isakmp inet $NHRP_SRCNBMA $NHRP_DESTNBMA || exit 1&lt;br /&gt;
    racoonctl establish-sa -w esp inet $NHRP_SRCNBMA $NHRP_DESTNBMA gre || exit 1&lt;br /&gt;
    ;;&lt;br /&gt;
peer-down)&lt;br /&gt;
    echo &amp;quot;Delete link from $NHRP_SRCADDR ($NHRP_SRCNBMA) to $NHRP_DESTADDR ($NHRP_DESTNBMA)&amp;quot;&lt;br /&gt;
    racoonctl delete-sa isakmp inet $NHRP_SRCNBMA $NHRP_DESTNBMA&lt;br /&gt;
    ip route del $NHRP_DESTNBMA src $NHRP_SRCNBMA proto 42&lt;br /&gt;
    ;;&lt;br /&gt;
nhs-up)&lt;br /&gt;
    echo &amp;quot;NHS UP $NHRP_DESTADDR&amp;quot;&lt;br /&gt;
    (&lt;br /&gt;
        flock -x 200&lt;br /&gt;
        vtysh -d bgpd \&lt;br /&gt;
            -c &amp;quot;configure terminal&amp;quot; \&lt;br /&gt;
            -c &amp;quot;router bgp $MYAS&amp;quot; \&lt;br /&gt;
            -c &amp;quot;neighbor $NHRP_DESTADDR remote-as 65000&amp;quot; \&lt;br /&gt;
            -c &amp;quot;neighbor $NHRP_DESTADDR peer-group core&amp;quot; \&lt;br /&gt;
            -c &amp;quot;exit&amp;quot; \&lt;br /&gt;
            -c &amp;quot;exit&amp;quot; \&lt;br /&gt;
            -c &amp;quot;clear bgp $NHRP_DESTADDR&amp;quot;&lt;br /&gt;
    ) 200&amp;gt;/var/lock/opennhrp-script.lock&lt;br /&gt;
    ;;&lt;br /&gt;
nhs-down)&lt;br /&gt;
    (&lt;br /&gt;
        flock -x 200&lt;br /&gt;
        vtysh -d bgpd \&lt;br /&gt;
            -c &amp;quot;configure terminal&amp;quot; \&lt;br /&gt;
            -c &amp;quot;router bgp $MYAS&amp;quot; \&lt;br /&gt;
            -c &amp;quot;no neighbor $NHRP_DESTADDR&amp;quot;&lt;br /&gt;
    ) 200&amp;gt;/var/lock/opennhrp-script.lock&lt;br /&gt;
    ;;&lt;br /&gt;
route-up)&lt;br /&gt;
    echo &amp;quot;Route $NHRP_DESTADDR/$NHRP_DESTPREFIX is up&amp;quot;&lt;br /&gt;
    ip route replace $NHRP_DESTADDR/$NHRP_DESTPREFIX proto 42 via $NHRP_NEXTHOP dev $NHRP_INTERFACE&lt;br /&gt;
    ip route flush cache&lt;br /&gt;
    ;;&lt;br /&gt;
route-down)&lt;br /&gt;
    echo &amp;quot;Route $NHRP_DESTADDR/$NHRP_DESTPREFIX is down&amp;quot;&lt;br /&gt;
    ip route del $NHRP_DESTADDR/$NHRP_DESTPREFIX proto 42&lt;br /&gt;
    ip route flush cache&lt;br /&gt;
    ;;&lt;br /&gt;
esac&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Make it executable and start service(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|chmod +x /etc/opennhrp/opennhrp-script&lt;br /&gt;
rc-service opennhrp start&lt;br /&gt;
rc-update add opennhrp}}&lt;br /&gt;
&lt;br /&gt;
== BGP ==&lt;br /&gt;
Install package(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add quagga&lt;br /&gt;
touch /etc/quagga/zebra.conf}}&lt;br /&gt;
&lt;br /&gt;
With your favorite editor open &amp;lt;code&amp;gt;/etc/quagga/bgpd.conf&amp;lt;/code&amp;gt; and change the content to the following (replace &amp;lt;code&amp;gt;strongpassword&amp;lt;/code&amp;gt; with a password of your choice and &amp;lt;code&amp;gt;%HUB_GRE_IP%&amp;lt;/code&amp;gt; with the &#039;&#039;&#039;Hub&#039;&#039;&#039; node GRE IP address):&lt;br /&gt;
* Add the line &amp;lt;code&amp;gt;neighbor %HUB_GRE_IP% remote-as 65000&amp;lt;/code&amp;gt; for each &#039;&#039;&#039;Hub&#039;&#039;&#039; host you have in your NBMA cloud.&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/quagga/bgpd.conf|&lt;br /&gt;
password strongpassword&lt;br /&gt;
enable password strongpassword&lt;br /&gt;
log syslog&lt;br /&gt;
&lt;br /&gt;
access-list 1 remark Command line access authorized IP&lt;br /&gt;
access-list 1 permit 127.0.0.1&lt;br /&gt;
line vty&lt;br /&gt;
 access-class 1&lt;br /&gt;
&lt;br /&gt;
hostname vpnc.example.net&lt;br /&gt;
&lt;br /&gt;
router bgp 65001&lt;br /&gt;
	bgp router-id 172.16.1.1&lt;br /&gt;
	network 10.1.0.0/16&lt;br /&gt;
	neighbor %HUB_GRE_IP% remote-as 65000&lt;br /&gt;
	neighbor %HUB_GRE_IP% remote-as 65000&lt;br /&gt;
        ...&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Start service(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|rc-service bgpd start&lt;br /&gt;
rc-update add bgpd}}&lt;br /&gt;
&lt;br /&gt;
== OpenVPN ==&lt;br /&gt;
Install package(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|echo tun &amp;gt;&amp;gt; /etc/modules&lt;br /&gt;
modprobe tun&lt;br /&gt;
apk add openvpn openssl&lt;br /&gt;
openssl dhparam -out /etc/openvpn/dh1024.pem 1024}}&lt;br /&gt;
&lt;br /&gt;
Configure openvpn:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/openvpn/openvpn.conf|&lt;br /&gt;
dev tun&lt;br /&gt;
proto udp&lt;br /&gt;
port 1194&lt;br /&gt;
&lt;br /&gt;
server 10.1.128.0 255.255.255.0&lt;br /&gt;
push &amp;quot;route 10.0.0.0 255.0.0.0&amp;quot;&lt;br /&gt;
push &amp;quot;dhcp-option DNS 10.1.0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tls-server&lt;br /&gt;
ca /etc/openvpn/cacert.pem&lt;br /&gt;
cert /etc/openvpn/servercert.pem&lt;br /&gt;
key /etc/openvpn/serverkey.pem&lt;br /&gt;
&lt;br /&gt;
crl-verify /etc/openvpn/crl.pem&lt;br /&gt;
&lt;br /&gt;
dh /etc/openvpn/dh1024.pem&lt;br /&gt;
&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
&lt;br /&gt;
keepalive 10 120&lt;br /&gt;
&lt;br /&gt;
comp-lzo&lt;br /&gt;
&lt;br /&gt;
status /var/log/openvpn.status&lt;br /&gt;
mute 20&lt;br /&gt;
verb 3&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Start service(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|rc-service openvpn start&lt;br /&gt;
rc-update add openvpn}}&lt;br /&gt;
&lt;br /&gt;
== Firewall ==&lt;br /&gt;
Install package(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add awall}}&lt;br /&gt;
&lt;br /&gt;
Enable IP forwarding:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|sysctl -w net.ipv4.ip_forward{{=}}1&lt;br /&gt;
sed -i &#039;s/.*net\.ipv4\.ip_forward.*$/net.ipv4.ip_forward {{=}} 1/g&#039; /etc/sysctl.conf}}&lt;br /&gt;
&lt;br /&gt;
With your favorite editor, edit the following files and set their contents as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/awall/optional/params.json|&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;description&amp;quot;: &amp;quot;params&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;variable&amp;quot;: {&lt;br /&gt;
    &amp;quot;B_IF&amp;quot;: &amp;quot;bond0.8&amp;quot;,&lt;br /&gt;
    &amp;quot;C_IF&amp;quot;: &amp;quot;bond0.64&amp;quot;,&lt;br /&gt;
    &amp;quot;DE_IF&amp;quot;: &amp;quot;bond0.620&amp;quot;,&lt;br /&gt;
    &amp;quot;ISP1_IF&amp;quot;: &amp;quot;bond0.256&amp;quot;,&lt;br /&gt;
    &amp;quot;ISP2_IF&amp;quot;: &amp;quot;bond0.257&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/awall/optional/internet-host.json|&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;description&amp;quot;: &amp;quot;Internet host&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;import&amp;quot;: &amp;quot;params&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;zone&amp;quot;: {&lt;br /&gt;
    &amp;quot;E&amp;quot;: { &amp;quot;iface&amp;quot;: [ &amp;quot;$ISP1_IF&amp;quot;, &amp;quot;$ISP2_IF&amp;quot; ] },&lt;br /&gt;
    &amp;quot;ISP1&amp;quot;: { &amp;quot;iface&amp;quot;: &amp;quot;$ISP1_IF&amp;quot; },&lt;br /&gt;
    &amp;quot;ISP2&amp;quot;: { &amp;quot;iface&amp;quot;: &amp;quot;$ISP2_IF&amp;quot; }&lt;br /&gt;
  },&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;filter&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;in&amp;quot;: &amp;quot;E&amp;quot;,&lt;br /&gt;
      &amp;quot;service&amp;quot;: &amp;quot;ping&amp;quot;,&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;,&lt;br /&gt;
      &amp;quot;flow-limit&amp;quot;: { &amp;quot;count&amp;quot;: 10, &amp;quot;interval&amp;quot;: 6 }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;in&amp;quot;: &amp;quot;E&amp;quot;,&lt;br /&gt;
      &amp;quot;out&amp;quot;: &amp;quot;_fw&amp;quot;,&lt;br /&gt;
      &amp;quot;service&amp;quot;: [ &amp;quot;ssh&amp;quot;, &amp;quot;https&amp;quot; ],&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;,&lt;br /&gt;
      &amp;quot;conn-limit&amp;quot;: { &amp;quot;count&amp;quot;: 3, &amp;quot;interval&amp;quot;: 60 }&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;in&amp;quot;: &amp;quot;_fw&amp;quot;,&lt;br /&gt;
      &amp;quot;out&amp;quot;: &amp;quot;E&amp;quot;,&lt;br /&gt;
      &amp;quot;service&amp;quot;: [ &amp;quot;dns&amp;quot;, &amp;quot;http&amp;quot;, &amp;quot;ntp&amp;quot; ],&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;in&amp;quot;: &amp;quot;_fw&amp;quot;,&lt;br /&gt;
      &amp;quot;service&amp;quot;: [ &amp;quot;ping&amp;quot;, &amp;quot;ssh&amp;quot; ],&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/awall/optional/openvpn.json|&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;description&amp;quot;: &amp;quot;OpenVPN support&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;import&amp;quot;: &amp;quot;internet-host&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;service&amp;quot;: { &lt;br /&gt;
     &amp;quot;openvpn&amp;quot;: { &amp;quot;proto&amp;quot;: &amp;quot;udp&amp;quot;, &amp;quot;port&amp;quot;: 1194 }&lt;br /&gt;
  },&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;filter&amp;quot;: [ &lt;br /&gt;
     { &amp;quot;in&amp;quot;: &amp;quot;E&amp;quot;, &amp;quot;out&amp;quot;: &amp;quot;_fw&amp;quot;, &amp;quot;service&amp;quot;: &amp;quot;openvpn&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot; }&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/awall/optional/clampmss.json|&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;description&amp;quot;: &amp;quot;Deal with ISPs afraid of ICMP&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;import&amp;quot;: &amp;quot;internet-host&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;clamp-mss&amp;quot;: [ { &amp;quot;out&amp;quot;: &amp;quot;E&amp;quot; } ]&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/awall/optional/mark.json|&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;description&amp;quot;: &amp;quot;Mark traffic based on ISP&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;import&amp;quot;: [ &amp;quot;params&amp;quot;, &amp;quot;internet-host&amp;quot; ],&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;route-track&amp;quot;: [&lt;br /&gt;
    { &amp;quot;out&amp;quot;: &amp;quot;ISP1&amp;quot;, &amp;quot;mark&amp;quot;: 1 },&lt;br /&gt;
    { &amp;quot;out&amp;quot;: &amp;quot;ISP2&amp;quot;, &amp;quot;mark&amp;quot;: 2 }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/awall/optional/dmvpn.json|&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;description&amp;quot;: &amp;quot;DMVPN router&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;import&amp;quot;: &amp;quot;internet-host&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;variable&amp;quot;: {&lt;br /&gt;
    &amp;quot;A_ADDR&amp;quot;: [ &amp;quot;10.0.0.0/8&amp;quot;, &amp;quot;172.16.0.0/16&amp;quot; ]&lt;br /&gt;
  },&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;zone&amp;quot;: {&lt;br /&gt;
    &amp;quot;A&amp;quot;: { &amp;quot;addr&amp;quot;: &amp;quot;$A_ADDR&amp;quot;, &amp;quot;iface&amp;quot;: &amp;quot;gre1&amp;quot; }&lt;br /&gt;
  },&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;filter&amp;quot;: [&lt;br /&gt;
    { &amp;quot;in&amp;quot;: &amp;quot;E&amp;quot;, &amp;quot;out&amp;quot;: &amp;quot;_fw&amp;quot;, &amp;quot;service&amp;quot;: &amp;quot;ipsec&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot; },&lt;br /&gt;
    { &amp;quot;in&amp;quot;: &amp;quot;_fw&amp;quot;, &amp;quot;out&amp;quot;: &amp;quot;E&amp;quot;, &amp;quot;service&amp;quot;: &amp;quot;ipsec&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot; },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;in&amp;quot;: &amp;quot;E&amp;quot;,&lt;br /&gt;
      &amp;quot;out&amp;quot;: &amp;quot;_fw&amp;quot;,&lt;br /&gt;
      &amp;quot;ipsec&amp;quot;: &amp;quot;in&amp;quot;,&lt;br /&gt;
      &amp;quot;service&amp;quot;: &amp;quot;gre&amp;quot;,&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;in&amp;quot;: &amp;quot;_fw&amp;quot;,&lt;br /&gt;
      &amp;quot;out&amp;quot;: &amp;quot;E&amp;quot;,&lt;br /&gt;
      &amp;quot;ipsec&amp;quot;: &amp;quot;out&amp;quot;,&lt;br /&gt;
      &amp;quot;service&amp;quot;: &amp;quot;gre&amp;quot;,&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    { &amp;quot;in&amp;quot;: &amp;quot;_fw&amp;quot;, &amp;quot;out&amp;quot;: &amp;quot;A&amp;quot;, &amp;quot;service&amp;quot;: &amp;quot;bgp&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot; },&lt;br /&gt;
    { &amp;quot;in&amp;quot;: &amp;quot;A&amp;quot;, &amp;quot;out&amp;quot;: &amp;quot;_fw&amp;quot;, &amp;quot;service&amp;quot;: &amp;quot;bgp&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;},&lt;br /&gt;
    { &amp;quot;out&amp;quot;: &amp;quot;E&amp;quot;, &amp;quot;dest&amp;quot;: &amp;quot;$A_ADDR&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;reject&amp;quot; }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/awall/optional/vpnc.json|&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;description&amp;quot;: &amp;quot;VPNc&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;import&amp;quot;: [ &amp;quot;params&amp;quot;, &amp;quot;internet-host&amp;quot;, &amp;quot;dmvpn&amp;quot; ],&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;zone&amp;quot;: {&lt;br /&gt;
    &amp;quot;B&amp;quot;: { &amp;quot;iface&amp;quot;: &amp;quot;$B_IF&amp;quot; },&lt;br /&gt;
    &amp;quot;C&amp;quot;: { &amp;quot;iface&amp;quot;: &amp;quot;$C_IF&amp;quot; },&lt;br /&gt;
    &amp;quot;DE&amp;quot;: { &amp;quot;iface&amp;quot;: &amp;quot;$DE_IF&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
  },&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;policy&amp;quot;: [&lt;br /&gt;
    { &amp;quot;in&amp;quot;: &amp;quot;A&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot; },&lt;br /&gt;
    { &amp;quot;in&amp;quot;: &amp;quot;B&amp;quot;, &amp;quot;out&amp;quot;: &amp;quot;A&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot; },&lt;br /&gt;
    { &amp;quot;in&amp;quot;: &amp;quot;C&amp;quot;, &amp;quot;out&amp;quot;: [ &amp;quot;A&amp;quot;, &amp;quot;E&amp;quot; ], &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot; },&lt;br /&gt;
    { &amp;quot;in&amp;quot;: &amp;quot;DE&amp;quot;, &amp;quot;out&amp;quot;: &amp;quot;E&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot; },&lt;br /&gt;
    { &amp;quot;in&amp;quot;: &amp;quot;E&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;drop&amp;quot; },&lt;br /&gt;
    { &amp;quot;in&amp;quot;: &amp;quot;_fw&amp;quot;, &amp;quot;out&amp;quot;: &amp;quot;A&amp;quot;, &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot; }&lt;br /&gt;
  ],&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;snat&amp;quot;: [&lt;br /&gt;
    { &amp;quot;out&amp;quot;: &amp;quot;E&amp;quot; }&lt;br /&gt;
  ],&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;filter&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;in&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
      &amp;quot;out&amp;quot;: &amp;quot;_fw&amp;quot;,&lt;br /&gt;
      &amp;quot;service&amp;quot;: [ &amp;quot;ping&amp;quot;, &amp;quot;ssh&amp;quot;, &amp;quot;http&amp;quot;, &amp;quot;https&amp;quot; ],&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;in&amp;quot;: [ &amp;quot;B&amp;quot;, &amp;quot;C&amp;quot; ],&lt;br /&gt;
      &amp;quot;out&amp;quot;: &amp;quot;_fw&amp;quot;,&lt;br /&gt;
      &amp;quot;service&amp;quot;: [ &amp;quot;dns&amp;quot;, &amp;quot;ntp&amp;quot;, &amp;quot;http&amp;quot;, &amp;quot;https&amp;quot;, &amp;quot;ssh&amp;quot; ],&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;in&amp;quot;: &amp;quot;_fw&amp;quot;,&lt;br /&gt;
      &amp;quot;out&amp;quot;: [ &amp;quot;B&amp;quot;, &amp;quot;C&amp;quot; ],&lt;br /&gt;
      &amp;quot;service&amp;quot;: [ &amp;quot;dns&amp;quot;, &amp;quot;ntp&amp;quot; ],&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    { &lt;br /&gt;
      &amp;quot;in&amp;quot;: [ &amp;quot;A&amp;quot;, &amp;quot;B&amp;quot;, &amp;quot;C&amp;quot; ],&lt;br /&gt;
      &amp;quot;out&amp;quot;: &amp;quot;_fw&amp;quot;,&lt;br /&gt;
      &amp;quot;proto&amp;quot;: &amp;quot;icmp&amp;quot;,&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;out&amp;quot;: &amp;quot;DE&amp;quot;,&lt;br /&gt;
      &amp;quot;service&amp;quot;: [ &amp;quot;ssh&amp;quot;, &amp;quot;http&amp;quot;, &amp;quot;https&amp;quot;, &amp;quot;ping&amp;quot; ],&lt;br /&gt;
      &amp;quot;action&amp;quot;: &amp;quot;accept&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Activate the firewall:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|modprobe ip_tables&lt;br /&gt;
modprobe iptable_nat &lt;br /&gt;
awall enable clampmss&lt;br /&gt;
awall enable openvpn&lt;br /&gt;
awall enable vpnc&lt;br /&gt;
awall activate -f&lt;br /&gt;
rc-update add iptables}}&lt;br /&gt;
&lt;br /&gt;
== ISP Failover ==&lt;br /&gt;
Install package(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add pingu&lt;br /&gt;
echo -e &amp;quot;1\tisp1&amp;quot;&amp;gt;&amp;gt; /etc/iproute2/rt_tables&lt;br /&gt;
echo -e &amp;quot;2\tisp2&amp;quot;&amp;gt;&amp;gt; /etc/iproute2/rt_tables}}&lt;br /&gt;
&lt;br /&gt;
Configure pingu to monitor our &amp;lt;code&amp;gt;bond0.256&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bond0.257&amp;lt;/code&amp;gt; interfaces in &amp;lt;code&amp;gt;/etc/pingu/pingu.conf&amp;lt;/code&amp;gt;.  Add the hosts to monitor for ISP failover to &amp;lt;code&amp;gt;/etc/pingu/pingu.conf&amp;lt;/code&amp;gt; and bind to primary ISP. We also set the ping timeout to 4 seconds.:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/pingu/pingu.conf|&lt;br /&gt;
timeout 4&lt;br /&gt;
required 2&lt;br /&gt;
retry 11&lt;br /&gt;
&lt;br /&gt;
interface bond0.256 { &lt;br /&gt;
  # route-table must correspond with mark in /etc/awall/optional/mark.json&lt;br /&gt;
  route-table 1&lt;br /&gt;
  fwmark 1&lt;br /&gt;
  rule-priority 20000&lt;br /&gt;
  # google dns&lt;br /&gt;
  ping 8.8.8.8&lt;br /&gt;
  # opendns&lt;br /&gt;
  ping 208.67.222.222&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
interface bond0.257 {&lt;br /&gt;
  # route-table must correspond with mark in /etc/awall/optional/mark.json&lt;br /&gt;
  route-table 2&lt;br /&gt;
  fwmark 2&lt;br /&gt;
  rule-priority 20000&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Make sure we can reach the public IP from our LAN by adding static route rules for our private net(s). Edit &amp;lt;code&amp;gt;/etc/pingu/route-rules&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/pingu/route-rules|&lt;br /&gt;
to 10.0.0.0/8 table main prio 1000&lt;br /&gt;
to 172.16.0.0/12 table main prio 1000&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Start service(s):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|rc-service pingu start&lt;br /&gt;
rc-update add pingu}}&lt;br /&gt;
&lt;br /&gt;
Now, if both hosts stop responding to pings, ISP-1 will be considered down and all gateways via bond0.256 will be removed from main route table. Note that the gateway will not be removed from the route table &#039;1&#039;. This is so we can continue try ping via &amp;lt;code&amp;gt;bond0.256&amp;lt;/code&amp;gt; so we can detect that the ISP is back online. When ISP starts working again, the gateways will be added back to main route table again.&lt;br /&gt;
&lt;br /&gt;
== Commit Configuration ==&lt;br /&gt;
Commit configuration:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|lbu ci}}&lt;br /&gt;
&lt;br /&gt;
= Hub Node =&lt;br /&gt;
We will document only what changes from the Spoke node setup.&lt;br /&gt;
&lt;br /&gt;
== Routing Tables ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo -e &amp;quot;42\tnhrp_shortcut\n43\tnhrp_mtu\n44\tquagga\n&amp;gt;&amp;gt; /etc/iproute2/rt_tables&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the following &amp;quot;up&amp;quot; commands:&lt;br /&gt;
{{cat|/etc/network/interfaces|&lt;br /&gt;
auto gre1&lt;br /&gt;
...&lt;br /&gt;
     up ip rule add lookup nhrp_shortcut pref 11000&lt;br /&gt;
     up ip rule add lookup quagga pref 11001&lt;br /&gt;
     up ip rule add lookup nhrp_mtu pref 11999&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== NHRP ==&lt;br /&gt;
With your favorite editor open &amp;lt;code&amp;gt;/etc/opennhrp/opennhrp.conf&amp;lt;/code&amp;gt; on Hub 2 and set the content as follows:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/opennhrp/opennhrp.conf|&lt;br /&gt;
interface gre1&lt;br /&gt;
  map %Hub1_GRE_IP%/%MaskBit% hub1.example.org&lt;br /&gt;
  route-table 44&lt;br /&gt;
  shortcut&lt;br /&gt;
  redirect&lt;br /&gt;
  non-caching&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Do the same on Hub 1 adding the data relative to Hub 2.&lt;br /&gt;
&lt;br /&gt;
With your favorite editor open &amp;lt;code&amp;gt;/etc/opennhrp/opennhrp-script&amp;lt;/code&amp;gt; and set the content as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
case $1 in&lt;br /&gt;
interface-up)&lt;br /&gt;
	ip route flush proto 42 dev $NHRP_INTERFACE&lt;br /&gt;
	ip neigh flush dev $NHRP_INTERFACE&lt;br /&gt;
	;;&lt;br /&gt;
peer-register)&lt;br /&gt;
	CERT=`racoonctl get-cert inet $NHRP_SRCNBMA $NHRP_DESTNBMA | openssl x509 -inform der -text -noout | egrep -o &amp;quot;/OU=[^/]*(/[0-9]+)?&amp;quot; | cut -b 5-`&lt;br /&gt;
	if [ -z &amp;quot;`echo &amp;quot;$CERT&amp;quot; | grep &amp;quot;^GRE=$NHRP_DESTADDR&amp;quot;`&amp;quot; ]; then&lt;br /&gt;
		logger -t opennhrp-script -p auth.err &amp;quot;GRE registration of $NHRP_DESTADDR to $NHRP_DESTNBMA DENIED&amp;quot;&lt;br /&gt;
		exit 1&lt;br /&gt;
	fi&lt;br /&gt;
	logger -t opennhrp-script -p auth.info &amp;quot;GRE registration of $NHRP_DESTADDR to $NHRP_DESTNBMA authenticated&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	(&lt;br /&gt;
		flock -x 200&lt;br /&gt;
		&lt;br /&gt;
		AS=`echo &amp;quot;$CERT&amp;quot; | grep &amp;quot;^AS=&amp;quot; | cut -b 4-`&lt;br /&gt;
		vtysh -d bgpd -c &amp;quot;configure terminal&amp;quot; \&lt;br /&gt;
			-c &amp;quot;router bgp 65000&amp;quot; \&lt;br /&gt;
			-c &amp;quot;neighbor $NHRP_DESTADDR remote-as $AS&amp;quot; \&lt;br /&gt;
			-c &amp;quot;neighbor $NHRP_DESTADDR peer-group leaf&amp;quot; \&lt;br /&gt;
			-c &amp;quot;neighbor $NHRP_DESTADDR prefix-list net-$AS-in in&amp;quot;&lt;br /&gt;
&lt;br /&gt;
		SEQ=5&lt;br /&gt;
		(echo &amp;quot;$CERT&amp;quot; | grep &amp;quot;^NET=&amp;quot; | cut -b 5-) | while read NET; do&lt;br /&gt;
			vtysh -d bgpd -c &amp;quot;configure terminal&amp;quot; \&lt;br /&gt;
				-c &amp;quot;ip prefix-list net-$AS-in seq $SEQ permit $NET le 26&amp;quot;&lt;br /&gt;
			SEQ=$(($SEQ+5))&lt;br /&gt;
		done&lt;br /&gt;
	) 200&amp;gt;/var/lock/opennhrp-script.lock&lt;br /&gt;
	;;&lt;br /&gt;
peer-up)&lt;br /&gt;
	echo &amp;quot;Create link from $NHRP_SRCADDR ($NHRP_SRCNBMA) to $NHRP_DESTADDR ($NHRP_DESTNBMA)&amp;quot;&lt;br /&gt;
	racoonctl establish-sa -w isakmp inet $NHRP_SRCNBMA $NHRP_DESTNBMA || exit 1&lt;br /&gt;
	racoonctl establish-sa -w esp inet $NHRP_SRCNBMA $NHRP_DESTNBMA gre || exit 1 &lt;br /&gt;
&lt;br /&gt;
	CERT=`racoonctl get-cert inet $NHRP_SRCNBMA $NHRP_DESTNBMA | openssl x509 -inform der -text -noout | egrep -o &amp;quot;/OU=[^/]*(/[0-9]+)?&amp;quot; | cut -b 5-`&lt;br /&gt;
	if [ -z &amp;quot;`echo &amp;quot;$CERT&amp;quot; | grep &amp;quot;^GRE=$NHRP_DESTADDR&amp;quot;`&amp;quot; ]; then&lt;br /&gt;
		logger -p daemon.err &amp;quot;GRE mapping of $NHRP_DESTADDR to $NHRP_DESTNBMA DENIED&amp;quot;&lt;br /&gt;
		exit 1&lt;br /&gt;
	fi&lt;br /&gt;
&lt;br /&gt;
	if [ -n &amp;quot;$NHRP_DESTMTU&amp;quot; ]; then&lt;br /&gt;
		ARGS=`ip route get $NHRP_DESTNBMA from $NHRP_SRCNBMA | head -1`&lt;br /&gt;
		ip route add $ARGS proto 42 mtu $NHRP_DESTMTU table nhrp_mtu&lt;br /&gt;
	fi&lt;br /&gt;
	;;&lt;br /&gt;
peer-down)&lt;br /&gt;
	echo &amp;quot;Delete link from $NHRP_SRCADDR ($NHRP_SRCNBMA) to $NHRP_DESTADDR ($NHRP_DESTNBMA)&amp;quot;&lt;br /&gt;
	if [ &amp;quot;$NHRP_PEER_DOWN_REASON&amp;quot; != &amp;quot;lower-down&amp;quot; ]; then&lt;br /&gt;
		racoonctl delete-sa isakmp inet $NHRP_SRCNBMA $NHRP_DESTNBMA&lt;br /&gt;
	fi&lt;br /&gt;
	ip route del $NHRP_DESTNBMA src $NHRP_SRCNBMA proto 42 table nhrp_mtu&lt;br /&gt;
	;;&lt;br /&gt;
route-up)&lt;br /&gt;
	echo &amp;quot;Route $NHRP_DESTADDR/$NHRP_DESTPREFIX is up&amp;quot;&lt;br /&gt;
	ip route replace $NHRP_DESTADDR/$NHRP_DESTPREFIX proto 42 via $NHRP_NEXTHOP dev $NHRP_INTERFACE table nhrp_shortcut&lt;br /&gt;
	ip route flush cache&lt;br /&gt;
	;;&lt;br /&gt;
route-down)&lt;br /&gt;
	echo &amp;quot;Route $NHRP_DESTADDR/$NHRP_DESTPREFIX is down&amp;quot;&lt;br /&gt;
	ip route del $NHRP_DESTADDR/$NHRP_DESTPREFIX proto 42 table nhrp_shortcut&lt;br /&gt;
	ip route flush cache&lt;br /&gt;
	;;&lt;br /&gt;
esac&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGP ==&lt;br /&gt;
With your favorite editor open &amp;lt;code&amp;gt;/etc/quagga/bgpd.conf&amp;lt;/code&amp;gt; on Hub 2 and set the content as follows:&lt;br /&gt;
&lt;br /&gt;
{{cat|/etc/quagga/bgpd.conf|&lt;br /&gt;
password zebra&lt;br /&gt;
enable password zebra&lt;br /&gt;
log syslog&lt;br /&gt;
&lt;br /&gt;
router bgp 65000&lt;br /&gt;
 bgp router-id %Hub2_GRE_IP%&lt;br /&gt;
 bgp deterministic-med&lt;br /&gt;
 network %GRE_NETWORK%/%MASK_BITS%&lt;br /&gt;
 neighbor hub peer-group&lt;br /&gt;
 neighbor hub next-hop-self&lt;br /&gt;
 neighbor hub route-map CORE-IN in&lt;br /&gt;
 neighbor spoke peer-group&lt;br /&gt;
 neighbor spoke passive&lt;br /&gt;
 neighbor spoke next-hop-self&lt;br /&gt;
 neighbor %Spoke1_GRE_IP% remote-as 65001&lt;br /&gt;
 neighbor %Spoke1_GRE_IP% peer-group spoke&lt;br /&gt;
 neighbor %Spoke1_GRE_IP% prefix-list net-65001-in in&lt;br /&gt;
 ...&lt;br /&gt;
 ...&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
 neighbor hub remote-as 65000&lt;br /&gt;
 neighbor %Hub1_GRE_IP% peer-group core&lt;br /&gt;
&lt;br /&gt;
 ip prefix-list net-65001-in seq 5 permit 10.1.0.0/16 le 26&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
 route-map CORE-IN permit 10&lt;br /&gt;
 set metric +100&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Add the lines &amp;lt;code&amp;gt;neighbor %Spoke1_GRE_IP%...&amp;lt;/code&amp;gt; for each spoke node you have. Do the same on Hub 1, changing the relevant data for Hub 2.&lt;br /&gt;
&lt;br /&gt;
= Troubleshooting the DMVPN =&lt;br /&gt;
== Broken [https://wikipedia.org/wiki/Path_MTU_Discovery Path MTU Discovery (PMTUD)] ==&lt;br /&gt;
ISPs afraid of ICMP (which is somehow legitimate) often just blindly add &amp;lt;code&amp;gt;no ip unreachables&amp;lt;/code&amp;gt; in their router interfaces, effectively creating a [https://wikipedia.org/wiki/Black_hole_%28networking%29 blackhole router] that breaks PMTUD, since ICMP Type 3 Code 4 packets (Fragmentation Needed) are dropped. PMTUD is needed by ISAKMP that runs on UDP (TCP works because it uses CLAMPMSS).&lt;br /&gt;
&lt;br /&gt;
For technical details see https://packetlife.net/blog/2008/oct/9/disabling-unreachables-breaks-pmtud/&lt;br /&gt;
&lt;br /&gt;
PMTUD could also be broken due to badly configured DSL modem/routers or bugged firmware. Turning off the firewall on modem itself or any VPN passthrough functionality it may help.&lt;br /&gt;
&lt;br /&gt;
You can easily detect which host is the blackhole router by pinging with DF bit set and with packets of standard MTU size, each hop given in your traceroute to destination:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|ping -M do -s 1472 %IP%}}&lt;br /&gt;
{{Note|&amp;quot;-M do&amp;quot; requires GNU ping, present in &amp;lt;code&amp;gt;iputils&amp;lt;/code&amp;gt; package}}&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t get a response back (either Echo-Response or Fragmentation-Needed) there&#039;s firewall dropping ICMP packets. If it answers to normal ping packets (DF bit cleared), most likely you have hit a blackhole router.&lt;br /&gt;
&lt;br /&gt;
== Kernel and NHRP Routing Cache Issues ==&lt;br /&gt;
{{Todo|...}}&lt;br /&gt;
&lt;br /&gt;
[[category: VPN]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=User:Deleted_user&amp;diff=30216</id>
		<title>User:Deleted user</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=User:Deleted_user&amp;diff=30216"/>
		<updated>2025-06-10T15:22:44Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Blanked the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=User:Deleted_user&amp;diff=30214</id>
		<title>User:Deleted user</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=User:Deleted_user&amp;diff=30214"/>
		<updated>2025-06-10T15:17:44Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Ikke moved page User:Casiobearing to User:Deleted user: Automatically moved page while merging the account &amp;quot;Casiobearing&amp;quot; to &amp;quot;Deleted user&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please delete my account&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=OpenRC&amp;diff=29451</id>
		<title>OpenRC</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=OpenRC&amp;diff=29451"/>
		<updated>2025-03-25T17:39:02Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Clarify status of user services, add `-p` flag to mkdir.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Alpine Linux uses [https://github.com/OpenRC/ openrc] for its init system.  The init system manages the services, startup and shutdown of your computer. &lt;br /&gt;
&lt;br /&gt;
Refer to the excellent guide [https://docs.alpinelinux.org/user-handbook/0.1a/Working/openrc.html working with OpenRC] from Alpine Linux documentation project to learn the basics quickly. Refer [[Writing Init Scripts]] and [[Multiple Instances of Services|Multiple instances of services]] pages for more advanced information.&lt;br /&gt;
&lt;br /&gt;
== Quickstart  ==&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot; style=&amp;quot;width:100%; border:1px #0771a6 solid; background:#f9f9f9; text-align:left; border-collapse:collapse;&amp;quot;&lt;br /&gt;
|- style=&amp;quot;background:#333333; color:#ffffff; font-size: 0.9em; text-align:center;&amp;quot;&lt;br /&gt;
| width=&amp;quot;50%&amp;quot; |Action&lt;br /&gt;
|             |Command&lt;br /&gt;
|-&lt;br /&gt;
|- style=&amp;quot;background:#333333; color:#ffffff; font-size: 0.9em; text-align:center;&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;3&amp;quot; | &#039;&#039;&#039;Managing a service - start,stop and restart&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Start &amp;lt;serviceName&amp;gt; now || {{ic|rc-service &amp;lt;serviceName&amp;gt; start}}&lt;br /&gt;
|-&lt;br /&gt;
| Stop &amp;lt;serviceName&amp;gt; now || {{ic|rc-service &amp;lt;serviceName&amp;gt; stop}} &lt;br /&gt;
|-&lt;br /&gt;
| Restart &amp;lt;serviceName&amp;gt; now || {{ic|rc-service &amp;lt;serviceName&amp;gt; restart}} &lt;br /&gt;
|-&lt;br /&gt;
|- style=&amp;quot;background:#333333; color:#ffffff; font-size: 0.9em; text-align:center;&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;3&amp;quot; | &#039;&#039;&#039;Adding and removing service from runlevels&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Add &amp;lt;serviceName&amp;gt; to &amp;lt;runlevel&amp;gt; || {{ic|rc-update add &amp;lt;serviceName&amp;gt; &amp;lt;runlevel&amp;gt;}} &lt;br /&gt;
|-&lt;br /&gt;
| Remove &amp;lt;serviceName&amp;gt; from &amp;lt;runlevel&amp;gt; || {{ic|rc-update del &amp;lt;serviceName&amp;gt; &amp;lt;runlevel&amp;gt;}} &lt;br /&gt;
|-&lt;br /&gt;
|- style=&amp;quot;background:#333333; color:#ffffff; font-size: 0.9em; text-align:center;&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;3&amp;quot; | &#039;&#039;&#039; Check services in a runlevel and their status&#039;&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background:#333333; color:#ffffff; font-size: 0.9em; text-align:center;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| To check status of  &amp;lt;serviceName&amp;gt; || {{ic|rc-service &amp;lt;serviceName&amp;gt; status}} &lt;br /&gt;
|-&lt;br /&gt;
| To view services configured at &amp;lt;runlevel&amp;gt;  || {{ic|rc-update show &amp;lt;runlevel&amp;gt;}} &lt;br /&gt;
|-&lt;br /&gt;
| To view currently active runlevels and state of services  || {{ic|rc-status}} &lt;br /&gt;
|-&lt;br /&gt;
|- style=&amp;quot;background:#333333; color:#ffffff; font-size: 0.9em; text-align:center;&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;3&amp;quot; | &#039;&#039;&#039; Check and manage runlevels&#039;&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background:#333333; color:#ffffff; font-size: 0.9em; text-align:center;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| To view available runlevels || {{ic|rc-status -l}} &lt;br /&gt;
|-&lt;br /&gt;
| To change to a different &amp;lt;runlevel&amp;gt; || {{ic|openrc &amp;lt;runlevel&amp;gt;}} &lt;br /&gt;
|-&lt;br /&gt;
| To add &amp;lt;s-runlevel&amp;gt; as a stacked &amp;lt;runlevel&amp;gt;  || {{ic|rc-update add -s &amp;lt;s-runlevel&amp;gt; &amp;lt;runlevel&amp;gt;}} &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Runlevels ==&lt;br /&gt;
&lt;br /&gt;
A runlevel is basically a collection of services that needs to be started. Instead of random numbers they are named, and users can create their own if needed. The default startup uses the runlevels sysinit, boot, and default, in that order. Shutdown uses the shutdown runlevel.&lt;br /&gt;
&lt;br /&gt;
The available runlevels are:&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - Used if no runlevel is specified. (This is generally the runlevel you want to add services to.)&lt;br /&gt;
* &#039;&#039;&#039;hotplugged&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;manual&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The special runlevels are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sysinit&#039;&#039;&#039; - Brings up system specific stuff such as &amp;lt;code&amp;gt;/dev&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/proc&amp;lt;/code&amp;gt; and optionally &amp;lt;code&amp;gt;/sys&amp;lt;/code&amp;gt; for Linux based systems. It also mounts &amp;lt;code&amp;gt;/lib/rc/init.d&amp;lt;/code&amp;gt; as a ramdisk using tmpfs where available unless &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; is mounted rw at boot. &amp;lt;code&amp;gt;&#039;&#039;&#039;rc&#039;&#039;&#039;&amp;lt;/code&amp;gt; uses &amp;lt;code&amp;gt;/lib/rc/init.d&amp;lt;/code&amp;gt; to hold state information about the services it runs. sysinit always runs when the host first starts and should not be run again.&lt;br /&gt;
* &#039;&#039;&#039;boot&#039;&#039;&#039; - Generally the only services you should add to the boot runlevel are those which deal with the mounting of filesystems, set the initial state of attached peripherals and logging. Hotplugged services are added to the boot runlevel by the system. All services in the boot and sysinit runlevels are automatically included in all other runlevels except for those listed here.&lt;br /&gt;
* &#039;&#039;&#039;single&#039;&#039;&#039; - Stops all services except for those in the sysinit runlevel.&lt;br /&gt;
* &#039;&#039;&#039;reboot&#039;&#039;&#039; - Changes to the shutdown runlevel and then reboots the host.&lt;br /&gt;
* &#039;&#039;&#039;shutdown&#039;&#039;&#039; - Changes to the shutdown runlevel and then halts the host.&lt;br /&gt;
&lt;br /&gt;
=== Stacked runlevels ===&lt;br /&gt;
&lt;br /&gt;
Runlevel &amp;quot;inheritance&amp;quot; is acheived through [https://docs.alpinelinux.org/user-handbook/0.1a/Working/openrc.html#_runlevel_stacking runlevel stacking]. For more detailed information, refer [https://wiki.gentoo.org/wiki/OpenRC/Stacked%20runlevel Gentoo wiki].&lt;br /&gt;
&lt;br /&gt;
== Configuration == &lt;br /&gt;
&lt;br /&gt;
System-wide configuration file for OpenRC is {{Path|/etc/rc.conf}}.&lt;br /&gt;
&lt;br /&gt;
If the setting {{Codeline|rc_parallel{{=}}&amp;quot;YES&amp;quot;}} is configured, the OpenRC system tries to start services in parallel for a slight speed improvement. This setting however comes with a message from openRC developers:{{Warning|whilst we have improved parallel, it can still potentially lock the boot process. Don&#039;t file bugs about this.}} To improve boot times, consider the idea suggested in the [[#Preventing slow services from delaying boot|preventing slow services]] from delaying boot section.&lt;br /&gt;
&lt;br /&gt;
=== cgroups v2 ===&lt;br /&gt;
&lt;br /&gt;
Since {{pkg|openrc}} 0.51 cgroups v2, or &amp;quot;unified&amp;quot;, is the default. You can enable hybrid cgroups v1 &amp;amp; v2 by editing {{Path|/etc/rc.conf}} and setting &amp;lt;code&amp;gt;rc_cgroup_mode=&amp;quot;hybrid&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Then you should run {{Cmd|# rc-service cgroups start}}&lt;br /&gt;
to take effect and {{Cmd|# rc-update add cgroups}}&lt;br /&gt;
to auto mount the cgroup filesystem on boot.&lt;br /&gt;
&lt;br /&gt;
== User services ==&lt;br /&gt;
&lt;br /&gt;
{{Note|Currently User services are experimental and available in [[Repositories#Edge|edge]] version only}}&lt;br /&gt;
&lt;br /&gt;
OpenRC supports managing services for users. The [[XDG_RUNTIME_DIR]] variable must be set before calling {{Codeline|openrc --user}}, as it&#039;s used to store state for openrc itself and the services it runs.&lt;br /&gt;
&lt;br /&gt;
For many [[wayland]] user services, a custom GUI runlevel needs to be created. &lt;br /&gt;
The below example shows how this is done for {{pkg|wlsunset}} package. wlsunset provides an OpenRC user services. &lt;br /&gt;
In order to use this service, the following steps need to be performed:&lt;br /&gt;
&lt;br /&gt;
In order to create this runlevel,run the following commands:{{Cmd|$ mkdir -p &amp;quot;${XDG_CONFIG_HOME:-$HOME/.config}/rc/runlevels/gui&lt;br /&gt;
$ rc-update --user --stack add default gui}}&lt;br /&gt;
&lt;br /&gt;
Enable the wlsunset service by adding it to this runlevel:{{Cmd|$ rc-update add -U wlsunset gui}}&lt;br /&gt;
&lt;br /&gt;
Next, allow propagation of the WAYLAND_DISPLAY environment variable by adding the following lines to file {{path|${XDG_CONFIG_HOME:-$HOME/.config}/rc/rc.conf}} as follows:{{Cat|rc.conf|&amp;lt;nowiki&amp;gt;rc_env_allow=&amp;quot;WAYLAND_DISPLAY&amp;quot;&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Finally, make sure to start services from the GUI runlevel from your Wayland compositor in its configuration file (i.e. after WAYLAND_DISPLAY is set) by&lt;br /&gt;
adding the following lines to the startup file of your compositor. &lt;br /&gt;
	openrc --user gui&lt;br /&gt;
&lt;br /&gt;
== Preventing slow services from delaying boot ==&lt;br /&gt;
&lt;br /&gt;
Services that take a while to start will block the boot process until they complete. E.g.: &amp;lt;code&amp;gt;iwd&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;networking&amp;lt;/code&amp;gt; might delay startup of an interactive system rather than start in the background.&lt;br /&gt;
&lt;br /&gt;
This can be remedied as per Patrycja&#039;s blog post titled [https://ptrcnull.me/posts/openrc-async-services/ OpenRC: Start services after login prompt]. This solution makes use of [[#Stacked runlevels|stacked runlevels]]. &lt;br /&gt;
&lt;br /&gt;
{{Warning|If the file {{Path|&#039;&#039;&#039;/etc/inittab&#039;&#039;&#039;}} is edited wrongly, the system may not boot. Take backup and learn how to restore using rescue disk  before proceeding.}}&lt;br /&gt;
* Create a custom runlevel (name is “async” here, but it doesn’t matter) {{Cmd|# mkdir /etc/runlevels/async}}&lt;br /&gt;
&lt;br /&gt;
* Add default as a stacked runlevel {{Cmd|# rc-update add -s default async}}&lt;br /&gt;
&lt;br /&gt;
* Remove slow services from default and add them to async {{Cmd|&amp;lt;nowiki&amp;gt;# rc-update del chronyd&lt;br /&gt;
# rc-update add chronyd async &amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
* Add changing of runlevel to async by adding the line &#039;&#039;&#039;::once:/sbin/openrc async&#039;&#039;&#039; to {{Path|/etc/inittab}} file as follows: {{Cat|/etc/inittab|&amp;lt;nowiki&amp;gt;...&lt;br /&gt;
::wait:/sbin/openrc default&lt;br /&gt;
::once:/sbin/openrc async -q&lt;br /&gt;
&lt;br /&gt;
# Set up a couple of getty&#039;s&lt;br /&gt;
tty1::respawn:/sbin/getty 38400 tty1&lt;br /&gt;
...&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
After rebooting, services from async will start separately. This change does not affect other services that start from Default runlevel and they may still block agetty from running due to the wait label.&lt;br /&gt;
&lt;br /&gt;
== Command usage ==&lt;br /&gt;
&lt;br /&gt;
 Usage: rc-update [options] add &amp;lt;service&amp;gt; [&amp;lt;runlevel&amp;gt;...]&lt;br /&gt;
   or: rc-update [options] del &amp;lt;service&amp;gt; [&amp;lt;runlevel&amp;gt;...]&lt;br /&gt;
   or: rc-update [options] [show [&amp;lt;runlevel&amp;gt;...]]&lt;br /&gt;
 Options: [ asuChqVv ]&lt;br /&gt;
  -a, --all                         Process all runlevels&lt;br /&gt;
  -s, --stack                       Stack a runlevel instead of a service&lt;br /&gt;
  -u, --update                      Force an update of the dependency tree&lt;br /&gt;
  -h, --help                        Display this help output&lt;br /&gt;
  -C, --nocolor                     Disable color output&lt;br /&gt;
  -V, --version                     Display software version&lt;br /&gt;
  -v, --verbose                     Run verbosely&lt;br /&gt;
  -q, --quiet                       Run quietly (repeat to suppress errors)&lt;br /&gt;
&lt;br /&gt;
 Usage: rc-status [options] [-f ini] &amp;lt;runlevel&amp;gt;...&lt;br /&gt;
   or: rc-status [options] [-f ini] [-a | -c | -l | -m | -r | -s | -u]&lt;br /&gt;
 Options: [ acf:lmrsSuChqVv ]&lt;br /&gt;
  -a, --all                         Show services from all run levels&lt;br /&gt;
  -c, --crashed                     Show crashed services&lt;br /&gt;
  -f, --format &amp;lt;arg&amp;gt;                format status to be parsable (currently arg must be ini)&lt;br /&gt;
  -l, --list                        Show list of run levels&lt;br /&gt;
  -m, --manual                      Show manually started services&lt;br /&gt;
  -r, --runlevel                    Show the name of the current runlevel&lt;br /&gt;
  -s, --servicelist                 Show service list&lt;br /&gt;
  -S, --supervised                  show supervised services&lt;br /&gt;
  -u, --unused                      Show services not assigned to any runlevel&lt;br /&gt;
  -h, --help                        Display this help output&lt;br /&gt;
  -C, --nocolor                     Disable color output&lt;br /&gt;
  -V, --version                     Display software version&lt;br /&gt;
  -v, --verbose                     Run verbosely&lt;br /&gt;
  -q, --quiet                       Run quietly (repeat to suppress errors)&lt;br /&gt;
&lt;br /&gt;
 Usage: rc-service [options] [-i] &amp;lt;service&amp;gt; &amp;lt;cmd&amp;gt;...&lt;br /&gt;
   or: rc-service [options] -e &amp;lt;service&amp;gt;&lt;br /&gt;
   or: rc-service [options] -l&lt;br /&gt;
   or: rc-service [options] -r &amp;lt;service&amp;gt;&lt;br /&gt;
 Options: [ cdDe:ilr:INsSZChqVv ]&lt;br /&gt;
  -d, --debug                       set xtrace when running the command&lt;br /&gt;
  -D, --nodeps                      ignore dependencies&lt;br /&gt;
  -e, --exists &amp;lt;arg&amp;gt;                tests if the service exists or not&lt;br /&gt;
  -c, --ifcrashed                   if the service is crashed run the command&lt;br /&gt;
  -i, --ifexists                    if the service exists run the command&lt;br /&gt;
  -I, --ifinactive                  if the service is inactive run the command&lt;br /&gt;
  -N, --ifnotstarted                if the service is not started run the command&lt;br /&gt;
  -s, --ifstarted                   if the service is started run the command&lt;br /&gt;
  -S, --ifstopped                   if the service is stopped run the command&lt;br /&gt;
  -l, --list                        list all available services&lt;br /&gt;
  -r, --resolve &amp;lt;arg&amp;gt;               resolve the service name to an init script&lt;br /&gt;
  -Z, --dry-run                     dry run (show what would happen)&lt;br /&gt;
  -h, --help                        Display this help output&lt;br /&gt;
  -C, --nocolor                     Disable color output&lt;br /&gt;
  -V, --version                     Display software version&lt;br /&gt;
  -v, --verbose                     Run verbosely&lt;br /&gt;
  -q, --quiet                       Run quietly (repeat to suppress errors)&lt;br /&gt;
&lt;br /&gt;
 Usage: openrc [options] [&amp;lt;runlevel&amp;gt;]&lt;br /&gt;
 Options: [ a:no:s:SChqVv ]&lt;br /&gt;
   -n, --no-stop                     do not stop any services&lt;br /&gt;
   -o, --override &amp;lt;arg&amp;gt;              override the next runlevel to change into&lt;br /&gt;
                                    when leaving single user or boot runlevels&lt;br /&gt;
   -s, --service &amp;lt;arg&amp;gt;               runs the service specified with the rest&lt;br /&gt;
                                    of the arguments&lt;br /&gt;
   -S, --sys                         output the RC system type, if any&lt;br /&gt;
   -h, --help                        Display this help output&lt;br /&gt;
   -C, --nocolor                     Disable color output&lt;br /&gt;
   -V, --version                     Display software version&lt;br /&gt;
   -v, --verbose                     Run verbosely&lt;br /&gt;
   -q, --quiet                       Run quietly (repeat to suppress errors) &lt;br /&gt;
&lt;br /&gt;
  Reboot/Halt/Poweroff: (And their equivalent from traditional GNU/Linux systems):{{Cmd|&amp;lt;nowiki&amp;gt;# reboot   # ⇔ shutdown now -r&lt;br /&gt;
# halt     # ⇔ shutdown now -H&lt;br /&gt;
# poweroff # ⇔ shutdown now -P&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
Whenever a openRC service fails to run, to troubleshoot enable debugging option and run the command. &lt;br /&gt;
&lt;br /&gt;
For example, if running the command {{ic|rc-service greetd start}} causes greetd service to immediately crash, then alter the command to enable and view the debug:{{Cmd|# rc-service -d greetd restart}}&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Writing Init Scripts]]&lt;br /&gt;
* [[Multiple Instances of Services]]&lt;br /&gt;
* [https://github.com/OpenRC/openrc/blob/master/user-guide.md OpenRC user Guide]&lt;br /&gt;
* [https://github.com/OpenRC/openrc/blob/master/service-script-guide.md OpenRC Service Script Writing Guide]&lt;br /&gt;
* [https://wiki.gentoo.org/wiki/OpenRC Gentoo Wiki]&lt;br /&gt;
* [https://wiki.archlinux.org/title/OpenRC ArchWiki]&lt;br /&gt;
* [https://wiki.postmarketos.org/wiki/OpenRC PostmarketOS Wiki]&lt;br /&gt;
* [https://ptrcnull.me/posts/openrc-async-services/ Start services after login prompt]&lt;br /&gt;
&lt;br /&gt;
[[Category:Booting]] &lt;br /&gt;
[[Category:System Administration]]&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Creating_an_Alpine_package&amp;diff=29115</id>
		<title>Creating an Alpine package</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Creating_an_Alpine_package&amp;diff=29115"/>
		<updated>2025-02-24T17:19:40Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOC right}}&lt;br /&gt;
This page documents the procedure to create and submit new package in Alpine Linux. &lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This is a brief list of the steps to create and submit new package in Alpine Linux. Please see the rest of this wiki for details on the steps. &lt;br /&gt;
&lt;br /&gt;
# Create an account on https://gitlab.alpinelinux.org&lt;br /&gt;
# [[Include:Setup your system and account for building packages |Setup the build environment]].&lt;br /&gt;
# Fork the [https://gitlab.alpinelinux.org/alpine/aports aports repository] and [[Git#Cloning_your_forked_repository|clone your fork]] . &lt;br /&gt;
# Set git pull.rebase=true, Configure your [[Git#Configure_your_global_git_config|git username and email]].&lt;br /&gt;
# Create and switch to a new branch (don&#039;t use master).&lt;br /&gt;
# Add a new directory under testing that is your new package name.&lt;br /&gt;
# Add your APKBUILD file.&lt;br /&gt;
# Run abuild checksum&lt;br /&gt;
# Make sure you run the apkbuild-lint and aport -r and there are no warnings.&lt;br /&gt;
# Commit your APKBUILD with the commit message: &#039;testing/packagename: new aport&#039;&lt;br /&gt;
# Push your changes to your fork on https://gitlab.alpinelinux.org/alpine.&lt;br /&gt;
# Create a merge request.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
[[Include:Setup your system and account for building packages|Setup your system and account]] for building packages in Alpine Linux. If you do not have Alpine Linux already, refer to [[Setting up the build environment]].&lt;br /&gt;
 &lt;br /&gt;
== Getting help ==&lt;br /&gt;
{{Seealso|Abuild and Helpers}}&lt;br /&gt;
The {{pkg|abuild}} package provides scripts necessary for creating packages for Alpine Linux. It implements functionality for building packages as well as additional commands and options for package maintenance. It might be wise to start by checking what the [[Abuild and Helpers|abuild]] program can/cannot do.{{Cmd|abuild -h}}&lt;br /&gt;
&lt;br /&gt;
For realtime help, you can also go on #alpine-devel on [[IRC]].&lt;br /&gt;
&lt;br /&gt;
A reference for APKBUILD files is available as [[APKBUILD Reference]] wiki page or a man page in the {{pkg|abuild-doc}} package:{{Cmd|man APKBUILD}}&lt;br /&gt;
&lt;br /&gt;
== Creating an APKBUILD file  ==&lt;br /&gt;
&lt;br /&gt;
=== Use a template APKBUILD ===&lt;br /&gt;
&lt;br /&gt;
Alpine Linux has the following tools to create a template APKBUILD file.&lt;br /&gt;
&lt;br /&gt;
==== newapkbuild ====&lt;br /&gt;
{{:Include:Newapkbuild}}&lt;br /&gt;
&lt;br /&gt;
If you doubt to which repository your package belongs to you can safely use &#039;&#039;&#039;testing&#039;&#039;&#039;. Building package in your aports/testing directory is not mandatory but this way the package is already at the right place.&lt;br /&gt;
&lt;br /&gt;
If you are creating a daemon package which needs initd scripts you can add the -c making it: {{Cmd|newapkbuild -c &#039;&#039;packagename&#039;&#039;}}&lt;br /&gt;
This will copy the sample initd and confd files to the build directory. A third file sample.install file will be copied as well (we will discuss this later on).&lt;br /&gt;
&lt;br /&gt;
==== apkbuild-cpan ====&lt;br /&gt;
{{:Include:apkbuild-cpan}}&lt;br /&gt;
&lt;br /&gt;
==== apkbuild-pypi ====&lt;br /&gt;
{{:Include:apkbuild-pypi}}&lt;br /&gt;
&lt;br /&gt;
=== Modify your APKBUILD ===&lt;br /&gt;
Edit APKBUILD and fill in the needed info (especially pkgname, pkgver, pkgdesc, url, license, depends and source). &lt;br /&gt;
&lt;br /&gt;
If you are going to use any of the variables for directories like $pkgdir, always make sure they are double quoted like: &lt;br /&gt;
&lt;br /&gt;
 &amp;quot;$pkgdir&amp;quot;/somedir&lt;br /&gt;
&lt;br /&gt;
This will prevent issues with spaces/special characters in the future. &lt;br /&gt;
&lt;br /&gt;
{{Note|If you like syntax highlighting we suggest you to install vim. We have setup vim to recognize the APKBUILD file as a bash scripts so its easier to read them.}}&lt;br /&gt;
&lt;br /&gt;
=== APKBUILD variables/functions  ===&lt;br /&gt;
&lt;br /&gt;
==== source  ====&lt;br /&gt;
&lt;br /&gt;
The source variable is not only used to list the remote source files to fetch, it is also used to list the local files that abuild will need in order to build the apk. Examples of such local files include: init.d files, conf.d files, install files (see [[Creating an Alpine package#install|install variable]]), patches, and all other necessary files.&lt;br /&gt;
&lt;br /&gt;
Here are few things to note:&lt;br /&gt;
&lt;br /&gt;
* When you are finished adding local and/or remote files to &#039;&#039;source&#039;&#039;, you can execute the following command to add their checksums to the APKBUILD file:&lt;br /&gt;
: {{cmd|abuild checksum}}&lt;br /&gt;
: {{Note|When later updating the content of &#039;&#039;source&#039;&#039;, or updating a file that is listed in &#039;&#039;source&#039;&#039;, you must also update their checksums again with the same command.}}&lt;br /&gt;
&lt;br /&gt;
* When the remote file is hosted at SourceForge, it&#039;s best to specify the special mirrors link used by SourceForge:&lt;br /&gt;
: &amp;lt;pre&amp;gt;http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz&amp;lt;/pre&amp;gt;&lt;br /&gt;
: (or similar depending on the package).&lt;br /&gt;
&lt;br /&gt;
* When the remote filename is not specified in the URI (ie, does not end in &#039;/software-1.0.tar.gz&#039;), such as:&lt;br /&gt;
: &amp;lt;pre&amp;gt;http://oss.example.org/?get=software&amp;amp;ver=1.0&amp;lt;/pre&amp;gt;&lt;br /&gt;
: You must prepend &#039;${pkgname}-${pkgver}.tar.gz::&#039; to the protocol, like so:&lt;br /&gt;
: &amp;lt;pre&amp;gt;source=&amp;quot;${pkgname}-${pkgver}.tar.gz::http://oss.example.org/?get=software&amp;amp;ver=1.0&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
: This causes the file to be saved as &#039;&#039;software-1.0.tar.gz&#039;&#039; where abuild can use it, instead of &#039;&#039;?get=software&amp;amp;ver=1.0&#039;&#039;, where abuild cannot use it.&lt;br /&gt;
&lt;br /&gt;
* Some projects didn&#039;t provide a release tarball. Beware that some git services (gitweg, cgit, …?) doesn’t provide &#039;&#039;stable&#039;&#039; tarballs, so when you point source to an tarball like &amp;lt;tt&amp;gt;https://repo.or.cz/w/gitstats.git/snapshot/ad7efbb9399e60cee6cb217c6b47e604174a8093.tar.gz&amp;lt;/tt&amp;gt;, then you will run into issues because the checksum changes when downloading on the build system. This is not a problem on GitHub, GitLab and other decent services provides, they provide &#039;&#039;stable&#039;&#039; tarballs.&lt;br /&gt;
&lt;br /&gt;
* abuild currently supports the following protocols for remote file retrieval:&lt;br /&gt;
** http&lt;br /&gt;
** https&lt;br /&gt;
** ftp&lt;br /&gt;
&amp;lt;!--: {{Note|If the you want to download from https, you need GNU wget installed on your system.}}--&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
* abuild currently supports the following archive types/archive file extensions:&lt;br /&gt;
** .tar&lt;br /&gt;
** .tar.gz / .tgz&lt;br /&gt;
** .tar.bz2&lt;br /&gt;
** .tar.lz (only in Alpine &amp;gt;=3.7)&lt;br /&gt;
** .tar.lzma&lt;br /&gt;
** .tar.xz&lt;br /&gt;
** .zip&lt;br /&gt;
&lt;br /&gt;
==== depends &amp;amp;amp; makedepends  ====&lt;br /&gt;
&lt;br /&gt;
Depends are the actual running dependencies that a package would need when it is running. Makedepends are only needed when you are building a package. If you set a package in depends, you do not need to add it to makedepends as well. The best way to find out what the depends and makedepends of a package are is to [https://en.wikipedia.org/wiki/Rtfm RTFM]. &lt;br /&gt;
&lt;br /&gt;
No kidding, lots of important information can be found in the package INSTALL and README files (or the likes). Another good way is the run &amp;lt;code&amp;gt;./configure --help&amp;lt;/code&amp;gt; from the source directory to see which options are needed for configure to finish without errors. If you do not yet have a source directory you can create one with the command: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild unpack}}&lt;br /&gt;
&lt;br /&gt;
Running &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; will also show you how you can disable a specific option for this package. For instance, a good example is &amp;quot;--disable-nls&amp;quot; which will disable native language support and thus does not depend on gettext (libiconv, glib, ...). &lt;br /&gt;
&lt;br /&gt;
Alpine likes to keep things small, so we try to disable as much as possible without losing too many features. The exact disable/enable options are decided by the package builder but please try to follow Alpine&#039;s design concept as much as possible.&lt;br /&gt;
&lt;br /&gt;
An easy way of quickly finding out the build info for a package is to check Arch Linux (Alpine package management and build scripts are similar) or Gentoo Linux ebuilds (previous versions of Alpine were based on Gentoo).&lt;br /&gt;
&lt;br /&gt;
* [https://gitweb.gentoo.org/repo/gentoo.git/tree/ Gentoo Ebuilds] &lt;br /&gt;
* [https://archlinux.org/packages/?q=search Arch Linux packages] [https://aur.archlinux.org/ Arch Linux User Repository]&lt;br /&gt;
&lt;br /&gt;
==== license  ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;license&#039;&#039;&#039; tag must reflect the license of the source code. Please check the source tarball for COPYING, LICENSE, or other files with names that indicates that it contains licensing information. Beside the license file most developer include headers in the source code files with licensing details.&lt;br /&gt;
&lt;br /&gt;
If the license is on the [https://spdx.org/licenses/ SPDX License List] or [https://spdx.org/licenses/exceptions-index.html SPDX License Exceptions], use the identifier specified by SPDX.&lt;br /&gt;
&lt;br /&gt;
Note that some licenses have additional requirements that should be adhered to. The &amp;lt;code&amp;gt;MIT&amp;lt;/code&amp;gt; license for example has the requirement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that we need to include the license as shipped with the project.&lt;br /&gt;
&lt;br /&gt;
Known licenses that require this:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;MIT&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ISC&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a package has a special/custom license or is not listed as [https://opensource.org/licenses/alphabetical OSI approved], use the identifier &amp;quot;custom&amp;quot;. In that case we need to provide the license file with the package as well.&lt;br /&gt;
&lt;br /&gt;
Because we want to save space and don&#039;t like to have licenses all over our system we have decided to include the license in the doc subpackage. Please follow the following guidelines to add a proper license. Locate the license file inside the source package. Add the doc subpackage to the $subpackages variable as follows: &lt;br /&gt;
&lt;br /&gt;
 subpackages=&amp;quot;$pkgname-doc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Add a similar line to the following to your package() function, depending on the license description file: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|install -Dm644 COPYING &amp;quot;$pkgdir&amp;quot;/usr/share/licenses/$pkgname/COPYING}}&lt;br /&gt;
&lt;br /&gt;
If you follow these steps then abuild will automatically add the license to the package-doc apk for you.&lt;br /&gt;
&lt;br /&gt;
{{Warning|It is not acceptable to package software with &amp;quot;unknown&amp;quot; license! If you can&#039;t find the license of the source code, please contact the author and ask them to specify the license. }}&lt;br /&gt;
&lt;br /&gt;
==== arch ====&lt;br /&gt;
&lt;br /&gt;
The package architecture(s) to build for.  This can be one of: &#039;&#039;x86, x86_64, all,&#039;&#039; or &#039;&#039;noarch&#039;&#039;, where &#039;&#039;all&#039;&#039; means all architectures, and &#039;&#039;noarch&#039;&#039; means it&#039;s architecture-independent (e.g., a pure-python package).&lt;br /&gt;
{{Tip|To determine if your APKBUILD can use &#039;&#039;noarch&#039;&#039;, build the package for your architecture and then run &amp;quot;scanelf -R pkg&amp;quot; from the directory that the APKBUILD resides in, in order to scan for ELF files in the &#039;&#039;./pkg&#039;&#039; directory.  If you do NOT get output from this, then &#039;&#039;noarch&#039;&#039; can be used.}}&lt;br /&gt;
&lt;br /&gt;
==== url  ====&lt;br /&gt;
&lt;br /&gt;
Website address for the program. This is useful later on when either finding documentation or other information about the package.&lt;br /&gt;
&lt;br /&gt;
==== pkgdesc  ====&lt;br /&gt;
&lt;br /&gt;
A brief, one line, description of what the package does. Useful for the package management system. It should start with a capital letter and does &#039;&#039;&#039;not&#039;&#039;&#039; end with a period.&lt;br /&gt;
&lt;br /&gt;
Here is an example from apk_info for the OpenSSH client package:&lt;br /&gt;
&lt;br /&gt;
 pkgdesc=&amp;quot;Port of OpenBSD&#039;s free SSH release - client&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== pkgver  ====&lt;br /&gt;
&lt;br /&gt;
Provide the release number of the package you are building.&lt;br /&gt;
&lt;br /&gt;
==== pkgrel  ====&lt;br /&gt;
&lt;br /&gt;
The $pkgrel versioning is made so that if you change something in your APKBUILD file without changing the actual $pkgver, you can increment pkgrel so apk tools will detect it as an update. For instance, if you forget to add a dependency, you can add it afterward and you can +1 pkgver so apk finds this update and adds the missing dependency. When there&#039;s an upstream version change, we reset the pkgrel to 0.&lt;br /&gt;
&lt;br /&gt;
==== pkgname  ====&lt;br /&gt;
&lt;br /&gt;
The base name of the package you are creating.  For Freeswitch 1.0.6, you would use &amp;quot;freeswitch&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== install  ====&lt;br /&gt;
&lt;br /&gt;
There are 6 different kinds of install scripts. Each script is called with the $pkgname.&#039;&#039;&amp;lt;action&amp;gt;&#039;&#039; where &#039;&#039;&amp;lt;action&amp;gt;&#039;&#039; is one of the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-install&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed before package is installed. Typical use is when package needs a group and a user to be created. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
addgroup -S clamav 2&amp;gt;/dev/null&lt;br /&gt;
adduser -S -D -H -s /bin/false -G clamav -g clamav clamav 2&amp;gt;/dev/null&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note the &#039;&#039;exit 0&#039;&#039; at the end. If the script exits with failure (if the user already exist), the package will not be installed and &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; will exit with failure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-install&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed after the package is installed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-upgrade&lt;br /&gt;
&amp;lt;dd&amp;gt;Same as pre-install but is executed before upgrading/downgrading/reinstalling an already installed package. Note that exiting with failure will not cause apk to exit with failure, but will mark the package as broken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-upgrade&lt;br /&gt;
&amp;lt;dd&amp;gt;Same as post-install but is executed after upgrading/downgrading/reinstalling an already installed package. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-deinstall&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed before uninstalling a package. If script exits with failure apk will not uninstall the package.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-deinstall&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed after a package have been uninstalled. For example, can be used to restore busybox links:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
busybox --install -s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the package has a pre-install and post-install script the APKBUILD should have the &#039;&#039;install&#039;&#039; variable defined:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
install=&amp;quot;$pkgname.pre-install $pkgname.post-install&amp;quot;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== subpackages  ====&lt;br /&gt;
&lt;br /&gt;
$subpackages are made to split up the normal &amp;quot;make install&amp;quot; into separate packages. The most common subpackages we use are doc and dev. Because we like to keep our target system small we move documentation and development files (only needed when building packages) into separate packages. To use the specific program a user only need to install the base apk without package-doc or package-dev, but if he wants to read the manual he will need to install package-doc. &lt;br /&gt;
&lt;br /&gt;
The easiest way to find out if you need to use -dev and -doc is to first build the package without these options set and wait until the build finishes. When its finished you should have a pkg directory which is the fake root directory. Inside this directory you will see the structure as how it would be installed in / on the target system. &lt;br /&gt;
&lt;br /&gt;
To see if you need the -dev package you can run the following cmd: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|find pkg/usr/ -name &#039;*.[acho]&#039; -o -name &#039;*.la&#039;}}&lt;br /&gt;
&lt;br /&gt;
If this returns any files you need to include the -dev package. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; To see if you need the -doc package you can run the following cmd: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|find pkg/usr/share -name doc -o -name man -o -name info -o -name html -o -name sgml -o -name licenses}}&lt;br /&gt;
&lt;br /&gt;
If this returns any directories you need to include the -doc package. &lt;br /&gt;
&lt;br /&gt;
===== Custom subpackages  =====&lt;br /&gt;
&lt;br /&gt;
Some software additionally has non-essential files that do not qualify as either documentation or development content. These files should be placed in their own, specialized subpackage(s). Some packages include large test suites which are only needed in specific circumstances or binaries which have depends which we prefer not to install. To handle those we create our own package/function. In the APKBUILD below the build() function we create another function: &lt;br /&gt;
&lt;br /&gt;
 test() {&lt;br /&gt;
        mkdir -p &amp;quot;$subpkgdir&amp;quot;/usr&lt;br /&gt;
        mv &amp;quot;$pkgdir&amp;quot;/usr/package-test &amp;quot;$subpkgdir&amp;quot;/usr/&lt;br /&gt;
        # or amove usr/package-test&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
We also need to add the package info to $subpackages variable: &lt;br /&gt;
&lt;br /&gt;
 subpackages=&amp;quot;$pkgname-doc $pkgname-dev $pkgname-test&amp;quot;&lt;br /&gt;
&lt;br /&gt;
After we finish building the package you should see another apk called packagename-test.apk which includes the files which we moved to the $subpkgdir dir. &lt;br /&gt;
&lt;br /&gt;
The above mentioned variables can also be used in our custom function. If we want for instance to build the test() function with perl support we would add: &lt;br /&gt;
&lt;br /&gt;
 depends=&amp;quot;perl&amp;quot;&lt;br /&gt;
 makedepends=&amp;quot;perl-dev&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If we would install the base package it would not install perl, but if we install the package-test package it would.&lt;br /&gt;
&lt;br /&gt;
==== Patches  ====&lt;br /&gt;
&lt;br /&gt;
Please make sure you always submit human readable patches. Ways to create them are: &lt;br /&gt;
&lt;br /&gt;
directory compare: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|diff -Nurp original_directory new_directory &amp;amp;gt; filename.patch}}&lt;br /&gt;
&lt;br /&gt;
file compare: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|diff -up original.file new.file &amp;amp;gt; filename.patch}}&lt;br /&gt;
&lt;br /&gt;
If a patch contains a completely new file but not *.rej or *.orig file, you need to add -N option to diff, but you may need to add exclusions with &amp;lt;code&amp;gt;--exclude PATTERN&amp;lt;/code&amp;gt; so that you do not inadvertently add files.  You may need to manually delete unwanted files inside the patch file.&lt;br /&gt;
&lt;br /&gt;
Because multiple patches can patch the same file, they can change the offsets required by subsequent patches. To make sure we always patch in a specific way, we should number the patches as follows: &lt;br /&gt;
&lt;br /&gt;
 10-patch1.patch 20-patch2.patch 30-patch3.patch&lt;br /&gt;
&lt;br /&gt;
This way we are always sure that patch 1 is applied first, and if we want to add additional patches between them we can use appropriate indexes (e.g. 11, 12, 21, 22).&lt;br /&gt;
&lt;br /&gt;
Add the names of the patch files to the &#039;&#039;source&#039;&#039; variable. If you haven&#039;t declared a custom &#039;&#039;prepare&#039;&#039; function, no further action is necessary. Otherwise, be sure to call &#039;&#039;default_prepare&#039;&#039; in your &#039;&#039;prepare&#039;&#039; function. For example:&lt;br /&gt;
&lt;br /&gt;
 prepare() {&lt;br /&gt;
 	default_prepare&lt;br /&gt;
 &lt;br /&gt;
 	# do your stuff&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note: Some older packages contain a &#039;&#039;for&#039;&#039; loop in the &#039;&#039;prepare&#039;&#039; function to apply patches. This is not needed anymore, as patches are handled by &#039;&#039;default_prepare&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In Alpine &amp;gt;=3.4 you can define patch_args to supply the patch level.  This only works if all the patches have the same patch level.  If there are a lot of patches from different sources, there is a good chance that you may need to edit them, as discussed below.&lt;br /&gt;
&lt;br /&gt;
To automatically patch the package (available only in Alpine &amp;gt;=3.4) if it uses a patch level (-pX) other than the default (-p1), you need to carefully modify the patch.  First, you&#039;ll need a text editor that does not automatically convert  between Windows and Unix new lines (or, disable this feature) so that it preserves the old code.  The next thing you&#039;ll need to do is modify the paths on &amp;quot;+++&amp;quot; and &amp;quot;---&amp;quot; lines in the .patch file.  You can begin the path with a/ and b/ like shown below.  Next, you need to adjust the paths so that the relative base path is from inside $builddir.  Anything to the left of $builddir, including $builddir itself, needs to be removed from the path.  So, if $builddir is /home/USER/aports/community/chromium/src/chromium-65, you need to erase it on the &amp;quot;+++&amp;quot; and &amp;quot;---&amp;quot; lines.  Inside the chromium-65 folder you can see a src folder that has 3rdparty as a descendant.  If a patch originally has a deeper patch level, you may need to fill in the missing portion of the path.  For example, use the &amp;lt;code&amp;gt;find . -name &amp;quot;Assertions.cpp&amp;quot;&amp;lt;/code&amp;gt; command to find the full path to the file relative to the base.&lt;br /&gt;
&lt;br /&gt;
{{Cat|example.patch|&amp;lt;nowiki&amp;gt;&lt;br /&gt;
Author: John Doe &amp;lt;johndoe@mail.com&amp;gt;&lt;br /&gt;
URL: http://.....&lt;br /&gt;
Summary: Fixes musl compatibility&lt;br /&gt;
----&lt;br /&gt;
--- a/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp.orig&lt;br /&gt;
+++ b/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp&lt;br /&gt;
@@ -142,7 +142,7 @@&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 FrameToNameScope::FrameToNameScope(void* addr) : m_name(0), m_cxaDemangled(0) {&lt;br /&gt;
-#if OS(MACOSX) || (OS(LINUX) &amp;amp;&amp;amp; !defined(__UCLIBC__))&lt;br /&gt;
+#if OS(MACOSX) || (OS(LINUX) &amp;amp;&amp;amp; defined(__GLIBC__))&lt;br /&gt;
   Dl_info info;&lt;br /&gt;
   if (!dladdr(addr, &amp;amp;info) || !info.dli_sname)&lt;br /&gt;
return;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Portions of the patch may be outdated, removed completely as in the source code file completely removed, or moved or renamed files.  You need to delete that section of the patch or find where that section of code changed and re-diff it.&lt;br /&gt;
&lt;br /&gt;
It is good etiquette to give credit at the top and the location of where you originally found them with notes.&lt;br /&gt;
&lt;br /&gt;
Excluding patches with global variable resembling patch_opts is not available on Alpine.  To exclude patches you need to create your own custom prepare().&lt;br /&gt;
&lt;br /&gt;
If you have a monolithic patch where there are a bunch of patches in one big patch, you could use filterdiff which is available in the patchutils package.&lt;br /&gt;
&lt;br /&gt;
Just do something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
makedepends=&amp;quot;patchutils&amp;quot;&lt;br /&gt;
&lt;br /&gt;
prepare() {&lt;br /&gt;
  ...&lt;br /&gt;
  cd &amp;quot;$builddir&amp;quot;&lt;br /&gt;
  filterdiff -x &#039;*drivers/video/logo*&#039; &amp;quot;$srcdir&amp;quot;/original.patch &amp;gt; &amp;quot;$builddir&amp;quot;/modified.patch&lt;br /&gt;
  patch -p1 -i &amp;quot;$builddir&amp;quot;/modified.patch&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to put the wildcard pattern in single quotes for it to work.&lt;br /&gt;
&lt;br /&gt;
==== Configure options  ====&lt;br /&gt;
&lt;br /&gt;
Alpine has some default configure options we set by default. We use /usr for prefix to make sure everything is installed with /usr in front of it. If you notice that anything is installed in the wrong directory please run {{Cmd|./configure --help}} and see if you can set the correct location. &lt;br /&gt;
&lt;br /&gt;
We are not covering the depend switches here we have discussed this already in the depend section.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Make options  ====&lt;br /&gt;
&lt;br /&gt;
If you notice weird problems when compiling or installing the package with make/make install you could try to disable [https://www.gnu.org/software/make/manual/make.html#Parallel parallel] building/installing. A normal make line would be: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make}}&lt;br /&gt;
&lt;br /&gt;
To disable parallel we use: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make -j1}}&lt;br /&gt;
&lt;br /&gt;
We can use the same for make install. &lt;br /&gt;
&lt;br /&gt;
Because we do not want to install the package in our build environment but we want to install it in a fake root directory we need to tell &#039;make install&#039; to use another destination directory instead of &#039;/&#039;. We do this by setting a variable when we execute make install as followed: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make DESTDIR{{=}}&amp;quot;$pkgdir&amp;quot; install}}&lt;br /&gt;
&lt;br /&gt;
Please note that some Makefiles do not support this variable and will always install software in &#039;/&#039;. To make sure you do not mess up your build system NEVER run your build system as root but always use a custom user and doas when needed. If by accident the Makefile does not support DESTDIR variable it will fail to install in our build system system directories.&lt;br /&gt;
&lt;br /&gt;
==== builddir ====&lt;br /&gt;
If you used &amp;lt;tt&amp;gt;newapkbuild&amp;lt;/tt&amp;gt; to create your APKBUILD file, you must specify the path to your unpacked sources. Inside the sections during the prepare/build/install process &#039;&#039;builddir&#039;&#039; is used. Most of the time a combination of &#039;&#039;$srcdir&#039;&#039; and &#039;&#039;$pkgname-$pkgver&#039;&#039; will work. When not, check the /src directory or the source tarball for the right string. Especially when you are working with automatically generated tarballs (like from github and gitorious), this needs to be adjusted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
builddir=&amp;quot;$srcdir&amp;quot;/$pkgname-$pkgver&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Additional files  ====&lt;br /&gt;
&lt;br /&gt;
If you want/need to install additional files not mentioned above you can use the following cmd (this is an example of a conf file): &lt;br /&gt;
&lt;br /&gt;
{{Cmd|install -Dm644 doc/$pkgname.conf &amp;quot;$pkgdir&amp;quot;/etc/$pkgname.conf}}&lt;br /&gt;
&lt;br /&gt;
== Build the package  ==&lt;br /&gt;
&lt;br /&gt;
If you did not already create the checksums as mentioned above you can do so now: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $pkgname&lt;br /&gt;
abuild checksum}}&lt;br /&gt;
&lt;br /&gt;
It&#039;s about time we build our package. Because a build system should never have all the package installed to prevent linking to packages we don&#039;t want it to link we use a abuild recursively with the &#039;&#039;&#039;-r&#039;&#039;&#039; switch. It will install all dependencies from your repository and builds it, afterwards it will uninstall all those depending packages again.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild -r}}&lt;br /&gt;
&lt;br /&gt;
See also [[Abuild_and_Helpers|Abuild and Helpers]].&lt;br /&gt;
&lt;br /&gt;
== Testing the package locally ==&lt;br /&gt;
&lt;br /&gt;
When it completes, your package will be found in a subfolder of &amp;lt;code&amp;gt;~/packages&amp;lt;/code&amp;gt;.  You may want to test it on your machine but only if the package is not a critical system package like musl or apk-tools package.  To avoid borking your system (as in making it impossible to use &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; or to restore back the system and the compiler toolchain) for a critical system package, you should test on a chroot first before using it live.&lt;br /&gt;
&lt;br /&gt;
The best way to test a package locally is to modify your &amp;lt;code&amp;gt;/etc/apk/repositories&amp;lt;/code&amp;gt; so that it includes the indexes to your locally built packages - the directories that contain &amp;lt;code&amp;gt;ARCH/APKINDEX.tar.gz&amp;lt;/code&amp;gt;. For example the &amp;lt;code&amp;gt;/etc/apk/repositories&amp;lt;/code&amp;gt; below includes locally built packages in testing, community and main. To use this example change &amp;lt;code&amp;gt;USER&amp;lt;/code&amp;gt; to your login name.&lt;br /&gt;
&lt;br /&gt;
{{Cat|/etc/apk/repositories|/home/USER/packages/testing/&lt;br /&gt;
/home/USER/packages/main/&lt;br /&gt;
/home/USER/packages/community/&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/main&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/community&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/testing&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
If you prefer to test a package without changing any other configuration you can use the &amp;lt;code&amp;gt;-X, --repository&amp;lt;/code&amp;gt; option to &amp;lt;code&amp;gt;apk&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|doas apk add --repository /home/USER/packages/testing $pkgname}}&lt;br /&gt;
&lt;br /&gt;
== Code review ==&lt;br /&gt;
&lt;br /&gt;
To successfully have your package pass through code reviewers (as of Feb 18, 2018 are nmeum and jirutka on GitHub) and possible increased acceptance, the following conventions need to be followed:&lt;br /&gt;
&lt;br /&gt;
# Custom global variables should be prefixed with underscore (_).&lt;br /&gt;
# Compact code as in merged commands, removed unused variables, removal of functions that do the same thing that are automatically handled by abuild.&lt;br /&gt;
# Versioning is done properly.  For details see [[APKBUILD_Reference#pkgver]].&lt;br /&gt;
# Licensing is done properly. Remove unnecessary copying of licensing that is already OSI approved.&lt;br /&gt;
# Naming conventions rules for unofficial variables as in _gitrev is preferred over commit.&lt;br /&gt;
# Indent with tabs not spaces.&lt;br /&gt;
# Removal of explicit return 1.  (They are still found the old APKBUILD files if you are learning but are now strongly discouraged.)&lt;br /&gt;
# Disabling check() requires either (1) a comment (#) stating next to options=&amp;quot;!check&amp;quot; that there is no test suite/unit tests or (2) functioning working check() function.&lt;br /&gt;
# Explicit call to subpackages=&amp;quot;$pkgname-doc&amp;quot; must be used instead of explicit gzip man page compression.&lt;br /&gt;
# Ideally, lines should be no more than 80 columns wide&lt;br /&gt;
&lt;br /&gt;
Additionally, make sure to run the linter on your package:&lt;br /&gt;
{{Cmd|doas apk add atools&lt;br /&gt;
apkbuild-lint APKBUILD}}&lt;br /&gt;
&lt;br /&gt;
For more information see [[Development using git:Quality assurance]] and [[Package_policies]].&lt;br /&gt;
Also check out [https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/COMMITSTYLE.md?ref_type=heads aports/COMMITSTYLE.md] and [https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/CODINGSTYLE.md?ref_type=heads aports/CODINGSTYLE.md]&lt;br /&gt;
&lt;br /&gt;
== Commit your work  ==&lt;br /&gt;
&lt;br /&gt;
After you successfully build your package and properly followed the conventions and requirements in the code review section, you can submit your APKBUILD to Alpine&#039;s git repository. &lt;br /&gt;
&lt;br /&gt;
Update your git repo, before adding new files: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $aportsdir&lt;br /&gt;
git pull}}&lt;br /&gt;
&lt;br /&gt;
This should pull all the changes made by others into your local git repo.&lt;br /&gt;
&lt;br /&gt;
When you think you are ready you can add your files to git: &lt;br /&gt;
&lt;br /&gt;
NOTE: when using our Gitlab instance, you can create MR&#039;s for each package. Please squash all commits related to the same package into a single one per MR.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $aportsdir&lt;br /&gt;
git add testing/$pkgdir (include any other files needed for the build; $pkgname.install...)&lt;br /&gt;
git commit}}&lt;br /&gt;
&lt;br /&gt;
Use the following commit message template for new aports (without the comments):&lt;br /&gt;
&lt;br /&gt;
{{Cat|template|testing/$pkgname: new aport   # this will be the subject line&lt;br /&gt;
                              # a blank line&lt;br /&gt;
$url                          # project homepage&lt;br /&gt;
$pkgdesc                      # one line description}}&lt;br /&gt;
&lt;br /&gt;
Or you could add the following and &amp;lt;code&amp;gt;chmod +x ports/.git/hooks/prepare-commit-msg&amp;lt;/code&amp;gt; to automatically generate commit message which the default aports/.githooks/ does not:&lt;br /&gt;
&lt;br /&gt;
{{Cat|aports/.git/hooks/prepare-commit-msg|&amp;lt;nowiki&amp;gt;#!/bin/sh&lt;br /&gt;
case &amp;quot;$2,$3&amp;quot; in&lt;br /&gt;
  ,|template,)&lt;br /&gt;
    if git diff-index --diff-filter=A --name-only --cached HEAD \&lt;br /&gt;
        | grep -q &#039;/APKBUILD$&#039;; then&lt;br /&gt;
      meta() { git diff --staged | grep &amp;quot;^+$1&amp;quot; | sed &#039;s/.*=&amp;quot;\?//;s/&amp;quot;$//&#039;;}&lt;br /&gt;
      printf &#039;testing/%s: new aport\n\n%s\n%s\n&#039; &amp;quot;$(meta pkgname)&amp;quot; \&lt;br /&gt;
        &amp;quot;$(meta url)&amp;quot; &amp;quot;$(meta pkgdesc)&amp;quot; &amp;quot;$(cat $1)&amp;quot; &amp;gt; &amp;quot;$1&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      printf &#039;%s\n\n%s&#039; `git diff-index --name-only --cached HEAD \&lt;br /&gt;
        | sed -n &#039;s/\/APKBUILD$//p;q&#039;` &amp;quot;$(cat $1)&amp;quot; &amp;gt; &amp;quot;$1&amp;quot;&lt;br /&gt;
    fi;;&lt;br /&gt;
esac&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now your changes are only available locally in your repository.&lt;br /&gt;
&lt;br /&gt;
Because you do not have push rights to the Alpine aports repository you need to create a merge request to [https://gitlab.alpinelinux.org/alpine/aports Alpine&#039;s GitLab instance].&lt;br /&gt;
&lt;br /&gt;
Alternatively you can also create a diff (patch) of the changes you made and send this patch to the &lt;br /&gt;
[https://lists.alpinelinux.org/~alpine/aports  alpine-aports mailinglist].&lt;br /&gt;
&lt;br /&gt;
To create a diff patch:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|git format-patch HEAD^}}&lt;br /&gt;
&lt;br /&gt;
or if you have sprunge, you can create a link to your patch for convenience&lt;br /&gt;
&lt;br /&gt;
{{Cmd|git format-patch HEAD^ --stdout &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; sprunge}}&lt;br /&gt;
&lt;br /&gt;
== Automated flagging of outdated ports ==&lt;br /&gt;
Consider adding your port to [https://release-monitoring.org/ Anitya], so it will be flagged as outdated&lt;br /&gt;
as soon as a new stable version is released by upstream.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[APKBUILD Reference]]&lt;br /&gt;
* [[APKBUILD examples]]&lt;br /&gt;
* [[Development using git]]&lt;br /&gt;
* [[Development using git:Quality assurance]]&lt;br /&gt;
&lt;br /&gt;
[[category: Development ]] [[category: Package Manager]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Creating_an_Alpine_package&amp;diff=29114</id>
		<title>Creating an Alpine package</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Creating_an_Alpine_package&amp;diff=29114"/>
		<updated>2025-02-24T17:13:37Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOC right}}&lt;br /&gt;
This page documents the procedure to create and submit new package in Alpine Linux. &lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This is a brief list of the steps to create and submit new package in Alpine Linux. Please see the rest of this wiki for details on the steps. &lt;br /&gt;
&lt;br /&gt;
# Create an account on https://gitlab.alpinelinux.org&lt;br /&gt;
# [[Include:Setup your system and account for building packages |Setup the build environment]].&lt;br /&gt;
# Fork the [https://gitlab.alpinelinux.org/alpine/aports aports repository] and [[Git#Cloning_your_forked_repository|clone your fork]] . &lt;br /&gt;
# Set git pull.rebase=true, Configure your [[Git#Configure_your_global_git_config|git username and email]].&lt;br /&gt;
# Create and switch to a new branch (don&#039;t use master).&lt;br /&gt;
# Add a new directory under testing that is your new package name.&lt;br /&gt;
# Add your APKBUILD file.&lt;br /&gt;
# Run abuild checksum&lt;br /&gt;
# Make sure you run the apkbuild-lint and aport -r and there are no warnings.&lt;br /&gt;
# Commit your APKBUILD with the commit message: &#039;testing/packagename: new aport&#039;&lt;br /&gt;
# Push your changes to your fork on https://gitlab.alpinelinux.org/alpine.&lt;br /&gt;
# Create a merge request.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
[[Include:Setup your system and account for building packages|Setup your system and account]] for building packages in Alpine Linux. If you do not have Alpine Linux already, refer to [[Setting up the build environment]].&lt;br /&gt;
 &lt;br /&gt;
== Getting help ==&lt;br /&gt;
{{Seealso|Abuild and Helpers}}&lt;br /&gt;
The {{pkg|abuild}} package provides scripts necessary for creating packages for Alpine Linux. It implements functionality for building packages as well as additional commands and options for package maintenance. It might be wise to start by checking what the [[Abuild and Helpers|abuild]] program can/cannot do.{{Cmd|abuild -h}}&lt;br /&gt;
&lt;br /&gt;
For realtime help, you can also go on #alpine-devel on [[IRC]].&lt;br /&gt;
&lt;br /&gt;
A reference for APKBUILD files is available as [[APKBUILD Reference]] wiki page or a man page in the {{pkg|abuild-doc}} package:{{Cmd|man APKBUILD}}&lt;br /&gt;
&lt;br /&gt;
== Creating an APKBUILD file  ==&lt;br /&gt;
&lt;br /&gt;
=== Use a template APKBUILD ===&lt;br /&gt;
&lt;br /&gt;
Alpine Linux has the following tools to create a template APKBUILD file.&lt;br /&gt;
&lt;br /&gt;
==== newapkbuild ====&lt;br /&gt;
{{:Include:Newapkbuild}}&lt;br /&gt;
&lt;br /&gt;
If you doubt to which repository your package belongs to you can safely use &#039;&#039;&#039;testing&#039;&#039;&#039;. Building package in your aports/testing directory is not mandatory but this way the package is already at the right place.&lt;br /&gt;
&lt;br /&gt;
If you are creating a daemon package which needs initd scripts you can add the -c making it: {{Cmd|newapkbuild -c &#039;&#039;packagename&#039;&#039;}}&lt;br /&gt;
This will copy the sample initd and confd files to the build directory. A third file sample.install file will be copied as well (we will discuss this later on).&lt;br /&gt;
&lt;br /&gt;
==== apkbuild-cpan ====&lt;br /&gt;
{{:Include:apkbuild-cpan}}&lt;br /&gt;
&lt;br /&gt;
==== apkbuild-pypi ====&lt;br /&gt;
{{:Include:apkbuild-pypi}}&lt;br /&gt;
&lt;br /&gt;
=== Modify your APKBUILD ===&lt;br /&gt;
Edit APKBUILD and fill in the needed info (especially pkgname, pkgver, pkgdesc, url, license, depends and source). &lt;br /&gt;
&lt;br /&gt;
If you are going to use any of the variables for directories like $pkgdir, always make sure they are double quoted like: &lt;br /&gt;
&lt;br /&gt;
 &amp;quot;$pkgdir&amp;quot;/somedir&lt;br /&gt;
&lt;br /&gt;
This will prevent issues with spaces/special characters in the future. &lt;br /&gt;
&lt;br /&gt;
{{Note|If you like syntax highlighting we suggest you to install vim. We have setup vim to recognize the APKBUILD file as a bash scripts so its easier to read them.}}&lt;br /&gt;
&lt;br /&gt;
=== APKBUILD variables/functions  ===&lt;br /&gt;
&lt;br /&gt;
==== source  ====&lt;br /&gt;
&lt;br /&gt;
The source variable is not only used to list the remote source files to fetch, it is also used to list the local files that abuild will need in order to build the apk. Examples of such local files include: init.d files, conf.d files, install files (see [[Creating an Alpine package#install|install variable]]), patches, and all other necessary files.&lt;br /&gt;
&lt;br /&gt;
Here are few things to note:&lt;br /&gt;
&lt;br /&gt;
* When you are finished adding local and/or remote files to &#039;&#039;source&#039;&#039;, you can execute the following command to add their checksums to the APKBUILD file:&lt;br /&gt;
: {{cmd|abuild checksum}}&lt;br /&gt;
: {{Note|When later updating the content of &#039;&#039;source&#039;&#039;, or updating a file that is listed in &#039;&#039;source&#039;&#039;, you must also update their checksums again with the same command.}}&lt;br /&gt;
&lt;br /&gt;
* When the remote file is hosted at SourceForge, it&#039;s best to specify the special mirrors link used by SourceForge:&lt;br /&gt;
: &amp;lt;pre&amp;gt;http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz&amp;lt;/pre&amp;gt;&lt;br /&gt;
: (or similar depending on the package).&lt;br /&gt;
&lt;br /&gt;
* When the remote filename is not specified in the URI (ie, does not end in &#039;/software-1.0.tar.gz&#039;), such as:&lt;br /&gt;
: &amp;lt;pre&amp;gt;http://oss.example.org/?get=software&amp;amp;ver=1.0&amp;lt;/pre&amp;gt;&lt;br /&gt;
: You must prepend &#039;${pkgname}-${pkgver}.tar.gz::&#039; to the protocol, like so:&lt;br /&gt;
: &amp;lt;pre&amp;gt;source=&amp;quot;${pkgname}-${pkgver}.tar.gz::http://oss.example.org/?get=software&amp;amp;ver=1.0&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
: This causes the file to be saved as &#039;&#039;software-1.0.tar.gz&#039;&#039; where abuild can use it, instead of &#039;&#039;?get=software&amp;amp;ver=1.0&#039;&#039;, where abuild cannot use it.&lt;br /&gt;
&lt;br /&gt;
* Some projects didn&#039;t provide a release tarball. Beware that some git services (gitweg, cgit, …?) doesn’t provide &#039;&#039;stable&#039;&#039; tarballs, so when you point source to an tarball like &amp;lt;tt&amp;gt;https://repo.or.cz/w/gitstats.git/snapshot/ad7efbb9399e60cee6cb217c6b47e604174a8093.tar.gz&amp;lt;/tt&amp;gt;, then you will run into issues because the checksum changes when downloading on the build system. This is not a problem on GitHub, GitLab and other decent services provides, they provide &#039;&#039;stable&#039;&#039; tarballs.&lt;br /&gt;
&lt;br /&gt;
* abuild currently supports the following protocols for remote file retrieval:&lt;br /&gt;
** http&lt;br /&gt;
** https&lt;br /&gt;
** ftp&lt;br /&gt;
&amp;lt;!--: {{Note|If the you want to download from https, you need GNU wget installed on your system.}}--&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
* abuild currently supports the following archive types/archive file extensions:&lt;br /&gt;
** .tar&lt;br /&gt;
** .tar.gz / .tgz&lt;br /&gt;
** .tar.bz2&lt;br /&gt;
** .tar.lz (only in Alpine &amp;gt;=3.7)&lt;br /&gt;
** .tar.lzma&lt;br /&gt;
** .tar.xz&lt;br /&gt;
** .zip&lt;br /&gt;
&lt;br /&gt;
==== depends &amp;amp;amp; makedepends  ====&lt;br /&gt;
&lt;br /&gt;
Depends are the actual running dependencies that a package would need when it is running. Makedepends are only needed when you are building a package. If you set a package in depends, you do not need to add it to makedepends as well. The best way to find out what the depends and makedepends of a package are is to [https://en.wikipedia.org/wiki/Rtfm RTFM]. &lt;br /&gt;
&lt;br /&gt;
No kidding, lots of important information can be found in the package INSTALL and README files (or the likes). Another good way is the run &amp;lt;code&amp;gt;./configure --help&amp;lt;/code&amp;gt; from the source directory to see which options are needed for configure to finish without errors. If you do not yet have a source directory you can create one with the command: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild unpack}}&lt;br /&gt;
&lt;br /&gt;
Running &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; will also show you how you can disable a specific option for this package. For instance, a good example is &amp;quot;--disable-nls&amp;quot; which will disable native language support and thus does not depend on gettext (libiconv, glib, ...). &lt;br /&gt;
&lt;br /&gt;
Alpine likes to keep things small, so we try to disable as much as possible without losing too many features. The exact disable/enable options are decided by the package builder but please try to follow Alpine&#039;s design concept as much as possible.&lt;br /&gt;
&lt;br /&gt;
An easy way of quickly finding out the build info for a package is to check Arch Linux (Alpine package management and build scripts are similar) or Gentoo Linux ebuilds (previous versions of Alpine were based on Gentoo).&lt;br /&gt;
&lt;br /&gt;
* [https://gitweb.gentoo.org/repo/gentoo.git/tree/ Gentoo Ebuilds] &lt;br /&gt;
* [https://archlinux.org/packages/?q=search Arch Linux packages] [https://aur.archlinux.org/ Arch Linux User Repository]&lt;br /&gt;
&lt;br /&gt;
==== license  ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;license&#039;&#039;&#039; tag must reflect the license of the source code. Please check the source tarball for COPYING, LICENSE, or other files with names that indicates that it contains licensing information. Beside the license file most developer include headers in the source code files with licensing details.&lt;br /&gt;
&lt;br /&gt;
If the license is on the [https://spdx.org/licenses/ SPDX License List] or [https://spdx.org/licenses/exceptions-index.html SPDX License Exceptions], use the identifier specified by SPDX.&lt;br /&gt;
&lt;br /&gt;
Note that some licenses have additional requirements that should be adhered to. The &amp;lt;code&amp;gt;MIT&amp;lt;/code&amp;gt; license for example has the requirement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that we need to include the license as shipped with the project.&lt;br /&gt;
&lt;br /&gt;
Known licenses that require this:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;MIT&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ISC&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a package has a special/custom license or is not listed as [https://opensource.org/licenses/alphabetical OSI approved], use the identifier &amp;quot;custom&amp;quot;. In that case we need to provide the license file with the package as well.&lt;br /&gt;
&lt;br /&gt;
Because we want to save space and don&#039;t like to have licenses all over our system we have decided to include the license in the doc subpackage. Please follow the following guidelines to add a proper license. Locate the license file inside the source package. Add the doc subpackage to the $subpackages variable as follows: &lt;br /&gt;
&lt;br /&gt;
 subpackages=&amp;quot;$pkgname-doc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Add a similar line to the following to your package() function, depending on the license description file: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|install -Dm644 COPYING &amp;quot;$pkgdir&amp;quot;/usr/share/licenses/$pkgname/COPYING}}&lt;br /&gt;
&lt;br /&gt;
If you follow these steps then abuild will automatically add the license to the package-doc apk for you.&lt;br /&gt;
&lt;br /&gt;
{{Warning|It is not acceptable to package software with &amp;quot;unknown&amp;quot; license! If you can&#039;t find the license of the source code, please contact the author and ask them to specify the license. }}&lt;br /&gt;
&lt;br /&gt;
==== arch ====&lt;br /&gt;
&lt;br /&gt;
The package architecture(s) to build for.  This can be one of: &#039;&#039;x86, x86_64, all,&#039;&#039; or &#039;&#039;noarch&#039;&#039;, where &#039;&#039;all&#039;&#039; means all architectures, and &#039;&#039;noarch&#039;&#039; means it&#039;s architecture-independent (e.g., a pure-python package).&lt;br /&gt;
{{Tip|To determine if your APKBUILD can use &#039;&#039;noarch&#039;&#039;, build the package for your architecture and then run &amp;quot;scanelf -R pkg&amp;quot; from the directory that the APKBUILD resides in, in order to scan for ELF files in the &#039;&#039;./pkg&#039;&#039; directory.  If you do NOT get output from this, then &#039;&#039;noarch&#039;&#039; can be used.}}&lt;br /&gt;
&lt;br /&gt;
==== url  ====&lt;br /&gt;
&lt;br /&gt;
Website address for the program. This is useful later on when either finding documentation or other information about the package.&lt;br /&gt;
&lt;br /&gt;
==== pkgdesc  ====&lt;br /&gt;
&lt;br /&gt;
A brief, one line, description of what the package does. Useful for the package management system. It should start with a capital letter and does &#039;&#039;&#039;not&#039;&#039;&#039; end with a period.&lt;br /&gt;
&lt;br /&gt;
Here is an example from apk_info for the OpenSSH client package:&lt;br /&gt;
&lt;br /&gt;
 pkgdesc=&amp;quot;Port of OpenBSD&#039;s free SSH release - client&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== pkgver  ====&lt;br /&gt;
&lt;br /&gt;
Provide the release number of the package you are building.&lt;br /&gt;
&lt;br /&gt;
==== pkgrel  ====&lt;br /&gt;
&lt;br /&gt;
The $pkgrel versioning is made so that if you change something in your APKBUILD file without changing the actual $pkgver, you can increment pkgrel so apk tools will detect it as an update. For instance, if you forget to add a dependency, you can add it afterward and you can +1 pkgver so apk finds this update and adds the missing dependency. When there&#039;s an upstream version change, we reset the pkgrel to 0.&lt;br /&gt;
&lt;br /&gt;
==== pkgname  ====&lt;br /&gt;
&lt;br /&gt;
The base name of the package you are creating.  For Freeswitch 1.0.6, you would use &amp;quot;freeswitch&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== install  ====&lt;br /&gt;
&lt;br /&gt;
There are 6 different kinds of install scripts. Each script is called with the $pkgname.&#039;&#039;&amp;lt;action&amp;gt;&#039;&#039; where &#039;&#039;&amp;lt;action&amp;gt;&#039;&#039; is one of the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-install&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed before package is installed. Typical use is when package needs a group and a user to be created. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
addgroup -S clamav 2&amp;gt;/dev/null&lt;br /&gt;
adduser -S -D -H -s /bin/false -G clamav -g clamav clamav 2&amp;gt;/dev/null&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note the &#039;&#039;exit 0&#039;&#039; at the end. If the script exits with failure (if the user already exist), the package will not be installed and &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; will exit with failure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-install&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed after the package is installed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-upgrade&lt;br /&gt;
&amp;lt;dd&amp;gt;Same as pre-install but is executed before upgrading/downgrading/reinstalling an already installed package. Note that exiting with failure will not cause apk to exit with failure, but will mark the package as broken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-upgrade&lt;br /&gt;
&amp;lt;dd&amp;gt;Same as post-install but is executed after upgrading/downgrading/reinstalling an already installed package. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-deinstall&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed before uninstalling a package. If script exits with failure apk will not uninstall the package.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-deinstall&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed after a package have been uninstalled. For example, can be used to restore busybox links:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
busybox --install -s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the package has a pre-install and post-install script the APKBUILD should have the &#039;&#039;install&#039;&#039; variable defined:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
install=&amp;quot;$pkgname.pre-install $pkgname.post-install&amp;quot;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== subpackages  ====&lt;br /&gt;
&lt;br /&gt;
$subpackages are made to split up the normal &amp;quot;make install&amp;quot; into separate packages. The most common subpackages we use are doc and dev. Because we like to keep our target system small we move documentation and development files (only needed when building packages) into separate packages. To use the specific program a user only need to install the base apk without package-doc or package-dev, but if he wants to read the manual he will need to install package-doc. &lt;br /&gt;
&lt;br /&gt;
The easiest way to find out if you need to use -dev and -doc is to first build the package without these options set and wait until the build finishes. When its finished you should have a pkg directory which is the fake root directory. Inside this directory you will see the structure as how it would be installed in / on the target system. &lt;br /&gt;
&lt;br /&gt;
To see if you need the -dev package you can run the following cmd: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|find pkg/usr/ -name &#039;*.[acho]&#039; -o -name &#039;*.la&#039;}}&lt;br /&gt;
&lt;br /&gt;
If this returns any files you need to include the -dev package. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; To see if you need the -doc package you can run the following cmd: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|find pkg/usr/share -name doc -o -name man -o -name info -o -name html -o -name sgml -o -name licenses}}&lt;br /&gt;
&lt;br /&gt;
If this returns any directories you need to include the -doc package. &lt;br /&gt;
&lt;br /&gt;
===== Custom subpackages  =====&lt;br /&gt;
&lt;br /&gt;
Some software additionally has non-essential files that do not qualify as either documentation or development content. These files should be placed in their own, specialized subpackage(s). Some packages include large test suites which are only needed in specific circumstances or binaries which have depends which we prefer not to install. To handle those we create our own package/function. In the APKBUILD below the build() function we create another function: &lt;br /&gt;
&lt;br /&gt;
 test() {&lt;br /&gt;
        mkdir -p &amp;quot;$subpkgdir&amp;quot;/usr&lt;br /&gt;
        mv &amp;quot;$pkgdir&amp;quot;/usr/package-test &amp;quot;$subpkgdir&amp;quot;/usr/&lt;br /&gt;
        # or amove usr/package-test&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
We also need to add the package info to $subpackages variable: &lt;br /&gt;
&lt;br /&gt;
 subpackages=&amp;quot;$pkgname-doc $pkgname-dev $pkgname-test&amp;quot;&lt;br /&gt;
&lt;br /&gt;
After we finish building the package you should see another apk called packagename-test.apk which includes the files which we moved to the $subpkgdir dir. &lt;br /&gt;
&lt;br /&gt;
The above mentioned variables can also be used in our custom function. If we want for instance to build the test() function with perl support we would add: &lt;br /&gt;
&lt;br /&gt;
 depends=&amp;quot;perl&amp;quot;&lt;br /&gt;
 makedepends=&amp;quot;perl-dev&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If we would install the base package it would not install perl, but if we install the package-test package it would.&lt;br /&gt;
&lt;br /&gt;
==== Patches  ====&lt;br /&gt;
&lt;br /&gt;
Please make sure you always submit human readable patches. Ways to create them are: &lt;br /&gt;
&lt;br /&gt;
directory compare: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|diff -Nurp original_directory new_directory &amp;amp;gt; filename.patch}}&lt;br /&gt;
&lt;br /&gt;
file compare: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|diff -up original.file new.file &amp;amp;gt; filename.patch}}&lt;br /&gt;
&lt;br /&gt;
If a patch contains a completely new file but not *.rej or *.orig file, you need to add -N option to diff, but you may need to add exclusions with &amp;lt;code&amp;gt;--exclude PATTERN&amp;lt;/code&amp;gt; so that you do not inadvertently add files.  You may need to manually delete unwanted files inside the patch file.&lt;br /&gt;
&lt;br /&gt;
Because multiple patches can patch the same file, they can change the offsets required by subsequent patches. To make sure we always patch in a specific way, we should number the patches as follows: &lt;br /&gt;
&lt;br /&gt;
 10-patch1.patch 20-patch2.patch 30-patch3.patch&lt;br /&gt;
&lt;br /&gt;
This way we are always sure that patch 1 is applied first, and if we want to add additional patches between them we can use appropriate indexes (e.g. 11, 12, 21, 22).&lt;br /&gt;
&lt;br /&gt;
Add the names of the patch files to the &#039;&#039;source&#039;&#039; variable. If you haven&#039;t declared a custom &#039;&#039;prepare&#039;&#039; function, no further action is necessary. Otherwise, be sure to call &#039;&#039;default_prepare&#039;&#039; in your &#039;&#039;prepare&#039;&#039; function. For example:&lt;br /&gt;
&lt;br /&gt;
 prepare() {&lt;br /&gt;
 	default_prepare&lt;br /&gt;
 &lt;br /&gt;
 	# do your stuff&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note: Some older packages contain a &#039;&#039;for&#039;&#039; loop in the &#039;&#039;prepare&#039;&#039; function to apply patches. This is not needed anymore, as patches are handled by &#039;&#039;default_prepare&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In Alpine &amp;gt;=3.4 you can define patch_args to supply the patch level.  This only works if all the patches have the same patch level.  If there are a lot of patches from different sources, there is a good chance that you may need to edit them, as discussed below.&lt;br /&gt;
&lt;br /&gt;
To automatically patch the package (available only in Alpine &amp;gt;=3.4) if it uses a patch level (-pX) other than the default (-p1), you need to carefully modify the patch.  First, you&#039;ll need a text editor that does not automatically convert  between Windows and Unix new lines (or, disable this feature) so that it preserves the old code.  The next thing you&#039;ll need to do is modify the paths on &amp;quot;+++&amp;quot; and &amp;quot;---&amp;quot; lines in the .patch file.  You can begin the path with a/ and b/ like shown below.  Next, you need to adjust the paths so that the relative base path is from inside $builddir.  Anything to the left of $builddir, including $builddir itself, needs to be removed from the path.  So, if $builddir is /home/USER/aports/community/chromium/src/chromium-65, you need to erase it on the &amp;quot;+++&amp;quot; and &amp;quot;---&amp;quot; lines.  Inside the chromium-65 folder you can see a src folder that has 3rdparty as a descendant.  If a patch originally has a deeper patch level, you may need to fill in the missing portion of the path.  For example, use the &amp;lt;code&amp;gt;find . -name &amp;quot;Assertions.cpp&amp;quot;&amp;lt;/code&amp;gt; command to find the full path to the file relative to the base.&lt;br /&gt;
&lt;br /&gt;
{{Cat|example.patch|&amp;lt;nowiki&amp;gt;&lt;br /&gt;
Author: John Doe &amp;lt;johndoe@mail.com&amp;gt;&lt;br /&gt;
URL: http://.....&lt;br /&gt;
Summary: Fixes musl compatibility&lt;br /&gt;
----&lt;br /&gt;
--- a/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp.orig&lt;br /&gt;
+++ b/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp&lt;br /&gt;
@@ -142,7 +142,7 @@&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 FrameToNameScope::FrameToNameScope(void* addr) : m_name(0), m_cxaDemangled(0) {&lt;br /&gt;
-#if OS(MACOSX) || (OS(LINUX) &amp;amp;&amp;amp; !defined(__UCLIBC__))&lt;br /&gt;
+#if OS(MACOSX) || (OS(LINUX) &amp;amp;&amp;amp; defined(__GLIBC__))&lt;br /&gt;
   Dl_info info;&lt;br /&gt;
   if (!dladdr(addr, &amp;amp;info) || !info.dli_sname)&lt;br /&gt;
return;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Portions of the patch may be outdated, removed completely as in the source code file completely removed, or moved or renamed files.  You need to delete that section of the patch or find where that section of code changed and re-diff it.&lt;br /&gt;
&lt;br /&gt;
It is good etiquette to give credit at the top and the location of where you originally found them with notes.&lt;br /&gt;
&lt;br /&gt;
Excluding patches with global variable resembling patch_opts is not available on Alpine.  To exclude patches you need to create your own custom prepare().&lt;br /&gt;
&lt;br /&gt;
If you have a monolithic patch where there are a bunch of patches in one big patch, you could use filterdiff which is available in the patchutils package.&lt;br /&gt;
&lt;br /&gt;
Just do something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
makedepends=&amp;quot;patchutils&amp;quot;&lt;br /&gt;
&lt;br /&gt;
prepare() {&lt;br /&gt;
  ...&lt;br /&gt;
  cd &amp;quot;$builddir&amp;quot;&lt;br /&gt;
  filterdiff -x &#039;*drivers/video/logo*&#039; &amp;quot;$srcdir&amp;quot;/original.patch &amp;gt; &amp;quot;$builddir&amp;quot;/modified.patch&lt;br /&gt;
  patch -p1 -i &amp;quot;$builddir&amp;quot;/modified.patch&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to put the wildcard pattern in single quotes for it to work.&lt;br /&gt;
&lt;br /&gt;
==== Configure options  ====&lt;br /&gt;
&lt;br /&gt;
Alpine has some default configure options we set by default. We use /usr for prefix to make sure everything is installed with /usr in front of it. If you notice that anything is installed in the wrong directory please run {{Cmd|./configure --help}} and see if you can set the correct location. &lt;br /&gt;
&lt;br /&gt;
We are not covering the depend switches here we have discussed this already in the depend section.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Make options  ====&lt;br /&gt;
&lt;br /&gt;
If you notice weird problems when compiling or installing the package with make/make install you could try to disable [https://www.gnu.org/software/make/manual/make.html#Parallel parallel] building/installing. A normal make line would be: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make}}&lt;br /&gt;
&lt;br /&gt;
To disable parallel we use: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make -j1}}&lt;br /&gt;
&lt;br /&gt;
We can use the same for make install. &lt;br /&gt;
&lt;br /&gt;
Because we do not want to install the package in our build environment but we want to install it in a fake root directory we need to tell &#039;make install&#039; to use another destination directory instead of &#039;/&#039;. We do this by setting a variable when we execute make install as followed: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make DESTDIR{{=}}&amp;quot;$pkgdir&amp;quot; install}}&lt;br /&gt;
&lt;br /&gt;
Please note that some Makefiles do not support this variable and will always install software in &#039;/&#039;. To make sure you do not mess up your build system NEVER run your build system as root but always use a custom user and doas when needed. If by accident the Makefile does not support DESTDIR variable it will fail to install in our build system system directories.&lt;br /&gt;
&lt;br /&gt;
==== builddir ====&lt;br /&gt;
If you used &amp;lt;tt&amp;gt;newapkbuild&amp;lt;/tt&amp;gt; to create your APKBUILD file, you must specify the path to your unpacked sources. Inside the sections during the prepare/build/install process &#039;&#039;builddir&#039;&#039; is used. Most of the time a combination of &#039;&#039;$srcdir&#039;&#039; and &#039;&#039;$pkgname-$pkgver&#039;&#039; will work. When not, check the /src directory or the source tarball for the right string. Especially when you are working with automatically generated tarballs (like from github and gitorious), this needs to be adjusted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
builddir=&amp;quot;$srcdir&amp;quot;/$pkgname-$pkgver&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Additional files  ====&lt;br /&gt;
&lt;br /&gt;
If you want/need to install additional files not mentioned above you can use the following cmd (this is an example of a conf file): &lt;br /&gt;
&lt;br /&gt;
{{Cmd|install -Dm644 doc/$pkgname.conf &amp;quot;$pkgdir&amp;quot;/etc/$pkgname.conf}}&lt;br /&gt;
&lt;br /&gt;
== Build the package  ==&lt;br /&gt;
&lt;br /&gt;
If you did not already create the checksums as mentioned above you can do so now: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $pkgname&lt;br /&gt;
abuild checksum}}&lt;br /&gt;
&lt;br /&gt;
It&#039;s about time we build our package. Because a build system should never have all the package installed to prevent linking to packages we don&#039;t want it to link we use a abuild recursively with the &#039;&#039;&#039;-r&#039;&#039;&#039; switch. It will install all dependencies from your repository and builds it, afterwards it will uninstall all those depending packages again.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild -r}}&lt;br /&gt;
&lt;br /&gt;
See also [[Abuild_and_Helpers|Abuild and Helpers]].&lt;br /&gt;
&lt;br /&gt;
== Testing the package locally ==&lt;br /&gt;
&lt;br /&gt;
When it completes, your package will be found in a subfolder of &amp;lt;code&amp;gt;~/packages&amp;lt;/code&amp;gt;.  You may want to test it on your machine but only if the package is not a critical system package like musl or apk-tools package.  To avoid borking your system (as in making it impossible to use &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; or to restore back the system and the compiler toolchain) for a critical system package, you should test on a chroot first before using it live.&lt;br /&gt;
&lt;br /&gt;
The best way to test a package locally is to modify your &amp;lt;code&amp;gt;/etc/apk/repositories&amp;lt;/code&amp;gt; so that it includes the indexes to your locally built packages - the directories that contain &amp;lt;code&amp;gt;ARCH/APKINDEX.tar.gz&amp;lt;/code&amp;gt;. For example the &amp;lt;code&amp;gt;/etc/apk/repositories&amp;lt;/code&amp;gt; below includes locally built packages in testing, community and main. To use this example change &amp;lt;code&amp;gt;USER&amp;lt;/code&amp;gt; to your login name.&lt;br /&gt;
&lt;br /&gt;
{{Cat|/etc/apk/repositories|/home/USER/packages/testing/&lt;br /&gt;
/home/USER/packages/main/&lt;br /&gt;
/home/USER/packages/community/&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/main&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/community&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/testing&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
If you prefer to test a package without changing any other configuration you can use the &amp;lt;code&amp;gt;-X, --repository&amp;lt;/code&amp;gt; option to &amp;lt;code&amp;gt;apk&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|doas apk add --repository /home/USER/packages/testing $pkgname}}&lt;br /&gt;
&lt;br /&gt;
== Code review ==&lt;br /&gt;
&lt;br /&gt;
To successfully have your package pass through code reviewers (as of Feb 18, 2018 are nmeum and jirutka on GitHub) and possible increased acceptance, the following conventions need to be followed:&lt;br /&gt;
&lt;br /&gt;
# Custom global variables should be prefixed with underscore (_).&lt;br /&gt;
# Compact code as in merged commands, removed unused variables, removal of functions that do the same thing that are automatically handled by abuild.&lt;br /&gt;
# Versioning is done properly.  For details see [[APKBUILD_Reference#pkgver]].&lt;br /&gt;
# Licensing is done properly. Remove unnecessary copying of licensing that is already OSI approved.&lt;br /&gt;
# Naming conventions rules for unofficial variables as in _gitrev is preferred over commit.&lt;br /&gt;
# Indent with tabs not spaces.&lt;br /&gt;
# Removal of explicit return 1.  (They are still found the old APKBUILD files if you are learning but are now strongly discouraged.)&lt;br /&gt;
# Disabling check() requires either (1) a comment (#) stating next to options=&amp;quot;!check&amp;quot; that there is no test suite/unit tests or (2) functioning working check() function.&lt;br /&gt;
# Explicit call to subpackages=&amp;quot;$pkgname-doc&amp;quot; must be used instead of explicit gzip man page compression.&lt;br /&gt;
# Ideally, lines should be no more than 80 columns wide&lt;br /&gt;
&lt;br /&gt;
Additionally, make sure to run the linter on your package:&lt;br /&gt;
{{Cmd|doas apk add atools&lt;br /&gt;
apkbuild-lint APKBUILD}}&lt;br /&gt;
&lt;br /&gt;
For more information see [[Development using git:Quality assurance]] and [[Package_policies]].&lt;br /&gt;
Also check out [https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/COMMITSTYLE.md?ref_type=heads aports/COMMITSTYLE.md] and [https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/CODINGSTYLE.md?ref_type=heads aports/CODINGSTYLE.md]&lt;br /&gt;
&lt;br /&gt;
== Commit your work  ==&lt;br /&gt;
&lt;br /&gt;
After you successfully build your package and properly followed the conventions and requirements in the code review section, you can submit your APKBUILD to Alpine&#039;s git repository. &lt;br /&gt;
&lt;br /&gt;
Update your git repo, before adding new files: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $aportsdir&lt;br /&gt;
git pull}}&lt;br /&gt;
&lt;br /&gt;
This should pull all the changes made by others into your local git repo.&lt;br /&gt;
&lt;br /&gt;
When you think you are ready you can add your files to git: &lt;br /&gt;
&lt;br /&gt;
NOTE: when using our Gitlab instance, you can create MR&#039;s for each package. Please squash all commits related to the same package into a single one per MR.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $aportsdir&lt;br /&gt;
git add testing/$pkgdir (include any other files needed for the build; $pkgname.install...)&lt;br /&gt;
git commit}}&lt;br /&gt;
&lt;br /&gt;
Use the following commit message template for new aports (without the comments):&lt;br /&gt;
&lt;br /&gt;
{{Cat|template|testing/$pkgname: new aport   # this will be the subject line&lt;br /&gt;
                              # a blank line&lt;br /&gt;
$url                          # project homepage&lt;br /&gt;
$pkgdesc                      # one line description}}&lt;br /&gt;
&lt;br /&gt;
Or you could add the following and &amp;lt;code&amp;gt;chmod +x ports/.git/hooks/prepare-commit-msg&amp;lt;/code&amp;gt; to automatically generate commit message which the default aports/.githooks/ does not:&lt;br /&gt;
&lt;br /&gt;
{{Cat|aports/.git/hooks/prepare-commit-msg|&amp;lt;nowiki&amp;gt;#!/bin/sh&lt;br /&gt;
case &amp;quot;$2,$3&amp;quot; in&lt;br /&gt;
  ,|template,)&lt;br /&gt;
    if git diff-index --diff-filter=A --name-only --cached HEAD \&lt;br /&gt;
        | grep -q &#039;/APKBUILD$&#039;; then&lt;br /&gt;
      meta() { git diff --staged | grep &amp;quot;^+$1&amp;quot; | sed &#039;s/.*=&amp;quot;\?//;s/&amp;quot;$//&#039;;}&lt;br /&gt;
      printf &#039;testing/%s: new aport\n\n%s\n%s\n&#039; &amp;quot;$(meta pkgname)&amp;quot; \&lt;br /&gt;
        &amp;quot;$(meta url)&amp;quot; &amp;quot;$(meta pkgdesc)&amp;quot; &amp;quot;$(cat $1)&amp;quot; &amp;gt; &amp;quot;$1&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      printf &#039;%s\n\n%s&#039; `git diff-index --name-only --cached HEAD \&lt;br /&gt;
        | sed -n &#039;s/\/APKBUILD$//p;q&#039;` &amp;quot;$(cat $1)&amp;quot; &amp;gt; &amp;quot;$1&amp;quot;&lt;br /&gt;
    fi;;&lt;br /&gt;
esac&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now your changes are only available locally in your repository.&lt;br /&gt;
&lt;br /&gt;
Because you do not have push rights to the Alpine aports repository you need to create a merge request to [https://gitlab.alpinelinux.org/alpine/aports Alpine&#039;s GitLab instance].&lt;br /&gt;
&lt;br /&gt;
Alternatively you can also create a diff (patch) of the changes you made and send this patch to the &lt;br /&gt;
[https://lists.alpinelinux.org/~alpine/aports  alpine-aports mailinglist].&lt;br /&gt;
&lt;br /&gt;
To create a diff patch:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|git format-patch HEAD^}}&lt;br /&gt;
&lt;br /&gt;
or if you have sprunge, you can create a link to your patch for convenience&lt;br /&gt;
&lt;br /&gt;
{{Cmd|git format-patch HEAD^ --stdout &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; sprunge}}&lt;br /&gt;
&lt;br /&gt;
== Automated flagging of outdated ports ==&lt;br /&gt;
Consider adding your port to [https://release-monitoring.org/ Anitya], so it will be flagged as outdated&lt;br /&gt;
as soon as a new stable version is released by upstream.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[APKBUILD Reference]]&lt;br /&gt;
* [[APKBUILD examples]]&lt;br /&gt;
* [[Development using git]]&lt;br /&gt;
* [[Development using git:Quality assurance]]&lt;br /&gt;
&lt;br /&gt;
[[category: Development | Package Manager]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Help:Editing&amp;diff=28736</id>
		<title>Help:Editing</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Help:Editing&amp;diff=28736"/>
		<updated>2025-01-10T06:58:21Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Update from User:Prabuanand/Editing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOC right}}&lt;br /&gt;
&lt;br /&gt;
An edit can contribute whole new paragraphs or pages of information, or it can be as simple as fixing a typo or a spelling mistake. Make sure you are always aiming to do something which &#039;&#039;improves&#039;&#039; the contents of the wiki. &lt;br /&gt;
&lt;br /&gt;
Before [[#Steps to edit wiki|editing]] or [[#Creating pages|creating pages]] refer [[Alpine Linux:Wiki etiquette|Wiki etiquette]], [[Help:Reading]] and [[Help:Style]] pages for an overview of the common conventions followed in Alpine Linux wiki. &lt;br /&gt;
&lt;br /&gt;
{{Tip|To experiment with editing, please use the [[sandbox]]. For a quick overview of wiki markup, see [[Help:Cheatsheet]].}}&lt;br /&gt;
&lt;br /&gt;
For additional reference, use the help pages of [http://www.mediawiki.org/wiki/Help:Contents MediaWiki] and [http://en.wikipedia.org/wiki/Help:Wiki_markup Wikipedia], as this wiki is also powered by [[MediaWiki]].&lt;br /&gt;
&lt;br /&gt;
== Steps to edit wiki ==&lt;br /&gt;
  &lt;br /&gt;
# Click the &amp;lt;code&amp;gt;Edit&amp;lt;/code&amp;gt; page tab at the top of the page. Make changes to the text. When you need to use some type of formatting, such as for new headings or bolding of text, you do this using wiki syntax or the buttons in the edit toolbar above the editing zone. &lt;br /&gt;
# Before you save a change, you must enter a short note in the &amp;lt;code&amp;gt;Summary&amp;lt;/code&amp;gt; box describing your changes. &lt;br /&gt;
# Mark the edit as minor by checking the &amp;lt;code&amp;gt;This is a minor edit&amp;lt;/code&amp;gt; box if the edit is fixing a typo or a spelling mistake.&lt;br /&gt;
# It&#039;s a good idea to use the &amp;lt;code&amp;gt;Show preview&amp;lt;/code&amp;gt; button to see what your change will look like, before you save it. It&#039;s good to get into the habit of eliminating mistakes in your own work, by using a preview before saving, rather than saving, then having to do &#039;&#039;another&#039;&#039; edit just to make one or more minor corrections. &lt;br /&gt;
# Another option is the &amp;lt;code&amp;gt;Show changes&amp;lt;/code&amp;gt; button which allows you to see the differences between the current version and the edited version.&lt;br /&gt;
# Click the &amp;lt;code&amp;gt;Save Changes&amp;lt;/code&amp;gt; button to save changes. If unsatisfied, click Cancel instead and redo again.&lt;br /&gt;
&lt;br /&gt;
== Creating pages == &lt;br /&gt;
&lt;br /&gt;
{{Note|Pay proper attention to name your page as it appears as Title or Heading1 of the page and changing the page name in Wiki is not trivial. Users new to Wiki are advised to use [[#Temporary pages|Temporary pages]].}} &lt;br /&gt;
&lt;br /&gt;
=== Starting a page ===&lt;br /&gt;
&lt;br /&gt;
There are 2 ways to start a new page:&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[Title for new page]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; link on an existing page and click save. Open the page again and click on the red colored &amp;lt;u style=&amp;quot;color:#ba0000&amp;quot;&amp;gt;Title for new page&amp;lt;/u&amp;gt; link to take you to the edit page of the new page. (Recommended)&lt;br /&gt;
# Type the URL for new page with proper &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[Title for new page]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; into the address bar. For example: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://wiki.alpinelinux.org/wiki/Title_for_new_page&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In both the above cases, simply type your text in the new page, save and the new page will be created. New pages should be assigned at least one [[#categories|catgeory]]. Tutorials should also be added to [[Tutorials and Howtos]], or if it concerns Alpine development, to [[Developer Documentation]].&lt;br /&gt;
&lt;br /&gt;
===Temporary pages ===&lt;br /&gt;
&lt;br /&gt;
If you wish to create a temporary page, please use a subpage of your User namespace. For example: [[Special:MyPage/Temporary page|User:Username/Temporary page]]. This helps to keep the main namespace tidy and prevents the pages from turning up in normal searches (the User namespace is not searched by default). &lt;br /&gt;
&lt;br /&gt;
=== Moving or renaming pages ===&lt;br /&gt;
&lt;br /&gt;
* If the move might be controversial, [[#move|propose it first]] and try to resolve any disagrements on the discussion page.&lt;br /&gt;
* The new name must either not exist as a page, or exist as a redirect page with only 1 entry in its page history.&lt;br /&gt;
* Use the &amp;quot;What links here&amp;quot; link in the sidebar, and be sure to update all links to internal page targets. If this isn&#039;t done, double redirects are created. (That&#039;s where a redirect leads to a redirect, and in such cases only the first redirect is followed automatically.)&lt;br /&gt;
* In the default wiki skin, the link to Move pages (and also to Watch them) is in the popup menu between &amp;quot;View history&amp;quot; and the Search box.&lt;br /&gt;
* Always move the discussion page, too, unless you have a very good reason for not doing so.&lt;br /&gt;
&lt;br /&gt;
=== Deleting pages ===&lt;br /&gt;
&lt;br /&gt;
Only administrators can delete pages. Other users should instead use &amp;lt;code&amp;gt;{{lb}}Delete{{rb}}&amp;lt;/code&amp;gt; to [[#delete|propose the page for deletion]]. (&#039;&#039;Don&#039;t&#039;&#039; clear the page&#039;s content except where it&#039;s obviously spam.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;dt&amp;gt;Subpages&lt;br /&gt;
&amp;lt;dd&amp;gt;&lt;br /&gt;
Subpages are a way to split up pages to make them easier to follow. They should be used where there are sections which only apply to certain setups or are optional extras. As a general guide, if you think some material should be in different (or extra) categories from those of a linking page, it probably shouldn&#039;t be a subpage.&lt;br /&gt;
&lt;br /&gt;
Also, subpages should not be used as a way to categorize (for example, using Wireless/Atheros 5xxx instead of just Atheros 5xxx; instead, use or create a Wireless category).&lt;br /&gt;
&lt;br /&gt;
The template &amp;lt;code&amp;gt;{{lb}}Subpage{{rb}}&amp;lt;/code&amp;gt; can be used to tag subpages so that they do not appear in the Uncategorized pages list. It has no visible content; but adds a page to Category:Subpage.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Formatting==&lt;br /&gt;
&lt;br /&gt;
=== Inline elements ===&lt;br /&gt;
* &#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;italic&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039; or use &amp;lt;i&amp;gt;&amp;amp;lt;i&amp;gt;&amp;lt;/i&amp;gt; or &amp;lt;em&amp;gt;&amp;amp;lt;em&amp;gt;&amp;lt;/em&amp;gt; or {font-style:italic} in a style attribute&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&#039;bold&#039;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; or use &amp;lt;b&amp;gt;&amp;amp;lt;b&amp;gt;&amp;lt;/b&amp;gt; or &amp;lt;strong&amp;gt;&amp;amp;lt;strong&amp;gt;&amp;lt;/strong&amp;gt; or {font-weight:bold} in a style attribute&lt;br /&gt;
&amp;lt;!-- &amp;lt;b&amp;gt;&amp;lt;nowiki&amp;gt;&#039;&#039;&#039;&#039;&amp;lt;/nowiki&amp;gt;&amp;lt;/b&amp;gt;&#039;&#039;&#039;&#039;bold and italic&#039;&#039;&#039;&#039;&amp;lt;b&amp;gt;&amp;lt;nowiki&amp;gt;&#039;&#039;&#039;&#039;&amp;lt;/nowiki&amp;gt;&amp;lt;/b&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;small&amp;gt;&amp;amp;lt;small&amp;gt;&amp;lt;/small&amp;gt; or use {font-size:smaller} in a style attribute&lt;br /&gt;
* &amp;lt;big&amp;gt;&amp;amp;lt;big&amp;gt;&amp;lt;/big&amp;gt; or use {font-size:larger} in a style attribute (invalid in HTML5)&lt;br /&gt;
* &amp;lt;sup&amp;gt;&amp;amp;lt;sup&amp;gt;&amp;lt;/sup&amp;gt; or use {vertical-align:super} in a style attribute&lt;br /&gt;
* &amp;lt;sub&amp;gt;&amp;amp;lt;sub&amp;gt;&amp;lt;/sub&amp;gt; or use {vertical-align:sub} in a style attribute&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Here is a footnote.&amp;lt;ref&amp;gt;Insert footnote text here.&amp;lt;/ref&amp;gt;&lt;br /&gt;
Here is a recallable footnote.&amp;lt;ref name=&amp;quot;foo&amp;quot;&amp;gt;Recallable footnote.&amp;lt;/ref&amp;gt;; now let&#039;s recall it.&amp;lt;ref name=&amp;quot;foo&amp;quot; /&amp;gt;&lt;br /&gt;
References: {{reflist}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;lt;font&amp;gt; is deprecated; use {font-size:10pt; color:red; font-family:&amp;quot;Courier&amp;quot;} in a style attribute&lt;br /&gt;
* &amp;lt;nowiki&amp;gt;&amp;lt;span style=&amp;quot;&amp;lt;/nowiki&amp;gt;&amp;lt;span style=&amp;quot;color:gray&amp;quot;&amp;gt;color:gray&amp;lt;/span&amp;gt;&amp;quot;&amp;amp;gt;&lt;br /&gt;
* &amp;lt;nowiki&amp;gt;&amp;lt;span style=&amp;quot;&amp;lt;/nowiki&amp;gt;&amp;lt;span style=&amp;quot;color:white; background:red;&amp;quot;&amp;gt;color:white; background:red&amp;lt;/span&amp;gt;&amp;quot;&amp;amp;gt;&lt;br /&gt;
* &amp;lt;u&amp;gt;&amp;amp;lt;u&amp;gt;&amp;lt;/u&amp;gt; or use &amp;lt;ins&amp;gt;&amp;amp;lt;ins&amp;gt;&amp;lt;/ins&amp;gt; or {text-decoration:underline} in a style attribute (&amp;amp;lt;u&amp;gt; is valid in HTML5 but not HTML4/strict; &amp;amp;lt;ins&amp;gt; can also be a block element)&lt;br /&gt;
* &amp;lt;s&amp;gt;&amp;amp;lt;s&amp;gt;&amp;lt;/s&amp;gt; or use &amp;lt;del&amp;gt;&amp;amp;lt;del&amp;gt;&amp;lt;/del&amp;gt; or {text-decoration:line-through} in a style attribute (&amp;amp;lt;s&amp;gt; is valid in HTML5 but not HTML4/strict; &amp;amp;lt;del&amp;gt; can also be a block element)&lt;br /&gt;
&amp;lt;!-- &amp;lt;strike&amp;gt; also works, but is deprecated --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;code&amp;gt;&amp;lt;/code&amp;gt; uses {font-family:monospace;} (&amp;amp;lt;tt&amp;gt; is invalid in HTML5)&lt;br /&gt;
*: &amp;lt;code&amp;gt;&amp;lt;var&amp;gt;markup&amp;lt;/var&amp;gt; and &amp;amp;rarr; entities are still honored&amp;lt;/code&amp;gt;&lt;br /&gt;
*: See also [[#inlinecode|below]]&lt;br /&gt;
* &amp;lt;kbd&amp;gt;&amp;amp;lt;kbd&amp;gt;&amp;lt;/kbd&amp;gt; and &amp;lt;samp&amp;gt;&amp;amp;lt;samp&amp;gt;&amp;lt;/samp&amp;gt;&lt;br /&gt;
* &amp;lt;var&amp;gt;&amp;amp;lt;var&amp;gt;&amp;lt;/var&amp;gt; and &amp;lt;dfn&amp;gt;&amp;amp;lt;dfn&amp;gt;&amp;lt;/dfn&amp;gt;&lt;br /&gt;
* &amp;lt;cite&amp;gt;&amp;amp;lt;cite&amp;gt;&amp;lt;/cite&amp;gt;&lt;br /&gt;
* &amp;lt;q&amp;gt;&amp;amp;lt;q&amp;gt;&amp;lt;/q&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;nowiki&amp;gt;{{Hint|&amp;lt;/nowiki&amp;gt;{{Hint|term|explanation}}&amp;lt;nowiki&amp;gt;|explanation}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* &amp;lt;nowiki&amp;gt;{{Path|&amp;lt;/nowiki&amp;gt;{{Path|/a/path/name}}&amp;lt;nowiki&amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* {{Lb}}Key| {{Key|Ctrl}}{{Rb}}+{{Lb}}Key| {{Key|C}}{{Rb}}&lt;br /&gt;
&lt;br /&gt;
* Here is one line, followed by &amp;amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- a line break here terminates the list item --&amp;gt; and another line.&lt;br /&gt;
&lt;br /&gt;
* Here is &amp;amp;lt;!-- a comment --&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* [[HTML Entities]]&lt;br /&gt;
&lt;br /&gt;
=== Headings ===&lt;br /&gt;
&lt;br /&gt;
An article with 4 or more headings automatically creates a table of contents. You can force a table of contents (or fine-tune its placement) by inserting &amp;lt;nowiki&amp;gt;__TOC__&amp;lt;/nowiki&amp;gt;. You can suppress the table of contents by inserting &amp;lt;nowiki&amp;gt;__NOTOC__&amp;lt;/nowiki&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Start headings at level 2, and don&#039;t skip levels. First-level headings are not allowed, their formatting is reserved for the article title. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;== Heading2 ==&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;h2&amp;gt;Heading2&amp;lt;/h2&amp;gt;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;=== Heading3 ===&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;!--will produce:&lt;br /&gt;
&amp;lt;h3&amp;gt;Heading3&amp;lt;/h3&amp;gt;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;==== Heading4 ====&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;!--will produce:&lt;br /&gt;
&amp;lt;h4&amp;gt;Heading4&amp;lt;/h4&amp;gt;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Block elements ===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
=== Lists ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Here is a numbered list item.&lt;br /&gt;
## Doubly-numbered&lt;br /&gt;
#* Numbered and bulleted.&lt;br /&gt;
&lt;br /&gt;
* Here is a bulleted list item.&lt;br /&gt;
** Doubly-bulleted&lt;br /&gt;
*# Bulleted and numbered.&lt;br /&gt;
*# Another item.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce:&lt;br /&gt;
# Here is a numbered list item.&lt;br /&gt;
## Doubly-numbered&lt;br /&gt;
#* Numbered and bulleted.&lt;br /&gt;
&lt;br /&gt;
* Here is a bulleted list item.&lt;br /&gt;
** Doubly-bulleted&lt;br /&gt;
*# Bulleted and numbered.&lt;br /&gt;
*# Another item.&lt;br /&gt;
&lt;br /&gt;
Blank lines, or non-bulleted/numbered lines, end the lists. You can also code a list manually, which gives you more flexibility with multi-line entries and styling: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;ol start=2&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Ordered list item&lt;br /&gt;
&amp;lt;li value=4&amp;gt;Another item&lt;br /&gt;
&amp;lt;li type=&amp;quot;disc&amp;quot;&amp;gt;&amp;lt;p&amp;gt;A third item&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Next line&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and similarly for &amp;lt;code&amp;gt;&amp;amp;lt;ul&amp;gt;&amp;lt;/code&amp;gt;. Closing &amp;lt;code&amp;gt;&amp;amp;lt;/li&amp;gt;&amp;lt;/code&amp;gt; tags are permitted but not necessary.&lt;br /&gt;
&lt;br /&gt;
Each of these:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;item: Body text&lt;br /&gt;
&lt;br /&gt;
{{Define|item|Body text}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;item&lt;br /&gt;
&amp;lt;dd&amp;gt;Body text&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce:&lt;br /&gt;
;item: Body text&lt;br /&gt;
&lt;br /&gt;
The second markup option also wraps a &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;span id=&amp;quot;item&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; around the block. Note that with the third option, you shouldn&#039;t use closing &amp;lt;code&amp;gt;&amp;amp;lt;/dt&amp;gt;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;amp;lt;/dd&amp;gt;&amp;lt;/code&amp;gt; tags.&lt;br /&gt;
&lt;br /&gt;
=== Indenting ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;b&amp;gt;:&amp;lt;/b&amp;gt; Simply indented text (on left side only).&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;blockquote&amp;gt;This is a blockquote.&lt;br /&gt;
 It collapses whitespace, and indents on both sides.&amp;amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce:&lt;br /&gt;
: Simply indented text (on left side only).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;This is a blockquote.&lt;br /&gt;
It collapses whitespace, and indents on both sides.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;center&amp;gt; is deprecated; use &amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width:auto; margin-left:auto; margin-right:auto;&amp;quot;&amp;gt;Centered text&amp;lt;/div&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Displaying code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt id=&amp;quot;inlinecode&amp;quot;&amp;gt;Inline code&lt;br /&gt;
&amp;lt;dd&amp;gt;Use &amp;lt;code&amp;gt;&amp;amp;lt;code&amp;gt;&amp;lt;/code&amp;gt; for styling, and &amp;lt;code&amp;gt;&amp;amp;lt;nowiki&amp;gt;&amp;lt;/code&amp;gt; to suppress markup. If you use both, they must appear in that order. &amp;lt;code&amp;gt;&amp;amp;lt;nowiki&amp;gt;&amp;lt;/code&amp;gt; converts &amp;amp;rarr; entities and collapses whitespace (even multiple &amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt;s), but ignores all &amp;lt;nowiki&amp;gt;&#039;&#039;&#039;wiki&#039;&#039;&#039;&amp;lt;/nowiki&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;/code&amp;gt;HTML&amp;lt;code&amp;gt;&amp;amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt; &amp;lt;nowiki&amp;gt;[[markup]]&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;User input&lt;br /&gt;
&amp;lt;dd&amp;gt;{{Cmd|{{lb}}[[Template:Cmd|Cmd]]{{!}}a &amp;amp;lt;var&amp;gt;&amp;lt;var&amp;gt;command&amp;lt;/var&amp;gt;&amp;amp;lt;/var&amp;gt; to try{{rb}}}}&lt;br /&gt;
This is a block-level equivalent for the inline HTML element &amp;lt;code&amp;gt;&amp;amp;lt;kbd&amp;gt;&amp;lt;/code&amp;gt;. Note that wiki markup is still honored in the command text; but whitespace is not collapsed. [[#cat|See below]] for how to escape some special characters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;Command output; or shell sessions that intermix prompts, user input, and command output; or segments of files&lt;br /&gt;
&amp;lt;dd&amp;gt;Use space-indented blocks or &amp;lt;code&amp;gt;&amp;amp;lt;pre&amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Every line&lt;br /&gt;
 begins with &#039;&#039;&#039;a space&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Lines aren&#039;t&lt;br /&gt;
indented with &#039;&#039;&#039;a space.&#039;&#039;&#039;&lt;br /&gt;
&amp;amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;nowiki&amp;gt;Only first&lt;br /&gt;
line begins with &#039;&#039;&#039;a space&#039;&#039;&#039;.&amp;amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce:&lt;br /&gt;
&lt;br /&gt;
 Every line&lt;br /&gt;
 begins with &#039;&#039;&#039;a space&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Lines aren&#039;t&lt;br /&gt;
indented with &#039;&#039;&#039;a space.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Only first&lt;br /&gt;
line begins with &#039;&#039;&#039;a space&#039;&#039;&#039;.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All of these render as styled blocks, in monospace, and don&#039;t collapse whitespace. They are block-level equivalents for the inline HTML elements &amp;lt;code&amp;gt;&amp;amp;lt;samp&amp;gt;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;amp;lt;code&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
All of these markup options convert &amp;amp;rarr; entities. The first also processes &amp;lt;nowiki&amp;gt;&#039;&#039;&#039;wiki&#039;&#039;&#039; and &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;HTML&amp;lt;/span&amp;gt; [[markup]]&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&amp;lt;!-- Can contain any inline element except: IMG OBJECT BIG SMALL SUP SUB --&amp;gt;&lt;br /&gt;
The second and the third don&#039;t; and they give equivalent presentations. With the third option, lines after the first should not be space-prefixed; the block will extend to the closing &amp;lt;code&amp;gt;&amp;amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt id=&amp;quot;cat&amp;quot;&amp;gt;File contents&lt;br /&gt;
&amp;lt;dd&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
{{Cat|/path/to/file|body &#039;&#039;&#039;text&#039;&#039;&#039; &amp;lt;br /&amp;gt; more&lt;br /&gt;
Second line.}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce:&lt;br /&gt;
{{Cat|/path/to/file|body &#039;&#039;&#039;text&#039;&#039;&#039; &amp;lt;br /&amp;gt; more&lt;br /&gt;
Second line.}}&lt;br /&gt;
Note that wiki and HTML markup in the file contents aren&#039;t converted, though entities still are. You must escape characters as follows:&lt;br /&gt;
: {{=}} not inside [[..]] use &amp;amp;amp;#61; or {{lb}}{{=}}{{rb}}&lt;br /&gt;
: {{!}} not inside [[..]] use &amp;amp;amp;#124; or {{lb}}!{{rb}}&lt;br /&gt;
: {{lb}}                  use &amp;amp;amp;#123; twice or {{lb}}lb{{rb}}&lt;br /&gt;
: {{rb}}                  use &amp;amp;amp;#125; twice or {{lb}}rb{{rb}}&lt;br /&gt;
: unmatched &amp;amp;#91;&amp;amp;#91;        use &amp;amp;amp;#91; twice&lt;br /&gt;
: unmatched &amp;amp;#93;&amp;amp;#93;        use &amp;amp;amp;#93; twice&lt;br /&gt;
: # at start of line          use &amp;amp;amp;#35;&lt;br /&gt;
: * at start of line          use &amp;amp;amp;#42;&lt;br /&gt;
&lt;br /&gt;
As an alternative to all of these escapes, you could instead wrap the body in &amp;amp;lt;nowiki&amp;gt; tags.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;Block-level code with no additional styling&lt;br /&gt;
&amp;lt;dd&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;white-space:pre; font-family:monospace;&amp;quot;&amp;gt;One line.&lt;br /&gt;
Second line.&lt;br /&gt;
&amp;lt;/p&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;p style=&amp;quot;white-space:pre; font-family:monospace;&amp;quot;&amp;gt;One line.&lt;br /&gt;
Second line.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
This would be the behavior of HTML&#039;s &amp;lt;code&amp;gt;&amp;amp;lt;pre&amp;gt;&amp;lt;/code&amp;gt; without any styling. To wrap to screen width, use {white-space:pre-wrap} in a style attribute.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- this extension not present&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\sum_{n=0}\infty\frac{x^n}{n!}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tables ===&lt;br /&gt;
&lt;br /&gt;
Tables may be created in wiki pages. As a general rule, it is best to avoid using a table unless you need one as table markup often complicates page editing. &lt;br /&gt;
&lt;br /&gt;
==== Simple table ====&lt;br /&gt;
&lt;br /&gt;
In wikitext editor, place the caret where you want to insert a table. Then, in the toolbar, press “Advanced”, then choose Table button. A dialog opens.&lt;br /&gt;
&lt;br /&gt;
From the dialog, you can choose whether to enable a table header row, to stylize the table with border and to make the table sortable. A preview example is displayed. You can also set row and column counts you need. Then, press “Insert” button. &lt;br /&gt;
&amp;lt;pre&amp;gt;{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Optional Caption text&lt;br /&gt;
|-&lt;br /&gt;
! Header 1 !! Header 2 !! Header 3&lt;br /&gt;
|-&lt;br /&gt;
| 1.1 || 1.2 || 1.3&lt;br /&gt;
|-&lt;br /&gt;
| 2.1 || 2.2 || 2.3&lt;br /&gt;
|-&lt;br /&gt;
| 3.1 || 3.2 || 3.3&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- The below code is equivalent to above, used here for reference--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Optional Caption text&lt;br /&gt;
|-&lt;br /&gt;
! Header 1 &lt;br /&gt;
! Header 2 &lt;br /&gt;
! Header 3&lt;br /&gt;
|-&lt;br /&gt;
| 1.1 &lt;br /&gt;
| 1.2 &lt;br /&gt;
| 1.3&lt;br /&gt;
|-&lt;br /&gt;
| 2.1 &lt;br /&gt;
| 2.2 &lt;br /&gt;
| 2.3&lt;br /&gt;
|-&lt;br /&gt;
| 3.1 &lt;br /&gt;
| 3.2 &lt;br /&gt;
| 3.3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced table ====&lt;br /&gt;
&lt;br /&gt;
You can add HTML attributes to tables. CSS style attributes can be added with or without other HTML attributes. Table alignment is achieved by using CSS. For more information, refer official mediawiki guide on [http://www.mediawiki.org/wiki/Help:Tables tables]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{|  border=&amp;quot;1&amp;quot; style=&amp;quot;width:75%; height:200px&amp;quot;  &amp;lt;!-- align=right makes table float --&amp;gt;&lt;br /&gt;
|+ The table&#039;s caption&lt;br /&gt;
|-&lt;br /&gt;
! width=100px | Advanced Table !! columnlabel 1&lt;br /&gt;
! columnlabel 2 !! columnlabel 3&lt;br /&gt;
|-&lt;br /&gt;
! rowlabel1&lt;br /&gt;
| Cell 1.1 || Cell 1.2 || Cell 1.3&lt;br /&gt;
|- style=&amp;quot;height:100px; background:none&amp;quot; &amp;lt;!-- or style=&amp;quot;background:transparent&amp;quot; --&amp;gt;&lt;br /&gt;
! align=right style=&amp;quot;width:200px&amp;quot; | rowlabel2&lt;br /&gt;
| style=&amp;quot;background:red; color:white&amp;quot; | Cell 2.1&lt;br /&gt;
| colspan=2 align=center | Cell 2.2 &amp;amp; 2.3 &lt;br /&gt;
|- valign=top &amp;lt;!-- have to be applied to every row, default is valign=middle; or use style=&amp;quot;vertical-align:top;&amp;quot; --&amp;gt;&lt;br /&gt;
! rowspan=2 | rowlabel 3 &amp;amp; 4 &lt;br /&gt;
| Cell 3.1 || Cell 3.2 || Cell 3.3&lt;br /&gt;
|-&lt;br /&gt;
| Cell 4.1 || Cell 4.2 || Cell 4.3&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|  border=&amp;quot;1&amp;quot; style=&amp;quot;width:75%; height:200px&amp;quot;  &amp;lt;!-- align=right makes table float --&amp;gt;&lt;br /&gt;
|+ The table&#039;s caption&lt;br /&gt;
|-&lt;br /&gt;
! width=100px | Advanced Table !! columnlabel 1&lt;br /&gt;
! columnlabel 2 !! columnlabel 3&lt;br /&gt;
|-&lt;br /&gt;
! rowlabel1&lt;br /&gt;
| Cell 1.1 || Cell 1.2 || Cell 1.3&lt;br /&gt;
|- style=&amp;quot;height:100px; background:none&amp;quot; &amp;lt;!-- or style=&amp;quot;background:transparent&amp;quot; --&amp;gt;&lt;br /&gt;
! align=right style=&amp;quot;width:200px&amp;quot; | rowlabel2&lt;br /&gt;
| style=&amp;quot;background:red; color:white&amp;quot; | Cell 2.1&lt;br /&gt;
| colspan=2 align=center | Cell 2.2 &amp;amp; 2.3 &lt;br /&gt;
|- valign=top &amp;lt;!-- have to be applied to every row, default is valign=middle; or use style=&amp;quot;vertical-align:top;&amp;quot; --&amp;gt;&lt;br /&gt;
! rowspan=2 | rowlabel 3 &amp;amp; 4 &lt;br /&gt;
| Cell 3.1 || Cell 3.2 || Cell 3.3&lt;br /&gt;
|-&lt;br /&gt;
| Cell 4.1 || Cell 4.2 || Cell 4.3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Images ===&lt;br /&gt;
&lt;br /&gt;
Basic example is given below. For more information, refer official mediawiki guide on [https://www.mediawiki.org/wiki/Help:Images Images] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;[[File:Alpinelinux 01.png|right|thumb|100px|Caption text]]&amp;lt;/pre&amp;gt; will produce:&lt;br /&gt;
&lt;br /&gt;
[[File:Alpinelinux 01.png|right|thumb|100px|Caption text]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
Options can appear in any order:&lt;br /&gt;
* &amp;lt;i&amp;gt;Caption text&amp;lt;/i&amp;gt; defaults to filename; to wholly suppress, use &amp;lt;code&amp;gt;&amp;amp;lt;span title=&amp;quot;&amp;quot;&amp;gt;&amp;amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;alt=&#039;&#039;&#039;&amp;lt;i&amp;gt;text&amp;lt;/i&amp;gt;&lt;br /&gt;
* Size can be [&amp;lt;i&amp;gt;width&amp;lt;/i&amp;gt;][&amp;lt;b&amp;gt;x&amp;lt;/b&amp;gt;&amp;lt;i&amp;gt;height&amp;lt;/i&amp;gt;]&amp;lt;b&amp;gt;px&amp;lt;/b&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;page=&#039;&#039;&#039;&amp;lt;i&amp;gt;number&amp;lt;/i&amp;gt;, for PDF images&lt;br /&gt;
* rendered inline, Caption shows as hover text: &#039;&#039;&#039;frameless&#039;&#039;&#039;, and/or &#039;&#039;&#039;border&#039;&#039;&#039;&lt;br /&gt;
** rendered inline, on separate line: &#039;&#039;&#039;none&#039;&#039;&#039;&lt;br /&gt;
** Valign for inline images, defaults to middle: &#039;&#039;&#039;middle|baseline|sub|super|top|text-top|bottom|text-bottom&#039;&#039;&#039;&lt;br /&gt;
** Text flow can be stopped by placing &amp;lt;nowiki&amp;gt;{{Clear}}&amp;lt;/nowiki&amp;gt; &amp;lt;!-- &amp;lt;code&amp;gt;&amp;amp;lt;br style=&amp;quot;clear:both&amp;quot; /&amp;gt;&amp;lt;/code&amp;gt; --&amp;gt; before the text that should start below the floating image&lt;br /&gt;
** &#039;&#039;&#039;link=&#039;&#039;&#039;&amp;lt;i&amp;gt;URL&amp;lt;/i&amp;gt;|&amp;lt;i&amp;gt;pagetitle&amp;lt;/i&amp;gt;|&amp;lt;i&amp;gt;blank&amp;lt;/i&amp;gt;, only for inline images&lt;br /&gt;
* rendered floating, defaults to right align, Caption displayed below image: &#039;&#039;&#039;thumb&#039;&#039;&#039;, &#039;&#039;&#039;thumb=&#039;&#039;&#039;&amp;lt;i&amp;gt;alternate filename&amp;lt;/i&amp;gt;, &#039;&#039;&#039;frame&#039;&#039;&#039; (ignores size options)&lt;br /&gt;
** rendered floating, defaults to thumb: &#039;&#039;&#039;left|right|center&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To instead link to the file, you need to add a colon: [[:File:Alpinelinux 01.png]].&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
{{Main|Help:Signature}}&lt;br /&gt;
In Talk pages, sign and date your posts. Adding &amp;lt;nowiki&amp;gt;--~~~~&amp;lt;/nowiki&amp;gt; gives a signature and timestamp: --[[User:Dubiousjim|Dubiousjim]] 10:00, 4 March 2012 (UTC)&lt;br /&gt;
&lt;br /&gt;
=== Other elements===&lt;br /&gt;
Create HRs like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;----&amp;lt;/pre&amp;gt; ----&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
Links are used to reference pages within this wiki, other Alpine Linux websites, or external websites.&lt;br /&gt;
&lt;br /&gt;
=== Internal links ===&lt;br /&gt;
&lt;br /&gt;
A valid Internal link or wikilink &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[Kernels|Linux Kernel wiki page]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will produce:[[Kernels|Linux Kernel wiki page]]. &lt;br /&gt;
&lt;br /&gt;
When you preview or save your changes, you will see a link that can be followed to the target page. If the page exists the link is displayed in blue (like the word &amp;quot;Linux Kernel wiki page&amp;quot; above); if the page does not exist, the link appears red. Following such a &amp;quot;redlink&amp;quot; to a missing page (whether or not it is actually red) will usually enable the user to create the page.&lt;br /&gt;
&lt;br /&gt;
=== Special links ===&lt;br /&gt;
&lt;br /&gt;
For official packages in [[Repositories]]:&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{Pkg|gtk+2.0}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will produce: {{Pkg|gtk+2.0}}.&lt;br /&gt;
&lt;br /&gt;
For existing [https://gitlab.alpinelinux.org/alpine/aports/ Issues in aports]: &lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{Issue|279}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will produce: {{Issue|279}}. &lt;br /&gt;
The issue&#039;s description can be included as an optional second argument.&lt;br /&gt;
&lt;br /&gt;
For existing [https://gitlab.alpinelinux.org/alpine/aports/ Merge Requests in aports]: &lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{MR|73024|Description}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will produce: {{MR|73024|Description}}. &lt;br /&gt;
Here the MR&#039;s description has been included as an optional second argument.&lt;br /&gt;
&lt;br /&gt;
===External links===&lt;br /&gt;
&lt;br /&gt;
Link to an external website  &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[http://www.example.org/ an external link]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will produce: [http://www.example.org/ an external link]. &lt;br /&gt;
&lt;br /&gt;
If no link text is supplied &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[http://www.example.org/]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will produce: [http:///www.example.org]. To avoid this, omit brackets and use &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://www.example.org/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; to produce: http://www.example.org/.&lt;br /&gt;
&lt;br /&gt;
For displaying an external URL without hyperlink use &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;amp;lt;nowiki&amp;gt;http://www.example.org/&amp;amp;lt;/nowiki&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; to produce &amp;lt;nowiki&amp;gt;http://www.example.org&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;nowiki /&amp;gt;(use &amp;amp;lt;nowiki&amp;gt; to suppress). &lt;br /&gt;
&amp;lt;nowiki /&amp;gt;&lt;br /&gt;
 This wiki&#039;s server can be specified using &amp;lt;nowiki&amp;gt;{{SERVERNAME}}&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;[mailto:&amp;lt;/nowiki&amp;gt;[mailto:info@example.org info@example.org]&amp;lt;nowiki&amp;gt;?Subject=URL%20Encoded%20Subject&amp;amp;body=Body%20Text info]&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In general when pointing to Alpine Linux downloads stick with the &#039;&#039;&#039;[[Downloads|Downloads Page]]&#039;&#039;&#039;, but if you for any reason need to include direct download information, do so by using one of below.&lt;br /&gt;
&lt;br /&gt;
==== Download Links ====&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{#latestalp:alpine|url}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will give you latest download url for Alpine Linux Standard:&amp;lt;br/&amp;gt;&lt;br /&gt;
:{{#latestalp:alpine|url}}&lt;br /&gt;
*&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{#latestalp:alpine-mini|url}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will give you latest download url for Alpine Linux mini:&amp;lt;br/&amp;gt;&lt;br /&gt;
:{{#latestalp:alpine|url}}&lt;br /&gt;
&amp;lt;big&amp;gt;&#039;&#039;&#039;Example:&#039;&#039;&#039;&amp;lt;/big&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
 Start from &amp;lt;nowiki&amp;gt;[{{#latestalp:alpine|url}}&amp;lt;/nowiki&amp;gt; Downloading latest Alpine Linux Standard], than continue ...&lt;br /&gt;
&#039;&#039;&#039;produces:&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
Start from [{{#latestalp:alpine|url}} Downloading latest Alpine Linux Standard], than continue ...&lt;br /&gt;
&lt;br /&gt;
==== Download Boxes ====&lt;br /&gt;
&lt;br /&gt;
{| cellspacing=&amp;quot;3&amp;quot; &lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|width=&amp;quot;33%&amp;quot; class=&amp;quot;ClassForFutureCSS&amp;quot; |&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: .4em .9em .1em&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{Download|alpine}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
For standard&amp;lt;/div&amp;gt;&lt;br /&gt;
|width=&amp;quot;33%&amp;quot; class=&amp;quot;ClassForFutureCSS&amp;quot; |&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: .4em .9em .1em&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{Download|alpine-mini}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
For mini&amp;lt;/div&amp;gt;&lt;br /&gt;
|width=&amp;quot;33%&amp;quot; class=&amp;quot;ClassForFutureCSS&amp;quot; |&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: .4em .9em .1em&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{DownloadDev|alpine}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
For standard&amp;lt;/div&amp;gt;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| &amp;lt;div style=&amp;quot;padding: .4em .9em .9em&amp;quot;&amp;gt;&amp;lt;center&amp;gt;{{Download|alpine}}&amp;lt;/center&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;lt;div style=&amp;quot;padding: .4em .9em .9em&amp;quot;&amp;gt;&amp;lt;center&amp;gt;{{Download|alpine-mini}}&amp;lt;/center&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
| &amp;lt;div style=&amp;quot;padding: .4em .9em .9em&amp;quot;&amp;gt;&amp;lt;center&amp;gt;{{DownloadDev|alpine}}&amp;lt;/center&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Categories == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;categories&amp;quot;&amp;gt;&lt;br /&gt;
Categories provide automatic indexes that are useful as tables of contents. These tags create links at the bottom of the page that take you to the list of all pages in that category, which makes it easy to browse related articles. &lt;br /&gt;
&lt;br /&gt;
Every page should be assigned at least one [[Special:Categories|Category]], by placing the following &#039;&#039;&#039;at the bottom of the page&#039;&#039;&#039;:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[Category:Category name]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Always us one of the existing category from among the [[Special:Categories|list of categories in this Wiki]] before creating a new category. To refer an existing category in your wiki page, for example to link [[:Category:kernel]] use &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[:Category:kernel]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
A redirect page should contain only:&lt;br /&gt;
&amp;lt;pre&amp;gt;#REDIRECT [[pagename]]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transclusion ==&lt;br /&gt;
&lt;br /&gt;
When same content needs to be included in multiple page, use [[Alpine_Linux:Glossary#transclusion|transclusion]]. This helps when updating same content in multiple documents without having to edit those documents separately. &lt;br /&gt;
&lt;br /&gt;
To include a page (e.g. &amp;quot;Daily driver guide&amp;quot;), a colon (:) must be added in front of the name: &amp;lt;nowiki&amp;gt;{{:Daily driver guide}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refer to the list of [[Special:MostTranscludedPages|transcluded pages]] in wiki.&lt;br /&gt;
&lt;br /&gt;
== Templates ==&lt;br /&gt;
&lt;br /&gt;
Templates are standard wiki pages whose content is designed to be transcluded inside other pages. [[Help:Template]] page provides information about designing templates. Templates can be inserted into an article to aid in formatting content. &lt;br /&gt;
&lt;br /&gt;
Refer full [[Special:AllPages/Template:|list of templates]] defined in this Wiki.&lt;br /&gt;
&lt;br /&gt;
The following Message box templates provide additional emphasis to the reader.&lt;br /&gt;
&lt;br /&gt;
{{Warning|&amp;lt;nowiki&amp;gt;{{Warning|Write your Warning here.}}&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
{{Note|&amp;lt;nowiki&amp;gt;{{Note|Write your Note here.}}&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
{{Tip|&amp;lt;nowiki&amp;gt;{{Tip|Write your Tip here.}}&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
{{Todo|&amp;lt;nowiki&amp;gt;{{Todo|Write your Todo here.}}&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
{{Box|Heading:|&amp;lt;nowiki&amp;gt;{{Box|Heading:|Body}}&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
{{Box|Heading:|&amp;lt;nowiki&amp;gt;{{Box|Heading:|Body then border-color then background-color|#DF0000|#FFDFDF}}&amp;lt;/nowiki&amp;gt;|#DF0000|#FFDFDF}}&lt;br /&gt;
&lt;br /&gt;
The following Message box templates contain a specific message about a specific issue with a page or section in Wiki. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;delete&amp;quot;&amp;gt;&lt;br /&gt;
 {{lb}}[[Template:Delete|Delete]]|Message.}}&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{subst:Delete|Message.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f1f1de; border:1px solid #cc9; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Tango-user-trash-full.png|48px|left|link=]] This material is proposed for deletion ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;Message.&lt;br /&gt;
([[{{TALKPAGENAME}}|Discuss]])&amp;lt;br /&amp;gt;Make sure no other pages link here and check the page&#039;s history before deleting.&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 {{lb}}[[Template:Obsolete|Obsolete]]|Alternate message.}}&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{subst:Obsolete|Alternate message.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f1f1de; border:1px solid #cc9; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Out_of_date_clock_icon.svg‎|54px|left|link=]] This material is obsolete ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;Alternate message.&lt;br /&gt;
([[{{TALKPAGENAME}}|Discuss]])&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 {{lb}}[[Template:Merge|Merge]]|Page to merge with|Additional message.}}&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{subst:Merge|Page to merge with|Additional message.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f6f6f6; border:1px solid #aaa; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Tango-two-arrows.png‎|75px|left|link=]] This material is proposed for merging ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;It should be merged with [[Page to merge with]].{{Ifn|Additional message.| Additional message.}}&lt;br /&gt;
([[{{TALKPAGENAME}}|Discuss]])&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;move&amp;quot;&amp;gt;&lt;br /&gt;
 {{lb}}[[Template:Move|Move]]|New page name|Reason.}}&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{subst:Move|New page name|Reason.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f6f6f6; border:1px solid #aaa; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Tango-go-next.png‎|48px|left|link=]] This page is proposed for moving ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;It should be renamed to [[New page name]]. Reason.&lt;br /&gt;
([[{{TALKPAGENAME}}|Discuss]])&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 {{lb}}[[Template:Draft|Draft]]|Alternate message.}}&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{subst:Draft|Alternate message.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f6f6f6; border:1px solid #aaa; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Underconstruction_clock_icon_gray.svg‎|64px|left|link=]] This material is work-in-progress ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;Alternate message.&amp;lt;br /&amp;gt;&amp;lt;i&amp;gt;(Last edited by &lt;br /&gt;
{{REVISIONUSER}} on {{REVISIONDAY}} {{Month|{{REVISIONMONTH}}}} {{REVISIONYEAR}}.)&amp;lt;/i&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 {{lb}}[[Template:Expand|Expand]]|Alternate message.}}&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{subst:Expand|Alternate message.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f6f6f6; border:1px solid #aaa; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Tango-view-fullscreen.png‎|48px|left|link=]] This material needs expanding ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;Alternate message.&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 {{lb}}[[Template:Style|Style]]|Alternate message.}}&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{subst:Style|Alternate message.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f6f6f6; border:1px solid #aaa; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Tango-edit-clear.png‎|48px|left|link=]] This material needs wiki syntax or style improvements ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;Alternate message.&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[How to write a HOWTO]]&lt;br /&gt;
* http://en.wikipedia.org/wiki/Help:Wiki_markup&lt;br /&gt;
* http://www.mediawiki.org/wiki/Help:Formatting&lt;br /&gt;
* [http://www.mediawiki.org/wiki/Help:Contents MediaWiki&#039;s User Manual]&lt;br /&gt;
* http://en.wikipedia.org/wiki/Help:HTML_in_wikitext&lt;br /&gt;
&lt;br /&gt;
[[Category:Wiki]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=VLAN&amp;diff=28243</id>
		<title>VLAN</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=VLAN&amp;diff=28243"/>
		<updated>2024-12-10T11:53:05Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Add warning about information being outdated&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Obsolete|The information is outdated and is not suitable for systems using ifupdown-ng. Installing the vlan package may prevent your network from being configured correctly}}&lt;br /&gt;
&lt;br /&gt;
This article shows how to configure a network interface as an IEEE 802.1q VLAN trunk.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
First, install the &#039;&#039;vlan&#039;&#039; package. This will give you support for VLANs in the {{path|/etc/network/interfaces}} file.&lt;br /&gt;
{{Cmd|apk add {{pkg|vlan|arch=}}}}&lt;br /&gt;
&lt;br /&gt;
{{Warning|Installing the vlan package may result in ifupdown-ng being replaced by busybox-ifupdown. If you use ifupdown-ng specific config, this may prevent your network from being configured properly.}}&lt;br /&gt;
==Configuration==&lt;br /&gt;
Edit the {{path|/etc/network/interfaces}} file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto eth0.8&lt;br /&gt;
iface eth0.8 inet static&lt;br /&gt;
	address 192.168.0.2&lt;br /&gt;
	netmask 255.255.255.0&lt;br /&gt;
	gateway 192.168.0.1&lt;br /&gt;
	vlan-raw-device eth0&lt;br /&gt;
	vlan_id 8&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the &#039;&#039;vlan&#039;&#039; package installed, {{ic|ifup}} will find the trailing .8 in eth0.8 and will create a VLAN interface with vid 8 over eth0.&lt;br /&gt;
&lt;br /&gt;
Alternatively with vlan8 over eth0:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto vlan8&lt;br /&gt;
iface vlan8 inet static&lt;br /&gt;
	address 192.168.0.2&lt;br /&gt;
	netmask 255.255.255.0&lt;br /&gt;
	gateway 192.168.0.1&lt;br /&gt;
	vlan-raw-device eth0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A static IP address was used in the examples shown above, but DHCP can be used as well.&lt;br /&gt;
&lt;br /&gt;
== Example with bridges associated with VLANs over bonding with differing MTUs on the various VLANs ==&lt;br /&gt;
This serves as an example of some of the more complicated networking possible. Particularly, this would work well for a hypervisor attached to a dedicated storage VLAN. Less complicated implementations can be achieved by merely removing the non-applicable parts.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto lo&lt;br /&gt;
iface lo inet loopback&lt;br /&gt;
&lt;br /&gt;
auto bond0&lt;br /&gt;
  iface bond0 inet manual&lt;br /&gt;
  bond_slaves eth0 eth1&lt;br /&gt;
  bond_mode 802.3ad&lt;br /&gt;
  bond_miimon 100&lt;br /&gt;
  bond_xmit_hash_policy layer2+3&lt;br /&gt;
  post-up ip link set dev bondi0 mtu 9000&lt;br /&gt;
&lt;br /&gt;
iface bond0.1&lt;br /&gt;
&lt;br /&gt;
auto br1&lt;br /&gt;
iface br1&lt;br /&gt;
  address 192.168.1.196/24&lt;br /&gt;
  gateway 192.168.1.1&lt;br /&gt;
  bridge_ports bond0.1&lt;br /&gt;
  bridge_stp off&lt;br /&gt;
  bridge_fd 0.0&lt;br /&gt;
  post-up ip link set dev bond0.1 mtu 1500&lt;br /&gt;
&lt;br /&gt;
iface bond0.10 inet manual&lt;br /&gt;
&lt;br /&gt;
auto br10&lt;br /&gt;
  iface br10 inet static&lt;br /&gt;
  address 192.168.10.1/24&lt;br /&gt;
  bridge_ports bond0.10&lt;br /&gt;
  bridge_stp off&lt;br /&gt;
  bridge_fd 0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example with two interfaces on the same adapter. One with VLAN and one without ==&lt;br /&gt;
&lt;br /&gt;
Since Linux doesn&#039;t allow multiple default gateways we need to use a second routing table using iproute2&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add {{pkg|iproute2|arch=}}}}&lt;br /&gt;
&lt;br /&gt;
Then we&#039;ll add two new routing tables to the config file. One for each network&lt;br /&gt;
&lt;br /&gt;
{{Cmd|echo &amp;quot;1 rt1&amp;quot; &amp;gt;&amp;gt; /etc/iproute2/rt_tables;echo &amp;quot;2 rt2&amp;quot; &amp;gt;&amp;gt; /etc/iproute2/rt_tables;}}&lt;br /&gt;
&lt;br /&gt;
Now we need to edit {{path|/etc/network/interfaces}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto lo&lt;br /&gt;
iface lo inet loopback&lt;br /&gt;
&lt;br /&gt;
# the native interface without a VLAN (also called untagged)&lt;br /&gt;
&lt;br /&gt;
auto eth0&lt;br /&gt;
iface eth0&lt;br /&gt;
        address 192.168.1.100/24&lt;br /&gt;
        gateway 192.168.1.1&lt;br /&gt;
        post-up ip route add 192.168.1.0/24 dev eth0 src 192.168.1.100 table rt1&lt;br /&gt;
        post-up ip route add default via 192.168.1.1 dev eth0 table rt1 # the actual gateway for this interface&lt;br /&gt;
        post-up ip rule add from 192.168.1.100/32 table rt1&lt;br /&gt;
        post-up ip rule add to 192.168.1.100/32 table rt1&lt;br /&gt;
&lt;br /&gt;
# second interface with the vlan tag 5&lt;br /&gt;
auto eth0.5&lt;br /&gt;
iface eth0.5&lt;br /&gt;
    address 192.168.5.100/24&lt;br /&gt;
    post-up ip route add 192.168.5.0/24 dev eth0.5 src 192.168.5.100 table rt2&lt;br /&gt;
    post-up ip route add default via 192.168.5.1 dev eth0.5 table rt2 # the actual gateway for this interface&lt;br /&gt;
    post-up ip rule add from 192.168.5.100/32 table rt2&lt;br /&gt;
    post-up ip rule add to 192.168.5.100/32 table rt2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that if you want to add a third interface this way, you&#039;ll have to add another routing table&lt;br /&gt;
&lt;br /&gt;
[[Category:Networking]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=User:-anthumchris-/kernel/howto&amp;diff=28020</id>
		<title>User:-anthumchris-/kernel/howto</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=User:-anthumchris-/kernel/howto&amp;diff=28020"/>
		<updated>2024-12-03T16:21:13Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Ikke moved page User:-anthumchris-/kernel/howto to User:Anthumchris/kernel/howto: Automatically moved page while renaming the user &amp;quot;-anthumchris-&amp;quot; to &amp;quot;Anthumchris&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[User:Anthumchris/kernel/howto]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=User:Anthumchris:How_to_build_the_Alpine_Linux_kernel&amp;diff=28019</id>
		<title>User:Anthumchris:How to build the Alpine Linux kernel</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=User:Anthumchris:How_to_build_the_Alpine_Linux_kernel&amp;diff=28019"/>
		<updated>2024-12-03T16:21:13Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Ikke moved page User:-anthumchris-/kernel/howto to User:Anthumchris/kernel/howto: Automatically moved page while renaming the user &amp;quot;-anthumchris-&amp;quot; to &amp;quot;Anthumchris&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== How To Do Something ==&lt;br /&gt;
&lt;br /&gt;
Summarize your article here so readers can decide&lt;br /&gt;
quickly whether to read it.&lt;br /&gt;
&lt;br /&gt;
== Before You Start Title ==&lt;br /&gt;
Your readers might need to get ready before they can do the work.&lt;br /&gt;
If so explain those prerequisites first. This section might alternatively &lt;br /&gt;
contain background information readers need to know before they can make &lt;br /&gt;
sense of your example or carry out your instructions.&lt;br /&gt;
&lt;br /&gt;
== Doing Something Title ==&lt;br /&gt;
Write the steps of how to do something in this section.&lt;br /&gt;
If possible, show an example first, then tell your readers the steps.&lt;br /&gt;
Break this procedure into separate procedures to avoid more than&lt;br /&gt;
about 7-9 steps per procedure.&lt;br /&gt;
&lt;br /&gt;
 INSERT GREAT EXAMPLE HERE&lt;br /&gt;
&lt;br /&gt;
#Answer the following three questions, at least in your head.&lt;br /&gt;
##What do I explain how to do?&lt;br /&gt;
##How do I do that?&lt;br /&gt;
##What do HOWTO readers already know about doing that?&lt;br /&gt;
#Write up a good example. This ensures you can do it.&lt;br /&gt;
#Write up the steps to do it.&lt;br /&gt;
#Write the background info/prerequisites readers need.&lt;br /&gt;
#Write the summary.&lt;br /&gt;
#Clean up your work.&lt;br /&gt;
# Add relevant category to your page, as every page should be assigned at least one Category.&lt;br /&gt;
#Revise, revise, revise.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
If you ought to point your readers to related information&lt;br /&gt;
they no doubt need but that does not fit in your HOWTO, add links here.&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=User:-anthumchris-&amp;diff=28018</id>
		<title>User:-anthumchris-</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=User:-anthumchris-&amp;diff=28018"/>
		<updated>2024-12-03T16:21:13Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Ikke moved page User:-anthumchris- to User:Anthumchris: Automatically moved page while renaming the user &amp;quot;-anthumchris-&amp;quot; to &amp;quot;Anthumchris&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[User:Anthumchris]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=User:Anthumchris&amp;diff=28017</id>
		<title>User:Anthumchris</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=User:Anthumchris&amp;diff=28017"/>
		<updated>2024-12-03T16:21:13Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Ikke moved page User:-anthumchris- to User:Anthumchris: Automatically moved page while renaming the user &amp;quot;-anthumchris-&amp;quot; to &amp;quot;Anthumchris&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;⚠️ requesting username change to &amp;quot;anthumchris&amp;quot; 16:19 GMT&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
👨‍💻 [https://gitlab.alpinelinux.org/anthumchris/ gitlab.alpinelinux.org/anthumchris]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.21.0&amp;diff=27465</id>
		<title>Release Notes for Alpine 3.21.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.21.0&amp;diff=27465"/>
		<updated>2024-10-05T20:13:25Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Ikke moved page Release Notes for Alpine 3.21.0 to Draft Release Notes for Alpine 3.21.0: Calling it release notes is confusing since it&amp;#039;s not released yet&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Highlights ==&lt;br /&gt;
&lt;br /&gt;
* Go 1.23.1&lt;br /&gt;
* Rust 1.81&lt;br /&gt;
* GNOME 47&lt;br /&gt;
* KDE Plasma 6.1.5&lt;br /&gt;
* LXQt 2.0.0&lt;br /&gt;
* GCC 14.2.0&lt;br /&gt;
&lt;br /&gt;
== OpenSSH ==&lt;br /&gt;
&lt;br /&gt;
{{Note|TODO: Remove this section if https://gitlab.alpinelinux.org/alpine/aports/-/merge_requests/68589 gets merged before 3.21 is released }}&lt;br /&gt;
&lt;br /&gt;
You need to restart your sshd service!&lt;br /&gt;
&lt;br /&gt;
Since the &amp;lt;code&amp;gt;9.8_p1&amp;lt;/code&amp;gt; release, openssh-server is now split into two binaries, sshd and sshd-session. With this change sshd needs to be restarted to be able to accept new connections.&lt;br /&gt;
&lt;br /&gt;
Since managing services has always been out-of-scope for apk, we will NOT do the following for you:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
rc-service --ifstarted sshd restart&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== GNOME 47 ==&lt;br /&gt;
&lt;br /&gt;
GNOME 47 made it into Alpine 3.21. Everything should work as expected. Make sure you read the GNOME 47 release notes: https://release.gnome.org/47/&lt;br /&gt;
&lt;br /&gt;
== LXQt 2.0.0 ==&lt;br /&gt;
&lt;br /&gt;
LXQt has been updated to release 2.0. &lt;br /&gt;
* It now uses Qt6&lt;br /&gt;
* Many parts of LXQt are now wayland ready¹, but wayland ports of the following are pending: {{pkg|screengrab}}, {{pkg|lxqt-globalkeys}}, LXQt Panel&#039;s task-bar² and keyboard indicator, some input settings, and settings of monitor, power button, and screen locker.&lt;br /&gt;
* LXQt Panel has a new default application menu called Fancy Menu.&lt;br /&gt;
¹ [https://github.com/lxqt/lxqt-wayland-session lxqt-wayland-session] has not been released or packaged yet, but most folks wanting to test on wayland will want to use it.&amp;lt;br&amp;gt;&lt;br /&gt;
² Most folks testing LXQt on wayland are using {{pkg|waybar}} temporarily until the task-bar is ported.&lt;br /&gt;
&lt;br /&gt;
== Jellyfin ==&lt;br /&gt;
&lt;br /&gt;
Jellyfin now uses the recommended fork of ffmpeg called &amp;lt;code&amp;gt;jellyfin-ffmpeg&amp;lt;/code&amp;gt; by default. If you want to change that, take a look at the &amp;lt;code&amp;gt;ffmpegpath&amp;lt;/code&amp;gt; variable in &amp;lt;code&amp;gt;/etc/conf.d/jellyfin&amp;lt;/code&amp;gt;. ([https://gitlab.alpinelinux.org/alpine/aports/-/merge_requests/69924 !69924])&lt;br /&gt;
&lt;br /&gt;
== Bats ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;main/bats&amp;quot; was renamed to &amp;quot;main/bats-core&amp;quot;. Now there is a meta package &amp;quot;community/bats&amp;quot; which contains:&lt;br /&gt;
&lt;br /&gt;
* bats-core&lt;br /&gt;
* bats-file&lt;br /&gt;
* bats-support&lt;br /&gt;
* bats-assert&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Creating_an_Alpine_package&amp;diff=27428</id>
		<title>Creating an Alpine package</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Creating_an_Alpine_package&amp;diff=27428"/>
		<updated>2024-09-30T05:33:38Z</updated>

		<summary type="html">&lt;p&gt;Ikke: /* license */ Add list of known licenses that require copyright notice to be included&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOC right}}&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This is a brief list of the steps to add a new package. Details are below, but a NB can miss a few steps.&lt;br /&gt;
&lt;br /&gt;
# Create an account on https://gitlab.alpinelinux.org&lt;br /&gt;
# [[Abuild_and_Helpers#Setting_up_the_build_environment|Setup the build environment for aports]].&lt;br /&gt;
# Fork the [https://gitlab.alpinelinux.org/alpine/aports aports repository]. &lt;br /&gt;
# Clone your new fork.&lt;br /&gt;
# Set git pull.rebase=true, set your username and email.&lt;br /&gt;
# Create and switch to a new branch (don&#039;t use master).&lt;br /&gt;
# Add a new directory under testing that is your new package name.&lt;br /&gt;
# Add your APKBUILD file.&lt;br /&gt;
# Run abuild checksum&lt;br /&gt;
# Make sure you run the apkbuild-lint and aport -r and there are no warnings.&lt;br /&gt;
# Commit your APKBUILD with the commit message: &#039;testing/packagename: new aport&#039;&lt;br /&gt;
# Push your changes to your fork on https://gitlab.alpinelinux.org/alpine.&lt;br /&gt;
# Create a merge request.&lt;br /&gt;
&lt;br /&gt;
Please see the rest of this wiki for details on the steps above.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
To build a package for Alpine Linux you need an Alpine Linux installation. Check the [[Installation]] page to see all available installation options.&lt;br /&gt;
&lt;br /&gt;
== Setup your system and account  ==&lt;br /&gt;
{{:Setup_your_system_and_account_for_building_packages}}&lt;br /&gt;
&lt;br /&gt;
== Getting some help ==&lt;br /&gt;
&lt;br /&gt;
It might be wise to start by checking what the [[Abuild and Helpers|abuild]] program can/cannot do.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild -h}}&lt;br /&gt;
&lt;br /&gt;
For real help, you can also go on #alpine-devel on [[IRC]].&lt;br /&gt;
&lt;br /&gt;
A reference for APKBUILD files is available as [[APKBUILD Reference]] wiki page or a man page in the &#039;abuild-doc&#039; package:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|man APKBUILD}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating an APKBUILD file  ==&lt;br /&gt;
&lt;br /&gt;
=== Use a template APKBUILD ===&lt;br /&gt;
&lt;br /&gt;
The newapkbuild tool, which is installed as part of the {{Pkg|abuild}} package, can create you a new APKBUILD template to start with. It will create a directory with the given package name, place an example/template APKBUILD file to the given directory, and fill some variables if those are provided. Please check the [[Package_policies| package policies]] page about naming details.&lt;br /&gt;
&lt;br /&gt;
If you doubt to which repository your package belongs to you can safely use &#039;&#039;&#039;testing&#039;&#039;&#039;. Building package in your aports/testing directory is not mandatory but this way the package is already at the right place.&lt;br /&gt;
&lt;br /&gt;
{{:Abuild and Helpers}}&lt;br /&gt;
&lt;br /&gt;
{{Note|On older Alpine systems, abuild -c -n &#039;&#039;packagename&#039;&#039; was the way to create APKBUILD files. The &#039;packagename&#039; was a parameter to the -n option so order of -c and -n matters. }}&lt;br /&gt;
&lt;br /&gt;
[[Abuild_and_Helpers#apkbuild-cpan|apkbuild-cpan]] simplifies the creation of perl packages from CPAN and [[Abuild_and_Helpers#apkbuild-pypi|apkbuild-pypi]] ease the generation of APKBUILD files for python packages from PyPi.  &lt;br /&gt;
&lt;br /&gt;
If you are creating a daemon package which needs initd scripts you can add the -c making it: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|newapkbuild -c &#039;&#039;packagename&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
This will copy the sample initd and confd files to the build directory.&amp;lt;BR&amp;gt;&lt;br /&gt;
A third file sample.install file will be copied as well (we will discuss this later on).&lt;br /&gt;
&lt;br /&gt;
=== Modify your APKBUILD ===&lt;br /&gt;
Edit APKBUILD and fill in the needed info (especially pkgname, pkgver, pkgdesc, url, license, depends and source). &lt;br /&gt;
&lt;br /&gt;
If you are going to use any of the variables for directories like $pkgdir, always make sure they are double quoted like: &lt;br /&gt;
&lt;br /&gt;
 &amp;quot;$pkgdir&amp;quot;/somedir&lt;br /&gt;
&lt;br /&gt;
This will prevent issues with spaces/special characters in the future. &lt;br /&gt;
&lt;br /&gt;
{{Note|If you like syntax highlighting we suggest you to install vim. We have setup vim to recognize the APKBUILD file as a bash scripts so its easier to read them.}}&lt;br /&gt;
&lt;br /&gt;
=== APKBUILD variables/functions  ===&lt;br /&gt;
&lt;br /&gt;
==== source  ====&lt;br /&gt;
&lt;br /&gt;
The source variable is not only used to list the remote source files to fetch, it is also used to list the local files that abuild will need in order to build the apk. Examples of such local files include: init.d files, conf.d files, install files (see [[Creating an Alpine package#install|install variable]]), patches, and all other necessary files.&lt;br /&gt;
&lt;br /&gt;
Here are few things to note:&lt;br /&gt;
&lt;br /&gt;
* When you are finished adding local and/or remote files to &#039;&#039;source&#039;&#039;, you can execute the following command to add their checksums to the APKBUILD file:&lt;br /&gt;
: {{cmd|abuild checksum}}&lt;br /&gt;
: {{Note|When later updating the content of &#039;&#039;source&#039;&#039;, or updating a file that is listed in &#039;&#039;source&#039;&#039;, you must also update their checksums again with the same command.}}&lt;br /&gt;
&lt;br /&gt;
* When the remote file is hosted at SourceForge, it&#039;s best to specify the special mirrors link used by SourceForge:&lt;br /&gt;
: &amp;lt;pre&amp;gt;http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz&amp;lt;/pre&amp;gt;&lt;br /&gt;
: (or similar depending on the package).&lt;br /&gt;
&lt;br /&gt;
* When the remote filename is not specified in the URI (ie, does not end in &#039;/software-1.0.tar.gz&#039;), such as:&lt;br /&gt;
: &amp;lt;pre&amp;gt;http://oss.example.org/?get=software&amp;amp;ver=1.0&amp;lt;/pre&amp;gt;&lt;br /&gt;
: You must prepend &#039;${pkgname}-${pkgver}.tar.gz::&#039; to the protocol, like so:&lt;br /&gt;
: &amp;lt;pre&amp;gt;source=&amp;quot;${pkgname}-${pkgver}.tar.gz::http://oss.example.org/?get=software&amp;amp;ver=1.0&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
: This causes the file to be saved as &#039;&#039;software-1.0.tar.gz&#039;&#039; where abuild can use it, instead of &#039;&#039;?get=software&amp;amp;ver=1.0&#039;&#039;, where abuild cannot use it.&lt;br /&gt;
&lt;br /&gt;
* Some projects didn&#039;t provide a release tarball. Beware that some git services (gitweg, cgit, …?) doesn’t provide &#039;&#039;stable&#039;&#039; tarballs, so when you point source to an tarball like &amp;lt;tt&amp;gt;https://repo.or.cz/w/gitstats.git/snapshot/ad7efbb9399e60cee6cb217c6b47e604174a8093.tar.gz&amp;lt;/tt&amp;gt;, then you will run into issues because the checksum changes when downloading on the build system. This is not a problem on GitHub, GitLab and other decent services provides, they provide &#039;&#039;stable&#039;&#039; tarballs.&lt;br /&gt;
&lt;br /&gt;
* abuild currently supports the following protocols for remote file retrieval:&lt;br /&gt;
** http&lt;br /&gt;
** https&lt;br /&gt;
** ftp&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--: {{Note|If the you want to download from https, you need GNU wget installed on your system.}}--&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
* abuild currently supports the following archive types/archive file extensions:&lt;br /&gt;
** .tar&lt;br /&gt;
** .tar.gz / .tgz&lt;br /&gt;
** .tar.bz2&lt;br /&gt;
** .tar.lz (only in Alpine &amp;gt;=3.7)&lt;br /&gt;
** .tar.lzma&lt;br /&gt;
** .tar.xz&lt;br /&gt;
** .zip&lt;br /&gt;
&lt;br /&gt;
==== depends &amp;amp;amp; makedepends  ====&lt;br /&gt;
&lt;br /&gt;
Depends are the actual running dependencies that a package would need when it is running. Makedepends are only needed when you are building a package. If you set a package in depends, you do not need to add it to makedepends as well. The best way to find out what the depends and makedepends of a package are is to [https://en.wikipedia.org/wiki/Rtfm RTFM]. &lt;br /&gt;
&lt;br /&gt;
No kidding, lots of important information can be found in the package INSTALL and README files (or the likes). Another good way is the run &amp;lt;code&amp;gt;./configure --help&amp;lt;/code&amp;gt; from the source directory to see which options are needed for configure to finish without errors. If you do not yet have a source directory you can create one with the command: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild unpack}}&lt;br /&gt;
&lt;br /&gt;
Running &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; will also show you how you can disable a specific option for this package. For instance, a good example is &amp;quot;--disable-nls&amp;quot; which will disable native language support and thus does not depend on gettext (libiconv, glib, ...). &lt;br /&gt;
&lt;br /&gt;
Alpine likes to keep things small, so we try to disable as much as possible without losing too many features. The exact disable/enable options are decided by the package builder but please try to follow Alpine&#039;s design concept as much as possible.&lt;br /&gt;
&lt;br /&gt;
An easy way of quickly finding out the build info for a package is to check Arch Linux (Alpine package management and build scripts are similar) or Gentoo Linux ebuilds (previous versions of Alpine were based on Gentoo).&lt;br /&gt;
&lt;br /&gt;
* [https://gitweb.gentoo.org/repo/gentoo.git/tree/ Gentoo Ebuilds] &lt;br /&gt;
* [https://archlinux.org/packages/?q=search Arch Linux packages] [https://aur.archlinux.org/ Arch Linux User Repository]&lt;br /&gt;
&lt;br /&gt;
==== license  ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;license&#039;&#039;&#039; tag must reflect the license of the source code. Please check the source tarball for COPYING, LICENSE, or other files with names that indicates that it contains licensing information. Beside the license file most developer include headers in the source code files with licensing details.&lt;br /&gt;
&lt;br /&gt;
If the license is on the [https://spdx.org/licenses/ SPDX License List] or [https://spdx.org/licenses/exceptions-index.html SPDX License Exceptions], use the identifier specified by SPDX.&lt;br /&gt;
&lt;br /&gt;
Note that some licenses have additional requirements that should be adhered to. The &amp;lt;code&amp;gt;MIT&amp;lt;/code&amp;gt; license for example has the requirement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that we need to include the license as shipped with the project.&lt;br /&gt;
&lt;br /&gt;
Known licenses that require this:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;MIT&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ISC&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a package has a special/custom license or is not listed as [https://opensource.org/licenses/alphabetical OSI approved], use the identifier &amp;quot;custom&amp;quot;. In that case we need to provide the license file with the package as well.&lt;br /&gt;
&lt;br /&gt;
Because we want to save space and don&#039;t like to have licenses all over our system we have decided to include the license in the doc subpackage. Please follow the following guidelines to add a proper license. Locate the license file inside the source package. Add the doc subpackage to the $subpackages variable as follows: &lt;br /&gt;
&lt;br /&gt;
 subpackages=&amp;quot;$pkgname-doc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Add a similar line to the following to your package() function, depending on the license description file: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|install -Dm644 COPYING &amp;quot;$pkgdir&amp;quot;/usr/share/licenses/$pkgname/COPYING}}&lt;br /&gt;
&lt;br /&gt;
If you follow these steps then abuild will automatically add the license to the package-doc apk for you.&lt;br /&gt;
&lt;br /&gt;
{{Warning|It is not acceptable to package software with &amp;quot;unknown&amp;quot; license! If you can&#039;t find the license of the source code, please contact the author and ask them to specify the license. }}&lt;br /&gt;
&lt;br /&gt;
==== arch ====&lt;br /&gt;
&lt;br /&gt;
The package architecture(s) to build for.  This can be one of: &#039;&#039;x86, x86_64, all,&#039;&#039; or &#039;&#039;noarch&#039;&#039;, where &#039;&#039;all&#039;&#039; means all architectures, and &#039;&#039;noarch&#039;&#039; means it&#039;s architecture-independent (e.g., a pure-python package).&lt;br /&gt;
{{Tip|To determine if your APKBUILD can use &#039;&#039;noarch&#039;&#039;, build the package for your architecture and then run &amp;quot;scanelf -R pkg&amp;quot; from the directory that the APKBUILD resides in, in order to scan for ELF files in the &#039;&#039;./pkg&#039;&#039; directory.  If you do NOT get output from this, then &#039;&#039;noarch&#039;&#039; can be used.}}&lt;br /&gt;
&lt;br /&gt;
==== url  ====&lt;br /&gt;
&lt;br /&gt;
Website address for the program. This is useful later on when either finding documentation or other information about the package.&lt;br /&gt;
&lt;br /&gt;
==== pkgdesc  ====&lt;br /&gt;
&lt;br /&gt;
A brief, one line, description of what the package does. Useful for the package management system. It should start with a capital letter and does &#039;&#039;&#039;not&#039;&#039;&#039; end with a period.&lt;br /&gt;
&lt;br /&gt;
Here is an example from apk_info for the OpenSSH client package:&lt;br /&gt;
&lt;br /&gt;
 pkgdesc=&amp;quot;Port of OpenBSD&#039;s free SSH release - client&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== pkgver  ====&lt;br /&gt;
&lt;br /&gt;
Provide the release number of the package you are building.&lt;br /&gt;
&lt;br /&gt;
==== pkgrel  ====&lt;br /&gt;
&lt;br /&gt;
The $pkgrel versioning is made so that if you change something in your APKBUILD file without changing the actual $pkgver, you can increment pkgrel so apk tools will detect it as an update. For instance, if you forget to add a dependency, you can add it afterward and you can +1 pkgver so apk finds this update and adds the missing dependency. When there&#039;s an upstream version change, we reset the pkgrel to 0.&lt;br /&gt;
&lt;br /&gt;
==== pkgname  ====&lt;br /&gt;
&lt;br /&gt;
The base name of the package you are creating.  For Freeswitch 1.0.6, you would use &amp;quot;freeswitch&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== install  ====&lt;br /&gt;
&lt;br /&gt;
There are 6 different kinds of install scripts. Each script is called with the $pkgname.&#039;&#039;&amp;lt;action&amp;gt;&#039;&#039; where &#039;&#039;&amp;lt;action&amp;gt;&#039;&#039; is one of the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-install&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed before package is installed. Typical use is when package needs a group and a user to be created. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
addgroup -S clamav 2&amp;gt;/dev/null&lt;br /&gt;
adduser -S -D -H -s /bin/false -G clamav -g clamav clamav 2&amp;gt;/dev/null&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note the &#039;&#039;exit 0&#039;&#039; at the end. If the script exits with failure (if the user already exist), the package will not be installed and &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; will exit with failure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-install&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed after the package is installed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-upgrade&lt;br /&gt;
&amp;lt;dd&amp;gt;Same as pre-install but is executed before upgrading/downgrading/reinstalling an already installed package. Note that exiting with failure will not cause apk to exit with failure, but will mark the package as broken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-upgrade&lt;br /&gt;
&amp;lt;dd&amp;gt;Same as post-install but is executed after upgrading/downgrading/reinstalling an already installed package. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-deinstall&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed before uninstalling a package. If script exits with failure apk will not uninstall the package.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-deinstall&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed after a package have been uninstalled. For example, can be used to restore busybox links:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
busybox --install -s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the package has a pre-install and post-install script the APKBUILD should have the &#039;&#039;install&#039;&#039; variable defined:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
install=&amp;quot;$pkgname.pre-install $pkgname.post-install&amp;quot;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== subpackages  ====&lt;br /&gt;
&lt;br /&gt;
$subpackages are made to split up the normal &amp;quot;make install&amp;quot; into separate packages. The most common subpackages we use are doc and dev. Because we like to keep our target system small we move documentation and development files (only needed when building packages) into separate packages. To use the specific program a user only need to install the base apk without package-doc or package-dev, but if he wants to read the manual he will need to install package-doc. &lt;br /&gt;
&lt;br /&gt;
The easiest way to find out if you need to use -dev and -doc is to first build the package without these options set and wait until the build finishes. When its finished you should have a pkg directory which is the fake root directory. Inside this directory you will see the structure as how it would be installed in / on the target system. &lt;br /&gt;
&lt;br /&gt;
To see if you need the -dev package you can run the following cmd: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|find pkg/usr/ -name &#039;*.[acho]&#039; -o -name &#039;*.la&#039;}}&lt;br /&gt;
&lt;br /&gt;
If this returns any files you need to include the -dev package. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; To see if you need the -doc package you can run the following cmd: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|find pkg/usr/share -name doc -o -name man -o -name info -o -name html -o -name sgml -o -name licenses}}&lt;br /&gt;
&lt;br /&gt;
If this returns any directories you need to include the -doc package. &lt;br /&gt;
&lt;br /&gt;
===== Custom subpackages  =====&lt;br /&gt;
&lt;br /&gt;
Some software additionally has non-essential files that do not qualify as either documentation or development content. These files should be placed in their own, specialized subpackage(s). Some packages include large test suites which are only needed in specific circumstances or binaries which have depends which we prefer not to install. To handle those we create our own package/function. In the APKBUILD below the build() function we create another function: &lt;br /&gt;
&lt;br /&gt;
 test() {&lt;br /&gt;
        mkdir -p &amp;quot;$subpkgdir&amp;quot;/usr&lt;br /&gt;
        mv &amp;quot;$pkgdir&amp;quot;/usr/package-test &amp;quot;$subpkgdir&amp;quot;/usr/&lt;br /&gt;
        # or amove usr/package-test&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
We also need to add the package info to $subpackages variable: &lt;br /&gt;
&lt;br /&gt;
 subpackages=&amp;quot;$pkgname-doc $pkgname-dev $pkgname-test&amp;quot;&lt;br /&gt;
&lt;br /&gt;
After we finish building the package you should see another apk called packagename-test.apk which includes the files which we moved to the $subpkgdir dir. &lt;br /&gt;
&lt;br /&gt;
The above mentioned variables can also be used in our custom function. If we want for instance to build the test() function with perl support we would add: &lt;br /&gt;
&lt;br /&gt;
 depends=&amp;quot;perl&amp;quot;&lt;br /&gt;
 makedepends=&amp;quot;perl-dev&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If we would install the base package it would not install perl, but if we install the package-test package it would.&lt;br /&gt;
&lt;br /&gt;
==== Patches  ====&lt;br /&gt;
&lt;br /&gt;
Please make sure you always submit human readable patches. Ways to create them are: &lt;br /&gt;
&lt;br /&gt;
directory compare: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|diff -Nurp original_directory new_directory &amp;amp;gt; filename.patch}}&lt;br /&gt;
&lt;br /&gt;
file compare: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|diff -up original.file new.file &amp;amp;gt; filename.patch}}&lt;br /&gt;
&lt;br /&gt;
If a patch contains a completely new file but not *.rej or *.orig file, you need to add -N option to diff, but you may need to add exclusions with &amp;lt;code&amp;gt;--exclude PATTERN&amp;lt;/code&amp;gt; so that you do not inadvertently add files.  You may need to manually delete unwanted files inside the patch file.&lt;br /&gt;
&lt;br /&gt;
Because multiple patches can patch the same file, they can change the offsets required by subsequent patches. To make sure we always patch in a specific way, we should number the patches as follows: &lt;br /&gt;
&lt;br /&gt;
 10-patch1.patch 20-patch2.patch 30-patch3.patch&lt;br /&gt;
&lt;br /&gt;
This way we are always sure that patch 1 is applied first, and if we want to add additional patches between them we can use appropriate indexes (e.g. 11, 12, 21, 22).&lt;br /&gt;
&lt;br /&gt;
Add the names of the patch files to the &#039;&#039;source&#039;&#039; variable. If you haven&#039;t declared a custom &#039;&#039;prepare&#039;&#039; function, no further action is necessary. Otherwise, be sure to call &#039;&#039;default_prepare&#039;&#039; in your &#039;&#039;prepare&#039;&#039; function. For example:&lt;br /&gt;
&lt;br /&gt;
 prepare() {&lt;br /&gt;
 	default_prepare&lt;br /&gt;
 &lt;br /&gt;
 	# do your stuff&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note: Some older packages contain a &#039;&#039;for&#039;&#039; loop in the &#039;&#039;prepare&#039;&#039; function to apply patches. This is not needed anymore, as patches are handled by &#039;&#039;default_prepare&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In Alpine &amp;gt;=3.4 you can define patch_args to supply the patch level.  This only works if all the patches have the same patch level.  If there are a lot of patches from different sources, there is a good chance that you may need to edit them, as discussed below.&lt;br /&gt;
&lt;br /&gt;
To automatically patch the package (available only in Alpine &amp;gt;=3.4) if it uses a patch level (-pX) other than the default (-p1), you need to carefully modify the patch.  First, you&#039;ll need a text editor that does not automatically convert  between Windows and Unix new lines (or, disable this feature) so that it preserves the old code.  The next thing you&#039;ll need to do is modify the paths on &amp;quot;+++&amp;quot; and &amp;quot;---&amp;quot; lines in the .patch file.  You can begin the path with a/ and b/ like shown below.  Next, you need to adjust the paths so that the relative base path is from inside $builddir.  Anything to the left of $builddir, including $builddir itself, needs to be removed from the path.  So, if $builddir is /home/USER/aports/community/chromium/src/chromium-65, you need to erase it on the &amp;quot;+++&amp;quot; and &amp;quot;---&amp;quot; lines.  Inside the chromium-65 folder you can see a src folder that has 3rdparty as a descendant.  If a patch originally has a deeper patch level, you may need to fill in the missing portion of the path.  For example, use the &amp;lt;code&amp;gt;find . -name &amp;quot;Assertions.cpp&amp;quot;&amp;lt;/code&amp;gt; command to find the full path to the file relative to the base.&lt;br /&gt;
&lt;br /&gt;
{{Cat|example.patch|&amp;lt;nowiki&amp;gt;&lt;br /&gt;
Author: John Doe &amp;lt;johndoe@mail.com&amp;gt;&lt;br /&gt;
URL: http://.....&lt;br /&gt;
Summary: Fixes musl compatibility&lt;br /&gt;
----&lt;br /&gt;
--- a/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp.orig&lt;br /&gt;
+++ b/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp&lt;br /&gt;
@@ -142,7 +142,7 @@&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 FrameToNameScope::FrameToNameScope(void* addr) : m_name(0), m_cxaDemangled(0) {&lt;br /&gt;
-#if OS(MACOSX) || (OS(LINUX) &amp;amp;&amp;amp; !defined(__UCLIBC__))&lt;br /&gt;
+#if OS(MACOSX) || (OS(LINUX) &amp;amp;&amp;amp; defined(__GLIBC__))&lt;br /&gt;
   Dl_info info;&lt;br /&gt;
   if (!dladdr(addr, &amp;amp;info) || !info.dli_sname)&lt;br /&gt;
return;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Portions of the patch may be outdated, removed completely as in the source code file completely removed, or moved or renamed files.  You need to delete that section of the patch or find where that section of code changed and re-diff it.&lt;br /&gt;
&lt;br /&gt;
It is good etiquette to give credit at the top and the location of where you originally found them with notes.&lt;br /&gt;
&lt;br /&gt;
Excluding patches with global variable resembling patch_opts is not available on Alpine.  To exclude patches you need to create your own custom prepare().&lt;br /&gt;
&lt;br /&gt;
If you have a monolithic patch where there are a bunch of patches in one big patch, you could use filterdiff which is available in the patchutils package.&lt;br /&gt;
&lt;br /&gt;
Just do something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
makedepends=&amp;quot;patchutils&amp;quot;&lt;br /&gt;
&lt;br /&gt;
prepare() {&lt;br /&gt;
  ...&lt;br /&gt;
  cd &amp;quot;$builddir&amp;quot;&lt;br /&gt;
  filterdiff -x &#039;*drivers/video/logo*&#039; &amp;quot;$srcdir&amp;quot;/original.patch &amp;gt; &amp;quot;$builddir&amp;quot;/modified.patch&lt;br /&gt;
  patch -p1 -i &amp;quot;$builddir&amp;quot;/modified.patch&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to put the wildcard pattern in single quotes for it to work.&lt;br /&gt;
&lt;br /&gt;
==== Configure options  ====&lt;br /&gt;
&lt;br /&gt;
Alpine has some default configure options we set by default. We use /usr for prefix to make sure everything is installed with /usr in front of it. If you notice that anything is installed in the wrong directory please run {{Cmd|./configure --help}} and see if you can set the correct location. &lt;br /&gt;
&lt;br /&gt;
We are not covering the depend switches here we have discussed this already in the depend section.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Make options  ====&lt;br /&gt;
&lt;br /&gt;
If you notice weird problems when compiling or installing the package with make/make install you could try to disable [https://www.gnu.org/software/make/manual/make.html#Parallel parallel] building/installing. A normal make line would be: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make}}&lt;br /&gt;
&lt;br /&gt;
To disable parallel we use: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make -j1}}&lt;br /&gt;
&lt;br /&gt;
We can use the same for make install. &lt;br /&gt;
&lt;br /&gt;
Because we do not want to install the package in our build environment but we want to install it in a fake root directory we need to tell &#039;make install&#039; to use another destination directory instead of &#039;/&#039;. We do this by setting a variable when we execute make install as followed: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make DESTDIR{{=}}&amp;quot;$pkgdir&amp;quot; install}}&lt;br /&gt;
&lt;br /&gt;
Please note that some Makefiles do not support this variable and will always install software in &#039;/&#039;. To make sure you do not mess up your build system NEVER run your build system as root but always use a custom user and doas when needed. If by accident the Makefile does not support DESTDIR variable it will fail to install in our build system system directories.&lt;br /&gt;
&lt;br /&gt;
==== builddir ====&lt;br /&gt;
If you used &amp;lt;tt&amp;gt;newapkbuild&amp;lt;/tt&amp;gt; to create your APKBUILD file, you must specify the path to your unpacked sources. Inside the sections during the prepare/build/install process &#039;&#039;builddir&#039;&#039; is used. Most of the time a combination of &#039;&#039;$srcdir&#039;&#039; and &#039;&#039;$pkgname-$pkgver&#039;&#039; will work. When not, check the /src directory or the source tarball for the right string. Especially when you are working with automatically generated tarballs (like from github and gitorious), this needs to be adjusted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
builddir=&amp;quot;$srcdir&amp;quot;/$pkgname-$pkgver&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Additional files  ====&lt;br /&gt;
&lt;br /&gt;
If you want/need to install additional files not mentioned above you can use the following cmd (this is an example of a conf file): &lt;br /&gt;
&lt;br /&gt;
{{Cmd|install -Dm644 doc/$pkgname.conf &amp;quot;$pkgdir&amp;quot;/etc/$pkgname.conf}}&lt;br /&gt;
&lt;br /&gt;
== Build the package  ==&lt;br /&gt;
&lt;br /&gt;
If you did not already create the checksums as mentioned above you can do so now: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $pkgname&lt;br /&gt;
abuild checksum}}&lt;br /&gt;
&lt;br /&gt;
It&#039;s about time we build our package. Because a build system should never have all the package installed to prevent linking to packages we don&#039;t want it to link we use a abuild recursively with the &#039;&#039;&#039;-r&#039;&#039;&#039; switch. It will install all dependencies from your repository and builds it, afterwards it will uninstall all those depending packages again.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild -r}}&lt;br /&gt;
&lt;br /&gt;
See also [[Abuild_and_Helpers|Abuild and Helpers]].&lt;br /&gt;
&lt;br /&gt;
== Testing the package locally ==&lt;br /&gt;
&lt;br /&gt;
When it completes, your package will be found in a subfolder of &amp;lt;code&amp;gt;~/packages&amp;lt;/code&amp;gt;.  You may want to test it on your machine but only if the package is not a critical system package like musl or apk-tools package.  To avoid borking your system (as in making it impossible to use &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; or to restore back the system and the compiler toolchain) for a critical system package, you should test on a chroot first before using it live.&lt;br /&gt;
&lt;br /&gt;
The best way to test a package locally is to modify your &amp;lt;code&amp;gt;/etc/apk/repositories&amp;lt;/code&amp;gt; so that it includes the indexes to your locally built packages - the directories that contain &amp;lt;code&amp;gt;ARCH/APKINDEX.tar.gz&amp;lt;/code&amp;gt;. For example the &amp;lt;code&amp;gt;/etc/apk/repositories&amp;lt;/code&amp;gt; below includes locally built packages in testing, community and main. To use this example change &amp;lt;code&amp;gt;USER&amp;lt;/code&amp;gt; to your login name.&lt;br /&gt;
&lt;br /&gt;
{{Cat|/etc/apk/repositories|/home/USER/packages/testing/&lt;br /&gt;
/home/USER/packages/main/&lt;br /&gt;
/home/USER/packages/community/&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/main&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/community&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/testing&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
If you prefer to test a package without changing any other configuration you can use the &amp;lt;code&amp;gt;-X, --repository&amp;lt;/code&amp;gt; option to &amp;lt;code&amp;gt;apk&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|doas apk add --repository /home/USER/packages/testing $pkgname}}&lt;br /&gt;
&lt;br /&gt;
== Code review ==&lt;br /&gt;
&lt;br /&gt;
To successfully have your package pass through code reviewers (as of Feb 18, 2018 are nmeum and jirutka on GitHub) and possible increased acceptance, the following conventions need to be followed:&lt;br /&gt;
&lt;br /&gt;
# Custom global variables should be prefixed with underscore (_).&lt;br /&gt;
# Compact code as in merged commands, removed unused variables, removal of functions that do the same thing that are automatically handled by abuild.&lt;br /&gt;
# Versioning is done properly.  For details see [[APKBUILD_Reference#pkgver]].&lt;br /&gt;
# Licensing is done properly. Remove unnecessary copying of licensing that is already OSI approved.&lt;br /&gt;
# Naming conventions rules for unofficial variables as in _gitrev is preferred over commit.&lt;br /&gt;
# Indent with tabs not spaces.&lt;br /&gt;
# Removal of explicit return 1.  (They are still found the old APKBUILD files if you are learning but are now strongly discouraged.)&lt;br /&gt;
# Disabling check() requires either (1) a comment (#) stating next to options=&amp;quot;!check&amp;quot; that there is no test suite/unit tests or (2) functioning working check() function.&lt;br /&gt;
# Explicit call to subpackages=&amp;quot;$pkgname-doc&amp;quot; must be used instead of explicit gzip man page compression.&lt;br /&gt;
# Ideally, lines should be no more than 80 columns wide&lt;br /&gt;
&lt;br /&gt;
Additionally, make sure to run the linter on your package:&lt;br /&gt;
{{Cmd|doas apk add atools&lt;br /&gt;
apkbuild-lint APKBUILD}}&lt;br /&gt;
&lt;br /&gt;
For more information see [[Development using git:Quality assurance]] and [[Package_policies]].&lt;br /&gt;
Also check out [https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/COMMITSTYLE.md?ref_type=heads aports/COMMITSTYLE.md] and [https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/CODINGSTYLE.md?ref_type=heads aports/CODINGSTYLE.md]&lt;br /&gt;
&lt;br /&gt;
== Commit your work  ==&lt;br /&gt;
&lt;br /&gt;
After you successfully build your package and properly followed the conventions and requirements in the code review section, you can submit your APKBUILD to Alpine&#039;s git repository. &lt;br /&gt;
&lt;br /&gt;
Update your git repo, before adding new files: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $aportsdir&lt;br /&gt;
git pull}}&lt;br /&gt;
&lt;br /&gt;
This should pull all the changes made by others into your local git repo.&lt;br /&gt;
&lt;br /&gt;
When you think you are ready you can add your files to git: &lt;br /&gt;
&lt;br /&gt;
NOTE: when using our Gitlab instance, you can create MR&#039;s for each package. Please squash all commits related to the same package into a single one per MR.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $aportsdir&lt;br /&gt;
git add testing/$pkgdir (include any other files needed for the build; $pkgname.install...)&lt;br /&gt;
git commit}}&lt;br /&gt;
&lt;br /&gt;
Use the following commit message template for new aports (without the comments):&lt;br /&gt;
&lt;br /&gt;
{{Cat|template|testing/$pkgname: new aport   # this will be the subject line&lt;br /&gt;
                              # a blank line&lt;br /&gt;
$url                          # project homepage&lt;br /&gt;
$pkgdesc                      # one line description}}&lt;br /&gt;
&lt;br /&gt;
Or you could add the following and &amp;lt;code&amp;gt;chmod +x ports/.git/hooks/prepare-commit-msg&amp;lt;/code&amp;gt; to automatically generate commit message which the default aports/.githooks/ does not:&lt;br /&gt;
&lt;br /&gt;
{{Cat|aports/.git/hooks/prepare-commit-msg|&amp;lt;nowiki&amp;gt;#!/bin/sh&lt;br /&gt;
case &amp;quot;$2,$3&amp;quot; in&lt;br /&gt;
  ,|template,)&lt;br /&gt;
    if git diff-index --diff-filter=A --name-only --cached HEAD \&lt;br /&gt;
        | grep -q &#039;/APKBUILD$&#039;; then&lt;br /&gt;
      meta() { git diff --staged | grep &amp;quot;^+$1&amp;quot; | sed &#039;s/.*=&amp;quot;\?//;s/&amp;quot;$//&#039;;}&lt;br /&gt;
      printf &#039;testing/%s: new aport\n\n%s\n%s\n&#039; &amp;quot;$(meta pkgname)&amp;quot; \&lt;br /&gt;
        &amp;quot;$(meta url)&amp;quot; &amp;quot;$(meta pkgdesc)&amp;quot; &amp;quot;$(cat $1)&amp;quot; &amp;gt; &amp;quot;$1&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      printf &#039;%s\n\n%s&#039; `git diff-index --name-only --cached HEAD \&lt;br /&gt;
        | sed -n &#039;s/\/APKBUILD$//p;q&#039;` &amp;quot;$(cat $1)&amp;quot; &amp;gt; &amp;quot;$1&amp;quot;&lt;br /&gt;
    fi;;&lt;br /&gt;
esac&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now your changes are only available locally in your repository.&lt;br /&gt;
&lt;br /&gt;
Because you do not have push rights to the Alpine aports repository you need to create a merge request to [https://gitlab.alpinelinux.org/alpine/aports Alpine&#039;s GitLab instance].&lt;br /&gt;
&lt;br /&gt;
Alternatively you can also create a diff (patch) of the changes you made and send this patch to the &lt;br /&gt;
[https://lists.alpinelinux.org/~alpine/aports  alpine-aports mailinglist].&lt;br /&gt;
&lt;br /&gt;
To create a diff patch:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|git format-patch HEAD^}}&lt;br /&gt;
&lt;br /&gt;
or if you have sprunge, you can create a link to your patch for convenience&lt;br /&gt;
&lt;br /&gt;
{{Cmd|git format-patch HEAD^ --stdout &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; sprunge}}&lt;br /&gt;
&lt;br /&gt;
== Automated flagging of outdated ports ==&lt;br /&gt;
Consider adding your port to [https://release-monitoring.org/ Anitya], so it will be flagged as outdated&lt;br /&gt;
as soon as a new stable version is released by upstream.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[APKBUILD Reference]]&lt;br /&gt;
* [[APKBUILD examples]]&lt;br /&gt;
* [[Development using git]]&lt;br /&gt;
* [[Development using git:Quality assurance]]&lt;br /&gt;
&lt;br /&gt;
[[category: Package Manager]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=MediaWiki:Copyright&amp;diff=26953</id>
		<title>MediaWiki:Copyright</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=MediaWiki:Copyright&amp;diff=26953"/>
		<updated>2024-07-27T03:27:08Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div align=&amp;quot;right&amp;quot;&amp;gt;&amp;lt;div id=&amp;quot;footer-inner&amp;quot;&amp;gt; &lt;br /&gt;
  &amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://wiki.alpinelinux.org/wiki/Alpine_Linux:Privacy_policy#License&amp;quot;&amp;gt;&amp;amp;copy; Original authors / CC-BY-SA-4.0&amp;lt;/a&amp;gt; &lt;br /&gt;
  &amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Alpine_Linux:Privacy_policy&amp;diff=26952</id>
		<title>Alpine Linux:Privacy policy</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Alpine_Linux:Privacy_policy&amp;diff=26952"/>
		<updated>2024-07-27T03:26:19Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
This site does not collect personal information about you. The web server does collect your web browser identification, IP address, and other non-personally identifiable information. We use this information to improve the site, provide aggregated statistics, and improve the Alpine Linux hosting platform. This information will not be sold, traded, or rented under any circumstances.&lt;br /&gt;
&lt;br /&gt;
=License=&lt;br /&gt;
&lt;br /&gt;
== Pages created before 2022-01-12 00:00:00 UTC ==&lt;br /&gt;
&lt;br /&gt;
All content is copyrighted by the original authors. It may not be republished in any form without prior permission.&lt;br /&gt;
&lt;br /&gt;
== Pages created after 2022-01-12 00:00:00 UTC ==&lt;br /&gt;
&lt;br /&gt;
Contributions are licensed as [https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0]&lt;br /&gt;
&lt;br /&gt;
If you agree that your contributed content is re-licensed, please send an reply to [https://lists.alpinelinux.org/~alpine/devel/%3CCH58XEZPYFYT.1MV854Y4P2Q2O%40taiga%3E this e-mail] or a new e-mail to ~alpine/devel@lists.alpinelinux.org with the following content:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
I, &amp;lt;your name&amp;gt;, hereby re-license my contributions to the Alpine Linux&lt;br /&gt;
wiki hosted at wiki.alpinelinux.org under the username &amp;lt;your wiki username&amp;gt;&lt;br /&gt;
under the terms of the CC-BY-SA 4.0 license.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Site Information=&lt;br /&gt;
This website is hosted in an Alpine Linux LXC container, running lighttpd and php (fastcgi). The web content is maintained using [[Special:Version|MediaWiki]].&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=MediaWiki:Copyright&amp;diff=26951</id>
		<title>MediaWiki:Copyright</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=MediaWiki:Copyright&amp;diff=26951"/>
		<updated>2024-07-27T03:25:11Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div align=&amp;quot;right&amp;quot;&amp;gt;&amp;lt;div id=&amp;quot;footer-inner&amp;quot;&amp;gt; &lt;br /&gt;
  &amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://wiki.alpinelinux.org/wiki/Alpine_Linux:Privacy_policy#License&amp;quot;&amp;gt;&amp;amp;copy; Individual authors / CC-BY-SA-4.0&amp;lt;/a&amp;gt; &lt;br /&gt;
  &amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=MediaWiki:Copyright&amp;diff=26950</id>
		<title>MediaWiki:Copyright</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=MediaWiki:Copyright&amp;diff=26950"/>
		<updated>2024-07-27T03:22:02Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div align=&amp;quot;right&amp;quot;&amp;gt;&amp;lt;div id=&amp;quot;footer-inner&amp;quot;&amp;gt; &lt;br /&gt;
  &amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://creativecommons.org/licenses/by-sa/4.0/deed.en&amp;quot;&amp;gt;CC-BY-SA-4.0&amp;lt;/a&amp;gt; &lt;br /&gt;
  &amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Template:Pkg&amp;diff=26798</id>
		<title>Template:Pkg</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Template:Pkg&amp;diff=26798"/>
		<updated>2024-05-28T19:07:51Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Correct the description for the branch parameter&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Template}}&lt;br /&gt;
An inline link to search for given packages in the Package Browser.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Pkg|package|branch=|repo=|arch=|maintainer=}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{define|package|The package name to search for.&lt;br /&gt;
:Special characters in the package name will automatically be urlencoded. &amp;quot;*&amp;quot; and &amp;quot;?&amp;quot; can be used as wildcards.&lt;br /&gt;
:This argument is required, if you&#039;re not using it, use the &amp;quot;*&amp;quot; wildcard.}}&lt;br /&gt;
{{define|branch{{=}}|The branch of alpine to search (e.g. &amp;quot;3.19&amp;quot; or &amp;quot;edge&amp;quot;), defaults to &amp;quot;edge&amp;quot; if unset.}}&lt;br /&gt;
{{define|repo{{=}}|The repository to search (main, community, or testing). If unspecified all repositories will be searched.}}&lt;br /&gt;
{{define|arch{{=}}|The architecture to search (x86_64, x86, aarch64, armhf, ppc64le, s390x, armv7, or risc64). Defaults to x86_64 if unset.&lt;br /&gt;
:Pass this parameter with no value (i.e. &amp;quot;arch{{=}}&amp;quot;) to search all arches.}}&lt;br /&gt;
{{define|maintainer{{=}}|Search for packages with a certain maintainer. (e.g. &amp;quot;None&amp;quot; to search for unmaintained packages) If unspecified packages from all maintainers will be searched}}&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
Search for gtk+2.0 under the edge branch on the x86_64 architecture:&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Pkg|gtk+2.0}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
will produce:&lt;br /&gt;
{{Pkg|gtk+2.0}}&lt;br /&gt;
&lt;br /&gt;
Search for all gtk packages under the edge branch on the x86_64 architecture:&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Pkg|gtk*}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
will produce:&lt;br /&gt;
{{Pkg|gtk*}}&lt;br /&gt;
&lt;br /&gt;
Search for ALSA-related packages under the 3.19 branch on the x86 (i.e. i686) architecture:&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Pkg|*alsa*|branch=v3.19|arch=x86}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
will produce:&lt;br /&gt;
{{Pkg|*alsa*|branch=v3.19|arch=x86}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;{{#if:{{{1|}}} | &amp;lt;span class=&amp;quot;plainlinks&amp;quot; style=&amp;quot;font-family: monospace, Courier;font-size:10pt;&amp;quot;&amp;gt;[https://pkgs.alpinelinux.org/packages?name={{urlencode:{{{1}}}}}&amp;amp;branch={{urlencode:{{ #if: {{{branch|}}} | {{{branch}}} | edge}}}}&amp;amp;repo={{urlencode:{{ #if: {{{repo|}}} | {{{repo}}}}}}}&amp;amp;arch={{urlencode:{{ #ifeq: {{{arch|+}}} | {{{arch|-}}} | {{{arch}}} | x86_64 }}}}&amp;amp;maintainer={{urlencode:{{ #if: {{{maintainer|}}} | {{{maintainer}}}}}}} {{{1}}}]&amp;lt;/span&amp;gt; | &amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;First parameter cannot be undefined or empty in template: &amp;lt;b&amp;gt;Template:Pkg&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;}}&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Template:AlpineLatest&amp;diff=26773</id>
		<title>Template:AlpineLatest</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Template:AlpineLatest&amp;diff=26773"/>
		<updated>2024-05-23T20:34:43Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Alpine 3.20 is released&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Template}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;3.20.0&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26398</id>
		<title>Release Notes for Alpine 3.20.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26398"/>
		<updated>2024-02-15T18:51:56Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Update cause of issues&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== grub 2.12 ===&lt;br /&gt;
&lt;br /&gt;
When upgrading existing installations using grub on UEFI systems, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.&lt;br /&gt;
&lt;br /&gt;
The problem is that grub added new configuration that executes &amp;lt;code&amp;gt;fwsetup --is-supported&amp;lt;/code&amp;gt;. The problem is that grub 2.06 does not supported the &amp;lt;code&amp;gt;--is-supported&amp;lt;code&amp;gt; argument yet, causing grub to unconditionally try to reboot into firmware.&lt;br /&gt;
&lt;br /&gt;
Here is an example assuming the default setup. Don&#039;t blindly copy this examples but verify what&#039;s applicable to your system.&lt;br /&gt;
 &lt;br /&gt;
==== EFI ====&lt;br /&gt;
&lt;br /&gt;
{{Cmd|&lt;br /&gt;
 # grub-install --target{{=}}&amp;lt;var&amp;gt;$target&amp;lt;/var&amp;gt; --efi-directory{{=}}&amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt; \&lt;br /&gt;
    --bootloader-id{{=}}alpine --boot-directory{{=}}/boot --no-nvram&lt;br /&gt;
 # install -D &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/alpine/grub&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/boot/boot&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
; target : The relevant [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 target] for your system&lt;br /&gt;
; efi_directory : Either {{Path|/boot/efi}} or {{Path|/boot}}. Run &amp;lt;code&amp;gt;awk &#039;$2 ~ /boot/ &amp;amp;&amp;amp; $3 ~ /fat|msdos/ { print $2 }&#039; /proc/mounts&amp;lt;/code&amp;gt; to confirm.&lt;br /&gt;
; fwa : The respective [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 firmware architecture] for your system&lt;br /&gt;
&lt;br /&gt;
==== Short-term work-around ====&lt;br /&gt;
&lt;br /&gt;
A short-term work-around to get the system bootable again is to restore the backup configuration:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|cp /boot/grub/grub.cfg.back /boot/grub.cfg }}&lt;br /&gt;
&lt;br /&gt;
This should allow you to boot the system again to fix it permanently. This will be reverted again when either grub or the kernel is updated again.&lt;br /&gt;
&lt;br /&gt;
This will only work if &amp;lt;code&amp;gt;update-grub&amp;lt;/code&amp;gt; has not been executed any more since the upgrade to grub 2.12.&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26366</id>
		<title>Release Notes for Alpine 3.20.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26366"/>
		<updated>2024-02-04T12:34:54Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Clarify when the work-around works\&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== grub 2.12 ===&lt;br /&gt;
&lt;br /&gt;
When upgrading existing installations using grub on UEFI systems, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.&lt;br /&gt;
&lt;br /&gt;
The problem is that grub added a new module called `bli`, and the updated grub configuration refers to that module, causing grub to fail on boot.&lt;br /&gt;
&lt;br /&gt;
Here is an example assuming the default setup. Don&#039;t blindly copy this examples but verify what&#039;s applicable to your system.&lt;br /&gt;
 &lt;br /&gt;
==== EFI ====&lt;br /&gt;
&lt;br /&gt;
{{Cmd|&lt;br /&gt;
 # grub-install --target{{=}}&amp;lt;var&amp;gt;$target&amp;lt;/var&amp;gt; --efi-directory{{=}}&amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt; \&lt;br /&gt;
    --bootloader-id{{=}}alpine --boot-directory{{=}}/boot --no-nvram&lt;br /&gt;
 # install -D &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/alpine/grub&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/boot/boot&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
; target : The relevant [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 target] for your system&lt;br /&gt;
; efi_directory : Either {{Path|/boot/efi}} or {{Path|/boot}}. Run &amp;lt;code&amp;gt;awk &#039;$2 ~ /boot/ &amp;amp;&amp;amp; $3 ~ /fat|msdos/ { print $2 }&#039; /proc/mounts&amp;lt;/code&amp;gt; to confirm.&lt;br /&gt;
; fwa : The respective [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 firmware architecture] for your system&lt;br /&gt;
&lt;br /&gt;
==== Short-term work-around ====&lt;br /&gt;
&lt;br /&gt;
A short-term work-around to get the system bootable again is to restore the backup configuration:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|cp /boot/grub/grub.cfg.back /boot/grub.cfg }}&lt;br /&gt;
&lt;br /&gt;
This should allow you to boot the system again to fix it permanently. This will be reverted again when either grub or the kernel is updated again.&lt;br /&gt;
&lt;br /&gt;
This will only work if &amp;lt;code&amp;gt;update-grub&amp;lt;/code&amp;gt; has not been executed any more since the upgrade to grub 2.12.&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26365</id>
		<title>Release Notes for Alpine 3.20.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26365"/>
		<updated>2024-02-04T12:10:59Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== grub 2.12 ===&lt;br /&gt;
&lt;br /&gt;
When upgrading existing installations using grub on UEFI systems, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.&lt;br /&gt;
&lt;br /&gt;
The problem is that grub added a new module called `bli`, and the updated grub configuration refers to that module, causing grub to fail on boot.&lt;br /&gt;
&lt;br /&gt;
Here is an example assuming the default setup. Don&#039;t blindly copy this examples but verify what&#039;s applicable to your system.&lt;br /&gt;
 &lt;br /&gt;
==== EFI ====&lt;br /&gt;
&lt;br /&gt;
{{Cmd|&lt;br /&gt;
 # grub-install --target{{=}}&amp;lt;var&amp;gt;$target&amp;lt;/var&amp;gt; --efi-directory{{=}}&amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt; \&lt;br /&gt;
    --bootloader-id{{=}}alpine --boot-directory{{=}}/boot --no-nvram&lt;br /&gt;
 # install -D &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/alpine/grub&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/boot/boot&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
; target : The relevant [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 target] for your system&lt;br /&gt;
; efi_directory : Either {{Path|/boot/efi}} or {{Path|/boot}}. Run &amp;lt;code&amp;gt;awk &#039;$2 ~ /boot/ &amp;amp;&amp;amp; $3 ~ /fat|msdos/ { print $2 }&#039; /proc/mounts&amp;lt;/code&amp;gt; to confirm.&lt;br /&gt;
; fwa : The respective [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 firmware architecture] for your system&lt;br /&gt;
&lt;br /&gt;
==== Short-term work-around ====&lt;br /&gt;
&lt;br /&gt;
A short-term work-around to get the system bootable again is to restore the backup configuration:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|cp /boot/grub/grub.cfg.back /boot/grub.cfg }}&lt;br /&gt;
&lt;br /&gt;
This should allow you to boot the system again to fix it permanently. This will be reverted again when either grub or the kernel is updated again.&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26300</id>
		<title>Release Notes for Alpine 3.20.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26300"/>
		<updated>2024-01-19T18:22:36Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Remove bios, since irrelevant and add more details.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== grub 2.12 ===&lt;br /&gt;
&lt;br /&gt;
When upgrading existing installations using grub on UEFI systems, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.&lt;br /&gt;
&lt;br /&gt;
The problem is that grub added a new module called `bli`, and the updated grub configuration refers to that module, causing grub to fail on boot.&lt;br /&gt;
&lt;br /&gt;
Here is an example assuming the default setup. Don&#039;t blindly copy this examples but verify what&#039;s applicable to your system.&lt;br /&gt;
 &lt;br /&gt;
==== EFI ====&lt;br /&gt;
&lt;br /&gt;
{{Cmd|&lt;br /&gt;
 # grub-install --target{{=}}&amp;lt;var&amp;gt;$target&amp;lt;/var&amp;gt; --efi-directory{{=}}&amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt; \&lt;br /&gt;
    --bootloader-id{{=}}alpine --boot-directory{{=}}/boot --no-nvram&lt;br /&gt;
 # install -D &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/alpine/grub&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/boot/boot&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
; target : The relevant [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 target] for your system&lt;br /&gt;
; efi_directory : Either {{Path|/boot/efi}} or {{Path|/boot}}. Run &amp;lt;code&amp;gt;awk &#039;$2 ~ /boot/ &amp;amp;&amp;amp; $3 ~ /fat|msdos/ { print $2 }&#039; /proc/mounts&amp;lt;/code&amp;gt; to confirm.&lt;br /&gt;
; fwa : The respective [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 firmware architecture] for your system&lt;br /&gt;
&lt;br /&gt;
==== Shot-term work-around ====&lt;br /&gt;
&lt;br /&gt;
A short-term work-around to get the system bootable again is to restore the backup configuration:&lt;br /&gt;
&lt;br /&gt;
{{Cmd cp /boot/grub/grub.cfg.back /boot/grub.cfg }}&lt;br /&gt;
&lt;br /&gt;
This should allow you to boot the system again to fix it permanently. This will be reverted again when either grub or the kernel is updated again.&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Template:Pkg&amp;diff=26152</id>
		<title>Template:Pkg</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Template:Pkg&amp;diff=26152"/>
		<updated>2024-01-09T21:38:23Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Support branch and arch arguments (author: zcrayfish)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Template}}&lt;br /&gt;
An inline link to search for given packages in the Package Browser.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Pkg|package|branch=|repo=|arch=|maintainer=}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{define|package|The package name to search for.&lt;br /&gt;
:Special characters in the package name will automatically be urlencoded. &amp;quot;*&amp;quot; and &amp;quot;?&amp;quot; can be used as wildcards.&lt;br /&gt;
:This argument is required, if you&#039;re not using it, use the &amp;quot;*&amp;quot; wildcard.}}&lt;br /&gt;
{{define|branch{{=}}|The branch of alpine to search (e.g. &amp;quot;3.19&amp;quot; or &amp;quot;edge&amp;quot;), defaults to &amp;quot;edge&amp;quot; if unset.&lt;br /&gt;
:Pass this parameter with no value (i.e. &amp;quot;branch{{=}}&amp;quot;) to search all branches}}&lt;br /&gt;
{{define|repo{{=}}|The repository to search (main, community, or testing). If unspecified all repositories will be searched.}}&lt;br /&gt;
{{define|arch{{=}}|The architecture to search (x86_64, x86, aarch64, armhf, ppc64le, s390x, armv7, or risc64). Defaults to x86_64 if unset.&lt;br /&gt;
:Pass this parameter with no value (i.e. &amp;quot;arch{{=}}&amp;quot;) to search all arches.}}&lt;br /&gt;
{{define|maintainer{{=}}|Search for packages with a certain maintainer. (e.g. &amp;quot;None&amp;quot; to search for unmaintained packages) If unspecified packages from all maintainers will be searched}}&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
Search for gtk+2.0 under the edge branch on the x86_64 architecture:&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Pkg|gtk+2.0}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
will produce:&lt;br /&gt;
{{Pkg|gtk+2.0}}&lt;br /&gt;
&lt;br /&gt;
Search for all gtk packages under the edge branch on the x86_64 architecture:&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Pkg|gtk*}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
will produce:&lt;br /&gt;
{{Pkg|gtk*}}&lt;br /&gt;
&lt;br /&gt;
Search for ALSA-related packages under the 3.19 branch on the x86 (i.e. i686) architecture:&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Pkg|*alsa*|branch=v3.19|arch=x86}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
will produce:&lt;br /&gt;
{{Pkg|*alsa*|branch=v3.19|arch=x86}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;{{#if:{{{1|}}} | &amp;lt;span class=&amp;quot;plainlinks&amp;quot; style=&amp;quot;font-family: monospace, Courier;font-size:10pt;&amp;quot;&amp;gt;[https://pkgs.alpinelinux.org/packages?name={{urlencode:{{{1}}}}}&amp;amp;branch={{urlencode:{{ #if: {{{branch|}}} | {{{branch}}} | edge}}}}&amp;amp;repo={{urlencode:{{ #if: {{{repo|}}} | {{{repo}}}}}}}&amp;amp;arch={{urlencode:{{ #ifeq: {{{arch|+}}} | {{{arch|-}}} | {{{arch}}} | x86_64 }}}}&amp;amp;maintainer={{urlencode:{{ #if: {{{maintainer|}}} | {{{maintainer}}}}}}} {{{1}}}]&amp;lt;/span&amp;gt; | &amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;First parameter cannot be undefined or empty in template: &amp;lt;b&amp;gt;Template:Pkg&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;}}&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26136</id>
		<title>Release Notes for Alpine 3.20.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26136"/>
		<updated>2024-01-07T10:26:55Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Remove stray &amp;quot; (thanks shinobi5747485)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== grub 2.12 ===&lt;br /&gt;
&lt;br /&gt;
When upgrading existing installations using grub, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.&lt;br /&gt;
&lt;br /&gt;
Here are some examples for various situations assuming default setups. Don&#039;t blindly copy these examples but verify what&#039;s applicable to your system.&lt;br /&gt;
&lt;br /&gt;
Afterwards, run the &amp;lt;code&amp;gt;update-grub&amp;lt;/code&amp;gt; command to update the grub configuration:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# update-grub}}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== BIOS ====&lt;br /&gt;
&lt;br /&gt;
For BIOS systems (x86 or x86_64)&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# grub-install --boot-directory{{=}}/boot --target{{=}}i386-pc &amp;lt;var&amp;gt;$disk&amp;lt;/var&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
; disk : The block device grub has been installed to.&lt;br /&gt;
&lt;br /&gt;
==== EFI ====&lt;br /&gt;
&lt;br /&gt;
{{Cmd|&lt;br /&gt;
 # grub-install --target{{=}}&amp;lt;var&amp;gt;$target&amp;lt;/var&amp;gt; --efi-directory{{=}}&amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt; \&lt;br /&gt;
    --bootloader-id{{=}}alpine --boot-directory{{=}}/boot --no-nvram&lt;br /&gt;
 # install -D &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/alpine/grub&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/boot/boot&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
; target : The relevant [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 target] for your system&lt;br /&gt;
; efi_directory : Either {{Path|/boot/efi}} or {{Path|/boot}}. Run &amp;lt;code&amp;gt;awk &#039;$2 ~ /boot/ &amp;amp;&amp;amp; $3 ~ /fat|msdos/ { print $2 }&#039; /proc/mounts&amp;lt;/code&amp;gt; to confirm.&lt;br /&gt;
; fwa : The respective [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 firmware architecture] for your system&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26133</id>
		<title>Release Notes for Alpine 3.20.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26133"/>
		<updated>2024-01-06T12:19:47Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== grub 2.12 ===&lt;br /&gt;
&lt;br /&gt;
When upgrading existing installations using grub, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.&lt;br /&gt;
&lt;br /&gt;
Here are some examples for various situations assuming default setups. Don&#039;t blindly copy these examples but verify what&#039;s applicable to your system.&lt;br /&gt;
&lt;br /&gt;
Afterwards, run the &amp;lt;code&amp;gt;update-grub&amp;lt;/code&amp;gt; command to update the grub configuration:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# update-grub}}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== BIOS ====&lt;br /&gt;
&lt;br /&gt;
For BIOS systems (x86 or x86_64)&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# grub-install --boot-directory{{=}}/boot --target{{=}}i386-pc &amp;lt;var&amp;gt;$disk&amp;lt;/var&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
; disk : The block device grub has been installed to.&lt;br /&gt;
&lt;br /&gt;
==== EFI ====&lt;br /&gt;
&lt;br /&gt;
{{Cmd|&lt;br /&gt;
 # grub-install --target{{=}}&amp;lt;var&amp;gt;$target&amp;lt;/var&amp;gt; --efi-directory{{=}}&amp;quot;&amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;&amp;quot; \&lt;br /&gt;
    --bootloader-id{{=}}alpine --boot-directory{{=}}&amp;quot;/boot --no-nvram&lt;br /&gt;
 # install -D &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/alpine/grub&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/boot/boot&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
; target : The relevant [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 target] for your system&lt;br /&gt;
; efi_directory : Either {{Path|/boot/efi}} or {{Path|/boot}}. Run &amp;lt;code&amp;gt;awk &#039;$2 ~ /boot/ &amp;amp;&amp;amp; $3 ~ /fat|msdos/ { print $2 }&#039; /proc/mounts&amp;lt;/code&amp;gt; to confirm.&lt;br /&gt;
; fwa : The respective [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 firmware architecture] for your system&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26132</id>
		<title>Release Notes for Alpine 3.20.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26132"/>
		<updated>2024-01-06T12:01:15Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== grub 2.12 ===&lt;br /&gt;
&lt;br /&gt;
When upgrading existing installations using grub, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.&lt;br /&gt;
&lt;br /&gt;
Here are some examples for various situations assuming default setups. Don&#039;t blindly copy these examples but verify what&#039;s applicable to your system.&lt;br /&gt;
&lt;br /&gt;
Afterwards, run the &amp;lt;code&amp;gt;update-grub&amp;lt;/code&amp;gt; command to update the grub configuration:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# update-grub}}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== BIOS ====&lt;br /&gt;
&lt;br /&gt;
For BIOS systems (x86 or x86_64)&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# grub-install --boot-directory{{=}}/boot --target{{=}}i386-pc &amp;lt;var&amp;gt;$disk&amp;lt;/var&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
; disk : The block device grub has been installed to.&lt;br /&gt;
&lt;br /&gt;
==== EFI ====&lt;br /&gt;
&lt;br /&gt;
{{Cmd|&lt;br /&gt;
 # grub-install --target{{=}}&amp;lt;var&amp;gt;$target&amp;lt;/var&amp;gt; --efi-directory{{=}}&amp;quot;&amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;&amp;quot; \&lt;br /&gt;
    --bootloader-id{{=}}alpine --boot-directory{{=}}&amp;quot;/boot --no-nvram&lt;br /&gt;
 # install -D &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/alpine/grub&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/boot/boot&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
; target : The relevant [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 target] for your system&lt;br /&gt;
; efi_directory : Either {{Path|/boot/efi}} or {{Path|/boot}}&lt;br /&gt;
; fwa : The respective [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in#L320-324 firmware architecture] for your system&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26131</id>
		<title>Release Notes for Alpine 3.20.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26131"/>
		<updated>2024-01-06T11:57:53Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== grub 2.12 ===&lt;br /&gt;
&lt;br /&gt;
When upgrading existing installations using grub, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.&lt;br /&gt;
&lt;br /&gt;
Here are some examples for various situations assuming default setups. Don&#039;t blindly copy these examples but verify what&#039;s applicable to your system.&lt;br /&gt;
&lt;br /&gt;
Afterwards, run the &amp;lt;code&amp;gt;update-grub&amp;lt;/code&amp;gt; command to update the grub configuration:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# update-grub}}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== BIOS ====&lt;br /&gt;
&lt;br /&gt;
For BIOS systems (x86 or x86_64)&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# grub-install --boot-directory{{=}}/boot --target{{=}}i386-pc &amp;lt;var&amp;gt;$disk&amp;lt;/var&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
; disk : The block device grub has been installed to.&lt;br /&gt;
&lt;br /&gt;
==== EFI ====&lt;br /&gt;
&lt;br /&gt;
{{Cmd|&lt;br /&gt;
 # grub-install --target{{=}}&amp;lt;var&amp;gt;$target&amp;lt;/var&amp;gt; --efi-directory{{=}}&amp;quot;&amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;&amp;quot; \&lt;br /&gt;
    --bootloader-id{{=}}alpine --boot-directory{{=}}&amp;quot;/boot --no-nvram&lt;br /&gt;
 # install -D &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/alpine/grub&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/boot/boot&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
; target : The relevant [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in?ref%20type=heads target] for your system&lt;br /&gt;
; efi_directory : Either {{Path|/boot/efi}} or {{Path|/boot}}&lt;br /&gt;
; fwa : The respective [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in?ref%20type=heads firmware architecture] for your system&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26127</id>
		<title>Release Notes for Alpine 3.20.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26127"/>
		<updated>2024-01-05T23:54:13Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== grub 2.12 ===&lt;br /&gt;
&lt;br /&gt;
When upgrading existing installations using grub, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.&lt;br /&gt;
&lt;br /&gt;
Here are some examples for various situations assuming default setups. Don&#039;t blindly copy these examples but verify what&#039;s applicable to your system.&lt;br /&gt;
 &lt;br /&gt;
==== BIOS ====&lt;br /&gt;
&lt;br /&gt;
For BIOS systems (x86 or x86_64)&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# grub-install --boot-directory{{=}}/boot --target{{=}}i386-pc &amp;lt;var&amp;gt;$disk&amp;lt;/var&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
; disk : The block device grub has been installed to.&lt;br /&gt;
&lt;br /&gt;
==== EFI ====&lt;br /&gt;
&lt;br /&gt;
{{Cmd|&lt;br /&gt;
 # grub-install --target{{=}}&amp;lt;var&amp;gt;$target&amp;lt;/var&amp;gt; --efi-directory{{=}}&amp;quot;&amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;&amp;quot; \&lt;br /&gt;
    --bootloader-id{{=}}alpine --boot-directory{{=}}&amp;quot;/boot --no-nvram&lt;br /&gt;
 # install -D &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/alpine/grub&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi &amp;lt;var&amp;gt;$efi_directory&amp;lt;/var&amp;gt;/EFI/boot/boot&amp;lt;var&amp;gt;$fwa&amp;lt;/var&amp;gt;.efi&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
; target : The relevant [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in?ref%20type=heads target] for your system&lt;br /&gt;
; efi_directory : Either {{Path|/boot/efi}} or {{Path|/boot}}&lt;br /&gt;
; fwa : The respective [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in?ref%20type=heads firmware architecture] for your system&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26126</id>
		<title>Release Notes for Alpine 3.20.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.20.0&amp;diff=26126"/>
		<updated>2024-01-05T23:33:15Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Created page with &amp;quot;== Base System ==  === grub 2.12 ===  When upgrading existing installations using grub, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.  Here are some examples for various situations assuming default setups. Don&amp;#039;t blindly copy these examples but verify what&amp;#039;s applicable to your system.   ==== BIOS ====  For BIOS systems (x86 or x86_64)  {{Cmd|# grub-install --boot-directory{{=}}/boot --target{{=}}i386-pc &amp;lt;var&amp;gt;disk&amp;lt;/va...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== grub 2.12 ===&lt;br /&gt;
&lt;br /&gt;
When upgrading existing installations using grub, make sure to update the installed bootloader before rebooting, otherwise your machine might not boot.&lt;br /&gt;
&lt;br /&gt;
Here are some examples for various situations assuming default setups. Don&#039;t blindly copy these examples but verify what&#039;s applicable to your system.&lt;br /&gt;
 &lt;br /&gt;
==== BIOS ====&lt;br /&gt;
&lt;br /&gt;
For BIOS systems (x86 or x86_64)&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# grub-install --boot-directory{{=}}/boot --target{{=}}i386-pc &amp;lt;var&amp;gt;disk&amp;lt;/var&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
; disk : The block device grub has been installed to.&lt;br /&gt;
&lt;br /&gt;
==== EFI ====&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# install --target{{=}}&amp;lt;var&amp;gt;target&amp;lt;/var&amp;gt; --efi-directory{{=}}&amp;quot;&amp;lt;var&amp;gt;efi_directory&amp;lt;/var&amp;gt;&amp;quot; --bootloader-id{{=}}alpine --boot-directory{{=}}&amp;quot;/boot --no-nvram}}&lt;br /&gt;
&lt;br /&gt;
; target : The relevant [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-disk.in?ref%20type=heads target] for your system&lt;br /&gt;
; efi_directory : Either {{Path|/boot/efi}} or {{Path|/boot}}&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Category:Articles_for_deletion&amp;diff=25965</id>
		<title>Category:Articles for deletion</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Category:Articles_for_deletion&amp;diff=25965"/>
		<updated>2023-12-21T13:05:57Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Articles that are proposed to be deleted&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Category:Articles_for_deletion&amp;diff=25964</id>
		<title>Category:Articles for deletion</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Category:Articles_for_deletion&amp;diff=25964"/>
		<updated>2023-12-21T13:03:48Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Created page with &amp;quot;Articles that are marked to be deleted&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Articles that are marked to be deleted&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Template:Delete&amp;diff=25963</id>
		<title>Template:Delete</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Template:Delete&amp;diff=25963"/>
		<updated>2023-12-21T12:56:44Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Add category &amp;#039;Articles for deletion&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Template}}&lt;br /&gt;
This template proposes a page or section for deletion.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
Only administrators can delete pages. Other users should instead use this template to propose a page for deletion. It can also be used to propose one section of a larger page for deletion.&lt;br /&gt;
&lt;br /&gt;
You should cite a brief reason in the first argument, and can expand in the article&#039;s discussion page. Don&#039;t clear the page&#039;s content except where it&#039;s obviously spam.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Delete|Reason.}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users are welcome to argue against deletion. You can override the default discussion page with a second argument to the template:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Delete|Reason.|Talk:Alternative Page}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flagged pages can be found in [[Special:WhatLinksHere/Template:Delete]].&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Delete|Message.}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f1f1de; border:1px solid #cc9; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Tango-user-trash-full.png|48px|left|link=]] This material is proposed for deletion ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;Message.&lt;br /&gt;
([[{{TALKPAGENAME}}|Discuss]])&amp;lt;br /&amp;gt;Make sure [[Special:WhatLinksHere/{{FULLPAGENAME}}|no other pages link here]] and check [[Special:PageHistory/{{FULLPAGENAME}}|the page&#039;s history]] before deleting.&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f1f1de; border:1px solid #cc9; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Tango-user-trash-full.png|48px|left|link=]] This material is proposed for deletion ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;{{{1|}}}&lt;br /&gt;
([[{{{2|{{TALKPAGENAME}}}}}|Discuss]])&amp;lt;br /&amp;gt;Make sure [[Special:WhatLinksHere/{{FULLPAGENAME}}|no other pages link here]] and check [[Special:PageHistory/{{FULLPAGENAME}}|the page&#039;s history]] before deleting.&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;[[Category:Articles for deletion]]&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Template:Delete&amp;diff=25962</id>
		<title>Template:Delete</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Template:Delete&amp;diff=25962"/>
		<updated>2023-12-21T12:55:07Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Add links to&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Template}}&lt;br /&gt;
This template proposes a page or section for deletion.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
Only administrators can delete pages. Other users should instead use this template to propose a page for deletion. It can also be used to propose one section of a larger page for deletion.&lt;br /&gt;
&lt;br /&gt;
You should cite a brief reason in the first argument, and can expand in the article&#039;s discussion page. Don&#039;t clear the page&#039;s content except where it&#039;s obviously spam.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Delete|Reason.}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users are welcome to argue against deletion. You can override the default discussion page with a second argument to the template:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Delete|Reason.|Talk:Alternative Page}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Flagged pages can be found in [[Special:WhatLinksHere/Template:Delete]].&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Delete|Message.}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f1f1de; border:1px solid #cc9; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Tango-user-trash-full.png|48px|left|link=]] This material is proposed for deletion ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;Message.&lt;br /&gt;
([[{{TALKPAGENAME}}|Discuss]])&amp;lt;br /&amp;gt;Make sure [[Special:WhatLinksHere/{{FULLPAGENAME}}|no other pages link here]] and check [[Special:PageHistory/{{FULLPAGENAME}}|the page&#039;s history]] before deleting.&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;width: 48em; padding:2px; margin:0; margin-bottom:10px; background-color:#f1f1de; border:1px solid #cc9; -moz-border-radius-bottomright: 0.5em; -moz-border-radius-bottomleft: 1em; border-radius-bottomright: 0.5em; border-radius-bottomleft: 1em; -webkit-border-bottom-right-radius: 0.5em; -webkit-border-bottom-left-radius: 1em;&amp;quot;&lt;br /&gt;
|&amp;lt;div style=&amp;quot;font-size: 1.5em; font-weight:bold; text-align:center;&amp;quot;&amp;gt; [[Image:Tango-user-trash-full.png|48px|left|link=]] This material is proposed for deletion ... &amp;lt;/div&amp;gt;&amp;lt;p style=&amp;quot;text-align: center; font-size: 87%;&amp;quot;&amp;gt;{{{1|}}}&lt;br /&gt;
([[{{{2|{{TALKPAGENAME}}}}}|Discuss]])&amp;lt;br /&amp;gt;Make sure [[Special:WhatLinksHere/{{FULLPAGENAME}}|no other pages link here]] and check [[Special:PageHistory/{{FULLPAGENAME}}|the page&#039;s history]] before deleting.&amp;lt;/p&amp;gt;&lt;br /&gt;
|}&amp;lt;/center&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Template:AlpineLatest&amp;diff=25867</id>
		<title>Template:AlpineLatest</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Template:AlpineLatest&amp;diff=25867"/>
		<updated>2023-12-08T06:22:53Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Template}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;3.19.0&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.19.0&amp;diff=25866</id>
		<title>Release Notes for Alpine 3.19.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.19.0&amp;diff=25866"/>
		<updated>2023-12-07T13:51:07Z</updated>

		<summary type="html">&lt;p&gt;Ikke: /* HashiCorp packages */ gramatical fix (software is uncountable)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base System ==&lt;br /&gt;
&lt;br /&gt;
=== iptables-nft ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;/sbin/iptables{,-save,-restore}&amp;lt;/code&amp;gt; symlinks now point to xtables-nft-multi instead of xtables-legacy-multi. This means they use the nftables kernel backend instead of the legacy iptables one.&lt;br /&gt;
&lt;br /&gt;
Since the new iptables- binaries also don&#039;t use the iptables backend, to work with any existing rules and save them, you need to install {{pkg|iptables-legacy}} and use &amp;lt;code&amp;gt;iptables-legacy-save&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Because mixing backends is not supported, you should reboot your system if you have to use the iptables commands after upgrading.&lt;br /&gt;
&lt;br /&gt;
=== netns ===&lt;br /&gt;
&lt;br /&gt;
The OpenRC package contains a patch to make it possible to start most services in netns namespaces. See also [[Netns|netns]].&lt;br /&gt;
&lt;br /&gt;
== Others ==&lt;br /&gt;
&lt;br /&gt;
=== HashiCorp packages ===&lt;br /&gt;
&lt;br /&gt;
Due to [https://www.hashicorp.com/blog/hashicorp-adopts-business-source-license the relicensing of HashiCorp software] to [https://spdx.org/licenses/BUSL-1.1.html BUSL-1.1], a non-Open-Source license, the following software has been removed from Alpine:&lt;br /&gt;
&lt;br /&gt;
* Consul&lt;br /&gt;
* Nomad&lt;br /&gt;
* Packer&lt;br /&gt;
* Terraform&lt;br /&gt;
* Vault&lt;br /&gt;
&lt;br /&gt;
Our discussion on the topic can be found [https://gitlab.alpinelinux.org/alpine/aports/-/issues/15193 here].&lt;br /&gt;
&lt;br /&gt;
{{pkg|opentofu}}, a fork of Terraform, is available in our testing repository for users of our rolling release, edge.&lt;br /&gt;
&lt;br /&gt;
=== Java 21 ===&lt;br /&gt;
&lt;br /&gt;
The latest LTS java release, openjdk21,  is now available in the community repository.&lt;br /&gt;
&lt;br /&gt;
=== KDE ===&lt;br /&gt;
&lt;br /&gt;
KDE Applications have been upgraded from 23.04.x to 23.08.x. KDE Frameworks have been upgraded from 5.105.0 to 5.112.0.&lt;br /&gt;
Note that the KDE Frameworks packages have been renamed to add a 5 suffix in preparation for the upcoming KDE 6 release in the next Alpine release. Everything should automatically be upgraded properly but if problems occur make sure to check if the right renamed packages are installed.&lt;br /&gt;
&lt;br /&gt;
=== GNOME ===&lt;br /&gt;
&lt;br /&gt;
GNOME packages have been updated to 45. As part of that release, Cheese has been replaced by Snapshot, and Eye of GNOME by Loupe as the default apps for taking and seeing pictures, respectively. In additions, GNOME Photos was dropped as being mostly unmaintained.&lt;br /&gt;
&lt;br /&gt;
=== Yggdrasil v0.5 ===&lt;br /&gt;
&lt;br /&gt;
{{pkg|yggdrasil}} was upgraded to 0.5.x and the new routing scheme is incompatible with previous versions. &amp;quot;Nodes running this new version &#039;&#039;&#039;will not&#039;&#039;&#039; be able to peer with earlier versions of Yggdrasil&amp;quot; ([https://github.com/yggdrasil-network/yggdrasil-go/releases/tag/v0.5.0 v0.5.0 release notes], [https://yggdrasil-network.github.io/2023/10/22/upcoming-v05-release.html v0.5 blog post]).&lt;br /&gt;
&lt;br /&gt;
=== GNU C Library Compatibility Layer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;libc6-compat&amp;lt;/code&amp;gt; [https://git.alpinelinux.org/aports/commit/?h=3.19-stable&amp;amp;id=1a122638315d6fe7908de9c34d3ac06eae76917a was removed] in favor of {{pkg|gcompat}} from Adélie Linux.&lt;br /&gt;
&lt;br /&gt;
=== ifupdown ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ifupdown&amp;lt;/code&amp;gt; aport (&#039;&#039;&#039;not&#039;&#039;&#039; {{pkg|busybox-ifupdown}}) was unmaintained and removed in favor of the preferred {{pkg|ifupdown-ng}}.&lt;br /&gt;
&lt;br /&gt;
== Upgrades ==&lt;br /&gt;
&lt;br /&gt;
* Linux 6.6&lt;br /&gt;
* GCC 13&lt;br /&gt;
* LLVM 17&lt;br /&gt;
* Kea 2.4&lt;br /&gt;
* Xen 4.18&lt;br /&gt;
* Git 2.43&lt;br /&gt;
* Perl 5.38&lt;br /&gt;
* PHP 8.3&lt;br /&gt;
* PostgreSQL 16&lt;br /&gt;
* SQLite 3.44&lt;br /&gt;
* Redis 7.2&lt;br /&gt;
* Node.js (lts) 20.10&lt;br /&gt;
* Node.js (current) 21.4&lt;br /&gt;
* QEMU 8.1&lt;br /&gt;
* Ceph 18.2&lt;br /&gt;
* GNOME 45&lt;br /&gt;
* LXQt 1.4&lt;br /&gt;
* wlroots 0.17&lt;br /&gt;
* Go 1.21&lt;br /&gt;
* Rust 1.72&lt;br /&gt;
* Crystal 1.10&lt;br /&gt;
* Racket 8.11&lt;br /&gt;
* ECL 23.9.9&lt;br /&gt;
* Erlang 26&lt;br /&gt;
* zlib 1.3&lt;br /&gt;
* libsodium 1.0.19&lt;br /&gt;
* ICU 74.1&lt;br /&gt;
* Protobuf 24.4&lt;br /&gt;
* fmt 10&lt;br /&gt;
* PipeWire 1.0.0&lt;br /&gt;
&lt;br /&gt;
== Raspberry pi ==&lt;br /&gt;
&lt;br /&gt;
[https://pkgs.alpinelinux.org/packages?name=linux-rpi&amp;amp;branch=edge linux-rpi] package has been simplified: there is now a single kernel flavor for each architecture. Previous [https://pkgs.alpinelinux.org/packages?name=linux-rpi2&amp;amp;branch=v3.18 linux-rpi2] and [https://pkgs.alpinelinux.org/packages?name=linux-rpi4&amp;amp;branch=v3.18 linux-rpi4] kernel packages are therefore replaced by [https://pkgs.alpinelinux.org/packages?name=linux-rpi&amp;amp;branch=edge linux-rpi].&amp;lt;br&amp;gt;&lt;br /&gt;
{{Path|config.txt}} file is now generated by [https://pkgs.alpinelinux.org/packages?name=raspberrypi-bootloader-common&amp;amp;branch=edge raspberrypi-bootloader-common].&lt;br /&gt;
&lt;br /&gt;
[[Category:News]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Creating_an_Alpine_package&amp;diff=25648</id>
		<title>Creating an Alpine package</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Creating_an_Alpine_package&amp;diff=25648"/>
		<updated>2023-11-13T21:44:54Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Explain that certain licenses have additional requirements&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOC right}}&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
To build a package for Alpine Linux you need an Alpine Linux installation. Check the [[Installation]] page to see all available installation options.&lt;br /&gt;
&lt;br /&gt;
== Setup your system and account  ==&lt;br /&gt;
{{:Include:Setup_your_system_and_account_for_building_packages}}&lt;br /&gt;
&lt;br /&gt;
== Getting some help ==&lt;br /&gt;
&lt;br /&gt;
It might be wise to start by checking what the [[Abuild|abuild]] program can/cannot do.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild -h}}&lt;br /&gt;
&lt;br /&gt;
For real help, you can also go on #alpine-devel on [[IRC]].&lt;br /&gt;
&lt;br /&gt;
A reference for APKBUILD files is available as [[APKBUILD Reference]] wiki page or a man page in the &#039;abuild-doc&#039; package:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|man APKBUILD}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating an APKBUILD file  ==&lt;br /&gt;
&lt;br /&gt;
=== Use a template APKBUILD ===&lt;br /&gt;
&lt;br /&gt;
To create the actual APKBUILD file {{Pkg|newapkbuild}} can serve you a template to start with. It will create a directory with the given package name, place an example/template APKBUILD file to the given directory, and fill some variables if those are provided. Please check the [[Package_policies| package policies]] page about naming details.&lt;br /&gt;
&lt;br /&gt;
If you doubt to which repository your package belongs to you can safely use &#039;&#039;&#039;testing&#039;&#039;&#039;. Building package in your aports/testing directory is not mandatory but this way the package is already at the right place.&lt;br /&gt;
&lt;br /&gt;
{{:Include:Newapkbuild}}&lt;br /&gt;
&lt;br /&gt;
{{Note|On older Alpine systems, abuild -c -n &#039;&#039;packagename&#039;&#039; was the way to create APKBUILD files. The &#039;packagename&#039; was a parameter to the -n option so order of -c and -n matters. }}&lt;br /&gt;
&lt;br /&gt;
[[Abuild_and_Helpers#apkbuild-cpan|apkbuild-cpan]] simplifies the creation of perl packages from CPAN and [[Abuild_and_Helpers#apkbuild-pypi|apkbuild-pypi]] ease the generation of APKBUILD files for python packages from PyPi.  &lt;br /&gt;
&lt;br /&gt;
If you are creating a daemon package which needs initd scripts you can add the -c making it: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|newapkbuild -c &#039;&#039;packagename&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
This will copy the sample initd and confd files to the build directory.&amp;lt;BR&amp;gt;&lt;br /&gt;
A third file sample.install file will be copied as well (we will discuss this later on).&lt;br /&gt;
&lt;br /&gt;
=== Modify your APKBUILD ===&lt;br /&gt;
Edit APKBUILD and fill in the needed info (especially pkgname, pkgver, pkgdesc, url, license, depends and source). &lt;br /&gt;
&lt;br /&gt;
If you are going to use any of the variables for directories like $pkgdir, always make sure they are double quoted like: &lt;br /&gt;
&lt;br /&gt;
 &amp;quot;$pkgdir&amp;quot;/somedir&lt;br /&gt;
&lt;br /&gt;
This will prevent issues with spaces/special characters in the future. &lt;br /&gt;
&lt;br /&gt;
{{Note|If you like syntax highlighting we suggest you to install vim. We have setup vim to recognize the APKBUILD file as a bash scripts so its easier to read them.}}&lt;br /&gt;
&lt;br /&gt;
=== APKBUILD variables/functions  ===&lt;br /&gt;
&lt;br /&gt;
==== source  ====&lt;br /&gt;
&lt;br /&gt;
The source variable is not only used to list the remote source files to fetch, it is also used to list the local files that abuild will need in order to build the apk. Examples of such local files include: init.d files, conf.d files, install files (see [[Creating an Alpine package#install|install variable]]), patches, and all other necessary files.&lt;br /&gt;
&lt;br /&gt;
Here are few things to note:&lt;br /&gt;
&lt;br /&gt;
* When you are finished adding local and/or remote files to &#039;&#039;source&#039;&#039;, you can execute the following command to add their checksums to the APKBUILD file:&lt;br /&gt;
: {{cmd|abuild checksum}}&lt;br /&gt;
: {{Note|When later updating the content of &#039;&#039;source&#039;&#039;, or updating a file that is listed in &#039;&#039;source&#039;&#039;, you must also update their checksums again with the same command.}}&lt;br /&gt;
&lt;br /&gt;
* When the remote file is hosted at SourceForge, it&#039;s best to specify the special mirrors link used by SourceForge:&lt;br /&gt;
: &amp;lt;pre&amp;gt;http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz&amp;lt;/pre&amp;gt;&lt;br /&gt;
: (or similar depending on the package).&lt;br /&gt;
&lt;br /&gt;
* When the remote filename is not specified in the URI (ie, does not end in &#039;/software-1.0.tar.gz&#039;), such as:&lt;br /&gt;
: &amp;lt;pre&amp;gt;http://oss.example.org/?get=software&amp;amp;ver=1.0&amp;lt;/pre&amp;gt;&lt;br /&gt;
: You must prepend &#039;${pkgname}-${pkgver}.tar.gz::&#039; to the protocol, like so:&lt;br /&gt;
: &amp;lt;pre&amp;gt;source=&amp;quot;${pkgname}-${pkgver}.tar.gz::http://oss.example.org/?get=software&amp;amp;ver=1.0&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
: This causes the file to be saved as &#039;&#039;software-1.0.tar.gz&#039;&#039; where abuild can use it, instead of &#039;&#039;?get=software&amp;amp;ver=1.0&#039;&#039;, where abuild cannot use it.&lt;br /&gt;
&lt;br /&gt;
* Some projects didn&#039;t provide a release tarball. Beware that some git services (gitweg, cgit, …?) doesn’t provide &#039;&#039;stable&#039;&#039; tarballs, so when you point source to an tarball like &amp;lt;tt&amp;gt;https://repo.or.cz/w/gitstats.git/snapshot/ad7efbb9399e60cee6cb217c6b47e604174a8093.tar.gz&amp;lt;/tt&amp;gt;, then you will run into issues because the checksum changes when downloading on the build system. This is not a problem on GitHub, GitLab and other decent services provides, they provide &#039;&#039;stable&#039;&#039; tarballs.&lt;br /&gt;
&lt;br /&gt;
* abuild currently supports the following protocols for remote file retrieval:&lt;br /&gt;
** http&lt;br /&gt;
** https&lt;br /&gt;
** ftp&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--: {{Note|If the you want to download from https, you need GNU wget installed on your system.}}--&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
* abuild currently supports the following archive types/archive file extensions:&lt;br /&gt;
** .tar&lt;br /&gt;
** .tar.gz / .tgz&lt;br /&gt;
** .tar.bz2&lt;br /&gt;
** .tar.lz (only in Alpine &amp;gt;=3.7)&lt;br /&gt;
** .tar.lzma&lt;br /&gt;
** .tar.xz&lt;br /&gt;
** .zip&lt;br /&gt;
&lt;br /&gt;
==== depends &amp;amp;amp; makedepends  ====&lt;br /&gt;
&lt;br /&gt;
Depends are the actual running dependencies that a package would need when it is running. Makedepends are only needed when you are building a package. If you set a package in depends, you do not need to add it to makedepends as well. The best way to find out what the depends and makedepends of a package are is to [https://en.wikipedia.org/wiki/Rtfm RTFM]. &lt;br /&gt;
&lt;br /&gt;
No kidding, lots of important information can be found in the package INSTALL and README files (or the likes). Another good way is the run &amp;lt;code&amp;gt;./configure --help&amp;lt;/code&amp;gt; from the source directory to see which options are needed for configure to finish without errors. If you do not yet have a source directory you can create one with the command: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild unpack}}&lt;br /&gt;
&lt;br /&gt;
Running &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; will also show you how you can disable a specific option for this package. For instance, a good example is &amp;quot;--disable-nls&amp;quot; which will disable native language support and thus does not depend on gettext (libiconv, glib, ...). &lt;br /&gt;
&lt;br /&gt;
Alpine likes to keep things small, so we try to disable as much as possible without losing too many features. The exact disable/enable options are decided by the package builder but please try to follow Alpine&#039;s design concept as much as possible.&lt;br /&gt;
&lt;br /&gt;
An easy way of quickly finding out the build info for a package is to check Arch Linux (Alpine package management and build scripts are similar) or Gentoo Linux ebuilds (previous versions of Alpine were based on Gentoo).&lt;br /&gt;
&lt;br /&gt;
* [https://gitweb.gentoo.org/repo/gentoo.git/tree/ Gentoo Ebuilds] &lt;br /&gt;
* [https://archlinux.org/packages/?q=search Arch Linux packages] [https://aur.archlinux.org/ Arch Linux User Repository]&lt;br /&gt;
&lt;br /&gt;
==== license  ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;license&#039;&#039;&#039; tag must reflect the license of the source code. Please check the source tarball for COPYING, LICENSE, or other files with names that indicates that it contains licensing information. Beside the license file most developer include headers in the source code files with licensing details.&lt;br /&gt;
&lt;br /&gt;
If the license is on the [https://spdx.org/licenses/ SPDX License List] or [https://spdx.org/licenses/exceptions-index.html SPDX License Exceptions], use the identifier specified by SPDX.&lt;br /&gt;
&lt;br /&gt;
Note that some licenses have additional requirements that should be adhered to. The &amp;lt;code&amp;gt;MIT&amp;lt;/code&amp;gt; license for example has the requirement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that we need to include the license as shipped with the project.&lt;br /&gt;
&lt;br /&gt;
If a package has a special/custom license or is not listed as [https://opensource.org/licenses/alphabetical OSI approved], use the identifier &amp;quot;custom&amp;quot;. In that case we need to provide the license file with the package as well.&lt;br /&gt;
&lt;br /&gt;
Because we want to save space and don&#039;t like to have licenses all over our system we have decided to include the license in the doc subpackage. Please follow the following guidelines to add a proper license. Locate the license file inside the source package. Add the doc subpackage to the $subpackages variable as follows: &lt;br /&gt;
&lt;br /&gt;
 subpackages=&amp;quot;$pkgname-doc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Add a similar line to the following to your package() function, depending on the license description file: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|install -Dm644 COPYING &amp;quot;$pkgdir&amp;quot;/usr/share/licenses/$pkgname/COPYING}}&lt;br /&gt;
&lt;br /&gt;
If you follow these steps then abuild will automatically add the license to the package-doc apk for you.&lt;br /&gt;
&lt;br /&gt;
{{Warning|It is not acceptable to package software with &amp;quot;unknown&amp;quot; license! If you can&#039;t find the license of the source code, please contact the author and ask them to specify the license. }}&lt;br /&gt;
&lt;br /&gt;
==== arch ====&lt;br /&gt;
&lt;br /&gt;
The package architecture(s) to build for.  This can be one of: &#039;&#039;x86, x86_64, all,&#039;&#039; or &#039;&#039;noarch&#039;&#039;, where &#039;&#039;all&#039;&#039; means all architectures, and &#039;&#039;noarch&#039;&#039; means it&#039;s architecture-independent (e.g., a pure-python package).&lt;br /&gt;
{{Tip|To determine if your APKBUILD can use &#039;&#039;noarch&#039;&#039;, build the package for your architecture and then run &amp;quot;scanelf -R pkg&amp;quot; from the directory that the APKBUILD resides in, in order to scan for ELF files in the &#039;&#039;./pkg&#039;&#039; directory.  If you do NOT get output from this, then &#039;&#039;noarch&#039;&#039; can be used.}}&lt;br /&gt;
&lt;br /&gt;
==== url  ====&lt;br /&gt;
&lt;br /&gt;
Website address for the program. This is useful later on when either finding documentation or other information about the package.&lt;br /&gt;
&lt;br /&gt;
==== pkgdesc  ====&lt;br /&gt;
&lt;br /&gt;
A brief, one line, description of what the package does. Useful for the package management system. It should start with a capital letter and does &#039;&#039;&#039;not&#039;&#039;&#039; end with a period.&lt;br /&gt;
&lt;br /&gt;
Here is an example from apk_info for the OpenSSH client package:&lt;br /&gt;
&lt;br /&gt;
 pkgdesc=&amp;quot;Port of OpenBSD&#039;s free SSH release - client&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== pkgver  ====&lt;br /&gt;
&lt;br /&gt;
Provide the release number of the package you are building.&lt;br /&gt;
&lt;br /&gt;
==== pkgrel  ====&lt;br /&gt;
&lt;br /&gt;
The $pkgrel versioning is made so that if you change something in your APKBUILD file without changing the actual $pkgver, you can increment pkgrel so apk tools will detect it as an update. For instance, if you forget to add a dependency, you can add it afterward and you can +1 pkgver so apk finds this update and adds the missing dependency. When there&#039;s an upstream version change, we reset the pkgrel to 0.&lt;br /&gt;
&lt;br /&gt;
==== pkgname  ====&lt;br /&gt;
&lt;br /&gt;
The base name of the package you are creating.  For Freeswitch 1.0.6, you would use &amp;quot;freeswitch&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== install  ====&lt;br /&gt;
&lt;br /&gt;
There are 6 different kinds of install scripts. Each script is called with the $pkgname.&#039;&#039;&amp;lt;action&amp;gt;&#039;&#039; where &#039;&#039;&amp;lt;action&amp;gt;&#039;&#039; is one of the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-install&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed before package is installed. Typical use is when package needs a group and a user to be created. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
addgroup -S clamav 2&amp;gt;/dev/null&lt;br /&gt;
adduser -S -D -H -s /bin/false -G clamav -g clamav clamav 2&amp;gt;/dev/null&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note the &#039;&#039;exit 0&#039;&#039; at the end. If the script exits with failure (if the user already exist), the package will not be installed and &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; will exit with failure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-install&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed after the package is installed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-upgrade&lt;br /&gt;
&amp;lt;dd&amp;gt;Same as pre-install but is executed before upgrading/downgrading/reinstalling an already installed package. Note that exiting with failure will not cause apk to exit with failure, but will mark the package as broken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-upgrade&lt;br /&gt;
&amp;lt;dd&amp;gt;Same as post-install but is executed after upgrading/downgrading/reinstalling an already installed package. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-deinstall&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed before uninstalling a package. If script exits with failure apk will not uninstall the package.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-deinstall&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed after a package have been uninstalled. For example, can be used to restore busybox links:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
busybox --install -s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the package has a pre-install and post-install script the APKBUILD should have the &#039;&#039;install&#039;&#039; variable defined:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
install=&amp;quot;$pkgname.pre-install $pkgname.post-install&amp;quot;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== subpackages  ====&lt;br /&gt;
&lt;br /&gt;
$subpackages are made to split up the normal &amp;quot;make install&amp;quot; into separate packages. The most common subpackages we use are doc and dev. Because we like to keep our target system small we move documentation and development files (only needed when building packages) into separate packages. To use the specific program a user only need to install the base apk without package-doc or package-dev, but if he wants to read the manual he will need to install package-doc. &lt;br /&gt;
&lt;br /&gt;
The easiest way to find out if you need to use -dev and -doc is to first build the package without these options set and wait until the build finishes. When its finished you should have a pkg directory which is the fake root directory. Inside this directory you will see the structure as how it would be installed in / on the target system. &lt;br /&gt;
&lt;br /&gt;
To see if you need the -dev package you can run the following cmd: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|find pkg/usr/ -name &#039;*.[acho]&#039; -o -name &#039;*.la&#039;}}&lt;br /&gt;
&lt;br /&gt;
If this returns any files you need to include the -dev package. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; To see if you need the -doc package you can run the following cmd: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|find pkg/usr/share -name doc -o -name man -o -name info -o -name html -o -name sgml -o -name licenses}}&lt;br /&gt;
&lt;br /&gt;
If this returns any directories you need to include the -doc package. &lt;br /&gt;
&lt;br /&gt;
===== Custom subpackages  =====&lt;br /&gt;
&lt;br /&gt;
Some software additionally has non-essential files that do not qualify as either documentation or development content. These files should be placed in their own, specialized subpackage(s). Some packages include large test suites which are only needed in specific circumstances or binaries which have depends which we prefer not to install. To handle those we create our own package/function. In the APKBUILD below the build() function we create another function: &lt;br /&gt;
&lt;br /&gt;
 test() {&lt;br /&gt;
        mkdir -p &amp;quot;$subpkgdir&amp;quot;/usr&lt;br /&gt;
        mv &amp;quot;$pkgdir&amp;quot;/usr/package-test &amp;quot;$subpkgdir&amp;quot;/usr/&lt;br /&gt;
        # or amove usr/package-test&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
We also need to add the package info to $subpackages variable: &lt;br /&gt;
&lt;br /&gt;
 subpackages=&amp;quot;$pkgname-doc $pkgname-dev $pkgname-test&amp;quot;&lt;br /&gt;
&lt;br /&gt;
After we finish building the package you should see another apk called packagename-test.apk which includes the files which we moved to the $subpkgdir dir. &lt;br /&gt;
&lt;br /&gt;
The above mentioned variables can also be used in our custom function. If we want for instance to build the test() function with perl support we would add: &lt;br /&gt;
&lt;br /&gt;
 depends=&amp;quot;perl&amp;quot;&lt;br /&gt;
 makedepends=&amp;quot;perl-dev&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If we would install the base package it would not install perl, but if we install the package-test package it would.&lt;br /&gt;
&lt;br /&gt;
==== Patches  ====&lt;br /&gt;
&lt;br /&gt;
Please make sure you always submit human readable patches. Ways to create them are: &lt;br /&gt;
&lt;br /&gt;
directory compare: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|diff -Nurp original_directory new_directory &amp;amp;gt; filename.patch}}&lt;br /&gt;
&lt;br /&gt;
file compare: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|diff -up original.file new.file &amp;amp;gt; filename.patch}}&lt;br /&gt;
&lt;br /&gt;
If a patch contains a completely new file but not *.rej or *.orig file, you need to add -N option to diff, but you may need to add exclusions with &amp;lt;code&amp;gt;--exclude PATTERN&amp;lt;/code&amp;gt; so that you do not inadvertently add files.  You may need to manually delete unwanted files inside the patch file.&lt;br /&gt;
&lt;br /&gt;
Because multiple patches can patch the same file, they can change the offsets required by subsequent patches. To make sure we always patch in a specific way, we should number the patches as follows: &lt;br /&gt;
&lt;br /&gt;
 10-patch1.patch 20-patch2.patch 30-patch3.patch&lt;br /&gt;
&lt;br /&gt;
This way we are always sure that patch 1 is applied first, and if we want to add additional patches between them we can use appropriate indexes (e.g. 11, 12, 21, 22).&lt;br /&gt;
&lt;br /&gt;
Add the names of the patch files to the &#039;&#039;source&#039;&#039; variable. If you haven&#039;t declared a custom &#039;&#039;prepare&#039;&#039; function, no further action is necessary. Otherwise, be sure to call &#039;&#039;default_prepare&#039;&#039; in your &#039;&#039;prepare&#039;&#039; function. For example:&lt;br /&gt;
&lt;br /&gt;
 prepare() {&lt;br /&gt;
 	default_prepare&lt;br /&gt;
 &lt;br /&gt;
 	# do your stuff&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note: Some older packages contain a &#039;&#039;for&#039;&#039; loop in the &#039;&#039;prepare&#039;&#039; function to apply patches. This is not needed anymore, as patches are handled by &#039;&#039;default_prepare&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In Alpine &amp;gt;=3.4 you can define patch_args to supply the patch level.  This only works if all the patches have the same patch level.  If there are a lot of patches from different sources, there is a good chance that you may need to edit them, as discussed below.&lt;br /&gt;
&lt;br /&gt;
To automatically patch the package (available only in Alpine &amp;gt;=3.4) if it uses a patch level (-pX) other than the default (-p1), you need to carefully modify the patch.  First, you&#039;ll need a text editor that does not automatically convert  between Windows and Unix new lines (or, disable this feature) so that it preserves the old code.  The next thing you&#039;ll need to do is modify the paths on &amp;quot;+++&amp;quot; and &amp;quot;---&amp;quot; lines in the .patch file.  You can begin the path with a/ and b/ like shown below.  Next, you need to adjust the paths so that the relative base path is from inside $builddir.  Anything to the left of $builddir, including $builddir itself, needs to be removed from the path.  So, if $builddir is /home/USER/aports/community/chromium/src/chromium-65, you need to erase it on the &amp;quot;+++&amp;quot; and &amp;quot;---&amp;quot; lines.  Inside the chromium-65 folder you can see a src folder that has 3rdparty as a descendant.  If a patch originally has a deeper patch level, you may need to fill in the missing portion of the path.  For example, use the &amp;lt;code&amp;gt;find . -name &amp;quot;Assertions.cpp&amp;quot;&amp;lt;/code&amp;gt; command to find the full path to the file relative to the base.&lt;br /&gt;
&lt;br /&gt;
{{Cat|example.patch|&amp;lt;nowiki&amp;gt;&lt;br /&gt;
Author: John Doe &amp;lt;johndoe@mail.com&amp;gt;&lt;br /&gt;
URL: http://.....&lt;br /&gt;
Summary: Fixes musl compatibility&lt;br /&gt;
----&lt;br /&gt;
--- a/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp.orig&lt;br /&gt;
+++ b/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp&lt;br /&gt;
@@ -142,7 +142,7 @@&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 FrameToNameScope::FrameToNameScope(void* addr) : m_name(0), m_cxaDemangled(0) {&lt;br /&gt;
-#if OS(MACOSX) || (OS(LINUX) &amp;amp;&amp;amp; !defined(__UCLIBC__))&lt;br /&gt;
+#if OS(MACOSX) || (OS(LINUX) &amp;amp;&amp;amp; defined(__GLIBC__))&lt;br /&gt;
   Dl_info info;&lt;br /&gt;
   if (!dladdr(addr, &amp;amp;info) || !info.dli_sname)&lt;br /&gt;
return;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Portions of the patch may be outdated, removed completely as in the source code file completely removed, or moved or renamed files.  You need to delete that section of the patch or find where that section of code changed and re-diff it.&lt;br /&gt;
&lt;br /&gt;
It is good etiquette to give credit at the top and the location of where you originally found them with notes.&lt;br /&gt;
&lt;br /&gt;
Excluding patches with global variable resembling patch_opts is not available on Alpine.  To exclude patches you need to create your own custom prepare().&lt;br /&gt;
&lt;br /&gt;
If you have a monolithic patch where there are a bunch of patches in one big patch, you could use filterdiff which is available in the patchutils package.&lt;br /&gt;
&lt;br /&gt;
Just do something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
makedepends=&amp;quot;patchutils&amp;quot;&lt;br /&gt;
&lt;br /&gt;
prepare() {&lt;br /&gt;
  ...&lt;br /&gt;
  cd &amp;quot;$builddir&amp;quot;&lt;br /&gt;
  filterdiff -x &#039;*drivers/video/logo*&#039; &amp;quot;$srcdir&amp;quot;/original.patch &amp;gt; &amp;quot;$builddir&amp;quot;/modified.patch&lt;br /&gt;
  patch -p1 -i &amp;quot;$builddir&amp;quot;/modified.patch&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to put the wildcard pattern in single quotes for it to work.&lt;br /&gt;
&lt;br /&gt;
==== Configure options  ====&lt;br /&gt;
&lt;br /&gt;
Alpine has some default configure options we set by default. We use /usr for prefix to make sure everything is installed with /usr in front of it. If you notice that anything is installed in the wrong directory please run {{Cmd|./configure --help}} and see if you can set the correct location. &lt;br /&gt;
&lt;br /&gt;
We are not covering the depend switches here we have discussed this already in the depend section.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Make options  ====&lt;br /&gt;
&lt;br /&gt;
If you notice weird problems when compiling or installing the package with make/make install you could try to disable [https://www.gnu.org/software/make/manual/make.html#Parallel parallel] building/installing. A normal make line would be: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make}}&lt;br /&gt;
&lt;br /&gt;
To disable parallel we use: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make -j1}}&lt;br /&gt;
&lt;br /&gt;
We can use the same for make install. &lt;br /&gt;
&lt;br /&gt;
Because we do not want to install the package in our build environment but we want to install it in a fake root directory we need to tell &#039;make install&#039; to use another destination directory instead of &#039;/&#039;. We do this by setting a variable when we execute make install as followed: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|make DESTDIR{{=}}&amp;quot;$pkgdir&amp;quot; install}}&lt;br /&gt;
&lt;br /&gt;
Please note that some Makefiles do not support this variable and will always install software in &#039;/&#039;. To make sure you do not mess up your build system NEVER run your build system as root but always use a custom user and doas when needed. If by accident the Makefile does not support DESTDIR variable it will fail to install in our build system system directories.&lt;br /&gt;
&lt;br /&gt;
==== builddir ====&lt;br /&gt;
If you used &amp;lt;tt&amp;gt;newapkbuild&amp;lt;/tt&amp;gt; to create your APKBUILD file, you must specify the path to your unpacked sources. Inside the sections during the prepare/build/install process &#039;&#039;builddir&#039;&#039; is used. Most of the time a combination of &#039;&#039;$srcdir&#039;&#039; and &#039;&#039;$pkgname-$pkgver&#039;&#039; will work. When not, check the /src directory or the source tarball for the right string. Especially when you are working with automatically generated tarballs (like from github and gitorious), this needs to be adjusted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
builddir=&amp;quot;$srcdir&amp;quot;/$pkgname-$pkgver&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Additional files  ====&lt;br /&gt;
&lt;br /&gt;
If you want/need to install additional files not mentioned above you can use the following cmd (this is an example of a conf file): &lt;br /&gt;
&lt;br /&gt;
{{Cmd|install -Dm644 doc/$pkgname.conf &amp;quot;$pkgdir&amp;quot;/etc/$pkgname.conf}}&lt;br /&gt;
&lt;br /&gt;
== Build the package  ==&lt;br /&gt;
&lt;br /&gt;
If you did not already create the checksums as mentioned above you can do so now: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $pkgname&lt;br /&gt;
abuild checksum}}&lt;br /&gt;
&lt;br /&gt;
It&#039;s about time we build our package. Because a build system should never have all the package installed to prevent linking to packages we don&#039;t want it to link we use a abuild recursively with the &#039;&#039;&#039;-r&#039;&#039;&#039; switch. It will install all dependencies from your repository and builds it, afterwards it will uninstall all those depending packages again.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild -r}}&lt;br /&gt;
&lt;br /&gt;
See also [[Abuild_and_Helpers|Abuild and Helpers]].&lt;br /&gt;
&lt;br /&gt;
== Testing the package locally ==&lt;br /&gt;
&lt;br /&gt;
When it completes, your package will be found in a subfolder of &amp;lt;code&amp;gt;~/packages&amp;lt;/code&amp;gt;.  You may want to test it on your machine but only if the package is not a critical system package like musl or apk-tools package.  To avoid borking your system (as in making it impossible to use &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; or to restore back the system and the compiler toolchain) for a critical system package, you should test on a chroot first before using it live.&lt;br /&gt;
&lt;br /&gt;
The best way to test a package locally is to modify your &amp;lt;code&amp;gt;/etc/apk/repositories&amp;lt;/code&amp;gt; so that it includes the indexes to your locally built packages - the directories that contain &amp;lt;code&amp;gt;ARCH/APKINDEX.tar.gz&amp;lt;/code&amp;gt;. For example the &amp;lt;code&amp;gt;/etc/apk/repositories&amp;lt;/code&amp;gt; below includes locally built packages in testing, community and main. To use this example change &amp;lt;code&amp;gt;USER&amp;lt;/code&amp;gt; to your login name.&lt;br /&gt;
&lt;br /&gt;
{{Cat|/etc/apk/repositories|/home/USER/packages/testing/&lt;br /&gt;
/home/USER/packages/main/&lt;br /&gt;
/home/USER/packages/community/&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/main&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/community&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/testing&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
If you prefer to test a package without changing any other configuration you can use the &amp;lt;code&amp;gt;-X, --repository&amp;lt;/code&amp;gt; option to &amp;lt;code&amp;gt;apk&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|doas apk add --repository /home/USER/packages/testing $pkgname}}&lt;br /&gt;
&lt;br /&gt;
== Code review ==&lt;br /&gt;
&lt;br /&gt;
To successfully have your package pass through code reviewers (as of Feb 18, 2018 are nmeum and jirutka on GitHub) and possible increased acceptance, the following conventions need to be followed:&lt;br /&gt;
&lt;br /&gt;
# Custom global variables should be prefixed with underscore (_).&lt;br /&gt;
# Compact code as in merged commands, removed unused variables, removal of functions that do the same thing that are automatically handled by abuild.&lt;br /&gt;
# Versioning is done properly.  For details see [[APKBUILD_Reference#pkgver]].&lt;br /&gt;
# Licensing is done properly. Remove unnecessary copying of licensing that is already OSI approved.&lt;br /&gt;
# Naming conventions rules for unofficial variables as in _gitrev is preferred over commit.&lt;br /&gt;
# Indent with tabs not spaces.&lt;br /&gt;
# Removal of explicit return 1.  (They are still found the old APKBUILD files if you are learning but are now strongly discouraged.)&lt;br /&gt;
# Disabling check() requires either (1) a comment (#) stating next to options=&amp;quot;!check&amp;quot; that there is no test suite/unit tests or (2) functioning working check() function.&lt;br /&gt;
# Explicit call to subpackages=&amp;quot;$pkgname-doc&amp;quot; must be used instead of explicit gzip man page compression.&lt;br /&gt;
# Ideally, lines should be no more than 80 columns wide&lt;br /&gt;
&lt;br /&gt;
Additionally, make sure to run the linter on your package:&lt;br /&gt;
{{Cmd|doas apk add atools&lt;br /&gt;
apkbuild-lint APKBUILD}}&lt;br /&gt;
&lt;br /&gt;
For more information see [[Development using git:Quality assurance]] and [[Package_policies]].&lt;br /&gt;
Also check out [https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/COMMITSTYLE.md?ref_type=heads aports/COMMITSTYLE.md] and [https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/CODINGSTYLE.md?ref_type=heads aports/CODINGSTYLE.md]&lt;br /&gt;
&lt;br /&gt;
== Commit your work  ==&lt;br /&gt;
&lt;br /&gt;
After you successfully build your package and properly followed the conventions and requirements in the code review section, you can submit your APKBUILD to Alpine&#039;s git repository. &lt;br /&gt;
&lt;br /&gt;
Update your git repo, before adding new files: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $aportsdir&lt;br /&gt;
git pull}}&lt;br /&gt;
&lt;br /&gt;
This should pull all the changes made by others into your local git repo.&lt;br /&gt;
&lt;br /&gt;
When you think you are ready you can add your files to git: &lt;br /&gt;
&lt;br /&gt;
NOTE: when using our Gitlab instance, you can create MR&#039;s for each package. Please squash all commits related to the same package into a single one per MR.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $aportsdir&lt;br /&gt;
git add testing/$pkgdir (include any other files needed for the build; $pkgname.install...)&lt;br /&gt;
git commit}}&lt;br /&gt;
&lt;br /&gt;
Use the following commit message template for new aports (without the comments):&lt;br /&gt;
&lt;br /&gt;
{{Cat|template|testing/$pkgname: new aport   # this will be the subject line&lt;br /&gt;
                              # a blank line&lt;br /&gt;
$url                          # project homepage&lt;br /&gt;
$pkgdesc                      # one line description}}&lt;br /&gt;
&lt;br /&gt;
Or you could add the following and &amp;lt;code&amp;gt;chmod +x ports/.git/hooks/prepare-commit-msg&amp;lt;/code&amp;gt; to automatically generate commit message which the default aports/.githooks/ does not:&lt;br /&gt;
&lt;br /&gt;
{{Cat|aports/.git/hooks/prepare-commit-msg|&amp;lt;nowiki&amp;gt;#!/bin/sh&lt;br /&gt;
case &amp;quot;$2,$3&amp;quot; in&lt;br /&gt;
  ,|template,)&lt;br /&gt;
    if git diff-index --diff-filter=A --name-only --cached HEAD \&lt;br /&gt;
        | grep -q &#039;/APKBUILD$&#039;; then&lt;br /&gt;
      meta() { git diff --staged | grep &amp;quot;^+$1&amp;quot; | sed &#039;s/.*=&amp;quot;\?//;s/&amp;quot;$//&#039;;}&lt;br /&gt;
      printf &#039;testing/%s: new aport\n\n%s\n%s\n&#039; &amp;quot;$(meta pkgname)&amp;quot; \&lt;br /&gt;
        &amp;quot;$(meta url)&amp;quot; &amp;quot;$(meta pkgdesc)&amp;quot; &amp;quot;$(cat $1)&amp;quot; &amp;gt; &amp;quot;$1&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      printf &#039;%s\n\n%s&#039; `git diff-index --name-only --cached HEAD \&lt;br /&gt;
        | sed -n &#039;s/\/APKBUILD$//p;q&#039;` &amp;quot;$(cat $1)&amp;quot; &amp;gt; &amp;quot;$1&amp;quot;&lt;br /&gt;
    fi;;&lt;br /&gt;
esac&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now your changes are only available locally in your repository.&lt;br /&gt;
&lt;br /&gt;
Because you do not have push rights to the Alpine aports repository you need to create a merge request to [https://gitlab.alpinelinux.org/alpine/aports Alpine&#039;s GitLab instance].&lt;br /&gt;
&lt;br /&gt;
Alternatively you can also create a diff (patch) of the changes you made and send this patch to the &lt;br /&gt;
[https://lists.alpinelinux.org/~alpine/aports  alpine-aports mailinglist].&lt;br /&gt;
&lt;br /&gt;
To create a diff patch:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|git format-patch HEAD^}}&lt;br /&gt;
&lt;br /&gt;
or if you have sprunge, you can create a link to your patch for convenience&lt;br /&gt;
&lt;br /&gt;
{{Cmd|git format-patch HEAD^ --stdout &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; sprunge}}&lt;br /&gt;
&lt;br /&gt;
== Automated flagging of outdated ports ==&lt;br /&gt;
Consider adding your port to [https://release-monitoring.org/ Anitya], so it will be flagged as outdated&lt;br /&gt;
as soon as a new stable version is released by upstream.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[APKBUILD Reference]]&lt;br /&gt;
* [[APKBUILD examples]]&lt;br /&gt;
* [[Development using git]]&lt;br /&gt;
* [[Development using git:Quality assurance]]&lt;br /&gt;
&lt;br /&gt;
[[category: Package Manager]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Template:AlpineLatest&amp;diff=25354</id>
		<title>Template:AlpineLatest</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Template:AlpineLatest&amp;diff=25354"/>
		<updated>2023-09-28T14:48:06Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Bump to 3.18.4&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Template}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;3.18.4&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=23784</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=23784"/>
		<updated>2023-07-06T13:37:03Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &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 (2023-07-06) disk usage in GB:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!edge&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;
!v3.10&lt;br /&gt;
!v3.11&lt;br /&gt;
!v3.12&lt;br /&gt;
!v3.13&lt;br /&gt;
!v3.14&lt;br /&gt;
!v3.15&lt;br /&gt;
!v3.16&lt;br /&gt;
!v3.17&lt;br /&gt;
!v3.18&lt;br /&gt;
&lt;br /&gt;
!total&lt;br /&gt;
|-&lt;br /&gt;
|348&lt;br /&gt;
|17&lt;br /&gt;
|18&lt;br /&gt;
|15&lt;br /&gt;
|21&lt;br /&gt;
|25&lt;br /&gt;
|27&lt;br /&gt;
|45&lt;br /&gt;
|43&lt;br /&gt;
|59&lt;br /&gt;
|73&lt;br /&gt;
|92&lt;br /&gt;
|126&lt;br /&gt;
|148&lt;br /&gt;
|156&lt;br /&gt;
|181&lt;br /&gt;
|186&lt;br /&gt;
|195&lt;br /&gt;
|214&lt;br /&gt;
|242&lt;br /&gt;
&lt;br /&gt;
|&#039;&#039;&#039;2222&#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;
#!/bin/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 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; 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=$(( old_total + size ))&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;
#!/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;
== 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;
#!/bin/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;
== Partial mirror using nginx ==&lt;br /&gt;
&lt;br /&gt;
For a private mirror it might make sense to sync only the newest versions of Alpine to save space, but if you &#039;&#039;do&#039;&#039; point an old Alpine version to your mirror they should still be able to install packages. We can achieve this by using nginx to serve the mirrored content and use regex location matching to redirect requests to a public mirror.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s assume you chose to only mirror Alpine versions up from v3.13. If a client asks your mirror for v.3.10 it should redirect to another mirror.&lt;br /&gt;
&lt;br /&gt;
Your nginx config server block should look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server {&lt;br /&gt;
        listen 80;&lt;br /&gt;
        server_name alpine.mydomain.local;&lt;br /&gt;
        root /data/alpine;          # point to where your alpine mirror is located. make sure nginx is allowed to read it&lt;br /&gt;
        autoindex on;               # Enable indexing&lt;br /&gt;
&lt;br /&gt;
        # the following location block will match for v3.0 to v3.12&lt;br /&gt;
        # and will forward it to dl-4.alpinelinux.org.&lt;br /&gt;
        location ~* /(v3\.([1-9]|1[012]))$&lt;br /&gt;
        {&lt;br /&gt;
          return 302 http://dl-cdn.alpinelinux.org/alpine$request_uri;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The corresponding sync script could look something like this:&lt;br /&gt;
&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=/data/alpine/&lt;br /&gt;
&lt;br /&gt;
  exclude=&amp;quot;--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&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  mkdir -p &amp;quot;$dest&amp;quot;&lt;br /&gt;
  /usr/bin/rsync -vvv \&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;
  --delete-excluded \&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Server]]&lt;br /&gt;
[[Category:Package Manager]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=How_to_setup_a_Alpine_Linux_mirror&amp;diff=23783</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=23783"/>
		<updated>2023-07-06T13:35:42Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Update mirror sizes&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 (2023-01-13) disk usage in GB:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!edge&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;
!v3.10&lt;br /&gt;
!v3.11&lt;br /&gt;
!v3.12&lt;br /&gt;
!v3.13&lt;br /&gt;
!v3.14&lt;br /&gt;
!v3.15&lt;br /&gt;
!v3.16&lt;br /&gt;
!v3.17&lt;br /&gt;
!v3.18&lt;br /&gt;
&lt;br /&gt;
!total&lt;br /&gt;
|-&lt;br /&gt;
|348&lt;br /&gt;
|17&lt;br /&gt;
|18&lt;br /&gt;
|15&lt;br /&gt;
|21&lt;br /&gt;
|25&lt;br /&gt;
|27&lt;br /&gt;
|45&lt;br /&gt;
|43&lt;br /&gt;
|59&lt;br /&gt;
|73&lt;br /&gt;
|92&lt;br /&gt;
|126&lt;br /&gt;
|148&lt;br /&gt;
|156&lt;br /&gt;
|181&lt;br /&gt;
|186&lt;br /&gt;
|195&lt;br /&gt;
|214&lt;br /&gt;
|242&lt;br /&gt;
&lt;br /&gt;
|&#039;&#039;&#039;2222&#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;
#!/bin/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 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; 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=$(( old_total + size ))&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;
#!/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;
== 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;
#!/bin/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;
== Partial mirror using nginx ==&lt;br /&gt;
&lt;br /&gt;
For a private mirror it might make sense to sync only the newest versions of Alpine to save space, but if you &#039;&#039;do&#039;&#039; point an old Alpine version to your mirror they should still be able to install packages. We can achieve this by using nginx to serve the mirrored content and use regex location matching to redirect requests to a public mirror.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s assume you chose to only mirror Alpine versions up from v3.13. If a client asks your mirror for v.3.10 it should redirect to another mirror.&lt;br /&gt;
&lt;br /&gt;
Your nginx config server block should look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
server {&lt;br /&gt;
        listen 80;&lt;br /&gt;
        server_name alpine.mydomain.local;&lt;br /&gt;
        root /data/alpine;          # point to where your alpine mirror is located. make sure nginx is allowed to read it&lt;br /&gt;
        autoindex on;               # Enable indexing&lt;br /&gt;
&lt;br /&gt;
        # the following location block will match for v3.0 to v3.12&lt;br /&gt;
        # and will forward it to dl-4.alpinelinux.org.&lt;br /&gt;
        location ~* /(v3\.([1-9]|1[012]))$&lt;br /&gt;
        {&lt;br /&gt;
          return 302 http://dl-cdn.alpinelinux.org/alpine$request_uri;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The corresponding sync script could look something like this:&lt;br /&gt;
&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=/data/alpine/&lt;br /&gt;
&lt;br /&gt;
  exclude=&amp;quot;--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&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  mkdir -p &amp;quot;$dest&amp;quot;&lt;br /&gt;
  /usr/bin/rsync -vvv \&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;
  --delete-excluded \&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Server]]&lt;br /&gt;
[[Category:Package Manager]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=VLAN&amp;diff=23353</id>
		<title>VLAN</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=VLAN&amp;diff=23353"/>
		<updated>2023-05-03T21:15:55Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This article shows how to configure a network interface as an IEEE 802.1q VLAN trunk.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
{{Note| Alpine Linux v2.4 or later is required}}&lt;br /&gt;
==Installation==&lt;br /&gt;
First, install the &#039;&#039;vlan&#039;&#039; package. This will give you support for vlans in the &#039;&#039;/etc/network/interfaces&#039;&#039; file.&lt;br /&gt;
{{Cmd|apk add vlan}}&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
Edit the &#039;&#039;/etc/network/interfaces&#039;&#039; file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto eth0.8&lt;br /&gt;
iface eth0.8&lt;br /&gt;
	address 192.168.0.2/24&lt;br /&gt;
	gateway 192.168.0.1&lt;br /&gt;
	vlan-raw-device eth0&lt;br /&gt;
	vlan_id 8&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the &#039;&#039;vlan&#039;&#039; package installed, ifup will find the trailing .8 in eth0.8 and will create a vlan interface with vid 8 over eth0.&lt;br /&gt;
&lt;br /&gt;
Alternativly with vlan8 over eth0:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto vlan8&lt;br /&gt;
iface vlan8&lt;br /&gt;
	address 192.168.0.2/24&lt;br /&gt;
	gateway 192.168.0.1&lt;br /&gt;
	vlan-raw-device eth0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A static ip address was used in the examples shown above, but dhcp can be used as well.&lt;br /&gt;
&lt;br /&gt;
== Example with bridges associated with VLANs over bonding with differing MTUs on the various VLANs ==&lt;br /&gt;
This serves as an example of some of the more complicated networking possible. Particularly, this would work well for a hypervisor attached to a dedicated storage VLAN. Less complicated implementations can be achieved by merely removing the non-applicable parts.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto lo&lt;br /&gt;
iface lo inet loopback&lt;br /&gt;
&lt;br /&gt;
auto bond0&lt;br /&gt;
  iface bond0 inet manual&lt;br /&gt;
  bond_slaves eth0 eth1&lt;br /&gt;
  bond_mode 802.3ad&lt;br /&gt;
  bond_miimon 100&lt;br /&gt;
  bond_xmit_hash_policy layer2+3&lt;br /&gt;
  post-up ip link set dev bondi0 mtu 9000&lt;br /&gt;
&lt;br /&gt;
iface bond0.1&lt;br /&gt;
&lt;br /&gt;
auto br1&lt;br /&gt;
iface br1&lt;br /&gt;
  address 192.168.1.196/24&lt;br /&gt;
  gateway 192.168.1.1&lt;br /&gt;
  bridge_ports bond0.1&lt;br /&gt;
  bridge_stp off&lt;br /&gt;
  bridge_fd 0.0&lt;br /&gt;
  post-up ip link set dev bond0.1 mtu 1500&lt;br /&gt;
&lt;br /&gt;
iface bond0.10 inet manual&lt;br /&gt;
&lt;br /&gt;
auto br10&lt;br /&gt;
  iface br10 inet static&lt;br /&gt;
  address 192.168.10.1/24&lt;br /&gt;
  bridge_ports bond0.10&lt;br /&gt;
  bridge_stp off&lt;br /&gt;
  bridge_fd 0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example with two interfaces on the same adapter. One with vlan and one without ==&lt;br /&gt;
&lt;br /&gt;
Since linux doesn&#039;t allow multiple default gateways we need to use a second routing table using iproute2&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add iproute2}}&lt;br /&gt;
&lt;br /&gt;
Then we&#039;ll add two new routig tables to the config file. One for each network&lt;br /&gt;
&lt;br /&gt;
{{Cmd|echo &amp;quot;1 rt1&amp;quot; &amp;gt;&amp;gt; /etc/iproute2/rt_tables;echo &amp;quot;2 rt2&amp;quot; &amp;gt;&amp;gt; /etc/iproute2/rt_tables;}}&lt;br /&gt;
&lt;br /&gt;
Now we need to edit /etc/network/interfaces&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto lo&lt;br /&gt;
iface lo inet loopback&lt;br /&gt;
&lt;br /&gt;
# the native interface without a vlan (also called untagged)&lt;br /&gt;
&lt;br /&gt;
auto eth0&lt;br /&gt;
iface eth0&lt;br /&gt;
        address 192.168.1.100/24&lt;br /&gt;
        gateway 192.168.1.1&lt;br /&gt;
        post-up ip route add 192.168.1.0/24 dev eth0 src 192.168.1.100 table rt1&lt;br /&gt;
        post-up ip route add default via 192.168.1.1 dev eth0 table rt1 # the actual gateway for this interface&lt;br /&gt;
        post-up ip rule add from 192.168.1.100/32 table rt1&lt;br /&gt;
        post-up ip rule add to 192.168.1.100/32 table rt1&lt;br /&gt;
&lt;br /&gt;
# second interface with the vlan tag 5&lt;br /&gt;
auto eth0.5&lt;br /&gt;
iface eth0.5&lt;br /&gt;
    address 192.168.5.100/24&lt;br /&gt;
    post-up ip route add 192.168.5.0/24 dev eth0.5 src 192.168.5.100 table rt2&lt;br /&gt;
    post-up ip route add default via 192.168.5.1 dev eth0.5 table rt2 # the actual gateway for this interface&lt;br /&gt;
    post-up ip rule add from 192.168.5.100/32 table rt2&lt;br /&gt;
    post-up ip rule add to 192.168.5.100/32 table rt2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that if you want to add a third interface this way, you&#039;ll have to add another routing table&lt;br /&gt;
&lt;br /&gt;
[[Category:Networking]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=VLAN&amp;diff=23352</id>
		<title>VLAN</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=VLAN&amp;diff=23352"/>
		<updated>2023-05-03T19:39:51Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Modernize examples for ifupdown-ng&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This article shows how to configure a network interface as an IEEE 802.1q VLAN trunk.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
{{Note| Alpine Linux v2.4 or later is required}}&lt;br /&gt;
==Installation==&lt;br /&gt;
First, install the &#039;&#039;vlan&#039;&#039; package. This will give you support for vlans in the &#039;&#039;/etc/network/interfaces&#039;&#039; file.&lt;br /&gt;
{{Cmd|apk add vlan}}&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
Edit the &#039;&#039;/etc/network/interfaces&#039;&#039; file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto eth0.8&lt;br /&gt;
iface eth0.8&lt;br /&gt;
	address 192.168.0.2/24&lt;br /&gt;
	gateway 192.168.0.1&lt;br /&gt;
    vlan-raw-device eth0&lt;br /&gt;
    vlan_id 8&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the &#039;&#039;vlan&#039;&#039; package installed, ifup will find the trailing .8 in eth0.8 and will create a vlan interface with vid 8 over eth0.&lt;br /&gt;
&lt;br /&gt;
Alternativly with vlan8 over eth0:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto vlan8&lt;br /&gt;
iface vlan8&lt;br /&gt;
	address 192.168.0.2/24&lt;br /&gt;
	gateway 192.168.0.1&lt;br /&gt;
	vlan-raw-device eth0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A static ip address was used in the examples shown above, but dhcp can be used as well.&lt;br /&gt;
&lt;br /&gt;
== Example with bridges associated with VLANs over bonding with differing MTUs on the various VLANs ==&lt;br /&gt;
This serves as an example of some of the more complicated networking possible. Particularly, this would work well for a hypervisor attached to a dedicated storage VLAN. Less complicated implementations can be achieved by merely removing the non-applicable parts.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto lo&lt;br /&gt;
iface lo inet loopback&lt;br /&gt;
&lt;br /&gt;
auto bond0&lt;br /&gt;
  iface bond0 inet manual&lt;br /&gt;
  bond_slaves eth0 eth1&lt;br /&gt;
  bond_mode 802.3ad&lt;br /&gt;
  bond_miimon 100&lt;br /&gt;
  bond_xmit_hash_policy layer2+3&lt;br /&gt;
  post-up ip link set dev bondi0 mtu 9000&lt;br /&gt;
&lt;br /&gt;
iface bond0.1&lt;br /&gt;
&lt;br /&gt;
auto br1&lt;br /&gt;
iface br1&lt;br /&gt;
  address 192.168.1.196/24&lt;br /&gt;
  gateway 192.168.1.1&lt;br /&gt;
  bridge_ports bond0.1&lt;br /&gt;
  bridge_stp off&lt;br /&gt;
  bridge_fd 0.0&lt;br /&gt;
  post-up ip link set dev bond0.1 mtu 1500&lt;br /&gt;
&lt;br /&gt;
iface bond0.10 inet manual&lt;br /&gt;
&lt;br /&gt;
auto br10&lt;br /&gt;
  iface br10 inet static&lt;br /&gt;
  address 192.168.10.1/24&lt;br /&gt;
  bridge_ports bond0.10&lt;br /&gt;
  bridge_stp off&lt;br /&gt;
  bridge_fd 0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example with two interfaces on the same adapter. One with vlan and one without ==&lt;br /&gt;
&lt;br /&gt;
Since linux doesn&#039;t allow multiple default gateways we need to use a second routing table using iproute2&lt;br /&gt;
&lt;br /&gt;
{{Cmd|apk add iproute2}}&lt;br /&gt;
&lt;br /&gt;
Then we&#039;ll add two new routig tables to the config file. One for each network&lt;br /&gt;
&lt;br /&gt;
{{Cmd|echo &amp;quot;1 rt1&amp;quot; &amp;gt;&amp;gt; /etc/iproute2/rt_tables;echo &amp;quot;2 rt2&amp;quot; &amp;gt;&amp;gt; /etc/iproute2/rt_tables;}}&lt;br /&gt;
&lt;br /&gt;
Now we need to edit /etc/network/interfaces&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auto lo&lt;br /&gt;
iface lo inet loopback&lt;br /&gt;
&lt;br /&gt;
# the native interface without a vlan (also called untagged)&lt;br /&gt;
&lt;br /&gt;
auto eth0&lt;br /&gt;
iface eth0&lt;br /&gt;
        address 192.168.1.100/24&lt;br /&gt;
        gateway 192.168.1.1&lt;br /&gt;
        post-up ip route add 192.168.1.0/24 dev eth0 src 192.168.1.100 table rt1&lt;br /&gt;
        post-up ip route add default via 192.168.1.1 dev eth0 table rt1 # the actual gateway for this interface&lt;br /&gt;
        post-up ip rule add from 192.168.1.100/32 table rt1&lt;br /&gt;
        post-up ip rule add to 192.168.1.100/32 table rt1&lt;br /&gt;
&lt;br /&gt;
# second interface with the vlan tag 5&lt;br /&gt;
auto eth0.5&lt;br /&gt;
iface eth0.5&lt;br /&gt;
    address 192.168.5.100/24&lt;br /&gt;
    post-up ip route add 192.168.5.0/24 dev eth0.5 src 192.168.5.100 table rt2&lt;br /&gt;
    post-up ip route add default via 192.168.5.1 dev eth0.5 table rt2 # the actual gateway for this interface&lt;br /&gt;
    post-up ip rule add from 192.168.5.100/32 table rt2&lt;br /&gt;
    post-up ip rule add to 192.168.5.100/32 table rt2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that if you want to add a third interface this way, you&#039;ll have to add another routing table&lt;br /&gt;
&lt;br /&gt;
[[Category:Networking]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.18.0&amp;diff=22781</id>
		<title>Release Notes for Alpine 3.18.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.18.0&amp;diff=22781"/>
		<updated>2022-12-14T18:53:30Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
* python 3.11 https://docs.python.org/3/whatsnew/3.11.html&lt;br /&gt;
* linux-lts 6.1 https://lkml.org/lkml/2022/12/11/206&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.18.0&amp;diff=22780</id>
		<title>Release Notes for Alpine 3.18.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Release_Notes_for_Alpine_3.18.0&amp;diff=22780"/>
		<updated>2022-12-14T18:52:54Z</updated>

		<summary type="html">&lt;p&gt;Ikke: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
- python 3.11 https://docs.python.org/3/whatsnew/3.11.html&lt;br /&gt;
- linux-lts 6.1 https://lkml.org/lkml/2022/12/11/206&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Creating_an_Alpine_package&amp;diff=22694</id>
		<title>Creating an Alpine package</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Creating_an_Alpine_package&amp;diff=22694"/>
		<updated>2022-11-26T12:47:52Z</updated>

		<summary type="html">&lt;p&gt;Ikke: /* Testing the package locally */ Update repositories&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOC right}}&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
To build a package for Alpine Linux you need an Alpine Linux installation. Check the [[Installation]] page to see all available installation options.&lt;br /&gt;
&lt;br /&gt;
== Setup your system and account  ==&lt;br /&gt;
{{:Include:Setup_your_system_and_account_for_building_packages}}&lt;br /&gt;
&lt;br /&gt;
== Getting some help ==&lt;br /&gt;
&lt;br /&gt;
It might be wise to start by checking what the [[Abuild|abuild]] program can/cannot do.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild -h}}&lt;br /&gt;
&lt;br /&gt;
For real help, you can also go on OFTC&#039;s #alpine-devel on IRC.&lt;br /&gt;
&lt;br /&gt;
A reference for APKBUILD files is available as [[APKBUILD Reference]] wiki page or a man page in the &#039;abuild-doc&#039; package:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|man APKBUILD}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating an APKBUILD file  ==&lt;br /&gt;
&lt;br /&gt;
=== Use a template APKBUILD ===&lt;br /&gt;
&lt;br /&gt;
To create the actual APKBUILD file {{Pkg|newapkbuild}} can serve you a template to start with. It will create a directory with the given package name, place an example/template APKBUILD file to the given directory, and fill some variables if those are provided. Please check the [[Package_policies| package policies]] page about naming details.&lt;br /&gt;
&lt;br /&gt;
If you doubt to which repository your package belongs to you can safely use &#039;&#039;&#039;testing&#039;&#039;&#039;. Building package in your aports/testing directory is not mandatory but this way the package is already at the right place.&lt;br /&gt;
&lt;br /&gt;
{{:Include:Newapkbuild}}&lt;br /&gt;
&lt;br /&gt;
{{Note|On older Alpine systems, abuild -c -n &#039;&#039;packagename&#039;&#039; was the way to create APKBUILD files. The &#039;packagename&#039; was a parameter to the -n option so order of -c and -n matters. }}&lt;br /&gt;
&lt;br /&gt;
[[Abuild_and_Helpers#apkbuild-cpan|apkbuild-cpan]] simplifies the creation of perl packages from CPAN and [[Abuild_and_Helpers#apkbuild-pypi|apkbuild-pypi]] ease the generation of APKBUILD files for python packages from PyPi.  &lt;br /&gt;
&lt;br /&gt;
If you are creating a daemon package which needs initd scripts you can add the -c making it: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|newapkbuild -c &#039;&#039;packagename&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
This will copy the sample initd and confd files to the build directory.&amp;lt;BR&amp;gt;&lt;br /&gt;
A third file sample.install file will be copied as well (we will discuss this later on).&lt;br /&gt;
&lt;br /&gt;
=== Modify your APKBUILD ===&lt;br /&gt;
Edit APKBUILD and fill in the needed info (especially pkgname, pkgver, pkgdesc, url, license, depends and source). &lt;br /&gt;
&lt;br /&gt;
If you are going to use any of the variables for directories like $pkgdir, always make sure they are double quoted like: &lt;br /&gt;
&lt;br /&gt;
 &amp;quot;$pkgdir&amp;quot;/somedir&lt;br /&gt;
&lt;br /&gt;
This will prevent issues with spaces/special characters in the future. &lt;br /&gt;
&lt;br /&gt;
{{Note|If you like syntax highlighting we suggest you to install vim. We have setup vim to recognize the APKBUILD file as a bash scripts so its easier to read them.}}&lt;br /&gt;
&lt;br /&gt;
=== APKBUILD variables/functions  ===&lt;br /&gt;
&lt;br /&gt;
==== source  ====&lt;br /&gt;
&lt;br /&gt;
The source variable is not only used to list the remote source files to fetch, it is also used to list the local files that abuild will need in order to build the apk. Examples of such local files include: init.d files, conf.d files, install files (see [[Creating an Alpine package#install|install variable]]), patches, and all other necessary files.&lt;br /&gt;
&lt;br /&gt;
Here are few things to note:&lt;br /&gt;
&lt;br /&gt;
* When you are finished adding local and/or remote files to &#039;&#039;source&#039;&#039;, you can execute the following command to add their checksums to the APKBUILD file:&lt;br /&gt;
: {{cmd|abuild checksum}}&lt;br /&gt;
: {{Note|When later updating the content of &#039;&#039;source&#039;&#039;, or updating a file that is listed in &#039;&#039;source&#039;&#039;, you must also update their checksums again with the same command.}}&lt;br /&gt;
&lt;br /&gt;
* When the remote file is hosted at SourceForge, it&#039;s best to specify the special mirrors link used by SourceForge:&lt;br /&gt;
: &amp;lt;pre&amp;gt;http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz&amp;lt;/pre&amp;gt;&lt;br /&gt;
: (or similar depending on the package).&lt;br /&gt;
&lt;br /&gt;
* When the remote filename is not specified in the URI (ie, does not end in &#039;/software-1.0.tar.gz&#039;), such as:&lt;br /&gt;
: &amp;lt;pre&amp;gt;http://oss.example.org/?get=software&amp;amp;ver=1.0&amp;lt;/pre&amp;gt;&lt;br /&gt;
: You must prepend &#039;${pkgname}-${pkgver}.tar.gz::&#039; to the protocol, like so:&lt;br /&gt;
: &amp;lt;pre&amp;gt;source=&amp;quot;${pkgname}-${pkgver}.tar.gz::http://oss.example.org/?get=software&amp;amp;ver=1.0&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
: This causes the file to be saved as &#039;&#039;software-1.0.tar.gz&#039;&#039; where abuild can use it, instead of &#039;&#039;?get=software&amp;amp;ver=1.0&#039;&#039;, where abuild cannot use it.&lt;br /&gt;
&lt;br /&gt;
* Some projects didn&#039;t provide a release tarball. Beware that some git services (gitweg, cgit, …?) doesn’t provide &#039;&#039;stable&#039;&#039; tarballs, so when you point source to an tarball like &amp;lt;tt&amp;gt;http://repo.or.cz/w/gitstats.git/snapshot/ad7efbb9399e60cee6cb217c6b47e604174a8093.tar.gz&amp;lt;/tt&amp;gt;, then you will run into issues because the checksum changes when downloading on the build system. This is not a problem on GitHub, GitLab and other decent services provides, they provide &#039;&#039;stable&#039;&#039; tarballs.&lt;br /&gt;
&lt;br /&gt;
* abuild currently supports the following protocols for remote file retrieval:&lt;br /&gt;
** http&lt;br /&gt;
** https&lt;br /&gt;
** ftp&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--: {{Note|If the you want to download from https, you need GNU wget installed on your system.}}--&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
* abuild currently supports the following archive types/archive file extensions:&lt;br /&gt;
** .tar&lt;br /&gt;
** .tar.gz / .tgz&lt;br /&gt;
** .tar.bz2&lt;br /&gt;
** .tar.lz (only in Alpine &amp;gt;=3.7)&lt;br /&gt;
** .tar.lzma&lt;br /&gt;
** .tar.xz&lt;br /&gt;
** .zip&lt;br /&gt;
&lt;br /&gt;
==== depends &amp;amp;amp; makedepends  ====&lt;br /&gt;
&lt;br /&gt;
Depends are the actual running dependencies that a package would need when it is running. Makedepends are only needed when you are building a package. If you set a package in depends, you do not need to add it to makedepends as well. The best way to find out what the depends and makedepends of a package are is to [http://en.wikipedia.org/wiki/Rtfm RTFM]. &lt;br /&gt;
&lt;br /&gt;
No kidding, lots of important information can be found in the package INSTALL and README files (or the likes). Another good way is the run &amp;lt;code&amp;gt;./configure --help&amp;lt;/code&amp;gt; from the source directory to see which options are needed for configure to finish without errors. If you do not yet have a source directory you can create one with the command: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild unpack}}&lt;br /&gt;
&lt;br /&gt;
Running &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; will also show you how you can disable a specific option for this package. For instance, a good example is &amp;quot;--disable-nls&amp;quot; which will disable native language support and thus does not depend on gettext (libiconv, glib, ...). &lt;br /&gt;
&lt;br /&gt;
Alpine likes to keep things small, so we try to disable as much as possible without losing too many features. The exact disable/enable options are decided by the package builder but please try to follow Alpine&#039;s design concept as much as possible.&lt;br /&gt;
&lt;br /&gt;
An easy way of quickly finding out the build info for a package is to check Arch Linux (Alpine package management and build scripts are similar) or Gentoo Linux ebuilds (previous versions of Alpine were based on Gentoo).&lt;br /&gt;
&lt;br /&gt;
* [https://gitweb.gentoo.org/repo/gentoo.git/tree/ Gentoo Ebuilds] &lt;br /&gt;
* [http://www.archlinux.org/packages/search/ Arch Linux packages] [https://aur.archlinux.org/ Arch Linux User Repository]&lt;br /&gt;
&lt;br /&gt;
==== license  ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;license&#039;&#039;&#039; tag must reflect the license of the source code. Please check the source tarball for COPYING, LICENSE, or other files with names that indicates that it contains licensing information. Beside the license file most developer include headers in the source code files with licensing details.&lt;br /&gt;
&lt;br /&gt;
If the license is on the [https://spdx.org/licenses/ SPDX License List] or [https://spdx.org/licenses/exceptions-index.html SPDX License Exceptions], use the identifier specified by SPDX.&lt;br /&gt;
&lt;br /&gt;
If a package has a special/custom license or is not listed as [https://opensource.org/licenses/alphabetical OSI approved], use the identifier &amp;quot;custom&amp;quot;. We additionally need to provide the license file with the release. Because we want to save space and don&#039;t like to have licenses all over our system we have decided to include the license in the doc subpackage. Please follow the following guidelines to add a proper license. Locate the license file inside the source package. Add the doc subpackage to the $subpackages variable as follows: &lt;br /&gt;
&lt;br /&gt;
 subpackages=&amp;quot;$pkgname-doc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Add a similar line to the following to your package() function, depending on the license description file: &lt;br /&gt;
&lt;br /&gt;
 install -Dm644 COPYING &amp;quot;$pkgdir&amp;quot;/usr/share/licenses/$pkgname/COPYING&lt;br /&gt;
&lt;br /&gt;
If you follow these steps then abuild will automatically add the license to the package-doc apk for you.&lt;br /&gt;
&lt;br /&gt;
{{Warning|It is not acceptable to package software with &amp;quot;unknown&amp;quot; license! If you can&#039;t find the license of the source code, please contact the author and ask them to specify the license. }}&lt;br /&gt;
&lt;br /&gt;
==== arch ====&lt;br /&gt;
&lt;br /&gt;
The package architecture(s) to build for.  This can be one of: &#039;&#039;x86, x86_64, all,&#039;&#039; or &#039;&#039;noarch&#039;&#039;, where &#039;&#039;all&#039;&#039; means all architectures, and &#039;&#039;noarch&#039;&#039; means it&#039;s architecture-independent (e.g., a pure-python package).&lt;br /&gt;
{{Tip|To determine if your APKBUILD can use &#039;&#039;noarch&#039;&#039;, build the package for your architecture and then run &amp;quot;scanelf -R pkg&amp;quot; from the directory that the APKBUILD resides in, in order to scan for ELF files in the &#039;&#039;./pkg&#039;&#039; directory.  If you do NOT get output from this, then &#039;&#039;noarch&#039;&#039; can be used.}}&lt;br /&gt;
&lt;br /&gt;
==== url  ====&lt;br /&gt;
&lt;br /&gt;
Website address for the program. This is useful later on when either finding documentation or other information about the package.&lt;br /&gt;
&lt;br /&gt;
==== pkgdesc  ====&lt;br /&gt;
&lt;br /&gt;
A brief, one line, description of what the package does. Useful for the package management system. It should start with a capital letter and does &#039;&#039;&#039;not&#039;&#039;&#039; end with a period.&lt;br /&gt;
&lt;br /&gt;
Here is an example from apk_info for the OpenSSH client package:&lt;br /&gt;
&lt;br /&gt;
 pkgdesc=&amp;quot;Port of OpenBSD&#039;s free SSH release - client&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== pkgver  ====&lt;br /&gt;
&lt;br /&gt;
Provide the release number of the package you are building.&lt;br /&gt;
&lt;br /&gt;
==== pkgrel  ====&lt;br /&gt;
&lt;br /&gt;
The $pkgrel versioning is made so that if you change something in your APKBUILD file without changing the actual $pkgver, you can increment pkgrel so apk tools will detect it as an update. For instance, if you forget to add a dependency, you can add it afterward and you can +1 pkgver so apk finds this update and adds the missing dependency. When there&#039;s an upstream version change, we reset the pkgrel to 0.&lt;br /&gt;
&lt;br /&gt;
==== pkgname  ====&lt;br /&gt;
&lt;br /&gt;
The base name of the package you are creating.  For Freeswitch 1.0.6, you would use &amp;quot;freeswitch&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== install  ====&lt;br /&gt;
&lt;br /&gt;
There are 6 different kinds of install scripts. Each script is called with the $pkgname.&#039;&#039;&amp;lt;action&amp;gt;&#039;&#039; where &#039;&#039;&amp;lt;action&amp;gt;&#039;&#039; is one of the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-install&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed before package is installed. Typical use is when package needs a group and a user to be created. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
addgroup -S clamav 2&amp;gt;/dev/null&lt;br /&gt;
adduser -S -D -H -s /bin/false -G clamav -g clamav clamav 2&amp;gt;/dev/null&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note the &#039;&#039;exit 0&#039;&#039; at the end. If the script exits with failure (if the user already exist), the package will not be installed and &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; will exit with failure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-install&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed after the package is installed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-upgrade&lt;br /&gt;
&amp;lt;dd&amp;gt;Same as pre-install but is executed before upgrading/downgrading/reinstalling an already installed package. Note that exiting with failure will not cause apk to exit with failure, but will mark the package as broken.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-upgrade&lt;br /&gt;
&amp;lt;dd&amp;gt;Same as post-install but is executed after upgrading/downgrading/reinstalling an already installed package. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.pre-deinstall&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed before uninstalling a package. If script exits with failure apk will not uninstall the package.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;$pkgname.post-deinstall&lt;br /&gt;
&amp;lt;dd&amp;gt;This script is executed after a package have been uninstalled. For example, can be used to restore busybox links:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
busybox --install -s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the package has a pre-install and post-install script the APKBUILD should have the &#039;&#039;install&#039;&#039; variable defined:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
install=&amp;quot;$pkgname.pre-install $pkgname.post-install&amp;quot;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== subpackages  ====&lt;br /&gt;
&lt;br /&gt;
$subpackages are made to split up the normal &amp;quot;make install&amp;quot; into separate packages. The most common subpackages we use are doc and dev. Because we like to keep our target system small we move documentation and development files (only needed when building packages) into separate packages. To use the specific program a user only need to install the base apk without package-doc or package-dev, but if he wants to read the manual he will need to install package-doc. &lt;br /&gt;
&lt;br /&gt;
The easiest way to find out if you need to use -dev and -doc is to first build the package without these options set and wait until the build finishes. When its finished you should have a pkg directory which is the fake root directory. Inside this directory you will see the structure as how it would be installed in / on the target system. &lt;br /&gt;
&lt;br /&gt;
To see if you need the -dev package you can run the following cmd: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|find pkg/usr/ -name &#039;*.[acho]&#039; -o -name &#039;*.la&#039;}}&lt;br /&gt;
&lt;br /&gt;
If this returns any files you need to include the -dev package. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; To see if you need the -doc package you can run the following cmd: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|find pkg/usr/share -name doc -o -name man -o -name info -o -name html -o -name sgml -o -name licenses}}&lt;br /&gt;
&lt;br /&gt;
If this returns any directories you need to include the -doc package. &lt;br /&gt;
&lt;br /&gt;
===== Custom subpackages  =====&lt;br /&gt;
&lt;br /&gt;
Some software additionally has non-essential files that do not qualify as either documentation or development content. These files should be placed in their own, specialized subpackage(s). Some packages include large test suites which are only needed in specific circumstances or binaries which have depends which we prefer not to install. To handle those we create our own package/function. In the APKBUILD below the build() function we create another function: &lt;br /&gt;
&lt;br /&gt;
 test() {&lt;br /&gt;
        mkdir -p &amp;quot;$subpkgdir&amp;quot;/usr&lt;br /&gt;
        mv &amp;quot;$pkgdir&amp;quot;/usr/package-test &amp;quot;$subpkgdir&amp;quot;/usr/&lt;br /&gt;
        # or amove usr/package-test&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
We also need to add the package info to $subpackages variable: &lt;br /&gt;
&lt;br /&gt;
 subpackages=&amp;quot;$pkgname-doc $pkgname-dev $pkgname-test&amp;quot;&lt;br /&gt;
&lt;br /&gt;
After we finish building the package you should see another apk called packagename-test.apk which includes the files which we moved to the $subpkgdir dir. &lt;br /&gt;
&lt;br /&gt;
The above mentioned variables can also be used in our custom function. If we want for instance to build the test() function with perl support we would add: &lt;br /&gt;
&lt;br /&gt;
 depends=&amp;quot;perl&amp;quot;&lt;br /&gt;
 makedepends=&amp;quot;perl-dev&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If we would install the base package it would not install perl, but if we install the package-test package it would.&lt;br /&gt;
&lt;br /&gt;
==== Patches  ====&lt;br /&gt;
&lt;br /&gt;
Please make sure you always submit human readable patches. Ways to create them are: &lt;br /&gt;
&lt;br /&gt;
directory compare: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|diff -Nurp original_directory new_directory &amp;amp;gt; filename.patch}}&lt;br /&gt;
&lt;br /&gt;
file compare: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|diff -up original.file new.file &amp;amp;gt; filename.patch}}&lt;br /&gt;
&lt;br /&gt;
If a patch contains a completely new file but not *.rej or *.orig file, you need to add -N option to diff, but you may need to add exclusions with &amp;lt;code&amp;gt;--exclude PATTERN&amp;lt;/code&amp;gt; so that you do not inadvertently add files.  You may need to manually delete unwanted files inside the patch file.&lt;br /&gt;
&lt;br /&gt;
Because multiple patches can patch the same file, they can change the offsets required by subsequent patches. To make sure we always patch in a specific way, we should number the patches as follows: &lt;br /&gt;
&lt;br /&gt;
 10-patch1.patch 20-patch2.patch 30-patch3.patch&lt;br /&gt;
&lt;br /&gt;
This way we are always sure that patch 1 is applied first, and if we want to add additional patches between them we can use appropriate indexes (e.g. 11, 12, 21, 22).&lt;br /&gt;
&lt;br /&gt;
Add the names of the patch files to the &#039;&#039;source&#039;&#039; variable. If you haven&#039;t declared a custom &#039;&#039;prepare&#039;&#039; function, no further action is necessary. Otherwise, be sure to call &#039;&#039;default_prepare&#039;&#039; in your &#039;&#039;prepare&#039;&#039; function. For example:&lt;br /&gt;
&lt;br /&gt;
 prepare() {&lt;br /&gt;
 	default_prepare&lt;br /&gt;
 &lt;br /&gt;
 	# do your stuff&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note: Some older packages contain a &#039;&#039;for&#039;&#039; loop in the &#039;&#039;prepare&#039;&#039; function to apply patches. This is not needed anymore, as patches are handled by &#039;&#039;default_prepare&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In Alpine &amp;gt;=3.4 you can define patch_args to supply the patch level.  This only works if all the patches have the same patch level.  If there are a lot of patches from different sources, there is a good chance that you may need to edit them, as discussed below.&lt;br /&gt;
&lt;br /&gt;
To automatically patch the package (available only in Alpine &amp;gt;=3.4) if it uses a patch level (-pX) other than the default (-p1), you need to carefully modify the patch.  First, you&#039;ll need a text editor that does not automatically convert  between Windows and Unix new lines (or, disable this feature) so that it preserves the old code.  The next thing you&#039;ll need to do is modify the paths on &amp;quot;+++&amp;quot; and &amp;quot;---&amp;quot; lines in the .patch file.  You can begin the path with a/ and b/ like shown below.  Next, you need to adjust the paths so that the relative base path is from inside $builddir.  Anything to the left of $builddir, including $builddir itself, needs to be removed from the path.  So, if $builddir is /home/USER/aports/community/chromium/src/chromium-65, you need to erase it on the &amp;quot;+++&amp;quot; and &amp;quot;---&amp;quot; lines.  Inside the chromium-65 folder you can see a src folder that has 3rdparty as a descendant.  If a patch originally has a deeper patch level, you may need to fill in the missing portion of the path.  For example, use the &amp;lt;code&amp;gt;find . -name &amp;quot;Assertions.cpp&amp;quot;&amp;lt;/code&amp;gt; command to find the full path to the file relative to the base.&lt;br /&gt;
&lt;br /&gt;
{{Cat|example.patch|&amp;lt;nowiki&amp;gt;&lt;br /&gt;
Author: John Doe &amp;lt;johndoe@mail.com&amp;gt;&lt;br /&gt;
URL: http://.....&lt;br /&gt;
Summary: Fixes musl compatibility&lt;br /&gt;
----&lt;br /&gt;
--- a/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp.orig&lt;br /&gt;
+++ b/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp&lt;br /&gt;
@@ -142,7 +142,7 @@&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 FrameToNameScope::FrameToNameScope(void* addr) : m_name(0), m_cxaDemangled(0) {&lt;br /&gt;
-#if OS(MACOSX) || (OS(LINUX) &amp;amp;&amp;amp; !defined(__UCLIBC__))&lt;br /&gt;
+#if OS(MACOSX) || (OS(LINUX) &amp;amp;&amp;amp; defined(__GLIBC__))&lt;br /&gt;
   Dl_info info;&lt;br /&gt;
   if (!dladdr(addr, &amp;amp;info) || !info.dli_sname)&lt;br /&gt;
return;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Portions of the patch may be outdated, removed completely as in the source code file completely removed, or moved or renamed files.  You need to delete that section of the patch or find where that section of code changed and re-diff it.&lt;br /&gt;
&lt;br /&gt;
It is good etiquette to give credit at the top and the location of where you originally found them with notes.&lt;br /&gt;
&lt;br /&gt;
Excluding patches with global variable resembling patch_opts is not available on Alpine.  To exclude patches you need to create your own custom prepare().&lt;br /&gt;
&lt;br /&gt;
If you have a monolithic patch where there are a bunch of patches in one big patch, you could use filterdiff which is available in the patchutils package.&lt;br /&gt;
&lt;br /&gt;
Just do something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
makedepends=&amp;quot;patchutils&amp;quot;&lt;br /&gt;
&lt;br /&gt;
prepare() {&lt;br /&gt;
  ...&lt;br /&gt;
  cd &amp;quot;$builddir&amp;quot;&lt;br /&gt;
  filterdiff -x &#039;*drivers/video/logo*&#039; &amp;quot;$srcdir&amp;quot;/original.patch &amp;gt; &amp;quot;$builddir&amp;quot;/modified.patch&lt;br /&gt;
  patch -p1 -i &amp;quot;$builddir&amp;quot;/modified.patch&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to put the wildcard pattern in single quotes for it to work.&lt;br /&gt;
&lt;br /&gt;
==== Configure options  ====&lt;br /&gt;
&lt;br /&gt;
Alpine has some default configure options we set by default. We use /usr for prefix to make sure everything is installed with /usr in front of it. If you notice that anything is installed in the wrong directory please run {{Cmd|./configure --help}} and see if you can set the correct location. &lt;br /&gt;
&lt;br /&gt;
We are not covering the depend switches here we have discussed this already in the depend section.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Make options  ====&lt;br /&gt;
&lt;br /&gt;
If you notice weird problems when compiling or installing the package with make/make install you could try to disable [http://www.gnu.org/software/make/manual/make.html#Parallel parallel] building/installing. A normal make line would be: &lt;br /&gt;
&lt;br /&gt;
 make&lt;br /&gt;
&lt;br /&gt;
To disable parallel we use: &lt;br /&gt;
&lt;br /&gt;
 make -j1&lt;br /&gt;
&lt;br /&gt;
We can use the same for make install. &lt;br /&gt;
&lt;br /&gt;
Because we do not want to install the package in our build environment but we want to install it in a fake root directory we need to tell &#039;make install&#039; to use another destination directory instead of &#039;/&#039;. We do this by setting a variable when we execute make install as followed: &lt;br /&gt;
&lt;br /&gt;
 make DESTDIR=&amp;quot;$pkgdir&amp;quot; install&lt;br /&gt;
&lt;br /&gt;
Please note that some Makefiles do not support this variable and will always install software in &#039;/&#039;. To make sure you do not mess up your build system NEVER run your build system as root but always use a custom user and doas when needed. If by accident the Makefile does not support DESTDIR variable it will fail to install in our build system system directories.&lt;br /&gt;
&lt;br /&gt;
==== builddir ====&lt;br /&gt;
If you used &amp;lt;tt&amp;gt;newapkbuild&amp;lt;/tt&amp;gt; to create your APKBUILD file, you must specify the path to your unpacked sources. Inside the sections during the prepare/build/install process &#039;&#039;builddir&#039;&#039; is used. Most of the time a combination of &#039;&#039;$srcdir&#039;&#039; and &#039;&#039;$pkgname-$pkgver&#039;&#039; will work. When not, check the /src directory or the source tarball for the right string. Especially when you are working with automatically generated tarballs (like from github and gitorious), this needs to be adjusted.&lt;br /&gt;
&lt;br /&gt;
builddir=&amp;quot;$srcdir&amp;quot;/$pkgname-$pkgver&lt;br /&gt;
&lt;br /&gt;
==== Additional files  ====&lt;br /&gt;
&lt;br /&gt;
If you want/need to install additional files not mentioned above you can use the following cmd (this is an example of a conf file): &lt;br /&gt;
&lt;br /&gt;
 install -Dm644 doc/$pkgname.conf &amp;quot;$pkgdir&amp;quot;/etc/$pkgname.conf&lt;br /&gt;
&lt;br /&gt;
== Build the package  ==&lt;br /&gt;
&lt;br /&gt;
If you did not already create the checksums as mentioned above you can do so now: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $pkgname&lt;br /&gt;
abuild checksum}}&lt;br /&gt;
&lt;br /&gt;
It&#039;s about time we build our package. Because a build system should never have all the package installed to prevent linking to packages we don&#039;t want it to link we use a abuild recursively with the &#039;&#039;&#039;-r&#039;&#039;&#039; switch. It will install all dependencies from your repository and builds it, afterwards it will uninstall all those depending packages again.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|abuild -r}}&lt;br /&gt;
&lt;br /&gt;
See also [[Abuild_and_Helpers|Abuild and Helpers]].&lt;br /&gt;
&lt;br /&gt;
== Testing the package locally ==&lt;br /&gt;
&lt;br /&gt;
When it completes, your package will be found in a subfolder of &amp;lt;code&amp;gt;~/packages&amp;lt;/code&amp;gt;.  You may want to test it on your machine but only if the package is not a critical system package like musl or apk-tools package.  To avoid borking your system (as in making it impossible to use &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; or to restore back the system and the compiler toolchain) for a critical system package, you should test on a chroot first before using it live.&lt;br /&gt;
&lt;br /&gt;
The best way to test a package locally is to modify your &amp;lt;code&amp;gt;/etc/apk/repositories&amp;lt;/code&amp;gt; so that it includes the indexes to your locally built packages - the directories that contain &amp;lt;code&amp;gt;ARCH/APKINDEX.tar.gz&amp;lt;/code&amp;gt;. For example the &amp;lt;code&amp;gt;/etc/apk/repositories&amp;lt;/code&amp;gt; below includes locally built packages in testing, community and main. To use this example change &amp;lt;code&amp;gt;USER&amp;lt;/code&amp;gt; to your login name.&lt;br /&gt;
&lt;br /&gt;
{{Cat|/etc/apk/repositories|/home/USER/packages/testing/&lt;br /&gt;
/home/USER/packages/main/&lt;br /&gt;
/home/USER/packages/community/&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/main&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/community&lt;br /&gt;
https://dl-cdn.alpinelinux.org/alpine/edge/testing&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
If you prefer to test a package without changing any other configuration you can use the &amp;lt;code&amp;gt;-X, --repository&amp;lt;/code&amp;gt; option to &amp;lt;code&amp;gt;apk&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|doas apk add --repository /home/USER/packages/testing $pkgname}}&lt;br /&gt;
&lt;br /&gt;
== Code review ==&lt;br /&gt;
&lt;br /&gt;
To successfully have your package pass through code reviewers (as of Feb 18, 2018 are nmeum and jirutka on GitHub) and possible increased acceptance, the following conventions need to be followed:&lt;br /&gt;
&lt;br /&gt;
# Custom global variables should be prefixed with underscore (_).&lt;br /&gt;
# Compact code as in merged commands, removed unused variables, removal of functions that do the same thing that are automatically handled by abuild.&lt;br /&gt;
# Versioning is done properly.  For details see [[APKBUILD_Reference#pkgver]].&lt;br /&gt;
# Licensing is done properly. Remove unnecessary copying of licensing that is already OSI approved.&lt;br /&gt;
# Naming conventions rules for unofficial variables as in _gitrev is preferred over commit.&lt;br /&gt;
# Indent with tabs not spaces.&lt;br /&gt;
# Removal of explicit return 1.  (They are still found the old APKBUILD files if you are learning but are now strongly discouraged.)&lt;br /&gt;
# Disabling check() requires either (1) a comment (#) stating next to options=&amp;quot;!check&amp;quot; that there is no test suite/unit tests or (2) functioning working check() function.&lt;br /&gt;
# Explicit call to subpackages=&amp;quot;$pkgname-doc&amp;quot; must be used instead of explicit gzip man page compression.&lt;br /&gt;
# Ideally, lines should be no more than 80 columns wide&lt;br /&gt;
&lt;br /&gt;
Additionally, make sure to run the linter on your package:&lt;br /&gt;
{{Cmd|doas apk add atools&lt;br /&gt;
apkbuild-lint APKBUILD}}&lt;br /&gt;
&lt;br /&gt;
For more information see [[Development using git:Quality assurance]] and [[Package_policies]].&lt;br /&gt;
&lt;br /&gt;
== Commit your work  ==&lt;br /&gt;
&lt;br /&gt;
After you successfully build your package and properly followed the conventions and requirements in the code review section, you can submit your APKBUILD to Alpine&#039;s git repository. &lt;br /&gt;
&lt;br /&gt;
Update your git repo, before adding new files: &lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $aportsdir&lt;br /&gt;
git pull}}&lt;br /&gt;
&lt;br /&gt;
This should pull all the changes made by others into your local git repo.&lt;br /&gt;
&lt;br /&gt;
When you think you are ready you can add your files to git: &lt;br /&gt;
&lt;br /&gt;
NOTE: when using our Gitlab instance, you can create MR&#039;s for each package. Please squash all commits related to the same package into a single one per MR.&lt;br /&gt;
&lt;br /&gt;
{{Cmd|cd $aportsdir&lt;br /&gt;
git add testing/$pkgdir (include any other files needed for the build; $pkgname.install...)&lt;br /&gt;
git commit}}&lt;br /&gt;
&lt;br /&gt;
Use the following commit message template for new aports (without the comments):&lt;br /&gt;
&lt;br /&gt;
{{Cat|template|testing/$pkgname: new aport   # this will be the subject line&lt;br /&gt;
                              # a blank line&lt;br /&gt;
$url                          # project homepage&lt;br /&gt;
$pkgdesc                      # one line description}}&lt;br /&gt;
&lt;br /&gt;
Or you could add the following and &amp;lt;code&amp;gt;chmod +x ports/.git/hooks/prepare-commit-msg&amp;lt;/code&amp;gt; to automatically generate commit message which the default aports/.githooks/ does not:&lt;br /&gt;
&lt;br /&gt;
{{Cat|aports/.git/hooks/prepare-commit-msg|&amp;lt;nowiki&amp;gt;#!/bin/sh&lt;br /&gt;
case &amp;quot;$2,$3&amp;quot; in&lt;br /&gt;
  ,|template,)&lt;br /&gt;
    if git diff-index --diff-filter=A --name-only --cached HEAD \&lt;br /&gt;
        | grep -q &#039;/APKBUILD$&#039;; then&lt;br /&gt;
      meta() { git diff --staged | grep &amp;quot;^+$1&amp;quot; | sed &#039;s/.*=&amp;quot;\?//;s/&amp;quot;$//&#039;;}&lt;br /&gt;
      printf &#039;testing/%s: new aport\n\n%s\n%s\n&#039; &amp;quot;$(meta pkgname)&amp;quot; \&lt;br /&gt;
        &amp;quot;$(meta url)&amp;quot; &amp;quot;$(meta pkgdesc)&amp;quot; &amp;quot;$(cat $1)&amp;quot; &amp;gt; &amp;quot;$1&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      printf &#039;%s\n\n%s&#039; `git diff-index --name-only --cached HEAD \&lt;br /&gt;
        | sed -n &#039;s/\/APKBUILD$//p;q&#039;` &amp;quot;$(cat $1)&amp;quot; &amp;gt; &amp;quot;$1&amp;quot;&lt;br /&gt;
    fi;;&lt;br /&gt;
esac&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Now your changes are only available locally in your repository.&lt;br /&gt;
&lt;br /&gt;
Because you do not have push rights to the Alpine aports repository you need to create a merge request to [https://gitlab.alpinelinux.org/alpine/aports Alpine&#039;s GitLab instance].&lt;br /&gt;
&lt;br /&gt;
Alternatively you can also create a diff (patch) of the changes you made and send this patch to the &lt;br /&gt;
[https://lists.alpinelinux.org/~alpine/aports  alpine-aports mailinglist].&lt;br /&gt;
&lt;br /&gt;
To create a diff patch:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|git format-patch HEAD^}}&lt;br /&gt;
&lt;br /&gt;
or if you have sprunge, you can create a link to your patch for convenience&lt;br /&gt;
&lt;br /&gt;
{{Cmd|git format-patch HEAD^ --stdout &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; sprunge}}&lt;br /&gt;
&lt;br /&gt;
== Send a patch ==&lt;br /&gt;
&lt;br /&gt;
[[Creating_patches#Only_the_last_commit_with_.27git_send-email.27|git send-email]] will do that for you.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[APKBUILD Reference]]&lt;br /&gt;
* [[APKBUILD examples]]&lt;br /&gt;
* [[Development using git]]&lt;br /&gt;
* [[Development using git:Quality assurance]]&lt;br /&gt;
&lt;br /&gt;
[[category: Package Manager]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Alpine_Linux:Contribute&amp;diff=22668</id>
		<title>Alpine Linux:Contribute</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Alpine_Linux:Contribute&amp;diff=22668"/>
		<updated>2022-11-18T11:42:32Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Remove old bugs e-mail address&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:kuser.png|left|link=]]&lt;br /&gt;
__NOTOC__&lt;br /&gt;
There are many ways that &#039;&#039;you&#039;&#039; can contribute. Whether you are a normal user, a geek, or a hardcore developer, the one and most important thing you can do is to actually &#039;&#039;&#039;use&#039;&#039;&#039; Alpine Linux.&lt;br /&gt;
&lt;br /&gt;
The list below explains some of the ways that you can contribute.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Contribute quality =&lt;br /&gt;
* Submit &#039;&#039;&#039;[https://gitlab.alpinelinux.org/alpine/aports/issues bug reports]&#039;&#039;&#039;.&lt;br /&gt;
* Suggest new &#039;&#039;&#039;[https://gitlab.alpinelinux.org/alpine features/ideas]&#039;&#039;&#039; (Previously: &#039;&#039;&#039;[[Project:Ideas|features/ideas]]&#039;&#039;&#039; and &#039;&#039;&#039;[[FAQ#Can_you_build_an_apk_package_for_....3F|packages]]&#039;&#039;&#039;)&lt;br /&gt;
* Submit new &#039;&#039;&#039;[[Creating_an_Alpine_package|packages]]&#039;&#039;&#039; that you&#039;ve created, or &#039;&#039;&#039;[[Development using git|patches]]&#039;&#039;&#039; to existing packages. For more information about developing on Alpine Linux, read our [[Developer Documentation]].&lt;br /&gt;
* Submit &#039;&#039;&#039;[[Special:NewFiles|artwork]]&#039;&#039;&#039; (icons, backgrounds, logos)&lt;br /&gt;
* Correct &#039;&#039;&#039;spelling and grammar&#039;&#039;&#039; mistakes in the documentation&lt;br /&gt;
* Help &#039;&#039;&#039;[[Project:Wiki_maintenance|maintain]]&#039;&#039;&#039; the wiki&lt;br /&gt;
&lt;br /&gt;
= Contribute documentation =&lt;br /&gt;
* Help write good &#039;&#039;&#039;[[Tutorials_and_Howtos|documentation]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Translate&#039;&#039;&#039; the documentation (and program texts) into another language&lt;br /&gt;
* &#039;&#039;&#039;Proofread&#039;&#039;&#039; existing documentation, follow the examples, and make corrections&lt;br /&gt;
* Create diagrams, &#039;&#039;&#039;screenshots&#039;&#039;&#039;, and graphics for the documentation&lt;br /&gt;
* Develop style, formatting, spelling, and grammar conventions for documenters&lt;br /&gt;
* Expand the &#039;&#039;&#039;[[Glossary]]&#039;&#039;&#039; of technical terms (so non-geeks can understand)&lt;br /&gt;
* Convert documentation into more formats&lt;br /&gt;
&lt;br /&gt;
= Contribute support =&lt;br /&gt;
* &#039;&#039;&#039;Answer questions&#039;&#039;&#039; on the wiki, [[mailing lists]], [[IRC]] channels and [http://stackoverflow.com/questions/tagged/alpine StackOverflow]&lt;br /&gt;
* Contribute to (or start) an online support group&lt;br /&gt;
* Post a tutorial or other to https://asciinema.org&lt;br /&gt;
* Write &#039;&#039;&#039;HOWTOs&#039;&#039;&#039; and post them in the [[Tutorials and Howtos]] or your own blog&lt;br /&gt;
&lt;br /&gt;
= Contribute projects = &lt;br /&gt;
* [[Wishlist]]&lt;br /&gt;
&lt;br /&gt;
= Contribute publicity =&lt;br /&gt;
{{Tip|As Alpine Linux gets more popular, there will be more people wanting to contribute.}}&lt;br /&gt;
* &#039;&#039;&#039;[[Project:Listings|Link to]]&#039;&#039;&#039; the Alpine Linux web site&lt;br /&gt;
* Write &#039;&#039;&#039;reviews&#039;&#039;&#039;&lt;br /&gt;
* Convince people to choose Open Source products when possible&lt;br /&gt;
* Write about new ways of using an Open Source application&lt;br /&gt;
&lt;br /&gt;
= Contribute appreciation =&lt;br /&gt;
* Be &#039;&#039;&#039;polite&#039;&#039;&#039; when reporting bugs or asking for new features; after all, the developers have no obligation to do it&lt;br /&gt;
* &#039;&#039;&#039;Express&#039;&#039;&#039; your appreciation to developers (through [[Mailing_lists|e-mail]], [https://gitlab.alpinelinux.org/alpine/aports/issues bug reports], and [[Alpine Linux:IRC|IRC]])&lt;br /&gt;
* Send the programmers post cards&lt;br /&gt;
* Give the project or [[Alpine_Linux:Developers|a developer a donation/gift]] (some have wish lists for this)&lt;br /&gt;
* Contribute to [https://www.patreon.com/musl musl libc development].&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Alpine_Linux:Wiki_maintenance&amp;diff=22329</id>
		<title>Alpine Linux:Wiki maintenance</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Alpine_Linux:Wiki_maintenance&amp;diff=22329"/>
		<updated>2022-09-18T13:26:05Z</updated>

		<summary type="html">&lt;p&gt;Ikke: Fix links for &amp;#039;pagest that&amp;#039; (thanks sliwkr)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== [[Special:SpecialPages|Special Pages]] ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Hey, [[User:Dubiousjim/Special|where did the link to the SpecialPages in the Sidebar go]]?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Click the header above to go to the original page.&lt;br /&gt;
&lt;br /&gt;
== Pages ==&lt;br /&gt;
* [[Special:NewPages|New]] or [[Special:PrefixIndex|all]] &amp;lt;!-- [[Special:AllPages]] --&amp;gt; pages&lt;br /&gt;
* Most: &amp;lt;!-- [[Special:PopularPages|viewed]] --&amp;gt; [[Special:MostLinkedPages|linked-to]] [[Special:MostRevisions|revised]] pages&lt;br /&gt;
* Redirects: [[Special:ListRedirects|all]] [[Special:BrokenRedirects|broken]] [[Special:DoubleRedirects|double]]&lt;br /&gt;
* [[Special:LinkSearch|What pages link to offsite url]] ___?&lt;br /&gt;
* Pages that:&lt;br /&gt;
** [[Special:WhatLinksHere/Template:Delete|are proposed for deletion]] ([[Special:Nuke|bulk delete]])&lt;br /&gt;
** [[Special:WhatLinksHere/Template:Obsolete|are obsolete]]&lt;br /&gt;
** [[Special:WhatLinksHere/Template:Merge|are proposed for merging]] ([[Special:MergeHistory|merge histories]])&lt;br /&gt;
** [[Special:WhatLinksHere/Template:Move|are proposed for moving]]&lt;br /&gt;
** [[Special:WhatLinksHere/Template:Draft|are drafts]]&lt;br /&gt;
** [[Special:WhatLinksHere/Template:Expand|need expanding]] ([[Special:ShortPages|short pages]])&lt;br /&gt;
** [[Special:WhatLinksHere/Template:Style|need style improvements]]&lt;br /&gt;
** [[Special:UncategorizedPages|have no category]]&lt;br /&gt;
** [[Special:LonelyPages|are orphaned]]&lt;br /&gt;
** [[Special:WantedPages|are wanted]]&lt;br /&gt;
** [[Special:ProtectedPages|are protected]] ([[Special:PagesWithProp|other properties]])&lt;br /&gt;
** [[Special:DeadendPages|have no links to other pages]]&lt;br /&gt;
&lt;br /&gt;
== Files/Images ==&lt;br /&gt;
* [[Special:NewFiles|New]] or [[Special:ListFiles|all]] files&lt;br /&gt;
* Files that:&lt;br /&gt;
** [[Special:UncategorizedFiles|have no category]]&lt;br /&gt;
** [[Special:UnusedFiles|are orphaned]]&lt;br /&gt;
** [[Special:WantedFiles|are wanted]]&lt;br /&gt;
** [[Special:ListDuplicatedFiles|are duplicates]]&lt;br /&gt;
&lt;br /&gt;
== Templates ==&lt;br /&gt;
* [[Special:MostTranscludedPages|Used]] or [[Special:AllPages/Template:|all]] templates&lt;br /&gt;
* Templates that:&lt;br /&gt;
** [[Special:UnusedTemplates|are unused]]&lt;br /&gt;
** [[Special:WantedTemplates|are wanted]]&lt;br /&gt;
* [[Special:ExpandTemplates|Sandbox]]&lt;br /&gt;
&lt;br /&gt;
== Categories ==&lt;br /&gt;
* Categories that:&lt;br /&gt;
** [[Special:AllPages/Category:|are described]]&lt;br /&gt;
** [[Special:Categories|are used]]&lt;br /&gt;
** [[Special:UnusedCategories|are unused]]&lt;br /&gt;
** [[Special:WantedCategories|are wanted]]&lt;br /&gt;
&lt;br /&gt;
* Uncategorized: [[Special:UncategorizedPages|pages]] [[Special:UncategorizedFiles|files]]&lt;br /&gt;
&lt;br /&gt;
== Wanted and Orphaned ==&lt;br /&gt;
* Wanted: [[Special:WantedPages|pages]] [[Special:WantedFiles|files]] [[Special:WantedTemplates|templates]] [[Special:WantedCategories|categories]] &lt;br /&gt;
* Orphaned: [[Special:LonelyPages|pages]] [[Special:UnusedFiles|files]]&lt;br /&gt;
* Unused: [[Special:UnusedTemplates|templates]] [[Special:UnusedCategories|categories]]&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
&lt;br /&gt;
* [[Special:ActiveUsers|Active]] or [[Special:ListUsers|all]] users&lt;br /&gt;
* [[Special:ListGroupRights|User privileges]]&lt;br /&gt;
* [[Project:Developers|Developers]]&lt;br /&gt;
* [[Special:ComparePages|Compare pages]]&lt;br /&gt;
&lt;br /&gt;
* Wiki [[Special:Log|logs]] [[:Category:Wiki|help]] | [[Special:Version|version]] [https://www.mediawiki.org/wiki/Help:Contents userman] ([https://meta.wikimedia.org/wiki/Help:Contents older]) [https://www.mediawiki.org/wiki/Manual:Contents adminman]&lt;br /&gt;
* Project [[Project:Overview|overview]] [[Alpine Linux:Releases|releases]] [http://pkgs.alpinelinux.org/packages packages] [[Special:AllPages/Alpine Linux:|pages]] [[glossary]]&lt;br /&gt;
* Project [http://alpinelinux.org/ news] [http://git.alpinelinux.org/ git] [http://bugs.alpinelinux.org/?query_id=15 bugs] [http://bugs.alpinelinux.org/projects/alpine/activity activity]&lt;br /&gt;
&lt;br /&gt;
* [http://bugs.alpinelinux.org/projects/alpine/roadmap Roadmap] | Older ideas: [[Talk:Tutorials_and_Howtos|1]] [[Wishlist|2]] [[Project:Ideas|3]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Wiki]]&lt;/div&gt;</summary>
		<author><name>Ikke</name></author>
	</entry>
</feed>