Skip to content

placebeyondtheclouds/pikvm-zero2w-eth

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 

Repository files navigation

Custom DIY IP KVM, pikvm on Raspberry Pi Zero 2W with ethernet

Description

Based on https://github.com/pikvm/pikvm

Use cases:

  • When a secure, truly open-source solution (unlike some closed-source KVM products are) is needed
  • A jump device to Wake-on-LAN other devices
  • Building with off-the-shelf components as a safeguard against supply chain attacks

Main differences

between my build and the official DIY V2 build instructions for Raspberry Pi Zero 2 W:

  • My hardware setup has ENC28J60 chip based ethernet adapter, connected to GPIO through SPI protocol (four-wire serial bus)
  • Full duplex mode for the ethernet adapter.
  • I2C OLED display
  • Didn't utilize ATX power control
  • Powered by the keyboard/mouse interface cable plugged into the USB socket of the rpi (can be changed to external power by cutting +5V wire in this cable and adding another cable plugged into PWR socket of the rpi)
  • RTC module

Build pictures

untitled-1.jpg untitled-2.jpg untitled-3.jpg
untitled-4.jpg untitled-5.jpg untitled-6.jpg
untitled-7.jpg untitled-8.jpg untitled-9.jpg
untitled-10.jpg untitled-11.jpg untitled-13.jpg
untitled-14.jpg untitled-15.jpg untitled-16.jpg
untitled-17.jpg untitled-18.jpg untitled-19.jpg
untitled-20.jpg untitled-21.jpg Screenshot from 2024-09-27 22-17-45.png

Parts list

Software

download https://files.pikvm.org/images/v2-hdmi-zero2w-latest.img.xz

or compile from source

Wiring

  • ENC28J60 board is connected to SPI0 bus (SPI0 pins are GPIO 7, 8, 9, 10, 11)
ENC28J60 RPI GPIO
GND GND (Pin 20)
VCC 3.3V (Pin 17)
CS GPIO8 CE0 (Pin 24)
SCK GPIO11 SCLK (Pin 23)
SI GPIO10 MOSI (Pin 19)
SO GPIO9 MISO (Pin 21)
INT GPIO 25 (Pin 22)
  • DS1307 chip RTC module is connected to I2C bus (default address 0x68). If decide to use the module, then the screen wires need to be soldered to the back of the board.

  • connect OLED module to I2C. By default the display is set to SPI mode. To set the display to I2C mode, remove the resistor R1 and change the address (the default is 0x3D) to 0x3C by shorting the resistor R2. OLED module I2C bus wiring:

OLED board RPI GPIO
VCC 3.3V (pin 1)
DIN SDA (pin 3)
CLK SCL (pin 5)
GND GND (pin 6)

