Alpine Linux

Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox.

In our home computers , i installed this OS to homepc2 along with Arch . I have also configured it such that both are identical in almost all functionalities. I intend to use this with pi instead of the default OS in it.

A few months back i.e around mid-april 2025, totally nuked the Arch installation.

The biggest negative is that proprietary software will not work on Alpine, unless the binary is released by the vendor for Alpine Linux.

For the above issue, a debian chroot has been configured with bwrap by following the Alpine Wiki. Tested working with VS Code, Obsidian, google-chrome etc..

Taking an inspiration from Arch wiki, i have been updating Alpine Wiki ↗ as part of giving back something to the community.

Found that gcompat can provide a compatibility to glibc and tested to find that it really works. I have updated the wiki of Alpine Linux mainly by re-organizing and existing content.

The configuration in Alpine is nearly identical to earlier setup i.e swaywm , hugo_server , rsync , rclone , btrfs filesystem with btrbk , Refind , Emacs , Beancount etc.

I have managed to get the Canon LBP2900 also configured manually as no package exists for it in Alpine Linux. As of 2024-12-04, Canon installation is not complete. At some point, the manual driver installation was completed drivers works great here.

Installed shotwell as lightweight photo manager to view timeline based photos.

replaced cronie by dcron

Earlier i was using anacron from cronie for running backup for btrbk and Beancount . However, recently understood that dcron does this elegantly with @daily directive.

So moved the entries in etc/anacrontab to /var/spool/cron/crontabs/root as follows:

# min   hour    day     month   weekday ID 			command
*/15    *       *       *       *       			run-parts /etc/periodic/15min
@hourly         			ID=periodic.hourly      run-parts /etc/periodic/hourly
@daily          			ID=periodic.daily       run-parts /etc/periodic/daily
@weekly         			ID=periodic.weekly      run-parts /etc/periodic/weekly
@monthly        			ID=periodic.monthly     run-parts /etc/periodic/monthly
@daily 					ID=daily-btrbk		sleep 420 && /usr/bin/btrbk -q -c /etc/btrbk/btrbk.conf run
@daily					ID=daily-beanbk		sleep 240 && /data/myhome/prabu/linux_config/scripts/backup_beancount 2>&1 | logger -t daily-beanbk
@weekly					ID=weekly-fstrim	sleep 720 && /sbin/fstrim -v /mnt/btrfs 2>&1 | logger -t weekly-fstrim

sending emails meant for root to gmail

To send and receive emails meant for root to a gmail account, installed and configured msmtp as MTA/SMTP client and mailx as mail user agent(MUA). Configured msmtp by copying the /etc/msmtprc from Openwrt .

$ cat /etc/aliases
root: kXXXX@gmail.com
$ ls -l /usr/sbin/sendmail
lrwxrwxrwx    1 root     root            14 Oct 10 14:15 /usr/sbin/sendmail -> /usr/bin/msmtp*
$ ls -l /etc/msmtprc
-rw-------    1 root     root          1580 Oct 10 14:11 /etc/msmtprc

Using edge as a tagged repository

Initially kept edge main and community as tagged repositories along with stable as apk-tools v3 was in edge only during mid'25.

Found the following solution to install a package without enabling the repository in IRC:

# apk add --repository=https://dl-cdn.alpinelinux.org/alpine/edge/main apk-tools

Well the above option fails, when time for upgrade comes. The package automatically goes to the untagged repository. So i restored back edge in /etc/apk/repositories and due to various other issues, went back to apk-tools v2 and removed the edge repositories.

OS upgrades

On 2024-12-04, the first OS upgrade from 3.20 to 3.21 was done. Followed the progress through RC1 to RC5 as based on wiki instructions using sed to change the version in /etc/apk/repositories file.

On 2025-05-30 the OS upgrade from 3.21 to 3.22 went through smoothly.

Earlier used a upgrade driver for the above adapter in Arch . When i moved to Alpine Linux it was working out of the box, so never bothered until today. Unable to connect from any android mobile as in termux arp it shows as “incomplete wlan0”.

