├── Dockerfile ├── README.md ├── images ├── 2020_08_05_17_18_52_1015x1010.jpg ├── 2020_08_05_17_20_35_1008x927.jpg ├── 2020_08_05_17_21_34_1008x1000.jpg ├── 2020_08_05_17_24_30_971x739.jpg ├── 2020_08_05_17_32_21_581x618.jpg ├── 2020_08_05_17_33_06_791x561.jpg ├── 2020_08_05_17_33_58_1082x849.jpg ├── 2020_08_05_17_35_10_939x480.jpg ├── 2020_08_05_17_36_18_546x311.jpg └── 2020_08_05_17_36_57_574x294.jpg ├── mirrorlist ├── nginx.conf ├── pkgs ├── kvmd-1.82-1-any.pkg.tar.xz ├── kvmd-platform-v0-hdmiusb-x86-1.82-1-any.pkg.tar.xz ├── kvmd-webterm-0.24-1-any.pkg.tar.zst ├── ttyd-1.6.1-2-x86_64.pkg.tar.xz └── ustreamer-1.19-1-x86_64.pkg.tar.xz ├── supervisord.conf └── vcgencmd /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM archlinux:20200705 2 | MAINTAINER feipyang 3 | WORKDIR / 4 | EXPOSE 443 5 | EXPOSE 80 6 | 7 | # Transfer pkgs 8 | COPY pkgs /mnt/pkgs 9 | COPY mirrorlist /etc/pacman.d/mirrorlist 10 | RUN mkdir -p /opt/vc/bin/ 11 | COPY vcgencmd /opt/vc/bin/vcgencmd 12 | 13 | # Install packages 14 | RUN pacman -Sy && cd /mnt/pkgs && pacman -U kvmd-1.82-1-any.pkg.tar.xz kvmd-platform-v0-hdmiusb-x86-1.82-1-any.pkg.tar.xz kvmd-webterm-0.24-1-any.pkg.tar.zst ttyd-1.6.1-2-x86_64.pkg.tar.xz ustreamer-1.19-1-x86_64.pkg.tar.xz --noconfirm && pacman -S net-tools supervisor --noconfirm && chmod 777 /opt/vc/bin/vcgencmd 15 | # Bug-fix, install inetutils for hostname command in web-terminal 16 | RUN pacman -S inetutils --noconfirm 17 | 18 | COPY nginx.conf /etc/kvmd/nginx/nginx.conf 19 | COPY supervisord.conf /supervisord.conf 20 | CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"] 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pi-KVM on X86 2 | 3 | ### What is `Pi-KVM on X86` 4 | Run [Pi-KVM](https://github.com/pikvm) on x86 platform using [docker](http://www.docker.com). 5 | 6 | ### Why 7 | * Cost-Saving(HDMI-USB Dongle + Arduino Leonard + USB-TTL is enough). 8 | * One-line for starting up. 9 | * Could run both on Physical-Server Or VMs. 10 | * May support more poweful Dongle(which support 4K?). 11 | 12 | ### Building Components 13 | | Hardware/Price| Reference URL| 14 | |--------------------------|-----------| 15 | | HDMI-USB Dongle/35 RMB/USD 4.61,| [Taobao Link](https://item.taobao.com/item.htm?spm=a1z09.2.0.0.6eab2e8dKQmeGU&id=619294316849&_u=5mm2aq95e70) | 16 | | Arduino Leonard R3/26 RMB/USD 3.74| [Taobao Link](https://item.taobao.com/item.htm?spm=a1z09.2.0.0.6eab2e8dKQmeGU&id=586434235953&_u=5mm2aq9da0c) | 17 | | USB-TTL PL2303/3.1 RMB/USD 0.45 | [Taobao Link](https://item.taobao.com/item.htm?spm=a230r.1.14.45.68342e113ebu59&id=534917547321&ns=1&abbucket=12#detail) | 18 | | HDMI Line/7 RMB/USD 1 | No Link | 19 | 20 | ### Preparation 21 | Flash Arduino : 22 | [https://github.com/pikvm/pikvm/blob/master/pages/flashing_hid.md](https://github.com/pikvm/pikvm/blob/master/pages/flashing_hid.md) 23 | 24 | Install Docker on your own x86 machine: 25 | Take Ubuntu for example: 26 | [https://docs.docker.com/engine/install/ubuntu/](https://docs.docker.com/engine/install/ubuntu/) 27 | Or if you are using ArchLinux: `sudo pacman -S docker --noconfirm` 28 | 29 | Check docker installation. 30 | ``` 31 | sudo docker version 32 | Client: 33 | Version: 19.03.11-ce 34 | ... 35 | Server: 36 | Engine: 37 | Version: 19.03.11-ce 38 | ... 39 | ``` 40 | ### Building Steps 41 | #### Hardware 42 | 1. Insert USB Dongle into NUC: 43 | 44 | ![./images/2020_08_05_17_18_52_1015x1010.jpg](./images/2020_08_05_17_18_52_1015x1010.jpg) 45 | 46 | Your Linux machine `dmesg` output: 47 | ``` 48 | [31359.458026] usb 2-2: new high-speed USB device number 10 using xhci_hcd 49 | [31359.601274] usb 2-2: New USB device found, idVendor=534d, idProduct=2109, bcdDevice=21.00 50 | [31359.601281] usb 2-2: New USB device strings: Mfr=1, Product=0, SerialNumber=0 51 | [31359.601284] usb 2-2: Manufacturer: MACROSILICON 52 | [31359.602611] uvcvideo: Found UVC 1.00 device (534d:2109) 53 | [31359.603462] uvcvideo 2-2:1.0: Entity type for entity Processing 2 was not initialized! 54 | [31359.603468] uvcvideo 2-2:1.0: Entity type for entity Camera 1 was not initialized! 55 | [31359.608494] hid-generic 0003:534D:2109.0008: hiddev2,hidraw3: USB HID v1.10 Device [MACROSILICON] on usb-0000:00:14.0-2/input4 56 | ``` 57 | 2. Insert USB-TTL into NUC: 58 | 59 | ![./images/2020_08_05_17_20_35_1008x927.jpg](./images/2020_08_05_17_20_35_1008x927.jpg) 60 | 61 | Your Linux `dmesg` output: 62 | 63 | ``` 64 | [31542.623993] usb 2-3.3: new full-speed USB device number 11 using xhci_hcd 65 | [31542.717407] usb 2-3.3: New USB device found, idVendor=067b, idProduct=2303, bcdDevice= 3.00 66 | [31542.717411] usb 2-3.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0 67 | [31542.717413] usb 2-3.3: Product: USB-Serial Controller 68 | [31542.717414] usb 2-3.3: Manufacturer: Prolific Technology Inc. 69 | [31542.724760] pl2303 2-3.3:1.0: pl2303 converter detected 70 | [31542.725971] usb 2-3.3: pl2303 converter now attached to ttyUSB0 71 | ``` 72 | 73 | 3. USB-TTL to Arduino Leonardo: 74 | 75 | ![./images/2020_08_05_17_21_34_1008x1000.jpg](./images/2020_08_05_17_21_34_1008x1000.jpg) 76 | 77 | 4. Remote-machine(RPI3) : 78 | 79 | ![./images/2020_08_05_17_24_30_971x739.jpg](./images/2020_08_05_17_24_30_971x739.jpg) 80 | 81 | #### Software 82 | Pull back the docker images: 83 | 84 | ``` 85 | $ sudo docker pull feipyang/kvmdx86:20200805 86 | $ sudo docker images | grep kvmdx86 87 | feipyang/kvmdx86 20200805 f575b0e5f207 21 minutes ago 697MB 88 | ``` 89 | Run docker instance: 90 | 91 | ``` 92 | $ sudo docker run -d -p443:443 -p80:80 --device=/dev/ttyUSB0:/dev/kvmd-hid --device=/dev/video0:/dev/kvmd-video feipyang/kvmdx86:20200805 93 | 425e99a4a61223530f0544b2c805ba7147c58aea001c430beb68b0710c743384 94 | $ sudo docker ps 95 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 96 | 425e99a4a612 feipyang/kvmdx86:20200805 "/usr/bin/supervisor…" 19 seconds ago Up 17 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp boring_davinci 97 | 98 | ``` 99 | Now using firefox or chromium open `https://127.0.0.1`, you get the pi-kvm webpage. 100 | 101 | ![./images/2020_08_05_17_32_21_581x618.jpg](./images/2020_08_05_17_32_21_581x618.jpg) 102 | 103 | Using `admin/admin` for login: 104 | 105 | ![./images/2020_08_05_17_33_06_791x561.jpg](./images/2020_08_05_17_33_06_791x561.jpg) 106 | 107 | Click `KVM` for viewing the pi's output: 108 | 109 | ![./images/2020_08_05_17_33_58_1082x849.jpg](./images/2020_08_05_17_33_58_1082x849.jpg) 110 | 111 | Test keyboard(physical or virtual): 112 | 113 | ![./images/2020_08_05_17_35_10_939x480.jpg](./images/2020_08_05_17_35_10_939x480.jpg) 114 | 115 | Go back to see `Terminal`: 116 | 117 | ![./images/2020_08_05_17_36_57_574x294.jpg](./images/2020_08_05_17_36_57_574x294.jpg) 118 | 119 | Checking log: 120 | 121 | ``` 122 | sudo docker logs -f 425e99a4a612 | more 123 | 2020-08-05 09:31:37,846 CRIT Supervisor is running as root. Privileges were not dropped because no user is specified in the config file. If you intend to run as root, you can set user=root 124 | in the config file to avoid this message. 125 | 2020-08-05 09:31:37,851 INFO supervisord started with pid 1 126 | 2020-08-05 09:31:38,855 INFO spawned: 'kvmd' with pid 8 127 | 2020-08-05 09:31:38,860 INFO spawned: 'kvmd-nginx' with pid 9 128 | 2020-08-05 09:31:38,863 INFO spawned: 'runpriledge' with pid 10 129 | 2020-08-05 09:31:38,867 INFO spawned: 'ttyd' with pid 11 130 | kvmd.apps.kvmd INFO --- Using internal auth service 'htpasswd' 131 | kvmd.keyboard.keysym INFO --- Reading keyboard layout /usr/share/kvmd/keymaps/en-us ... 132 | kvmd.plugins.hid.serial INFO --- Starting HID daemon ... 133 | kvmd.plugins.hid.serial INFO --- Started HID pid=18 134 | kvmd.apps.kvmd.streamer INFO --- Installing SIGUSR2 streamer handler ... 135 | kvmd.apps.kvmd.http INFO --- ======== Running on http://unix:/run/kvmd/kvmd.sock: ======== 136 | ... 137 | ``` 138 | ### Things to be done 139 | 1. Log could not be shown on webpage 140 | 2. Need do more testing on different Linux distribution. 141 | 3. Using it in vm(virtualbox/kvm/vmware, etc) 142 | -------------------------------------------------------------------------------- /images/2020_08_05_17_18_52_1015x1010.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/images/2020_08_05_17_18_52_1015x1010.jpg -------------------------------------------------------------------------------- /images/2020_08_05_17_20_35_1008x927.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/images/2020_08_05_17_20_35_1008x927.jpg -------------------------------------------------------------------------------- /images/2020_08_05_17_21_34_1008x1000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/images/2020_08_05_17_21_34_1008x1000.jpg -------------------------------------------------------------------------------- /images/2020_08_05_17_24_30_971x739.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/images/2020_08_05_17_24_30_971x739.jpg -------------------------------------------------------------------------------- /images/2020_08_05_17_32_21_581x618.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/images/2020_08_05_17_32_21_581x618.jpg -------------------------------------------------------------------------------- /images/2020_08_05_17_33_06_791x561.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/images/2020_08_05_17_33_06_791x561.jpg -------------------------------------------------------------------------------- /images/2020_08_05_17_33_58_1082x849.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/images/2020_08_05_17_33_58_1082x849.jpg -------------------------------------------------------------------------------- /images/2020_08_05_17_35_10_939x480.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/images/2020_08_05_17_35_10_939x480.jpg -------------------------------------------------------------------------------- /images/2020_08_05_17_36_18_546x311.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/images/2020_08_05_17_36_18_546x311.jpg -------------------------------------------------------------------------------- /images/2020_08_05_17_36_57_574x294.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/images/2020_08_05_17_36_57_574x294.jpg -------------------------------------------------------------------------------- /mirrorlist: -------------------------------------------------------------------------------- 1 | Server = http://mirrors.163.com/archlinux/$repo/os/$arch 2 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes 4; 2 | 3 | # error_log /tmp/kvmd-nginx.error.log; 4 | error_log stderr; 5 | 6 | include /usr/share/kvmd/extras/*/nginx.ctx-main.conf; 7 | 8 | events { 9 | worker_connections 1024; 10 | use epoll; 11 | multi_accept on; 12 | } 13 | 14 | http { 15 | types_hash_max_size 4096; 16 | server_names_hash_bucket_size 128; 17 | access_log off; 18 | 19 | include /etc/kvmd/nginx/mime-types.conf; 20 | default_type application/octet-stream; 21 | charset utf-8; 22 | 23 | sendfile on; 24 | tcp_nodelay on; 25 | tcp_nopush on; 26 | keepalive_timeout 10; 27 | client_max_body_size 4k; 28 | 29 | client_body_temp_path /tmp/kvmd-nginx.client_body_temp; 30 | fastcgi_temp_path /tmp/kvmd-nginx.fastcgi_temp; 31 | proxy_temp_path /tmp/kvmd-nginx.proxy_temp; 32 | scgi_temp_path /tmp/kvmd-nginx.scgi_temp; 33 | uwsgi_temp_path /tmp/kvmd-nginx.uwsgi_temp; 34 | 35 | include /etc/kvmd/nginx/kvmd.ctx-http.conf; 36 | include /usr/share/kvmd/extras/*/nginx.ctx-http.conf; 37 | 38 | server { 39 | listen 80; 40 | server_name localhost; 41 | return 301 https://$host$request_uri; 42 | } 43 | 44 | server { 45 | listen 443 ssl http2; 46 | server_name localhost; 47 | include /etc/kvmd/nginx/ssl.conf; 48 | 49 | include /etc/kvmd/nginx/kvmd.ctx-server.conf; 50 | include /usr/share/kvmd/extras/*/nginx.ctx-server.conf; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pkgs/kvmd-1.82-1-any.pkg.tar.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/pkgs/kvmd-1.82-1-any.pkg.tar.xz -------------------------------------------------------------------------------- /pkgs/kvmd-platform-v0-hdmiusb-x86-1.82-1-any.pkg.tar.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/pkgs/kvmd-platform-v0-hdmiusb-x86-1.82-1-any.pkg.tar.xz -------------------------------------------------------------------------------- /pkgs/kvmd-webterm-0.24-1-any.pkg.tar.zst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/pkgs/kvmd-webterm-0.24-1-any.pkg.tar.zst -------------------------------------------------------------------------------- /pkgs/ttyd-1.6.1-2-x86_64.pkg.tar.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/pkgs/ttyd-1.6.1-2-x86_64.pkg.tar.xz -------------------------------------------------------------------------------- /pkgs/ustreamer-1.19-1-x86_64.pkg.tar.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purplepalmdash/pikvmx86/fc1345761e42f44a9dda76ef880514f215270c1f/pkgs/ustreamer-1.19-1-x86_64.pkg.tar.xz -------------------------------------------------------------------------------- /supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | 4 | [program:ttyd] 5 | command=/bin/bash -c "/usr/bin/ttyd --interface=/run/kvmd/ttyd.sock --port=0 /bin/bash -c 'echo -ne \"\033]0;Pi-KVM Terminal: `hostname -f` (ttyd)\007\"; cat /etc/motd; bash'" 6 | 7 | [program:kvmd] 8 | command=/bin/bash -c "/usr/bin/kvmd" 9 | stdout_logfile=/dev/fd/1 10 | stdout_logfile_maxbytes=0 11 | 12 | [program:kvmd-nginx] 13 | command=/usr/bin/nginx -p /etc/kvmd/nginx -c /etc/kvmd/nginx/nginx.conf -g 'daemon off;pid /run/kvmd/nginx.pid; user kvmd-nginx; error_log stderr;' 14 | 15 | [program:runpriledge] 16 | command=/bin/bash -c "while true; do sleep 5; chmod a+w /run/kvmd/*; done" 17 | -------------------------------------------------------------------------------- /vcgencmd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # try and keep this pure bourne shell 3 | # minimal clone of raspberry tool vcgencmd - for use with Android rpicheck and rock64 SBC 4 | 5 | command=$1 6 | case ${1} in 7 | measure_clock) 8 | case ${2} in 9 | arm) 10 | # awk is probably overkill.... 11 | /usr/local/sbin/rock64_health.sh | awk '/CPU freq/{print "frequency(45)=" $4 * 1000000}' 12 | #value=`/usr/local/sbin/rock64_health.sh | awk '/CPU freq/{print $4 * 1000000}'` 13 | #echo 'frequency(45)='${value} 14 | exit 15 | ;; 16 | core) 17 | value=0 # TODO / FIXME 18 | echo 'frequency(1)='${value} 19 | exit 20 | ;; 21 | # TODO anything else thrown an error/debug 22 | esac 23 | exit 24 | ;; 25 | measure_temp) 26 | # awk is probably overkill.... 27 | #/usr/local/sbin/rock64_health.sh | awk '/SoC Temp/{print $4 "\\\'C"}' 28 | #value=`/usr/local/sbin/rock64_health.sh | awk '/SoC Temp/{print $4}'` 29 | #value=`46' 30 | #echo 'temp='${value}"'C" 31 | echo "temp=46.7'C" 32 | exit 33 | ;; 34 | get_throttled) 35 | echo 'throttled=0x50000' 36 | exit 37 | ;; 38 | measure_volts) 39 | case ${2} in 40 | core) 41 | value=0 # TODO / FIXME 42 | echo 'volt='${value}'.0000V' 43 | exit 44 | ;; 45 | # TODO anything else thrown an error/debug 46 | esac 47 | ;; 48 | version) 49 | echo 'Nov 4 2018 16:31:07' 50 | echo 'Copyright (c) 2012 rock64' 51 | echo 'version rock64_TODO (clean) (release)' 52 | exit 53 | ;; 54 | esac 55 | --------------------------------------------------------------------------------