Setting up

  • Flash the image, then remount and edit the file pikvm.txt on the boot partition

  • nano pikvm.txt

    •   ETH_ADDR=192.168.1.150/24
        ETH_DNS=192.168.1.1
        ETH_GW=192.168.1.1
        WIFI_ESSID='tempwifi'
        WIFI_PASSWD='9eu8xdexm08rfh0w9erf9ewf09wexr'
        WIFI_REGDOM=CH
        WIFI_ADDR=192.168.18.150/24
        WIFI_DNS=192.168.18.1
        WIFI_GW=192.168.18.1
      
  • Boot

  • http://192.168.18.150 user admin, password admin

  • ssh root@192.168.18.150 user root, password root

  • Change the passwords:

    • rw
    • passwd root
    • kvmd-htpasswd set admin
    • ro
  • Update:

    Make sure there is Internet connectivity

    • rw
    • pacman -Syy
    • pacman -S pikvm-os-updater iperf3 chrony i2c-tools
    • pikvm-update
    • ro
    • on error failed to synchronize any databases:
      • rm -f /var/lib/pacman/db.lck
  • Disable IPv6:

    • rw
    • echo ipv6.disable_ipv6=1 >> /boot/cmdline.txt
    • ro
  • Set up the ethernet module:

    • rw

    • nano /boot/config.txt

      •   dtparam=spi=on
          dtoverlay=enc28j60,int_pin=25,speed=20000000
        
    • ro

    • sudo /sbin/reboot

    • lsmod

    • dmesg | grep Ethernet

    • switch to full duplex:

      • nano /etc/systemd/system/enc28j60-full-duplex.service

        •     [Unit]
              Description=ENC28J60 Full Duplex
              After=multi-user.target
          
              [Service]
              Type=simple
              Restart=always
              ExecStartPre=/bin/sleep 60
              ExecStart=ifconfig eth0 down && ethtool -s eth0 speed 10 duplex full autoneg off && systemctl restart systemd-networkd.service && systemctl restart systemd-networkd.service && ifconfig eth0 up
          
              [Install]
              WantedBy=multi-user.target
          
      • chmod 644 /etc/systemd/system/enc28j60-full-duplex.service

      • systemctl daemon-reload

      • systemctl enable enc28j60-full-duplex.service

      • systemctl start enc28j60-full-duplex.service

      • ro

  • Test the stability of the ethernet connection:

    • on the pikvm:

      • iperf3 -s 192.168.1.150
    • on the host machine:

      • iperf3 -c 192.168.1.150 -P 2 -t 30
  • Set up the OLED display for use with I2C:

    • rw

    • nano /boot/config.txt

      •   dtparam=i2c_arm=on
        
    • nano /etc/modules-load.d/raspberrypi.conf

      •   i2c-dev
        
    • systemctl enable --now kvmd-oled kvmd-oled-reboot kvmd-oled-shutdown

    • ro

    • sudo /sbin/reboot

    • i2cdetect -y 1 should display 3c at the address 0x3C

  • (optional) Set up rtc:

    • rw

    • nano /boot/config.txt

      •   dtoverlay=i2c-rtc,ds1307
        
    • sudo /sbin/reboot

    • i2cdetect -y 1 should display UU at the address 0x68

    • timedatectl set-timezone Asia/Shanghai

    • systemctl enable chronyd

    • systemctl start chronyd

    • date

    • hwclock --show

    • hwclock --systohc, do it once to write the current time to the RTC

    • add read from the hardware clock at boot:

      • nano /etc/systemd/system/hwclock-sync.service

        • [Unit]
          Description=Sync hwclock from system clock
          After=systemd-modules-load.service
          Before=systemd-timesyncd.service
          
          [Service]
          Type=oneshot
          ExecStart=/usr/bin/hwclock --hctosys
          RemainAfterExit=yes
          
          [Install]
          WantedBy=multi-user.target
          
      • chmod 644 /etc/systemd/system/hwclock-sync.service

      • systemctl daemon-reload

      • systemctl enable hwclock-sync.service

    • ro

  • (optional) Change ethernet ip:

    • rw

    • nano /etc/systemd/network/eth0.network

      •   [Match]
          Name=eth0
        
        
          [Network]
          Address=192.168.1.150/24
          Gateway=192.168.1.1
          DNS=192.168.1.1
        
        
    • systemctl enable systemd-networkd.service

    • systemctl enable systemd-resolved.service

    • systemctl restart systemd-networkd.service

    • systemctl restart systemd-resolved.service

    • or temporarily:

      • ip a show
      • ip link set eth0 up
      • ip a add 192.168.1.150/24 broadcast + dev eth0
        • ip a del 192.168.1.150/24 dev eth0
      • ip r show
      • ip r add 0.0.0.0/0 via 192.168.1.1 dev eth0
    • ro

    • ethtool eth0

  • (optional) Change wifi ip and parameters (https://docs.pikvm.org/wifi/#setting-up-wi-fi-manually):

    • rw

    • nano /etc/systemd/network/wlan0.network

      •   [Match]
          Name=wlan0
        
          [Network]
          Address=192.168.18.150/24
          DNS=192.168.18.1
          DNSSEC=no
        
          [Route]
          Gateway=192.168.18.1
          # https://github.com/pikvm/pikvm/issues/583
          Metric=50
        
      • wpa_passphrase 'tempwifi' '9eu8xdexm08rfh0w9erf9ewf09wexr' > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

      • chmod 640 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

      • systemctl enable wpa_supplicant@wlan0.service

      • systemctl start wpa_supplicant@wlan0.service

      • ro

  • Disable wifi:

    • rw
    • echo > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
    • systemctl disable wpa_supplicant@wlan0.service
    • systemctl stop wpa_supplicant@wlan0.service
    • ro
  • Disable talking to the outside STUN servers:

    • rw
    • systemctl disable --now kvmd-janus
    • systemctl enable --now kvmd-janus-static
    • ro
  • Configure the KVM software

    • rw
    • nano /etc/kvmd/override.yaml An indent of 4 spaces is used. Comments starts with the # symbol. more: https://technotim.live/posts/pikvm-at-scale/#pikvm-config
      • kvmd:
            gpio:
                drivers:
                    wol_server1:
                        type: wol
                        mac: 00:00:00:00:00:00
                    wol_server2:
                        type: wol
                        mac: 00:00:00:00:00:00
                    reboot:
                        type: cmd
                        cmd: [/usr/bin/sudo, reboot]
                    restart_service:
                        type: cmd
                        cmd: [/usr/bin/sudo, systemctl, restart, kvmd]
                scheme:
                    pikvm_led:
                        pin: 0
                        mode: input
                    wol_server1:
                        driver: wol_server1
                        pin: 0
                        mode: output
                        switch: false
                    wol_server2:
                        driver: wol_server2
                        pin: 0
                        mode: output
                        switch: false
                    reboot_button:
                        driver: reboot
                        pin: 0
                        mode: output
                        switch: false
                    restart_service_button:
                        driver: restart_service
                        pin: 0
                        mode: output
                        switch: false
                view:
                    table:
                        - ["#server3", ]
                        - ["#server2", "wol_server1 | WoL"]
                        - ["#server1", "wol_server2 | WoL"]
                        - ["#PiKVM", "pikvm_led|green", "restart_service_button|confirm|Service", "reboot_button|confirm|Reboot"]
        
    • ro

Results

  • It's working as it supposed to
  • Power consumption 2.5W when streaming and half of that when idle
  • The adapter doesn't support auto-negotiation, so full duplex is not supposed to work with auto-negotiation on the other end (requres setting full duplex mode manually on both ends), but it is working with every usb-ethernet adapter I tested as well as with tl-sf1008m 100M switch. Default half-duplex mode connection is unstable and hangs on traffic.
  • Ethernet stability:
    • [ ID] Interval           Transfer     Bitrate         Retr
      [  5]   0.00-30.00  sec  20.5 MBytes  5.73 Mbits/sec    2             sender
      [  5]   0.00-30.01  sec  18.9 MBytes  5.28 Mbits/sec                  receiver
      [  7]   0.00-30.00  sec  14.0 MBytes  3.91 Mbits/sec    2             sender
      [  7]   0.00-30.01  sec  11.9 MBytes  3.32 Mbits/sec                  receiver
      [SUM]   0.00-30.00  sec  34.5 MBytes  9.65 Mbits/sec    4             sender
      [SUM]   0.00-30.01  sec  30.8 MBytes  8.60 Mbits/sec                  receiver
      

References

About

Custom DIY IP KVM, pikvm on Raspberry Pi Zero 2W with ethernet, build notes

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published