On further troubleshooting found that the default driver rtl8xxxu has this known behavior of not working with Android mobiles.

After installing the driver from https://github.com/clnhub/rtl8192eu-linux ↗ the issue got resolved.

TL-WN823Nv2/v3 is supported by the above driver.

[Sat Aug 23 13:28:27 2025] 8192eu: loading out-of-tree module taints kernel.
[Sat Aug 23 13:28:27 2025] 8192eu: module verification failed: signature and/or required key missing - tainting kernel
[Sat Aug 23 13:28:27 2025] usbcore: registered new interface driver rtl8192eu

The loading of the driver was automated using the below script:

cat /etc/modprobe.d/rtl8192eu.conf
# Blacklist conflicting drivers
blacklist rtl8xxxu
# Auto-load new driver
install rtl8192eu /sbin/modprobe --ignore-install 8192eu

However still the WiFi module loading failed when kernel got upgraded. So added a script to recompile and load the driver was added as apk commit-hook

ls -l /etc/apk/commit_hooks.d/rebuild-rtl8192eu
-rwxr-xr-x 1 root root 1129 Aug 28 10:15 /etc/apk/commit_hooks.d/rebuild-rtl8192eu*

Convert sys mode to diskless

  1. Set media name to save apkvol in the /etc/lbu/lbu.conf file LBU_MEDIA=mmcblk0p1 (Replace mmcblk0p1 with the correct partition name.)
  2. Configure /etc/fstab for Diskless Operation
    • Ensure the media partition (LBU_MEDIA) is listed with noauto.
    • Prevent it from being mounted read-write elsewhere.
    • Example: If the media was previously used for /boot. Update /etc/fstab:
      • UUID=E8C9-4979 /boot vfat noauto,ro,relatime,fmask=0022,dmask=0022,errors=remount-ro 0 2
      • UUID=E8C9-4979 /media/mmcblk0p1 vfat noauto,ro 0 0
    • Note: If /boot partition is FAT and was previously mounted automatically, no additional changes are needed for booting the diskless OS.
  3. Mount Root (/) Filesystem as Read-Only. Update /etc/fstab:
    • UUID=8e293498-41d6-4d3a-9832-fb4d3334dcc9 / ext4 ro,relatime 0 1
  4. Include Additional Files for Persistence outside of etc folder using lbu include command
  5. Commit Changes & Create apkvol using the command $doas lbu commit
  6. Reboot the pi into Diskless Mode .. $doas reboot

update packages.. or upgrade to newer release or update kernel..

  1. Remount (/) root and /boot(mandatory if kernel update is involved) as Read-Write

    • $doas mount -o remount,rw /
    • $doas mount -o remount,rw /boot
  2. Perform Updates finish updating of packages/kernel change or configure files

  3. Synchronize Disk Writes $doas sync

  4. Remount as Read-Only

    • $doas mount -o remount,ro /
    • $doas mount -o remount,ro /boot
  5. Commit Changes to apkvol $lbu commit

  6. Reboot $doas reboot

    For unbound following additional changes made Added roothints as per alpine linux wiki Update /etc/resolv.conf to use Unbound locally doas sh -c ’echo -e “nameserver 127.0.0.1\nsearch lan” > /etc/resolv.conf'

prabu@pizero2w ~> cat /etc/resolv.conf nameserver 127.0.0.1 search lan Prevent /etc/resolv.conf from being overwritten doas chattr +i /etc/resolv.conf doas chattr -i /etc/resolv.conf (to update later)

on the homepc2, the following changes made

Solution 1: Disable DHCP-provided DNS in iwd NameResolvingService=none # <— Change this from resolvconf to none Adjust resolvconf.conf (Preferred)

Edit /etc/resolvconf.conf to control what openresolv writes:

resolv_conf=/etc/resolv.conf name_servers=192.168.1.3 name_servers_only=yes # <— Add this line

The name_servers_only=yes directive ensures only your specified DNS servers (192.168.1.3) are listed.

Then, regenerate /etc/resolv.conf: $ doas resolvconf -u

