[{"content":"Introduction As established in my previous post on UICC history, an eUICC is a programmable platform. Android™ provides multiple ways for users to manage their eUICC (referred to as \u0026rsquo;eSIM\u0026rsquo; below), including but not limited to using LPAs (Local Profile Assistants) via OMAPI (Open Mobile API, requires Android 9 / API level 28 or later) or the Android Telephony API (requires root permission and Android 11 or later; you can replace the default eSIM management portal on your phone using Magisk).\nThis article mainly demonstrates the difference between OMAPI and Android Telephony API using OpenEUICC and EasyEUICC apps. These apps are developed by Peter Cai and shared the same codebase. The only difference is the management API used (EasyEUICC for unprivileged users and OpenEUICC for privileged users). Their differences are shown below:\nOpenEUICC EasyEUICC Privileged Must be installed as system app No Internal eSIM Supported Unsupported External eSIM 1 Supported Supported USB Readers Supported Supported Requires allowlisting by eSIM No Yes \u0026ndash; except USB System Integration Partial 2 No Minimum Android Version Android 11 or higher Android 9 or higher If you are interested in purchasing compatible Removable eSIM cards We have collaborated with multiple excellent manufacturers and have some discounts for your choices. Check the following to purchase cheaper and support me if you like this article.\neSTK.me - The no-fuss choice. Use any LPA apps and even be able to manage profiles on Any Android or iPhone. Use OUS50 as coupon code at checkout to get 10% OFF. 9eSIM - affordable choices. use OUS50 at checkout to get 10% OFF. EasyEUICC - OMAPI Note Unless you compile the EasyEUICC by yourself, you have to make sure your external eSIM device is compatible with EasyEUICC, which means the device MUST comply with the GSMA SGP.22 specification and MUST support this specific ARA-M SHA-1 value: 2A2FA878BC7C3354C2CF82935A5945A3EDAE4AFA before proceeding. Download You may download the app directly from EasyEUICC official page.\nFirst usage At first launch, the EasyEUICC app will check your Android phone\u0026rsquo;s OMAPI compatibility and show the SIM slot(s) you can use to manage your compatible external eSIM devices\nClick the Continue button to proceed, and you will be taken to the main interface:\nNote If you just want to add/manage your eSIM profiles, just go here Settings page Click the ⋮ button in the upper right corner to check the settings:\nAdd eSIM profiles Click the + button in the lower right corner, and select the eSIM device you want to download the profile to:\nNote You should check your eSIM via eID, not ICCID. eID is your eSIM device(the card inserted into your phone) identification number and ICCID is your eSIM profile identification number. Choose the method you want to use (usually scanning a QR code with the camera or loading it from the gallery). The profile download will start after checking with the target server:\nWarning Make sure you have a stable and reachable connection when you are downloading profiles. Otherwise you may lose your profile permanently since the profile issuing server has marked your profile as downloaded. If you need to download profile with raw data provided, or QR code is not working Then select the last option Enter manually. Type in the strings your provider gave you:\nAfter Profile downloaded When the profile is downloaded, you can view, toggle, and rename the profile on the main page:\nNote I have been using esim.gg every day for several years, and it has been exceptionally reliable and stable while I travel globally. Currently there is no discount for data-only eSIMs, but you can get 0.3 EUR off if you purchase a new Estonian number using ous50 at checkout. Troubleshooting OMAPI detection failed In this case, your phone or system does not support EasyEUICC via OMAPI. Consider using OpenEUICC after gaining root access, or switch to a more modern device.\nProfile download failed Check the error code, try scanning the QR code again or downloading the profile manually.\nWarning Make sure you have a stable and reachable connection when you are downloading profiles. Otherwise you may lose your profile permanently since the profile issuing server has marked your profile as downloaded. If you have run out of download attempts, contact your eSIM profile provider for further assistance.\nno eSIM card/device found Your eSIM card/device might not be compatible with EasyEUICC. Check here for more information.\nFAQ Will I get banned by my provider for using this app? Generally no. But providers have their own blacklist. Some eSIM card manufacturer/models might be blacklisted. Purchase a good eSIM card listed above and follow the instructions from your provider.\nCan I use these cards on other phones? Yes, you can use these cards like normal physical SIM cards after you have properly set up the eSIM card/device and have toggled and configured your desired profile.\nYou can use the EasyEUICC app on any OMAPI-compatible Android phone to manage profiles on compatible cards.\nFor eSTK cards, you can even manage your profiles on iPhones using the STK application.\nFootnotes Also known as \u0026ldquo;Removable eSIM\u0026rdquo;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nCarrier Partner API not implemented yet\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"2026-04-06T22:39:01+08:00","permalink":"/en/p/euicc-management-explained/","title":"eUICC management explained"},{"content":" Note Please be advised that this article is written for RouterOS 7.20.1 and ShellCrash 1.9.4beta6 on 2026-01-29, both operated as KVM instance in PVE. Contents might vary for different version of RouterOS and ShellCrash. Introduction Previously I used DHCP gateway nomination to let devices in my network use proxy. Although it successfully enables me to use proxy seamlessly, I can\u0026rsquo;t expand this experience to all devices, since sometimes ShellCrash may really \u0026ldquo;crashed\u0026rdquo; and would affect normal network traffic. I have heard OSPF feature for a long time, so recently I set up OSPF using RouterOS according to DeepRouter\u0026rsquo;s article. This article is to record my experience and share my way to enhance the robustness.\nShellCrash and Bird Configuration Although it is fine to deploy ShellCrash and BIRD in separate instance, it is highly recommended to deploy in the same one.\nShellCrash installation process is ignored, just make sure you are using MIX in DNS configuration(press 2(feature setting) - 2(DNS Setting)).\nCheck IPv4 and IPv6 forward configuration run sudo sysctl -p and check if the following are properly configured:\nnet.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1 If not, edit /etc/sysctl.conf.\nBIRD We will use !chnroutes to distinguish chn ips.\nMake sure you doesn\u0026rsquo;t enable/start bird service after installation. There are several things to do.\nFor Debian:\nsudo apt update sudo apt install bird2 make bird.conf Edit /etc/bird/bird.conf and change as below.\nmake sure:\nrouter id is your ShellCrash/BIRD instance IP The interface in both ospf v2 and v3 is set to the interface this instance used to connect to the gateway(the LAN port). You may check using ip a or ip link, and find the one OTHER THAN lo. log syslog all; router id 192.168.114.51; #This line change to instance IP protocol device { scan time 60; } protocol kernel { ipv4 { import none; export none; }; } protocol kernel { ipv6 { import none; export none; }; } protocol static { ipv4; include \u0026#34;/etc/bird/routes4.conf\u0026#34;; } protocol static { ipv6; include \u0026#34;/etc/bird/routes6.conf\u0026#34;; } protocol ospf v2 { ipv4 { export all; }; area 0.0.0.0 { interface \u0026#34;ens18\u0026#34; { # Change this to your networking interface type pointopoint; }; }; } protocol ospf v3 { ipv6 { export all; }; area 0.0.0.0 { interface \u0026#34;ens18\u0026#34; { # Change this to your networking interface type pointopoint; }; }; } Generating routes git clone https://github.com/ous50/nchnroutes.git cd nchnroutes make If you have trouble connecting to github.com, use a mirror instead:\ngit clone https://hk.gh-proxy.org/https://github.com/ous50/nchnroutes.git cd nchnroutes make You are pleased to continue if the following output is shown:\npython3 produce.py sudo mv routes4.conf /etc/bird/routes4.conf sudo mv routes6.conf /etc/bird/routes6.conf sudo birdc configure BIRD 2.0.12 ready. Reading configuration from /etc/bird/bird.conf Reconfigured RouterOS Configuration You need to set up bypassing routing table first to prevent looping instantly after OSPF neighbor is found.\nBypass ShellCrash looping and setting up exceptions We are going to make another routing table to bypass the traffic from ShellCrash to prevent loop.\n/routing table add disabled=no fib name=bypass-shellcrash /routing rule add action=lookup-only-in-table comment=\u0026#34;Bypass Shellcrash Gateway using Routing Mark\u0026#34; disabled=no routing-mark=bypass-shellcrash table=bypass-shellcrash Migrate your routes from main to bypass-shellcrash:\n/ip route add disabled=no distance=1 dst-address=\u0026lt;Your LAN with CIDR\u0026gt; gateway=lan routing-table=bypass-shellcrash scope=30 suppress-hw-offload=no target-scope=10 add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\u0026lt;Your Internet Gateway\u0026gt; routing-table=bypass-shellcrash scope=30 suppress-hw-offload=no target-scope=10 Firewall tagging Make sure:\nChange the dst-address to your LAN, preserving the !. Change the src-mac-address to the ShellCrash networking interface port MAC address(check using ip link in shellcrash instance or directly from PVE) /ip firewall mangle add action=mark-routing chain=prerouting comment=bypass-shellcrash-gateway dst-address=!192.168.0.0/23 new-routing-mark=bypass-shellcrash src-mac-address=11:45:14:19:19:81 OSPF config By default you do not need to change anything in this script.\n/routing ospf instance add disabled=no name=shellcrash add disabled=no name=shellcrash-v6 version=3 /routing ospf area add disabled=no instance=shellcrash name=ospf-area-v4 add disabled=no instance=shellcrash-v6 name=ospf-area-v6 /routing ospf interface-template add area=ospf-area-v4 cost=10 disabled=no priority=32 type=ptp add area=ospf-area-v6 cost=10 disabled=no priority=32 type=ptp Tricks Robust DNS setting Due to the fake-ip used by ShellCrash, you should set ShellCrash\u0026rsquo;s DNS as an upstream.\nIn this case we assume nominating RouterOS\u0026rsquo;s DNS to clients and use the following RouterOS script to update upstream DNS source to enhance the robustness, in case of ShellCrash failed.\n:global ospfInstance \u0026#34;shellsrash\u0026#34; :global ospfDNS \u0026#34;1.1.4.5\u0026#34; # Your ShellCrash instance IP :global publicDNS \u0026#34;223.5.5.5\u0026#34; # Change this DNS for your direct internet access # (true / false), turn debug off after testing or your logs have abundant annoying debug messages. :local DEBUG false # marking the final status default value is false (down) :local isOspfActive false # Trying to find the neighbor :local neighborIds [/routing ospf neighbor find instance=$ospfInstance] # check if neighbor is found :if ([:len $neighborIds] \u0026gt; 0) do={ # Note: In this case we will only use one instance. # If you have multiple instance, you might need to traversal and find the instance. :local neighborState [/routing ospf neighbor get ($neighborIds-\u0026gt;0) state] :if ($DEBUG) do={:log info \u0026#34;[DEBUG] Neighbor found! State: $neighborState\u0026#34;} # Only consider ospf active when state is \u0026#34;Full\u0026#34;. Remember, not \u0026#34;full\u0026#34;. This state might vary on different RouterOS version :if ($neighborState = \u0026#34;Full\u0026#34;) do={ :set isOspfActive true } } else={ # if length is 0, this neighbor is not found. check bird configuration/status. :if ($DEBUG) do={:log info \u0026#34;[DEBUG] No OSPF neighbor found. Logic assumes DOWN.\u0026#34;} :set isOspfActive false } # change DNS according to the variable isOspfActive :local currentDNS [/ip dns get servers] :if ($isOspfActive) do={ # OSPF Up :if ($DEBUG) do={:log info \u0026#34;[DEBUG] Decision: OSPF is UP.\u0026#34;} :if ($currentDNS != $ospfDNS) do={ :log warning \u0026#34;OSPF Shellcrash Up: Switching to OSPF DNS ($ospfDNS).\u0026#34; /ip dns set servers=$ospfDNS /ip dns cache flush } else={ :if ($DEBUG) do={:log info \u0026#34;[DEBUG] DNS is already correct (OSPF).\u0026#34;} } } else={ # OSPF Down (or missing neighbor) :if ($DEBUG) do={:log info \u0026#34;[DEBUG] Decision: OSPF is DOWN/MISSING.\u0026#34;} :if ($currentDNS != $publicDNS) do={ :log warning \u0026#34;OSPF Shellcrash Down: Switching to Public DNS ($publicDNS).\u0026#34; /ip dns set servers=$publicDNS /ip dns cache flush } else={ :if ($DEBUG) do={:log info \u0026#34;[DEBUG] DNS is already correct (Public).\u0026#34;} } } Switch off bird when shellcrash is crashed We will use a bash script to actively check if shellcrash is alive. If the API is unreachable, it will stop the Bird service to withdraw OSPF routes.\nCopy and paste the following block into your PVE Shell (logged in as the clash user, or a user with sudo privileges):\n# 1. Create the watchdog script # Note: We use \u0026#39;EOF\u0026#39; (quoted) to prevent variable expansion during creation. sudo tee /home/clash/check_clash.sh \u0026gt; /dev/null \u0026lt;\u0026lt; \u0026#39;EOF\u0026#39; #!/bin/bash # Configuration API_URL=\u0026#34;http://127.0.0.1:9999/\u0026#34; LOG_FILE=\u0026#34;/home/clash/clash_watchdog.log\u0026#34; DEBUG=false INTERVAL=3 # Init state (0=unknown, 1=normal, 2=crashed) LAST_STATE=0 while true; do # Check ShellCrash API HTTP_CODE=$(curl -s -m 1 -o /dev/null -w \u0026#34;%{http_code}\u0026#34; \u0026#34;$API_URL\u0026#34;) if [ \u0026#34;$DEBUG\u0026#34; = \u0026#34;true\u0026#34; ]; then echo \u0026#34;[DEBUG] Dashboard code: $HTTP_CODE\u0026#34; fi if [ \u0026#34;$HTTP_CODE\u0026#34; == \u0026#34;200\u0026#34; ]; then # ShellCrash is ALIVE if [ \u0026#34;$LAST_STATE\u0026#34; != \u0026#34;1\u0026#34; ]; then DATE=$(date \u0026#34;+%Y-%m-%d %H:%M:%S\u0026#34;) # Check if Bird is running using systemctl\u0026#39;s return code (more reliable) sudo systemctl is-active --quiet bird BIRD_EXIT_CODE=$? if [ $BIRD_EXIT_CODE -ne 0 ]; then if [ \u0026#34;$DEBUG\u0026#34; = \u0026#34;true\u0026#34; ]; then echo \u0026#34;ShellCrash detected. Starting Bird...\u0026#34; fi echo \u0026#34;[$DATE] ShellCrash recovered/detected. Starting Bird...\u0026#34; \u0026gt;\u0026gt; $LOG_FILE sudo systemctl start bird fi LAST_STATE=1 fi else # ShellCrash is DEAD if [ \u0026#34;$LAST_STATE\u0026#34; != \u0026#34;2\u0026#34; ]; then DATE=$(date \u0026#34;+%Y-%m-%d %H:%M:%S\u0026#34;) if [ \u0026#34;$DEBUG\u0026#34; = \u0026#34;true\u0026#34; ]; then echo \u0026#34;[$DATE] Alert! ShellCrash died (Code: $HTTP_CODE). Stopping Bird!\u0026#34; fi echo \u0026#34;[$DATE] Alert! ShellCrash died (Code: $HTTP_CODE). Stopping Bird!\u0026#34; \u0026gt;\u0026gt; $LOG_FILE sudo systemctl stop bird LAST_STATE=2 fi fi sleep $INTERVAL done EOF # 2. Make it executable sudo chmod +x /home/clash/check_clash.sh # 3. Create Systemd Service sudo tee /etc/systemd/system/clash-watchdog.service \u0026gt; /dev/null \u0026lt;\u0026lt; EOF [Unit] Description=ShellCrash Watchdog for Bird OSPF After=network.target [Service] User=clash Group=clash ExecStart=/home/clash/check_clash.sh Restart=always RestartSec=3 [Install] WantedBy=multi-user.target EOF # 4. Enable and Start sudo systemctl daemon-reload sudo systemctl enable --now clash-watchdog.service sudo systemctl status clash-watchdog.service ","date":"2026-01-29T00:58:18+08:00","permalink":"/en/p/how-i-create-seamless-network-using-ospf-on-routeros-and-shellcrash-on-pve/","title":"How I Create Seamless Network Using OSPF on Routeros and Shellcrash on PVE"},{"content":"If your internet provider interferes with the GitHub, you can use the following commands to install EasyTier:\napt update -y sudo unzip openssl wget -O /tmp/easytier.sh \u0026#34;https://ghfast.top/https://raw.githubusercontent.com/EasyTier/EasyTier/main/script/install.sh\u0026#34; \u0026amp;\u0026amp; sudo bash /tmp/easytier.sh install --gh-proxy https://ghfast.top/ systemctl disable --now easytier@default.service Check the latest proxy here.\nOtherwise just simply use the default GitHub URL.\napt update -y sudo unzip openssl wget -O /tmp/easytier.sh \u0026#34;https://raw.githubusercontent.com/EasyTier/EasyTier/main/script/install.sh\u0026#34; \u0026amp;\u0026amp; sudo bash /tmp/easytier.sh install systemctl disable --now easytier@default.service Should you wish to use easytier dashboard to manage, you can enable the service with the following command:\nexport USER=\u0026lt;your_username\u0026gt; echo \u0026#34;[Unit] Description=EasyTier Service After=network.target syslog.target Wants=network.target [Service] Type=simple ExecStart=/usr/sbin/easytier-core -w $USER [Install] WantedBy=multi-user.target \u0026#34; | sudo tee /etc/systemd/system/easytier.service systemctl enable --now easytier.service Then you are able to access the EasyTier dashboard at https://easytier.cn/web.\n","date":"2025-08-26T10:30:16+08:00","permalink":"/en/p/install-easytier-on-pve/","title":"Install Easytier on Pve"},{"content":"This article focuses on optimizing FnOS. For instructions on installing FnOS on PVE or a physical machine, please see the previous article.\nNetwork Optimization The following optional steps can improve network throughput and privacy.\nExecute this script to enable the BBR congestion control algorithm:\ncat \u0026gt; /etc/sysctl.d/99-enable-bbr.conf \u0026lt;\u0026lt;EOF net.core.default_qdisc=fq net.ipv4.tcp_congestion_control=bbr EOF Apply the BBR configuration without rebooting:\nsysctl -p /etc/sysctl.d/99-enable-bbr.conf Execute this script to enable modern IPv6 privacy address standards (RFC 7217 and RFC 4941):\ncat \u0026gt; /etc/sysctl.d/99-enable-private-ipv6.conf \u0026lt;\u0026lt;EOF net.ipv6.conf.all.use_tempaddr = 2 net.ipv6.conf.default.use_tempaddr = 2 net.ipv6.conf.all.addr_gen_mode=1 net.ipv6.conf.default.addr_gen_mode=1 EOF Apply the sysctl configuration:\nsysctl -p /etc/sysctl.d/99-enable-private-ipv6.conf 🚨 Warning: Do not use the “EUI-64” option in the FnOS web interface. Doing so will negate these privacy enhancements by exposing the device’s MAC address in its IPv6 address.\nApplying Network Changes\nTo activate the new IPv6 address settings, the network interface must be reset. This can be done with nmcli without a full system reboot.\n🚨 Important: Execute these commands from the PVE web console (Xterm.js), as running them over SSH will cause a disconnection due to the IPv6 address change and may not be recoverable.\nStep 1: Identify the Connection Name List all active connections to find the name of your primary interface.\nnmcli connection show The output will list available connections. Note the name of your Ethernet connection, which is often Wired connection 1.\nStep 2: Reset the Connection Use the identified name to restart the network interface:\nnmcli connection down \u0026#34;Wired connection 1\u0026#34; \u0026amp;\u0026amp; nmcli connection up \u0026#34;Wired connection 1\u0026#34; The network interface will restart. You can confirm the new IPv6 address configuration using ip a or in the Summary page for the VM in the PVE web console.\nEnabling IPv6 Router Advertisements (RA) for Hosted Virtual Machines\nTo allow VMs inside it to also acquire IPv6 addresses via SLAAC, its RA settings must be changed:\ncat \u0026gt; /etc/sysctl.d/99-virtual-machine.conf \u0026lt;\u0026lt;EOF net.ipv6.conf.all.accept_ra = 2 net.ipv6.conf.default.accept_ra = 2 EOF sysctl -p /etc/sysctl.d/99-virtual-machine.conf Enabling Memory and CPU Hot-plug as a PVE/QEMU Guest Modify /etc/default/grub to enable memory hot-plug:\n- GRUB_CMDLINE_LINUX=\u0026#34;modprobe.blacklist=pcspkr\u0026#34; + GRUB_CMDLINE_LINUX=\u0026#34;modprobe.blacklist=pcspkr memhp_default_state=online\u0026#34; Create a UDEV rule to enable CPU hot-plug:\ncat \u0026gt; /lib/udev/rules.d/80-hotplug-cpu.rules \u0026lt;\u0026lt;EOF SUBSYSTEM==\u0026#34;cpu\u0026#34;, ACTION==\u0026#34;add\u0026#34;, TEST==\u0026#34;online\u0026#34;, ATTR{online}==\u0026#34;0\u0026#34;, ATTR{online}=\u0026#34;1\u0026#34; EOF Shut down the virtual machine.\nIn the PVE web console, on the Processor page, check \u0026ldquo;Enable NUMA\u0026rdquo;.\nIn the PVE web console, on the Options page, check Memory and CPU in the \u0026ldquo;Hotplug\u0026rdquo; options list.\n","date":"2025-08-08T11:26:29+08:00","permalink":"/en/p/advanced-fnos-configuration-and-usage-tips/","title":"Advanced FnOS Configuration and Usage Tips"},{"content":"Introduction This document addresses common issues encountered on the process of installing FnOS in a PVE environment, such as a locked system and an unresponsive PVE web console. By following these steps, you will achieve a fully accessible, secure, and optimized FnOS virtual machine.\nIf you have already completed the installation and want to see more optimization tips, please see this article.\nPre-Installation FnOS ISO: Visit https://www.fnnas.com/ and obtain it via “Direct Download”.\nIt is recommended that the FnOS VM has at least 3GB of RAM and 2 cores.\nFollow the official guide to install the system.\nPost-Installation Configuration On the first boot, two primary issues prevent access to the new FnOS instance:\nLogin Disabled: The system console does not accept any credentials (including root) until the web-based initial setup is complete. This is problematic for remote machines that may only have IPv6 access. Unresponsive PVE Console: The Xterm.js serial console in the PVE web UI does not work by default. The following sections provide solutions to these problems.\n1. Gaining Initial Root Access First, we must bypass the standard boot sequence to set a root password.\nIn the PVE console, restart the VM. At the GRUB boot menu, press e to edit the boot parameters. Find the line that begins with linux. It will look similar to this: linux /boot/vmlinuz-6.12.18-trim root=UUID=... ro quiet At the end of this line, add single init=/bin/bash. This parameter boots the system directly into a root shell. Press Ctrl+X or F10 to boot. In the root shell, execute the passwd command to set a new password for the root user. Once done, reboot the VM. The boot parameter change is temporary and will not persist. 2. Enabling Permanent Console Access and Functionality With root access established, permanently modify the GRUB configuration to enable the PVE serial console and other features.\nLog in as root with the newly set password.\nEdit the GRUB configuration file: nano /etc/default/grub.\nModify the GRUB_CMDLINE_LINUX_DEFAULT line to include serial console and optional nested virtualization IOMMU support.\nFor Intel CPUs:\n- GRUB_CMDLINE_LINUX_DEFAULT=\u0026#34;quiet\u0026#34; + GRUB_CMDLINE_LINUX_DEFAULT=\u0026#34;quiet console=tty0 console=ttyS0,115200 intel_iommu=on iommu=pt\u0026#34; For AMD CPUs:\n- GRUB_CMDLINE_LINUX_DEFAULT=\u0026#34;quiet\u0026#34; + GRUB_CMDLINE_LINUX_DEFAULT=\u0026#34;quiet console=tty0 console=ttyS0,115200 amd_iommu=on iommu=pt\u0026#34; Note: console=ttyS0,115200 is the key parameter for PVE Xterm.js functionality.\nSave the changes and exit the editor.\nApply the new configuration by executing:\nupdate-grub Reboot the VM. The PVE web console should now be fully functional.\n3. Installing the QEMU Guest Agent For better integration with PVE, such as displaying network information in the VM summary, we need to install the qemu-guest-agent.\n```shell apt update \u0026amp;\u0026amp; apt -y install qemu-guest-agent systemctl enable --now qemu-guest-agent ``` Conclusion You have successfully configured an FnOS instance on Proxmox VE. The system is now fully accessible and properly integrated with the PVE host. Further configurations and optimizations will be presented in a new article.\n","date":"2025-08-03T10:12:00+08:00","permalink":"/en/p/installing-fnos-on-proxmox-ve-pve/","title":"Installing FnOS on Proxmox VE (PVE)"},{"content":"Install WSL Linux and Compiling Dependency By default Ubuntu is installed:\n# Make downloads faster by not displaying progress bar: $ProgressPreference = \u0026#39;SilentlyContinue\u0026#39; # Using the URL you found above, download the appx package: Invoke-WebRequest -Uri https://aka.ms/wslubuntu -OutFile Linux.appx -UseBasicParsing # Make a backup and unpack: Copy-Item .\\Linux.appx .\\Linux.zip Expand-Archive .\\Linux.zip # Search for the installer: Get-Childitem -Filter *.exe # Install compiling dependency for Ubuntu sudo apt install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev libelf-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev git For Debian Bookworm: sudo apt install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git git-lfs gnupg gperf imagemagick lib32readline-dev lib32z1-dev libelf-dev liblz4-tool libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev libncurses5 Install build packages: Repo curl https://storage.googleapis.com/git-repo-downloads/repo |sudo tee /usr/bin/repo sudo chmod a+x /usr/bin/repo Platform tools If you haven’t previously installed adb and fastboot, you can download the original version from Google and extract it:\nwget https://dl.google.com/android/repository/platform-tools-latest-linux.zip wget https://dl.google.cn/android/repository/platform-tools-latest-linux.zip # For readers located in China unzip platform-tools-latest-linux.zip -d ~/.local/bin Now you have to add adb and fastboot to your PATH. Open ~/.profile and add the following:\n# add Android SDK platform tools to path if [ -d \u0026#34;$HOME/.local/bin/platform-tools\u0026#34; ] ; then PATH=\u0026#34;$HOME/.local/bin/platform-tools:$PATH\u0026#34; fi Run source ~/.profile to update your environment, or simply restart the shell.\nPython For Lineage OS 18+, python3 is required to build a package.\nConfigure Git You would have to set your name to sync android source code.\ngit config --global user.email \u0026#34;you@example.com\u0026#34; git config --global user.name \u0026#34;Your Name\u0026#34; Some large files may be required to download when syncing source code, hence install git-lfs:\ngit lfs intall Make new directory to pull source code mkdir lineage-21.0 \u0026amp;\u0026amp; cd lineage-21.0 Initialize repo repo init -u https://github.com/LineageOS/android.git -b lineage-21.0 # Sync the whole repo with all commit log, takes a lot of spaces. repo init -u https://github.com/LineageOS/android.git -b lineage-21.0 --depth=1 # Only pull the latest commit without commit logs, takes not much spaces Start syncing repo repo sync -c -j$(nproc --all) --force-sync --no-clone-bundle --no-tags Then follow Lineage OS building guide\u0026hellip;\n","date":"2024-01-25T03:46:22Z","permalink":"/en/p/compiling-lineage-os-on-wsl2/","title":"Compiling Lineage OS on WSL2"},{"content":"Before installation Create a virtual machine and adjust depend config on your need(Except for the UEFI firmware part):\nTo prevent the creation of vmem files for acceleration, add the following lines to your .vmx file(:\nprefvmx.minVmMemPct = \u0026#34;100\u0026#34; MemTrimRate = \u0026#34;0\u0026#34; mainMem.useNamedFile = \u0026#34;FALSE\u0026#34; sched.mem.pshare.enable = \u0026#34;FALSE\u0026#34; prefvmx.useRecommendedLockedMemSize = \u0026#34;TRUE\u0026#34; Boot up the vm, and check if the firmware is UEFI or not:\nls /sys/firmware/efi/efivars if it\u0026rsquo;s legacy BIOS, it will returns No such file or directory.\nPartitioning Create a new GPT partition table and partitioned with an EFI Partition no less than 300MiB and an Linux partition with cgdisk or any other partition tools you want to use:\ncgdisk /dev/sda Format partitions EFI mkfs.fat -F32 /dev/sda1 Root system mkfs.btrfs -f -L Arch /dev/sda2 Building BTRFS subvolume @：corresponding to / @home：corresponding to/home @cache：corresponding to /var/cache @docker：corresponding to /var/lib/docker @log：corresponding to /var/log Enabling COW in @cache, @log is not needed.\nMount root partition to /mnt: mount -t btrfs -o compress=lzo /dev/sda2 /mnt Generally we lzo is good enough. Reports shows that btrfs is way slower even under Zstd:1, while lzo has nearly no difference compared with non-compressed.\nCreate subvolumes: btrfs subvol create /mnt/@ btrfs subvol create /mnt/@home btrfs subvol create /mnt/@cache btrfs subvol create /mnt/@docker btrfs subvol create /mnt/@log btrfs subvol create /mnt/@tmp btrfs subvol create /mnt/@swap # Use chattr to disable COW chattr +C /mnt/@cache chattr +C /mnt/@log chattr +C /mnt/@swap # Umount the partition umount /mnt Mount partitions and subvolumes mount -o noatime,nodiratime,ssd,compress=lzo,subvol=@ /dev/sda2 /mnt mkdir -p /mnt/{boot/efi,home,var/{log,lib/docker,cache},tmp,swap} mount -o noatime,nodiratime,ssd,compress=lzo,subvol=@home /dev/sda2 /mnt/home mount -o noatime,nodiratime,ssd,compress=lzo,subvol=@log /dev/sda2 /mnt/var/log mount -o noatime,nodiratime,ssd,compress=lzo,subvol=@docker /dev/sda2 /mnt/var/lib/docker mount -o noatime,nodiratime,ssd,compress=lzo,subvol=@cache /dev/sda2 /mnt/var/cache mount -o noatime,nodiratime,ssd,compress=lzo,subvol=@tmp /dev/sda2 /mnt/tmp mount -o noatime,nodiratime,ssd,compress=lzo,subvol=@swap /dev/sda2 /mnt/swap Mount EFI partition: mount /dev/sda1 /mnt/boot/EFI Install the system pacstrap /mnt base base-devel linux linux-firmware btrfs-progs networkmanager dhcpcd iwd vim sudo zsh zsh-completions {intel,amd}-ucode net-tools linux-headers curl git wget Generate fstab genfstab -U /mnt \u0026gt; /mnt/etc/fstab Check again carefully after generation. Then proceed to post installation.\nPost Installation arch-chroot /mnt\tSet mirror for pacman Use reflector or just update /etc/pacman.d/mirrorlist, then apply changes via pacman -Syy.\nInstall bootloader In this article we use grub as the bootloader, since it is one of a few bootloaders has a good support to btrfs.\npacman -S grub efibootmgr os-prober grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=Arch successful results is shown below.\nThen do some optimization. Increase the log level and add nowatchdog param to accelerate the speed of booting and powering off:\nnano /etc/default/grub and edit as below:\n- GRUB_CMDLINE_LINUX_DEFAULT= \u0026#34;loglevel=5\u0026#34; + GRUB_CMDLINE_LINUX_DEFAULT= \u0026#34;loglevel=5 nowatchdog\u0026#34; Save it and then generate new grub config file to apply changes.\n[root@archiso /] # grub—mkconfig —o /boot/grub/grub.cfg Generating grub configuration file ... Found linux image: /boot/vmlinuz-linux Found initrd image: /boot/intel—ucode.img /bootzamd—ucode.img /boot/initramfs—linux.img Found fal Iback initrd image(s) in /boot : intel—ucode.img amd—ucode.img initramfs—linux—fallback.img Warning: os—prober will not be executed to detect other bootable partitions. Systems on them will not be added to the GRUB boot configuration. Check documentation entry. Adding boot menu entry for UEFI Firmware Settings ... done Set hostname and hosts newHostname=\u0026#34;Your-new-hostname\u0026#34; echo $newHostname \u0026gt; /etc/hostname echo -e \u0026#34;127.0.0.1 localhost\\n\u0026#34; \u0026#34;::1 localhost\\n\u0026#34; \u0026#34;127.0.1.1 $newHostname.localdomain $newHostname\u0026#34; \u0026gt;\u0026gt; /etc/hosts Set Timezone ln -sf /usr/share/zoneinfo/Asia/Hong_Kong /etc/localtime Set locale nano /etc/locale.gen and uncomment en-US.UTF-8 UTF-8 and any locale you wanna to use, then generate locale and set en_US locale:\nlocale-gen \u0026amp;\u0026amp; echo \u0026#39;LANG=en_US.UTF-8\u0026#39; \u0026gt; /etc/locale.conf Setting up user accounts First set the root account password:\npasswd root\tyourName=\u0026#34;example\u0026#34; useradd -m $yourName \u0026amp;\u0026amp; echo \u0026#34;Set a new password for the user $yourName\u0026#34; \u0026amp;\u0026amp; passwd $yourName Desktop Environment In this article we install KDE:\npacman -S plasma plasma-wayland-session egl-wayland kde-{accessibility,graphics,multimedia,network,pim,sdk,system,utilities}-meta VMware Tools Arch Linux is not supported in the official VMware Tools. OpenVMTools is commonly used.\nUsing Open VM Tools one cannot resize the screeen properly. Here\u0026rsquo;s a solution following to a reddit post:\nsudo pacman -Syu sudo pacman -S open-vm-tools sudo pacman -Su xf86-input-vmmouse xf86-video-vmware mesa gtk2 gtkmm echo needs_root_rights=yes | sudo tee /etc/X11/Xwrapper.config sudo systemctl enable --now vmtoolsd And you are good to go.\nReference:\nhttps://blog.zrlab.org/posts/arch-btrfs\nhttps://wiki.archwiki.org\nhttps://ericclose.github.io/Installing-Arch-as-a-guest-with-UEFI-and-GPT.html\nhttps://arch.icekylin.online/rookie/basic-install.html\nhttps://www.reddit.com/r/archlinux/comments/b0ona0/vmtools_on_arch_linux_full_screen_or_resizing/\n","date":"2023-01-13T23:07:11+08:00","permalink":"/en/p/installing-archlinux-with-btrfs-in-vmware/","title":"Installing ArchLinux With Btrfs in Vmware"},{"content":"Intro Lenovo Legion series Laptops uses IdeaPad ACPI and ones in normal configuration can use nearly all of the function keys except for F9(Favorite key), F11(tab switching key) and F12(Calculator key), since ACPI key functions is not defined:\nsudo acpi_listen 8FC0DE0C-B4E4- 000000d0 00000000 #F9 ^[^[[27;5;9~ #F11 8FC0DE0C-B4E4- 000000d0 00000000 #F12 But for users have \u0026ldquo;discrete graphics\u0026rdquo; option switched on in BIOS, F5(Brightness Up) and F6(Brightness Down) is not working, although running acpi_listen shows everything is normal:\nsudo acpi_listen video/brightnessup BRTUP 00000086 00000000 #F6 video/brightnessdown BRTDN 00000087 00000000 #F5 ​\tThe reason is the device controlling backlight now has changed to nvidia_0, not correspond to the defined acpi actions. For Arch Linux users You can install xbacklight to tweak the backlight via command line. But that experience is extremely awful: everytime you want to adjust, you have to turn on console and run xbacklight with root permission. This article is aimed to fix the malfunctioned key.\n​\tREMEMBER: you still can not adjust brightness in \u0026ldquo;battery and brightness\u0026rdquo;.\nSolution ​\tJust create these files and reboot.\n/etc/acpi/events/FnF6-brightnessup #FnF6 video/brightnessup BRTUP 00000086 00000000 event=video/brightnessup action=/etc/acpi/actions/FnF6-brightnessup.sh /etc/acpi/actions/FnF6-brightnessup.sh #!/bin/bash # Set the static increment value. Keep in mind that this will # be done twice. # This Value is depended on the actual changing value of the DE(in KDE it\u0026#39;s 6) IncVal=6 # Get the Maximum value for use. #MaxVal=$(cat /sys/class/backlight/intel_backlight/max_brightness); read -r MaxVal \u0026lt; \u0026#34;/sys/class/backlight/nvidia_0/max_brightness\u0026#34; # Get the current brightness value. #CurrVal=$(cat /sys/class/backlight/nvidia_0/brightness); read -r CurrVal \u0026lt; \u0026#34;/sys/class/backlight/nvidia_0/brightness\u0026#34; # Set the new value minus the decrement value. NewVal=$(($CurrVal + $IncVal)); echo $NewVal # Set it to the threshold of the max value. ThresholdVal=$(($NewVal\u0026lt;$MaxVal?$NewVal:$MaxVal)) echo $ThresholdVal # Set the new value directly. echo -n $ThresholdVal \u0026gt; /sys/class/backlight/nvidia_0/brightness logger \u0026#34;[ACPI] brightnessup |$CurrVal| |$NewVal| |$ThresholdVal|\u0026#34; /etc/acpi/events/FnF5-brightnessdown #FnF5 video/brightnessdown BRTDN 00000087 00000000 event=video/brightnessdown action=/etc/acpi/actions/FnF5-brightnessdown.sh /etc/acpi/actions/FnF5-brightnessdown.sh #!/bin/bash # Set the static decrement value. Keep in mind that this will # be done twice. # This Value is depended on the actual changing value of the DE(in KDE it\u0026#39;s 6) DecVal=6 # Set the Minimum we will accept. MinVal=0 # Get the current brightness value. #CurrVal=$(cat /sys/class/backlight/nvidia_0/brightness); read -r CurrVal \u0026lt; \u0026#34;/sys/class/backlight/nvidia_0/brightness\u0026#34; # Set the new value minus the decrement value. NewVal=$(($CurrVal - $DecVal)); echo $NewVal # Set it to the threshold of the min value. ThresholdVal=$(($NewVal\u0026gt;$MinVal?$NewVal:$MinVal)) echo $ThresholdVal # Set the new value directly. echo -n $ThresholdVal \u0026gt; /sys/class/backlight/nvidia_0/brightness logger \u0026#34;[ACPI] brightnessdown |$CurrVal| |$NewVal| |$ThresholdVal|\u0026#34; ","date":"2022-11-08T02:06:00Z","permalink":"/en/p/fixing-the-brightness-function-keys-in-legion-laptops-with-discrete-graphics-option-enabled/","title":"Fixing the brightness function keys in Legion laptops with discrete graphics option enabled"},{"content":"Some useful markdown note taking codes Maths In-line maths(LaTeX?) expressions Turn on the \u0026ldquo;In-line Math Equation\u0026rdquo; option in your editor. In my editor Typora, you can turn it on in File\u0026gt;\u0026gt;Preferences\u0026gt;\u0026gt;Markdown\u0026gt;\u0026gt;Syntax Support\u0026gt;\u0026gt;Inline Math. Then just write as the following(Please don\u0026rsquo;t judge whether the equation is wrong or not, after all, this is just a demonstration.):\n$inline \\ math \\ example: \\ f(x)=x^2+y_2$ It will look like: $inline \\ math \\ example: \\ f(x)=x^2+y_2$\nNote taking Changing the text and background colour Markdown is not able to change text number by default. But by writing HTML code, one could change the text color and bkg colour.\nHere\u0026rsquo;s an example\n\u0026lt;span style=\u0026#34;color:\u0026#39;the colour name or the html colour code\u0026#39;\u0026#34;\u0026gt;text\u0026lt;/span\u0026gt; //text colour \u0026lt;span style=\u0026#34;background-color:\u0026#39;the colour name or the html colour code\u0026#39;\u0026#34;\u0026gt;text\u0026lt;/span\u0026gt; //background colour blue\nyellow background colour\nMore interestingly, you could still use markdown format inside the html rendering:\n\u0026lt;span style=\u0026#34;background-color:#00ffff\u0026#34;\u0026gt;\u0026lt;span style=\u0026#34;color:red\u0026#34;\u0026gt;Red text\u0026lt;/span\u0026gt; in cyan background colour\u0026lt;/span\u0026gt; \u0026lt;span style=\u0026#34;background-color:#00ffff\u0026#34;\u0026gt;\u0026lt;span style=\u0026#34;color:red\u0026#34;\u0026gt;**Bold red text**\u0026lt;/span\u0026gt; in cyan background colour\u0026lt;/span\u0026gt; \u0026lt;span style=\u0026#34;background-color:#00ffff\u0026#34;\u0026gt;\u0026lt;span style=\u0026#34;color:red\u0026#34;\u0026gt;**Bold red $LaTeX$ expression**\u0026lt;/span\u0026gt; in cyan background colour\u0026lt;/span\u0026gt; Red text in cyan background colour\nBold red text in cyan background colour\nBold red $LaTeX$ expression in cyan background colour\n","date":"2022-09-16T16:00:00Z","permalink":"/en/p/some-useful-markdown-noting-codes/","title":"Some useful markdown noting codes"},{"content":"How to make a combined brother printer driver AUR package TODO Analyze differences of file trees between the two types Analyze differences of the installation processes between the two types Intro Traditionally, Brother printers\u0026rsquo; drivers are divided with cupswrapper and lpr. The Arch-Wiki gives the solution on how to package them. But there\u0026rsquo;s some printers, e.g. DCP-B7500D and HL-L2350DW, have a combined driver with different file tree. This article is to record how I package.\nPreparation Arch-Linux PC (of cause) .deb or .rpm download link Have learn how to make AUR package https://wiki.archlinux.org/title/Arch_package_guidelines Write PKGBUILD Usually they have a common version 4.0.0\nJust make your own adaptation to my PKGBUILD (adapted from Roman Schmocker\u0026rsquo;s brother-hll2350dw package):\n# Maintainer: ous50 pkgname=brother-dcpb7500d printerModel=DCPB7500D pkgver=4.0.0 pkgrel=1 pkgdesc=\u0026#34;Printing driver for Brother DCP-B7500 printer\u0026#34; arch=(\u0026#34;i686\u0026#34; \u0026#34;x86_64\u0026#34; \u0026#34;armv7l\u0026#34;) //check the \u0026#39;/opt/brother/Printers/$printerModel/lpd\u0026#39; in the data.tar.gz url=\u0026#34;https://support.brother.com/g/b/producttop.aspx?c=in\u0026amp;lang=en\u0026amp;prod=dcpb7500d_as_cn\u0026#34; license=(\u0026#34;EULA\u0026#34;) groups=(\u0026#34;base-devel\u0026#34;) depends=(\u0026#39;cups\u0026#39; \u0026#39;ghostscript\u0026#39;) depends_x86_64=(\u0026#39;lib32-glibc\u0026#39;) install=\u0026#34;$pkgname.install\u0026#34; source=( \u0026#34;https://download.brother.com/welcome/dlf103663/dcpb7500dpdrv-$pkgver-1.i386.deb\u0026#34; \u0026#39;cupswrapper-license.txt\u0026#39; \u0026#39;lpr-license.txt\u0026#39; ) md5sums=( \u0026#34;c5d5c7febae0eab6254cb7332f4038c0\u0026#34; \u0026#39;97ad0cffd216059e9d1d3121899d8646\u0026#39; \u0026#39;5e87a3dc0f3e3438c088eda0f3565f0d\u0026#39; ) package(){ tar xf data.tar.gz // If you use .deb as your source, you must use this to fully decompress. (Not tested on .rpm packages) cp -R \u0026#34;$srcdir/opt\u0026#34; \u0026#34;$pkgdir/opt\u0026#34; ln -s \u0026#34;/opt/brother/Printers/DCPB7500D/lpd/$CARCH/rawtobr3\u0026#34; \u0026#34;$pkgdir/opt/brother/Printers/DCPB7500D/lpd/rawtobr3\u0026#34; ln -s \u0026#34;/opt/brother/Printers/DCPB7500D/lpd/$CARCH/brprintconflsr3\u0026#34; \u0026#34;$pkgdir/opt/brother/Printers/DCPB7500D/lpd/brprintconflsr3\u0026#34; install -d \u0026#34;$pkgdir/usr/lib/cups/filter/\u0026#34; ln -s \u0026#34;/opt/brother/Printers/DCPB7500D/cupswrapper/lpdwrapper\u0026#34; \u0026#34;$pkgdir/usr/lib/cups/filter/brother_lpdwrapper_DCPB7500D\u0026#34; install -d \u0026#34;$pkgdir/usr/share/cups/model/\u0026#34; ln -s \u0026#34;/opt/brother/Printers/DCPB7500D/cupswrapper/brother-DCPB7500D-cups-en.ppd\u0026#34; \u0026#34;$pkgdir/usr/share/cups/model\u0026#34; install -Dm644 \u0026#34;$srcdir/opt/brother/Printers/DCPB7500D/LICENSE_ENG.txt\u0026#34; \u0026#34;$pkgdir/usr/share/licenses/$pkgname/LICENSE_ENG.txt\u0026#34; install -Dm644 \u0026#34;$srcdir/opt/brother/Printers/DCPB7500D/LICENSE_JPN.txt\u0026#34; \u0026#34;$pkgdir/usr/share/licenses/$pkgname/LICENSE_JPN.txt\u0026#34; } Remember to get \u0026lsquo;cupswrapper-license.txt\u0026rsquo; and \u0026rsquo;lpr-license.txt\u0026rsquo; or just delete them from source\nFor better notice of user installation, you could write a xxx.install file to help(in my case the filename is brother-dcpb7500d.install):\npost_install() { post_upgrade; } post_upgrade() { echo \u0026#34;Restart CUPS service to load the new files\u0026#34; echo \u0026#34;You can now register your new printer using the web interface at:\u0026#34; echo \u0026#34; http://localhost:631/\u0026#34; } Test installation and upload After you have saved the PKGBUILD, do a test installation:\nmakepkg -rcsi restart cups.service after installation and go to check if your model has shown in the list:\nIf it\u0026rsquo;s shown, then you could upload it to AUR\nTips: In settings you might see an error like:\nFailed to search for a recommended driver: \u0026#39;The name org.fedoraproject.Config.Printing was not provided by any .service files\u0026#39; In this case you need to install system-config-printer package:\nsudo pacman -S system-config-printer Thanks Many thanks to Roman Schmocker. Without you it would be much harder to finish my AUR package and of course, this blog.\nThanks Arch-Wiki contributors for good documentations.\n","date":"2022-01-25T03:46:22Z","permalink":"/en/p/how-to-make-a-combined-brother-printer-driver-aur-package/","title":"How to make a combined brother printer driver AUR package"}]