This article is currently an experimental machine translation and may contain errors. If anything is unclear, please refer to the original Chinese version. I am continuously working to improve the translation.
Behind every burst bubble, there’s a batch of crying韭菜 (lettuces), and even more joyous garbage hunters having the time of their lives~ (just kidding)
The N1 box has become a thing of the past. But since my Orange Pi is still unrepairable, and Raspberry Pi prices are skyrocketing, the ARM64-powered N1 suddenly looks like a solid alternative. (Well, it just lacks GPIO pins.)
(I really should’ve gone with the N1 instead of the Orange Pi back then, but youth is full of regrets… so now I’m making up for it.)
Sure, the S905 chip can’t compete with the newer S905X3 found in modern foreign-branded set-top boxes, but the N1’s price and popularity have both dropped significantly. The price difference is often more than 2x, sometimes approaching 3x. So I picked up a brand-new, unscratched N1 (K-code intact) from Xianyu (a Chinese secondhand marketplace) for just 90 RMB.
Apart from USB 2.0, it’s practically a perfect little toy.
This time, I’m trying a new approach. With 2GB of RAM—quite generous—I decided to flash Armbian and run OpenWrt inside Docker. It’ll serve as both a server and a soft router. This way, I get access to the latest Linux kernel while running a clean OpenWrt instance—perfect for use as a dorm room router (since 5G Wi-Fi coverage is weak and speed isn’t great).
Since many existing guides for the N1 are outdated or inaccurate, I’ve compiled and verified everything from scratch. Note: This is a post-event write-up, so I missed capturing some steps with screenshots—my apologies.
0x00 Downgrade the Original Firmware
Connect the Phicomm N1 to a display via HDMI. (I personally used a USB capture card—it’s more convenient.)
Also connect a mouse. Power on the device and use the mouse to connect to Wi-Fi.
Then tap the “Firmware Version” four times in a row to reveal the Enable ADB option.
In your command prompt, run adb connect x.x.x.x, where x.x.x.x is the N1’s IP address.
Then run **adb shell reboot fastboot**—the box should reboot into fastboot mode.
Use a dual-headed USB cable to connect your PC’s USB port to the USB port on the N1 closest to the HDMI port.
Similar to iPlay30, you can install the fastboot driver automatically via Windows Update.
Now, flash the older boot, bootloader, and recovery images that support USB booting:
1 | fastboot flash bootloader N1bootloader.img |
Download the three required files here.
After flashing, run fastboot reboot. The device should boot back into Android (the version number may not change—that’s normal, but the bootloader has been downgraded).
0x01 Prepare the Linux Boot Drive
You can download the latest image compiled by @150balbes: https://disk.yandex.com/d/srrtn6kpnsKz2/RK_AML_AW.
I chose the Debian headless (no GUI) version. No need to extract—just use balenaEtcher to write the image directly to a USB drive.
Since this image supports multiple devices, some boot files need modification to boot correctly.
After writing, Windows should automatically detect the boot partition.
Open the extlinux.conf file inside the extlinux folder, comment out the FDT and APPEND lines under rk-3399, then uncomment the APPEND line under aml s9xxx, and add FDT /dtb/amlogic/meson-gxl-s905d-phicomm-n1.dtb at the end.
If you’re unsure, just replace the entire extlinux.conf content with the following (this ensures the correct dtb is used):
1 | LABEL Armbian |
Rename the u-boot-s905x-s912 file in the boot partition to u-boot.ext. (The N1 uses the S905D SoC, so the S905X u-boot is compatible.)
Add a new file create-mbr-linux.sh to the boot partition with the following content (a script to create an MBR partition table):
1 |
|
Boot drive preparation is now complete.
0x02 Boot into Linux and Flash to eMMC
Back in Android, run adb connect x.x.x.x && adb reboot update to reboot into update mode.
Quickly insert the USB drive into the USB port next to HDMI right after running the command—the system should boot from the USB drive. Do NOT insert the USB drive before or during Android boot, or ext4 permissions may get corrupted.
If it boots into recovery mode instead, that means the USB wasn’t detected. Power off and repeat the ADB command to re-enter the boot process.
After Linux boots, complete initial setup and log in as root.
Run the two scripts: /boot/create-mbr-linux.sh and install-aml.sh.
Wait a moment. If no errors occur, power off, remove the USB drive, and reboot—the system should now boot from eMMC.
p.s.: The N1’s default boot method is unusual—it lacks an MBR partition table, which may cause the install script to fail. That’s why we first run create-mbr-linux.sh to create the partition table before installing.
0x03 Fix the High Average Load Bug in Linux
Reverse-compile the dtb file:dtc -I dtb -O dts -o n1.dts /boot/dtb/amlogic/meson-gxl-s905d-phicomm-n1.dtb
Edit the n1.dts file using vim.
Comment out the phandle = < 0x21 >; line inside interrupt-controller@9880:
1 | interrupt-controller@9880 { |
Then recompile and replace the original dtb:
1 | dtc -I dts -O dtb -o n1.dtb n1.dts |
After reboot, the high load average issue should be resolved.
0x04 Install Docker and Change Package Sources
Skipped—there are already good guides on Enshan Forum: https://www.right.com.cn/forum/forum.php?mod=viewthread&tid=430903.
0x05 Set Up Wireless Hotspot
Run sudo armbian-config, go to Network → Hotspot. Wait for the required packages to install, then exit.
Edit /etc/default/hostapd and uncomment: DAEMON_CONF="/etc/hostapd.conf".
Run sudo systemctl enable hostapd to ensure hostapd starts on boot.
Replace the content of /etc/hostapd.conf with the following (default is 5G band; change hw_mode and channel for 2.4G):
1 | # Wi-Fi name |
Then edit /etc/network/interfaces and set iface wlan0 inet manual.
Run sudo systemctl disable NetworkManager to disable Debian’s built-in network manager.
sudo reboot. After reboot, your phone should detect the Wi-Fi. It may hang at “Obtaining IP address,” but you can connect using a static IP—this means the hotspot is working.
(p.s. If hotspot fails, try sudo hostapd -d /etc/hostapd.conf to debug manually. You can also check ps -ef | grep hostapd to see if hostapd is running.)
(p.s.s. I discovered a weird issue: without ht_capab=[HT40+] in the IEEE 802.11n section, 5G 80MHz Wi-Fi fails to start with error Could not set channel for kernel driver. The exact cause is unclear from hostapd docs. But with current settings, 5G 80MHz Wi-Fi (433 Mbps) works fine.)
0x06 Running OpenWRT via Docker
Run sudo docker import https://downloads.openwrt.org/releases/21.02.0/targets/armvirt/64/openwrt-21.02.0-armvirt-64-default-rootfs.tar.gz openwrt:21.02.0 to import the official OpenWRT Docker image.
Enable promiscuous mode on eth0: sudo ip link set eth0 promisc on (allows multiple MAC addresses on one interface).
Now configure networking between OpenWRT and the host.
First, an excerpt from Docker Docs about macvlan:
Some applications, especially legacy applications or applications which monitor network traffic, expect to be directly connected to the physical network. In this type of situation, you can use themacvlannetwork driver to assign a MAC address to each container’s virtual network interface, making it appear to be a physical network interface directly connected to the physical network. In this case, you need to designate a physical interface on your Docker host to use for themacvlan, as well as the subnet and gateway of themacvlan. You can even isolate yourmacvlannetworks using different physical network interfaces.
And from Docker Docs about bridge:
In terms of Docker, a bridge network uses a software bridge which allows containers connected to the same bridge network to communicate, while providing isolation from containers which are not connected to that bridge network. The Docker bridge driver automatically installs rules in the host machine so that containers on different bridge networks cannot communicate directly with each other.
My approach: pass the host’s eth0 to OpenWRT via macvlan, using eth0 as WAN (get IP via DHCP). Then create a bridge LAN to connect OpenWRT’s LAN with Armbian’s LAN.
Create bridge-lan interface:1
2
3
4
5
6
7
8
9
10vim /etc/network/interfaces.d/bridge
# Add the following content. OpenWRT IP: 10.10.10.1, Armbian IP: 10.10.10.2
auto br-lan
iface br-lan inet static
address 10.10.10.2
netmask 255.255.255.0
dns-nameserver 10.10.10.1
gateway 10.168.10.1
bridge_ports wlan0In hostapd config, uncommentbridge=br-lanCreate Docker networks:
1 | # Create LAN network lanet |
0x06 Direct NAT and DHCP Setup on Armbian for Router Functionality
Originally, I wanted the box to act like a regular router: connect via Ethernet, obtain IP via DHCP or PPPoE, then assign internal IPs to connected devices.
However, I found Docker’s macvlan setup problematic—it requires specifying the upstream router’s subnet and gateway upfront. (I suspect Docker needs this to configure firewall and routing rules, and since it can’t dynamically get DHCP info, this becomes a hard requirement. This is just my theory—might not be accurate.) Either way, it defeats the purpose of automatic DHCP detection.
So I switched plans: skip OpenWRT and implement all routing features directly on Armbian.
Install dnsmasq (DHCP server) and enable at boot:
sudo apt-get install dnsmasqsudo systemctl enable dnsmasqConfigure wlan0 interface:
1
2
3
4
5
6
7sudo vim /etc/network/interfaces # Edit network interfaces
# Change wlan0 settings to:
allow-hotplug wlan0
iface wlan0 inet static
address 10.0.0.1
netmask 255.255.255.0Edit dnsmasq config:
1
2
3
4
5
6sudo vim /etc/dnsmasq.conf # Edit config
# Add:
interface=wlan0
dhcp-range=10.0.0.2,10.0.0.100,12h
dhcp-option=6,10.0.0.1This provides DHCP service on wlan0, IP range 10.0.0.2–10.0.0.100, 12h lease, gateway 10.0.0.1.
Enable kernel IP forwarding permanently by adding to
/etc/sysctl.conf:net.ipv4.ip_forward=1Set up iptables NAT and forwarding rules—add to startup script:
1
2
3
4
5
6
7sudo vim /etc/rc.local # Edit startup script
# Add before exit 0:
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# Only allow established/related connections from eth0 to wlan0
iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPTReboot. Connect to the Wi-Fi broadcasted by the N1—you should now have internet access.
0x07 IPv6 Configuration (Bridge Mode)
In universities, IPv6 access is often free and doesn’t require login, so setting it up is worthwhile.
(Though I actually went with the 0x07.1 method below.)
Get IPv6 address on eth0
Debian should auto-acquire a global IPv6 address. Check with
ifconfig. If not, try addingiface eth0 inet6 autoto/etc/network/interfaces.However, due to Nanjing University’s weird eduroam network (see this post), Armbian couldn’t get an IPv6 address. My workaround: manually assign one.
1
2
3
4sudo ifconfig eth0 inet6 add 2001:250:5002:8000::2:d666/64
# Ping multicast router address to discover gateway
ping6 ff02::2%eth0
sudo route -A inet6 add default gw fe80::1251:72ff:fe1b:249f dev eth0Follow instructions from http://www.dohooe.com/2017/02/26/455.html to complete setup.
0x07.1 IPv6 Proxy for Free Internet Access
While IPv6 allows free access on campus, many websites still don’t support it.
So I opted to proxy IPv4 traffic over IPv6. Benefits:
- Access home network resources directly from campus via the proxy.
- Free access to all IPv4 and IPv6 websites.
Initially considered SSH tunneling, but performance was poor, connections unstable, and it doesn’t support transparent proxying (e.g., RDP can’t go through SOCKS5).
Switched to the popular tool: v2Ray.
Set up a server with both IPv4 and IPv6. (If you don’t have one, consider the IPv6 bridging method above.)
Run the proxy server. Sample config below. Note:
listen: "[::]"means listening on IPv6.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20{
"inbounds": [{
"port": 9000,
"listen": "[::]",
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "c95f3ab6-62c2-4426-8027-7833c7ba2e86",
"level": 1,
"alterId": 0
}
]
}
}],
"outbounds": [{
"protocol": "freedom",
"settings": {}
}]
}Setup details omitted.
Install v2Ray client on Armbian:
sudo apt install v2rayClient config (for reference):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75{
"inbounds":[
// This inbound is for my phone/tablet to connect via LAN (relay). Remove if not needed.
{
"port": 8503,
"listen": "172.26.73.226",
"protocol": "vmess",
"settings": {
"clients": [{
"id": "c95f3ab6-62c2-4426-8027-7833c7ba2e86",
"level": 1,
"alterId": 0
}]
}
},
{
"port":12315,
"protocol":"dokodemo-door",
"settings":{
"network":"tcp,udp",
"followRedirect":true
},
"sniffing":{
"enabled":true,
"destOverride":[
"http",
"tls"
]
}
}
],
"outbounds":[
// First outbound is default proxy
{
"tag":"proxy",
"protocol":"vmess",
"settings":{
"vnext":[
{
// Replace these with your server settings!
"address":"ipv6.xxxxx.com",
"port":9000,
"users":[
{
"id":"c95f3ab6-62c2-4426-8027-7833c7ba2e86",
"alterId":0
}
]
}
]
}
},
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
}
],
"routing":{
"domainStrategy":"IPOnDemand",
"rules":[
// Don't proxy 172.x campus network
// Don't proxy 10.x Armbian internal network
// Proxy everything else
{
"type":"field",
"outboundTag":"direct",
"ip":[
"10.0.0.0/8",
"172.0.0.0/8"
]
}
]
}
}After config, run:
sudo systemctl enable v2ray && sudo systemctl start v2rayConfigure gateway. Add to
/etc/rc.localbeforeexit 0:1
2
3
4
5iptables -t nat -N V2RAY
# Only allow internal network to use transparent proxy
iptables -t nat -A V2RAY -p tcp -s 10.0.0.0/24 -j REDIRECT --to-ports 12315
iptables -t nat -A V2RAY -p udp -s 10.0.0.0/24 -j REDIRECT --to-ports 12315
iptables -t nat -A PREROUTING -p all -j V2RAYReboot. Connect to the Wi-Fi from Armbian—no login required, internet should work.
0x08 Mission Accomplished!
Now you can enjoy both a personal playground server and a home-like network environment in your dorm. :P
Appendix 0x00 Bluetooth Driver Issue on Armbian
The default image compiled by @150balbes has Bluetooth disabled. You need to replace the dtb file.
Download the correct dtb: https://www.right.com.cn/forum/forum.php?mod=viewthread&tid=4057309
Bluetooth activation guide: https://www.right.com.cn/forum/thread-517710-1-1.html
Direct download link: https://pan.lyc8503.net/Public/%E5%9B%BA%E4%BB%B6/n1/meson-gxl-s905d-phicomm-n1.dtb
To enable Bluetooth, download and replace /boot/dtb/amlogic/meson-gxl-s905d-phicomm-n1.dtb (remember to back up!).
Tested and confirmed: Bluetooth works perfectly after replacement—Armbian runs flawlessly.
This article is licensed under the CC BY-NC-SA 4.0 license.
Author: lyc8503, Article link: https://blog.lyc8503.net/en/post/phicomm-n1/
If this article was helpful or interesting to you, consider buy me a coffee¬_¬
Feel free to comment in English below o/