In case of any issues in 192.168.1.3, just change the main.conf file and restart iwd: NameResolvingService=resolvconf # <— Change this from none to resolvconf prabu@homepc2 ~> doas service iwd restart prabu@homepc2 ~> cat /etc/resolv.conf

search lan nameserver 192.168.1.3 nameserver 192.168.1.1

To update local git to match upstream

When working with aports below is a typical configuration.

$git remote -v
origin    git@gitlab.alpinelinux.org:prabuanand/aports.git (fetch)
origin    git@gitlab.alpinelinux.org:prabuanand/aports.git (push)
upstream    https://gitlab.alpinelinux.org/alpine/aports.git (fetch)
upstream    https://gitlab.alpinelinux.org/alpine/aports.git (push)

Here are the complete steps for rebase operation. Ensure upstream is updated and rebase your local master onto upstream/master as follows:

Core Sync Steps (Always First) This ensures your local copy knows about the newest commits on the official server.

$git fetch upstream
$git checkout master

When there are local commits that should not be lost..

$git rebase upstream/master
$git push --force-with-lease origin master

The first command REPLAYS your unique local commits on top of the new, official history from upstream/master. 2nd command UPDATES your remote fork (origin). The –force-with-lease is mandatory because the rebase rewrites history (creating new commits for your local changes).

when you have NO local commits, the last step pushes to own fork.

$git reset --hard upstream/master
$git push origin master

Summary of commands for feature branch workflow for aports:

  1. Sync master Update your local master branch with the latest from the official upstream.

    $ git fetch upstream
    $ git reset --hard upstream/master
    

    Ensures your new work starts from the very latest code base. (Use this since you never commit to master).

  2. Create Branch Create a new, descriptive branch for your specific task (e.g., pkg-refind-0.14.3).

    $ git checkout -b new-feature-name
    

    Isolates your work. If you mess up, you just delete the branch without affecting master.

  3. Develop Make your changes and commit them locally.

    $ git commit -m "..."
    

    You can commit as many times as you need for your changes.

  4. Rebase (Crucial Prior to Push) Before submitting the MR, ensure your branch is up-to-date with upstream/master.

    $ git rebase master (If necessary: git rebase upstream/master)
    

    This is the crucial step that creates the clean, linear history required for a clean merge/MR.

  5. Push to Fork Push your feature branch to your personal fork (origin).

    $ git push origin new-feature-name
    

    Makes the branch visible on GitLab so you can create the MR.

  6. Submit MR Go to GitLab and submit a Merge Request from your new branch into the upstream/master branch. (Web UI action) This allows the maintainers to review, test, and accept your changes.

  7. Cleanup After the MR is merged, delete the remote and local feature branches.

    $ git push origin --delete new-feature-name
    $ git branch -d new-feature-name
    

    Keeps your repository clean and tidy.

Contributing to aports

Summary of workflow

A Git fork is a personal copy of a repository. Your fork lives on your GitLab account (prabuanand/aports.git) and serves as your central workspace for all your changes. You can create multiple branches within this single fork for different tasks.

For each new aport you want to contribute, you should create a new branch from your fork’s master branch. This keeps each contribution isolated and prevents conflicts. Fetch the latest changes from the main Alpine repository:

$git fetch upstream

Update your local master branch:

git checkout master && git merge upstream/master.

Create a new branch for your aport:

git checkout -b my-new-aport-branch.

Make your changes and commit them and Push the new branch to your fork:

git push -u origin my-new-aport-branch.

Create a merge request on GitLab website from my-new-aport-branch to the main Alpine aports repository’s master branch.

Detailed steps

Forking and other Initial Steps

The initial forking of aports can be done on gitlab.alpinelinux.org to ones’ namespace.

git clone https://gitlab.alpinelinux.org/prabuanand/aports.git  --depth 1
Cloning into 'aports'...
remote: Enumerating objects: 34804, done.
remote: Counting objects: 100% (34804/34804), done.
remote: Compressing objects: 100% (24048/24048), done.
remote: Total 34804 (delta 2216), reused 24175 (delta 1796), pack-reused 0 (from 0)
Receiving objects: 100% (34804/34804), 17.40 MiB | 539.00 KiB/s, done.
Resolving deltas: 100% (2216/2216), done.
Updating files: 100% (22832/22832), done.
prabu@homepc2 /d/m/p/l/alpine> cd aports/
prabu@homepc2 /d/m/p/l/a/aports (master)> git remote add upstream https://gitlab.alpinelinux.org/alpine/aports.git
prabu@homepc2 /d/m/p/l/a/aports (master)> git remote -v
origin	https://gitlab.alpinelinux.org/prabuanand/aports.git (fetch)
origin	https://gitlab.alpinelinux.org/prabuanand/aports.git (push)
upstream	https://gitlab.alpinelinux.org/alpine/aports.git (fetch)
upstream	https://gitlab.alpinelinux.org/alpine/aports.git (push)
# Check if you have SSH keys locally.
ls -la ~/.ssh/

# If you don't have keys, generate them
ssh-keygen -t ed25519 -C "your.email@example.com"

# Add key to SSH agent
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

# Copy public key to add to GitLab
cat ~/.ssh/id_ed25519.pub

Make sure you have copied over your SSH key to your GitLab account from the website and test the SSH Connection.

# Test connection to GitLab
ssh -T git@gitlab.alpinelinux.org
Welcome to GitLab, @prabuanand!

Change from https to git to complete setup for SSH access by changing your fork to SSH. With SSH, one can push and pull without entering credentials.

# Change your fork (origin) to SSH
git remote set-url origin git@gitlab.alpinelinux.org:prabuanand/aports.git
# Optional: Change upstream to SSH as well (read-only, but consistent)
git remote set-url upstream git@gitlab.alpinelinux.org:alpine/aports.git

git config pull.rebase true

prabu@homepc2 /d/m/p/l/a/aports (master) [SIGHUP]> abuild-keygen -a -i
>>> Generating public/private rsa key pair for abuild
Enter file in which to save the key [/home/prabu/.abuild/kprabuanand@gmail.com-68ce6f9c.rsa]:
writing RSA key
>>> Installing /home/prabu/.abuild/kprabuanand@gmail.com-68ce6f9c.rsa.pub to /etc/apk/keys...
doas (prabu@homepc2) password:
doas (prabu@homepc2) password:
>>>
>>> Please remember to make a safe backup of your private key:
>>> /home/prabu/.abuild/kprabuanand@gmail.com-68ce6f9c.rsa
>>>
# Don't do this, instead do the next i.e Regular sync workflow
git fetch upstream
# Regular sync workflow
git fetch --depth=20 upstream
git checkout master
git merge upstream/master

If You Need More History Later
# Deepen the repository
git fetch --unshallow upstream

# Or fetch more commits
git fetch --depth=1000 upstream

Start with –depth=50 or even –depth=20. This gives you enough recent history to understand recent changes while keeping the repository size manageable.

Creating branches for each package

ls community/*/APKBUILD | grep -E "(rtl|wireless|driver)" | head -5
ls testing/*/APKBUILD | grep -E "(rtl)" | head -5
testing/rtl-power-fftw/APKBUILD
testing/rtl8812au-src/APKBUILD
testing/rtl8821ce-src/APKBUILD
testing/rtl88x2bu-src/APKBUILD

Create the Package Directory Structure with a new git branch

git checkout -b rtl8192eu
mkdir -p testing/rtl8192eu-src
cd testing/rtl8192eu-src
abuild checksum
abuild validate
apkbuild-lint APKBUILD

#Test Build the Package

abuild -r

#Test Installation (Optional but Recommended)

doas apk add --allow-untrusted ~/packages/testing/x86_64/rtl8192eu-src-*.apk
cd ../../
prabu@homepc2 /d/m/p/l/a/aports (rtl8192eu)> git status
On branch rtl8192eu
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        testing/rtl8192eu-src/

nothing added to commit but untracked files present (use "git add" to track)
prabu@homepc2 /d/m/p/l/a/aports (rtl8192eu)> git add testing/rtl8192eu-src/
git commit -m "testing/rtl8192eu-src: new aport

Realtek RTL8192EU USB WiFi driver using AKMS

Fixes: #<issue_number_if_applicable>"
prabu@homepc2 /d/m/p/l/a/aports (rtl8192eu)> git add testing/rtl8192eu-src/
prabu@homepc2 /d/m/p/l/a/aports (rtl8192eu)> git commit -m "testing/rtl8192eu-src: new aport

                                             https://github.com/clnhub/rtl8192eu-linux
                                             Realtek RTL8192EU wireless driver for Linux"
[rtl8192eu 7ed73d4a8a] testing/rtl8192eu-src: new aport
 1 file changed, 44 insertions(+)
 create mode 100644 testing/rtl8192eu-src/APKBUILD
prabu@homepc2 /d/m/p/l/a/aports (rtl8192eu)> git push origin rtl8192eu
Enumerating objects: 21, done.
Counting objects: 100% (21/21), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 1.20 KiB | 1.21 MiB/s, done.
Total 5 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
remote:
remote: To create a merge request for rtl8192eu, visit:
remote:   https://gitlab.alpinelinux.org/prabuanand/aports/-/merge_requests/new?merge_request%5Bsource_branch%5D=rtl8192eu
remote:
To gitlab.alpinelinux.org:prabuanand/aports.git
 * [new branch]            rtl8192eu -> rtl8192eu

The merge request must be raised at the website as shown in the previous step.

Post-merger Activities

As part of Post-Merge Activities, Clean Up Your Local Environment

git checkout master
git fetch --depth=20 upstream
git merge upstream/master
git push origin master
git branch -d rtl8192eu
git push origin --delete rtl8192eu
rm -rf ~/packages/testing/x86_64/rtl8192eu-src-*

Monitor Your Package status for build and approval

Ongoing Maintenance Responsibilities

As the maintainer, you’re now responsible for Package Maintenance

git checkout -b update-rtl8192eu
cd testing/rtl8192eu-src
abuild checksum  # Update checksums
abuild -r        # Test build
git add .
git commit -m "testing/rtl8192eu-src: upgrade to X.Y.Z"
git push origin update-rtl8192eu

Handle Bug Reports and Issues Handle Security Updates

git checkout -b rtl8192eu-security-fix
git commit -m "testing/rtl8192eu-src: security fix for CVE-XXXX-XXXX"

Set Up Anitya Monitoring for Your Project

  1. Visit Anitya Website

Go to https://release-monitoring.org/ ↗

  1. Create an Account

Sign up for an account on Anitya if you don’t have one You can usually sign in with GitHub, GitLab, or other OAuth providers

  1. Add Your Project

Project Name: rtl8192eu-linux-driver (or similar) Homepage: https://github.com/Mange/rtl8192eu-linux-driver ↗ Backend: GitHub (since it’s hosted on GitHub) Version URL: https://api.github.com/repos/Mange/rtl8192eu-linux-driver/releases ↗

  1. Create Alpine Linux Mapping

After adding the project:

Click “Add new mapping” Distribution: Alpine Linux Package name: rtl8192eu-dkms (your exact package name) This links the upstream project to your Alpine package

  1. Configure Version Detection

Set up how Anitya should detect new versions:

GitHub Backend: Monitors GitHub releases/tags Version pattern: Configure if needed (e.g., if versions follow specific patterns) Filter: Set up filters to ignore pre-releases if desired

Benefits After Setup Once the mapping is made, it should automatically send an email to the maintainer whenever a new version is available - Alpine Linux packages

Manual Process for Your RTL8192EU Driver Here’s the step-by-step process:

Go to: https://release-monitoring.org/ ↗ Sign in/Register: Create account Add Project:

Click “Add a project” Project name: rtl8192eu-linux-driver Homepage: https://github.com/Mange/rtl8192eu-linux-driver ↗ Backend: GitHub Regex: Leave default unless you need custom version parsing

Add Mapping: After project is created, click “Add a mapping” Distribution: Alpine Linux Package name: rtl8192eu-dkms Confirm the mapping


© Prabu Anand K 2020-2026