commit 8e1410252d80dd1488e1b03d21fe89a60c545fd7 Author: <> Date: Tue Oct 28 18:45:34 2025 +0000 Deployed 4bad432 with MkDocs version: 1.6.1 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/3d_printing/index.html b/3d_printing/index.html new file mode 100644 index 00000000..9e8749f8 --- /dev/null +++ b/3d_printing/index.html @@ -0,0 +1,2751 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Cases for 3D printing - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Cases for 3D printing

+ +

PiKVM V3 HAT cases

+ +

DIY cases

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ModelNotes
https://www.thingiverse.com/thing:4799094Case for the USB-C/PWR Splitter without Barrel jack
https://www.thingiverse.com/thing:4931970Raspberry Pi 4 Pi-KVM Case
https://www.thingiverse.com/thing:4862304Case for PiKVM (LCD + ATX)
https://www.thingiverse.com/thing:4868258R4C3R - Low Profile PCIe bracket for PiKVM based on Raspberry Pi Zero + Lusya + ATX controls
https://www.thingiverse.com/thing:4866005R4C3R - Full Profile PCIe bracket for PiKVM based on Raspberry Pi Zero + Lusya + ATX controls
https://www.thingiverse.com/thing:4832248Case for the USB-C/PWR Splitter without Barrel jack and HDMI-CSI bridge
https://www.thingiverse.com/thing:4916230A very compact case without internal power splitter
https://www.thingiverse.com/thing:4915627ZeroW + CSI case
https://www.thingiverse.com/thing:4950281PiKVM RETRO Case for CSI-2 C779 Bridge w/ OLED Display Screen
https://www.thingiverse.com/thing:4950280USB Power Blocker Case
https://www.thingiverse.com/thing:4642116Conix's PI-KVM case for v2
https://www.thingiverse.com/thing:7148243Wall mount for PiKVM v3
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/3g/index.html b/3g/index.html new file mode 100644 index 00000000..db411a9a --- /dev/null +++ b/3g/index.html @@ -0,0 +1,14 @@ + + + + + + Redirecting... + + + + + +You're being redirected to a new destination. + + diff --git a/404.html b/404.html new file mode 100644 index 00000000..48aef884 --- /dev/null +++ b/404.html @@ -0,0 +1,2564 @@ + + + + + + + + + + + + + + + + + + + + + + + PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/4g/index.html b/4g/index.html new file mode 100644 index 00000000..db411a9a --- /dev/null +++ b/4g/index.html @@ -0,0 +1,14 @@ + + + + + + Redirecting... + + + + + +You're being redirected to a new destination. + + diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..06cd23be --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +docs.pikvm.org diff --git a/_assets/add_paragraphs.js b/_assets/add_paragraphs.js new file mode 100644 index 00000000..6d65b605 --- /dev/null +++ b/_assets/add_paragraphs.js @@ -0,0 +1,36 @@ +document.addEventListener('DOMContentLoaded', function () { + document.querySelectorAll('details').forEach(details => { + const summary = details.querySelector('summary'); + + if (!summary) return; + + if (window.matchMedia('(hover: none)').matches) return; + + let linkEl; + + details.addEventListener('mouseenter', () => { + if (details.open) return; + + const summaryText = summary.textContent.trim(); + console.log(`${summaryText}`); + const hash = '#' + encodeURIComponent(summaryText); + + if (linkEl) return; + + linkEl = document.createElement('a'); + linkEl.href = hash; + linkEl.textContent = '¶'; + linkEl.title = 'Permanent link'; + linkEl.className = 'hoverlink'; + + summary.appendChild(linkEl); + }); + + details.addEventListener('mouseleave', () => { + if (linkEl) { + linkEl.remove(); + linkEl = null; + } + }); + }); +}); \ No newline at end of file diff --git a/_assets/favicon.ico b/_assets/favicon.ico new file mode 100644 index 00000000..90554d14 Binary files /dev/null and b/_assets/favicon.ico differ diff --git a/_assets/logo.png b/_assets/logo.png new file mode 100644 index 00000000..96038661 Binary files /dev/null and b/_assets/logo.png differ diff --git a/_assets/scroll_to_summary.js b/_assets/scroll_to_summary.js new file mode 100644 index 00000000..f71cc3c8 --- /dev/null +++ b/_assets/scroll_to_summary.js @@ -0,0 +1,32 @@ +function scroll_to_summary() { + const hash = decodeURIComponent(window.location.hash.slice(1)).trim(); + if (!hash) return; + + const summaries = document.querySelectorAll('details > summary'); + + for (const summary of summaries) { + const text = summary.textContent.trim(); + + if (text.toLowerCase().includes(hash.toLowerCase())) { + const details = summary.closest('details'); + if (details) { + details.open = true; + + const yOffset = -60 + const y = details.getBoundingClientRect().top + window.pageYOffset + yOffset; + + window.scrollTo({ top: y, behavior: 'smooth' }); + + break; + } + } + } +} + +document.addEventListener('DOMContentLoaded', function () { + scroll_to_summary(); + + window.addEventListener("hashchange", () => { + scroll_to_summary(); + }); +}); \ No newline at end of file diff --git a/_assets/user.css b/_assets/user.css new file mode 100644 index 00000000..03236dbd --- /dev/null +++ b/_assets/user.css @@ -0,0 +1,203 @@ +:root>* { + --md-primary-fg-color: #435071; + --md-primary-fg-color--light: #575b64; + --md-primary-fg-color--dark: #1c1d20; +} + +a { + color: var(--md-typeset-a-color); +} + +a:hover { + text-decoration: underline; +} + +a.md-source { + color: white; +} + +a.md-source:hover { + text-decoration: none; +} + +/*.md-header__button.md-logo img { + width: unset; +}*/ + +li.md-nav__item--section>label.md-nav__link { + font-size: large; +} + +.md-main__inner { + margin-top: unset; +} + +@media screen and (min-width: 76.3em) { + .md-nav__title { + display: none; + } +} + +.md-sidebar--primary .md-nav__link--active { + font-weight: bold; + color: #e82062 !important; +} + +.md-sidebar--primary .md-nav__link--active:before { + content: "\21D2"; + margin-right: 6px; +} + +@media screen and (min-width: 76.3em) { + .md-post__back>.md-nav__title { + /* Blog: Enable "Back to index" */ + display: block; + } +} + +.md-post__back { + /* Blog */ + padding-top: 1.2rem; +} + +/*.md-header,*/ +.md-footer { + background-color: #333333; +} + +@media screen and (min-width: 76.3em) { + .md-footer__inner.md-grid { + display: none; + } +} + +.md-sidebar { + padding-top: 0px; +} + +/*.md-sidebar.md-sidebar--primary { + position: unset; +}*/ + +.md-nav__toggle~.md-nav>.md-nav__list { + margin-left: 15px; +} + +.md-sidebar.md-sidebar--secondary { + padding-top: 10px; +} + +.md-sidebar.md-sidebar--primary .md-sidebar__scrollwrap, +.md-sidebar.md-sidebar--post .md-sidebar__scrollwrap { + /*overflow-y: unset;*/ + padding-right: 1px; + border-right: 1px solid #adadad; +} + +.md-sidebar.md-sidebar--primary .md-sidebar__inner { + /*border-right: 1px solid #adadad;*/ + padding-bottom: 30px; +} + +.md-sidebar.md-sidebar--secondary .md-sidebar__inner { + border-left: 1px solid #adadad; +} + +.md-nav__item .md-nav__list { + padding-left: 10px; +} + +.md-content { + margin-top: 25px; + /*border-left: 1px solid #adadad; + border-right: 1px solid #adadad;*/ +} + +.md-content.md-content--post { + /* Blog */ + margin-top: 0px; +} + +@media screen and (min-width: 76.3em) { + .md-top { + display: none; + } +} + +.md-typeset hr { + border-bottom: 1px solid #adadad; +} + +.md-typeset h1, +.md-typeset h2, +.md-typeset h3, +.md-typeset h4, +.md-typeset h5 { + font-weight: bold; +} + +.md-typeset table:not([class]) td:not(:last-child), +.md-typeset table:not([class]) th:not(:last-child) { + border-right: .05rem solid var(--md-typeset-table-color); +} + +ol li::marker { + font-weight: bold; +} + +[dir=ltr] .md-typeset summary { + padding-right: 80px; +} + +.md-typeset summary:after { + background-color: unset; + content: " Expand ▼"; + height: unset; + -webkit-mask-image: unset; + mask-image: unset; + -webkit-mask-position: unset; + mask-position: unset; + -webkit-mask-repeat: unset; + mask-repeat: unset; + -webkit-mask-size: unset; + mask-size: unset; + position: absolute; + top: 8px; + transform: unset; + transition: unset; + width: 80px; + text-align: right; +} + +.md-typeset details[open]>summary:after { + transform: unset; + content: " Collapse ▲"; + width: 80px; +} + +.md-typeset details:not([open]) { + border-left-width: 16px; +} + +.md-typeset li>p+details, +.md-typeset li>p+.admonition, +.md-typeset li>details:only-child, +.md-typeset li>.admonition:only-child { + margin: 0; +} + +.md-button--stretch { + width: 100%; +} + +.hoverlink { + font-size: 1.0em; + margin-left: 8px; + text-decoration: none; +} + +@media (hover: hover) { + .hoverlink:hover { + text-decoration: none; + } +} \ No newline at end of file diff --git a/_basic_troubleshooting/index.html b/_basic_troubleshooting/index.html new file mode 100644 index 00000000..dcd2b220 --- /dev/null +++ b/_basic_troubleshooting/index.html @@ -0,0 +1,2610 @@ + + + + + + + + + + + + + + + + + + + + + + basic troubleshooting - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

basic troubleshooting

+ +
    +
  • +

    Ensure that you are using the right OS image for your platform + by running the following command: pacman -Q | grep kvmd-platform.

    +
  • +
  • +

    If you are not getting a display, run the two following commands:

    +
      +
    • dmesg | egrep 'tc35|1-1.4|uvc'
    • +
    • systemctl status kvmd-tc358743
    • +
    +

    If you see a failed message on that output, be sure verify the orientation of the CSI cable or try reseating it.

    +

    Note that this is not a hotplug device, and you must first turn off the power.

    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_config/index.html b/_config/index.html new file mode 100644 index 00000000..674c0243 --- /dev/null +++ b/_config/index.html @@ -0,0 +1,2643 @@ + + + + + + + + + + + + + + + + + + + + + + config - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

config

+ +
+Configuring PiKVM OS +
+

Need more info? We have it!

+

The following is a brief guide to configuring PiKVM. +For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), +please refer to this page.

+
+

Most of the PiKVM configuration files are located in the /etc/kvmd directory.

+

The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. +To redefine system parameters use the file /etc/kvmd/override.yaml. +All other files that are also not recommended for editing have read-only permissions.

+

You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory +to split your customization into logical parts. +The override.yaml file definitions takes precedence over the override.d directory.

+

A complete list of all parameters can be viewed using the kvmd -m command.

+

Files with the *.yaml suffix uses the YAML syntax +and describes a parameter tree with key-value pairs of different types. +To define the parameters within one section, an indent of 4 spaces is used. +Comments starts with the # symbol.

+
+

Only 4 spaces should be used for indentation

+

Be careful when editing YAML and follow this rule. +Invalid indentation or tabs instead of spaces will cause an error when starting the services.

+
+

Sections under the same keys should be merged:

+
    +
  • +

    Wrong:

    +
    kvmd:
    +    gpio:
    +        drivers: ...
    +kvmd:
    +    gpio:
    +        scheme: ...
    +
    +
  • +
  • +

    Correct:

    +
    kvmd:
    +    gpio:
    +        drivers: ...
    +        scheme: ...
    +
    +
  • +
+

In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_device_guides/index.html b/_device_guides/index.html new file mode 100644 index 00000000..cde0dde6 --- /dev/null +++ b/_device_guides/index.html @@ -0,0 +1,2601 @@ + + + + + + + + + + + + + + + + + + + + + + device guides - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_diy/atx_connection.png b/_diy/atx_connection.png new file mode 100644 index 00000000..84ccad02 Binary files /dev/null and b/_diy/atx_connection.png differ diff --git a/_diy/open_mipi_csi.jpg b/_diy/open_mipi_csi.jpg new file mode 100644 index 00000000..5ec546d6 Binary files /dev/null and b/_diy/open_mipi_csi.jpg differ diff --git a/_diy/rpi2w_csi_connection.jpg b/_diy/rpi2w_csi_connection.jpg new file mode 100644 index 00000000..cb9f50db Binary files /dev/null and b/_diy/rpi2w_csi_connection.jpg differ diff --git a/_diy/rpi4_csi_connection.jpg b/_diy/rpi4_csi_connection.jpg new file mode 100644 index 00000000..7ab622b4 Binary files /dev/null and b/_diy/rpi4_csi_connection.jpg differ diff --git a/_diy/usbcap_rpi2.jpg b/_diy/usbcap_rpi2.jpg new file mode 100644 index 00000000..90fc65a2 Binary files /dev/null and b/_diy/usbcap_rpi2.jpg differ diff --git a/_diy/usbcap_rpi4.jpg b/_diy/usbcap_rpi4.jpg new file mode 100644 index 00000000..8b68d714 Binary files /dev/null and b/_diy/usbcap_rpi4.jpg differ diff --git a/_diy/usbcap_zero2w.jpg b/_diy/usbcap_zero2w.jpg new file mode 100644 index 00000000..5f37bab2 Binary files /dev/null and b/_diy/usbcap_zero2w.jpg differ diff --git a/_diy_parts_atx/index.html b/_diy_parts_atx/index.html new file mode 100644 index 00000000..c84563ad --- /dev/null +++ b/_diy_parts_atx/index.html @@ -0,0 +1,2614 @@ + + + + + + + + + + + + + + + + + + + + + + diy parts atx - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

diy parts atx

+ +

With this part, you will be able to remotely turn on, turn off and restart your computer!

+
    +
  • x4 optocouplers + TLP241BF(F + or PC817X2NSZ9F (the input polarity must be observed) + or OMRON G3VM-61A1 + or OMRON G3VM-61AY1
    + Don't use random relay modules or random optocouplers! Some of these may not be sensitive enough + for the Raspberry Pi, some others may be low-level controlled. Either use relays that are activated by a high logic level, + or follow the design provided. See details here.
  • +
  • x4 390 Ohm resistors (see here for alternatives).
  • +
  • 2x 4.7 kOhm resistors.
  • +
  • x10+ dupont wires male-male.
  • +
  • x1 a breadboard.
  • +
  • various wires for the breadboard.
  • +
+

This can be partially replaced by using Wake-on-LAN in the software, but it will not allow +to reboot a hung system, and it is not as reliable as an ATX controller. Sometimes the Wake-on-LAN +on the host just stops working, for its own or network reasons.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_diy_setup_video_csi/index.html b/_diy_setup_video_csi/index.html new file mode 100644 index 00000000..20bf5b19 --- /dev/null +++ b/_diy_setup_video_csi/index.html @@ -0,0 +1,2640 @@ + + + + + + + + + + + + + + + + + + + + + + diy setup video csi - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

diy setup video csi

+ +

Insert the flexible flat cable of the HDMI-CSI bridge into the narrow white connector on the Raspberry Pi +(the closest one to big USB sockets). It is labeled CAMERA. To insert you need to open the connector first. +On the Raspberry Pi side you can gently lift the black part up and a little bit sideways:

+ + + + + + + + + + + +
Opening the MIPI CSI slot on the Raspberry Pi
+

For the HDMI-CSI bridge this operation depends on the version you bought. +Either pull it gently up as on the Raspberry or push it sideways. +Make sure that the cable is inserted on the correct side and until it stops, and then push the black latch back. +Avoid using force when pushing the cable in, as the slots bond to the PCB is quite fragile. +Never connect or disconnect the flat cable from a powered device. This is not Plug-and-Play, and you can damage it. +Also use only the cable that was included with the device package, or make sure that the third-party cable has the correct pinout.

+ + + + + + + + + + + +
HDMI-CSI bridge connected to Raspberry Pi 4
+ + + + + + + + + + + +
HDMI-CSI bridge connected to Raspberry Pi 2 W (using the adapter cable)
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_diy_setup_video_usb/index.html b/_diy_setup_video_usb/index.html new file mode 100644 index 00000000..09626de5 --- /dev/null +++ b/_diy_setup_video_usb/index.html @@ -0,0 +1,2614 @@ + + + + + + + + + + + + + + + + + + + + + + diy setup video usb - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

diy setup video usb

+ +

Connect USB dongle to exactly this port. It is bound in the software so the OS does not confuse the video device with something else.

+ + + + + + + + + + + + + +
Raspberry Pi 2 and 3Raspberry Pi 4
+

There are many revisions of the Raspberry Pi boards and you may come across one that we haven't tested. +If the binding fails, the device will be available for all ports. +Everything will work, but if you use a webcam and Linux mistakes it for a dongle, +write to us and we will fix it.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_diy_wiring_atx/index.html b/_diy_wiring_atx/index.html new file mode 100644 index 00000000..3c16e939 --- /dev/null +++ b/_diy_wiring_atx/index.html @@ -0,0 +1,2608 @@ + + + + + + + + + + + + + + + + + + + + + + diy wiring atx - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

diy wiring atx

+ +

To control the power, two display LEDs (power and HDD activity) and two buttons (power and reset) are provided +on the front panel of the computer case. They are connected by wires to pins on the motherboard.

+

+

All you have to do is connect the PiKVM ATX controller to their wires by making a parallel connection. +Please note that the pinout differs on different motherboards, so before you continue, +check the documentation on your motherboard for correct pinout.

+

The following illustration shows how the connection between the power LED and the power button should be performed:

+

+

On the left are the wires from the PiKVM ATX controller, the pad in the middle indicates the pins on the motherboard, +and on the right are the LED and button of the target host. The implementation of this scheme is left to your discretion +and can be performed, for example, by cutting wires and performing twisting, followed by insulation with duct tape.

+

Be careful and respect the polarity of the LEDs. The polarity of the button does not matter (they have no polarity at all). +The connection of HDD LED and reset switch is performed in the same way.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_edidconf_options/index.html b/_edidconf_options/index.html new file mode 100644 index 00000000..25996809 --- /dev/null +++ b/_edidconf_options/index.html @@ -0,0 +1,2625 @@ + + + + + + + + + + + + + + + + + + + + + + edidconf options - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

edidconf options

+ +
+

Quick IDs changing on PiKVM V4 Plus

+

PiKVM V4 Plus has a simple way read and adopt display identifiers like model and serial number +from your physical display. See here for details.

+
+

Run kvmd-edidconf on PiKVM:

+
[root@pikvm ~]# kvmd-edidconf
+Manufacturer ID: LNX
+Product ID:      0x7773 (30579)
+Serial number:   0x01010101 (16843009)
+Monitor name:    PiKVM V4 Plus
+Monitor serial:  CAFEBABE
+Audio:           yes
+
+

The fields have obvious names and purposes. Note the two similar fields Serial number and Monitor serial. +The first has a numeric value, and the second is ASCII. If you are using a custom EDID from some real display, some fields may be missing.

+

To change the values of the EDID fields, use the kvmd-edidconf with options, a complete list is available in kvmd-edidconfi --help.

+

Here the small example of changing all available fields from the previous listing:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# kvmd-edidconf --set-mfc-id=TTP --set-product-id=0x5B81 --set-serial=0x8DE11B79 --set-monitor-name=TOSHIBA --set-monitor-serial=ABCD1234 --apply
+Manufacturer ID: TTP
+Product ID:      0x5B81 (23425)
+Serial number:   0x8DE11B79 (2380340089)
+Monitor name:    TOSHIBA
+Monitor serial:  ABCD1234
+Audio:           yes
+...
+[root@pikvm ~]# ro
+
+

The full list of manufacturer IDs is available here.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_fahrenheit/index.html b/_fahrenheit/index.html new file mode 100644 index 00000000..044cd570 --- /dev/null +++ b/_fahrenheit/index.html @@ -0,0 +1,2606 @@ + + + + + + + + + + + + + + + + + + + + + + fahrenheit - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

fahrenheit

+ +
+How to set up Fahrenheit on the OLED +

Create a directory for a configuration file:

+
[root@pikvm ~]# mkdir -p /etc/systemd/system/kvmd-oled.service.d
+
+

Create file /etc/systemd/system/kvmd-oled.service.d/override.conf:

+
[Service]
+ExecStart=
+ExecStart=/usr/bin/kvmd-oled --clear-on-exit --fahrenheit
+
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_multiport_usb/index.html b/_multiport_usb/index.html new file mode 100644 index 00000000..6bba7730 --- /dev/null +++ b/_multiport_usb/index.html @@ -0,0 +1,2608 @@ + + + + + + + + + + + + + + + + + + + + + + multiport usb - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

multiport usb

+ +
+

PiKVM + Multiport Switches compatibility

+

Please note that this switch requires a USB port for control. The following devices can provide this:

+
    +
  • PiKVM V3 & V4 Plus.
  • +
  • DIY devices based on Raspberry Pi 2, 3 and 4.
  • +
+

The following devices are not compatible:

+
    +
  • PiKVM V4 Mini - it doesn't have a USB host port and cannot control switches, it's a single-host device.
  • +
  • DIY based on Raspberry Pi Zero 2 W - it doesn't have USB host port too.
  • +
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_passwd/index.html b/_passwd/index.html new file mode 100644 index 00000000..2e64f2d1 --- /dev/null +++ b/_passwd/index.html @@ -0,0 +1,2631 @@ + + + + + + + + + + + + + + + + + + + + + + passwd - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

passwd

+ +
+Changing PiKVM Passwords +

PiKVM comes with the following default passwords:

+
    +
  • +

    Linux OS-level admin (SSH, console...):

    +
      +
    • Username: root
    • +
    • Password: root
    • +
    +
  • +
  • +

    KVM user (Web Interface, API, VNC...):

    +
      +
    • Username: admin
    • +
    • Password: admin
    • +
    • No 2FA code
    • +
    +
  • +
+

They are two separate accounts with independent passwords.

+

To change passwords, you will need to use the console access via SSH or the Web Terminal. +If you are using the Web Terminal, enter the su - command to get the root access (enter the root user password).

+
[root@pikvm ~]# rw
+[root@pikvm ~]# passwd root
+[root@pikvm ~]# kvmd-htpasswd set admin
+[root@pikvm ~]# ro
+
+

If you require additional user for the Web UI access, use the following:

+
[root@pikvm ~]# kvmd-htpasswd add <user> # Add a new user with password
+[root@pikvm ~]# kvmd-htpasswd del <user> # Remove/delete a user
+
+

Optionally you can enable the two-factor authentication for more security.

+

Changing the VNCAuth key and IPMI password at the first start of PiKVM is not required, +since these services are disabled by default. But it is here just so that you remember their existence.

+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_pico_hid_flashing/index.html b/_pico_hid_flashing/index.html new file mode 100644 index 00000000..9124ff61 --- /dev/null +++ b/_pico_hid_flashing/index.html @@ -0,0 +1,2606 @@ + + + + + + + + + + + + + + + + + + + + + + pico hid flashing - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

pico hid flashing

+ +

To upload the firmware to Pico HID, you can use any computer with a USB port.

+
    +
  1. Download the latest release of the firmware. The file is called pico-hid.uf2.
  2. +
  3. Press and hold the white button on the Pico board.
  4. +
  5. While still holding the button, plug it in the computer using a USB cable.
  6. +
  7. Release the button.
  8. +
  9. The Pico board appears as a flash drive on your computer.
  10. +
  11. Copy the pico-hid.uf2 file to this flash drive.
  12. +
  13. Safely eject the USB device.
  14. +
+

If you want to compile the firmware yourself, you can find the source code here.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_pico_hid_parts/index.html b/_pico_hid_parts/index.html new file mode 100644 index 00000000..fe7246e8 --- /dev/null +++ b/_pico_hid_parts/index.html @@ -0,0 +1,2617 @@ + + + + + + + + + + + + + + + + + + + + + + pico hid parts - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

pico hid parts

+ +
    +
  • +

    x1 Raspberry Pi Pico board with soldered pins. Pico 2 is not supported right now.

    +
  • +
  • +

    x1 USB-A to Micro-USB cable.

    +
  • +
  • +

    x10 dupont wires female-female.

    +
  • +
  • +

    x1 1N5819 diode. It's optional but strongly recommended. Any similar one will do.

    +
    +

    Warning

    +

    The diode is needed to provide power to the Pico HID regardless of the target host state, +which prevents the backpowering problem. It will allow you to keep the keyboard buttons pressed +during the target host power cycle, which is, for example, important for MacOS to get into the boot menu.

    +

    Do not connect the red wire (the VSYS (Pico) -> 5V (Pi) line) without a diode. +If you can't find a diode, don't connect this wire at all.

    +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_update_os/index.html b/_update_os/index.html new file mode 100644 index 00000000..de3bb198 --- /dev/null +++ b/_update_os/index.html @@ -0,0 +1,2612 @@ + + + + + + + + + + + + + + + + + + + + + + update os - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

update os

+ +
+Updating PiKVM OS +

To update, run following commands under the root user:

+
[root@pikvm ~]# pikvm-update
+
+

If you encounter an error like:

+
[root@pikvm ~]# pikvm-update
+bash: pikvm-update: command not found
+
+

It's most likely you have an old OS release. You can update the OS as follows:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# pacman -Syy
+[root@pikvm ~]# pacman -S pikvm-os-updater
+[root@pikvm ~]# pikvm-update
+
+

Next time you will be able to use the usual method with pikvm-update.

+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_usb_limits/index.html b/_usb_limits/index.html new file mode 100644 index 00000000..70d142d4 --- /dev/null +++ b/_usb_limits/index.html @@ -0,0 +1,2601 @@ + + + + + + + + + + + + + + + + + + + + + + usb limits - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

usb limits

+ +
+

USB limitations

+

Each emulated USB device consumes a limited hardware resource called endpoints.

+

Short info: by default, you can add only one additional USB device.

+

To get more information about the endpoints, add more devices, and flexibly manage the configuration on the fly, see here.

+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api/index.html b/api/index.html new file mode 100644 index 00000000..4cfc9d1d --- /dev/null +++ b/api/index.html @@ -0,0 +1,6301 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + HTTP API reference - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

HTTP API reference

+ +

This document describes the PiKVM API. Since the system consists of microservices, here is a common API with a common entry point provided by Nginx. The below examples use curl and websocat with the -k option disables SSL certificate verification, since the self-signed certificateis are used in the default installation.

+

There is a third-party library for using the PiKVM API. Please note that this is an unofficial library, so use it carefully.

+
+

Authentication

+

All APIs are restricted to authentication. To make requests, you either need to auth each request individually, or get a token and pass it as a cookie with each request.

+

With enabled 2FA, you will need to add the one-time code to the password without spaces. That is, if the password is foobar and the code is 123456, then you need to use foobar123456 as the password.

+

The code can be generated using any TOTP library, for example in Python:

+
import requests
+import pyotp
+
+user = "admin"
+passwd = "admin"
+secret = "3OBBOGSJRYRBZH35PGXURM4CMWTH3WSU"  # Can be found in /etc/kvmd/totp.secret
+
+print(requests.get(
+    url="https://pikvm/api/info",
+    verify=False,  # For self-signed SSL certificate
+    headers={
+        "X-KVMD-User": user,
+        "X-KVMD-Passwd": passwd + pyotp.TOTP(secret).now(),
+    },
+).text)
+
+

Since in the borderline case of the 2FA code lifetime, the code may be invalid, +it makes sense to either handle error 403 by repeating the request in seconds.

+

A more correct way is to combine this method and check the remaining lifetime +and postpone the request if there is a second or so left. You can find out how much +time is left in this way:

+
totp = pyotp.TOTP(secret)
+now = int(time.time())
+remaining = now - (now % totp.interval)
+
+

Single-request authentication

+

There are two options here:

+
    +
  • +

    Using X-headers. Just pass X-KVMD-User and X-KVMD-Passwd with the request:

    +
    $ curl -k -H X-KVMD-User:admin -H X-KVMD-Passwd:admin https://<pikvm-ip>/api/auth/check
    +
    +
  • +
  • +

    Using HTTP Basic Auth. Please note: contrary to the standard, this method DOES NOT use the WWW-Authenticate header. HTTP Basic Auth in this implementation is intended only for compatibility with other systems, such as Prometheus.

    +
    $ curl -k -u admin:admin https://<pikvm-ip>/api/auth/check
    +
    +
  • +
+ +
    +
  1. +

    Get the access token for the user using POST /api/auth/login:

    +
    $ curl -k -v -X POST --data user=admin --data passwd=admin https://pikvm/api/auth/login
    +...
    +< Set-Cookie: auth_token=796cb83b11de4fcb749bc1bad14a91fb06dede84672b2f847fef1e988e6900de; Path=/
    +...
    +
    +

    On success the cookie auth_token will be received with 200 OK. On invalid user or password you will get 403 Forbidden.

    +
  2. +
  3. +

    The handle GET /api/auth/check can be used for check the auth status. Return of 200 OK will signal that user is authenticated. If the token or any of the single-request auth methods are missing, 401 Unauthorized will be returned. In case of incorrect credentials or token, 403 Forbidden will be returned.

    +
  4. +
  5. +

    The handle POST /api/auth/logout can be used to invalidate session token. The response codes will be similar to the previous handle.

    +
  6. +
+

Session-based login using HTML form

+

You can submit PiKVM credentials from another site and go directly to the KVM page by passing the redirect parameter as follows:

+
<html>
+<body>
+    <form method="POST" action="https://pikvm/api/auth/login">
+        <input name="user" value="admin">
+        <input name="passwd" value="admin">
+        <input name="expire" value="0">
+        <input name="redirect" value="/kvm/"> <!-- Available since KVMD 4.108 -->
+        <button type="submit">Open PiKVM</button>
+    </form>
+</body>
+<html>
+
+
+

WebSocket events

+

Most of the data during the user's work with PiKVM is transmitted over WebSocket. This includes mouse events, keyboard input, and changing the state of the various subsystems (such as ATX and Mass Storage Drive). Each event type will be described in the corresponding paragraph for its component. When connecting via WebSocket, the client receives current states as separate events. Then, as the states change, it will receive new events.

+

In a normal situation, opening a socket session triggers the video streamer to start. The streamer works as long as there is at least one client connected via WebSocket. After the last connection is closed and the client timeout expires, the streamer will also be terminated.

+

It is possible create a session that will not start the streamer and will not be counted when counting clients to stop the streamer. To do this, use the URL parameter stream=0:

+
$ websocat -k wss://<pikvm-ip>/api/ws?stream=0 -H X-KVMD-User:admin -H X-KVMD-Passwd:admin
+
+
+Output with initial events +
{"event_type": "gpio_model_state", "event": {"scheme": {"inputs": {"led1": {"hw": {"driver": "__gpio__", "pin": 19}}, "led2": {"hw": {"driver": "__gpio__", "pin": 16}}}, "outputs": {"button1": {"switch": false, "pulse": {"delay": 0.1, "min_delay": 0.1, "max_delay": 0.1}, "hw": {"driver": "__gpio__", "pin": 26}}, "button2": {"switch": false, "pulse": {"delay": 0.1, "min_delay": 0.1, "max_delay": 0.1}, "hw": {"driver": "__gpio__", "pin": 20}}, "relay1": {"switch": true, "pulse": {"delay": 0.1, "min_delay": 0.1, "max_delay": 0.1}, "hw": {"driver": "relay", "pin": 0}}, "relay2": {"switch": true, "pulse": {"delay": 2.0, "min_delay": 0.1, "max_delay": 5.0}, "hw": {"driver": "relay", "pin": 1}}}}, "view": {"header": {"title": "Switches"}, "table": [[{"type": "label", "text": "Generic GPIO leds"}], null, [{"type": "label", "text": "Test 1:"}, {"type": "input", "channel": "led1", "color": "green"}, {"type": "output", "channel": "button1", "text": "Click"}], [{"type": "label", "text": "Test 2:"}, {"type": "input", "channel": "led2", "color": "green"}, {"type": "output", "channel": "button2", "text": "Click"}], null, [{"type": "label", "text": "HID Relays /dev/hidraw0"}], null, [{"type": "label", "text": "Relay #1:"}, {"type": "output", "channel": "relay1", "text": "Boop 0.1"}], [{"type": "label", "text": "Relay #2:"}, {"type": "output", "channel": "relay2", "text": "Boop 2.0"}]]}}}
+{"event_type": "info_extras_state", "event": {"vnc": {"name": "VNC", "description": "Show VNC information", "icon": "share/svg/vnc.svg", "path": "vnc", "keyboard_cap": false, "daemon": "kvmd-vnc", "port": 5900, "place": 20, "enabled": true}, "ipmi": {"name": "IPMI", "description": "Show IPMI information", "icon": "share/svg/ipmi.svg", "path": "ipmi", "keyboard_cap": false, "daemon": "kvmd-ipmi", "port": 623, "place": 21, "enabled": true}}}
+{"event_type": "info_hw_state", "event": {"platform": {"type": "rpi", "base": "Virtual Raspberry Pi"}, "health": {"temp": {"cpu": 36.511, "gpu": 35.0}, "throttling": {"raw_flags": 0, "parsed_flags": {"undervoltage": {"now": false, "past": false}, "freq_capped": {"now": false, "past": false}, "throttled": {"now": false, "past": false}}}}}}
+{"event_type": "info_meta_state", "event": {"server": {"host": "localhost.localdomain"}, "kvm": {}}}
+{"event_type": "info_system_state", "event": {"kvmd": {"version": "1.102"}, "streamer": {"app": "ustreamer", "version": "1.25", "features": {"WITH_OMX": false, "WITH_GPIO": false, "WITH_PTHREAD_NP": true, "WITH_SETPROCTITLE": true, "HAS_PDEATHSIG": true}}, "kernel": {"system": "Linux", "release": "5.8.10-arch1-1", "version": "#1 SMP PREEMPT Thu, 17 Sep 2020 18:01:06 +0000", "machine": "x86_64"}}}
+{"event_type": "wol_state", "event": {"enabled": false, "target": {"ip": "255.255.255.255", "port": 9, "mac": ""}}}
+{"event_type": "gpio_state", "event": {"inputs": {"led1": {"online": true, "state": false}, "led2": {"online": true, "state": false}}, "outputs": {"button1": {"online": true, "state": false, "busy": false}, "button2": {"online": true, "state": false, "busy": false}, "relay1": {"online": false, "state": false, "busy": false}, "relay2": {"online": false, "state": false, "busy": false}}}}
+{"event_type": "hid_state", "event": {"online": true, "keyboard": {"online": true, "leds": {"caps": false, "scroll": false, "num": false}}, "mouse": {"online": true}}}
+{"event_type": "atx_state", "event": {"enabled": true, "busy": false, "leds": {"power": false, "hdd": false}}}
+{"event_type": "msd_state", "event": {"enabled": true, "online": true, "busy": false, "storage": {"size": 234950152192, "free": 23514271744, "images": {}, "uploading": false}, "drive": {"image": null, "connected": false, "cdrom": true}, "features": {"multi": true, "cdrom": true}}}
+{"event_type": "streamer_state", "event": {"limits": {"max_fps": 40}, "params": {"desired_fps": 30, "quality": 80}, "snapshot": {"saved": null}, "streamer": null, "features": {"quality": true, "resolution": false}}}
+{"event_type": "loop", "event": {}}
+
+
+

After connecting the client receives a bundle of states of all KVMD subsystems. After the batch is completed, it sends a loop event, which means that the websocket has entered event loop mode. Now it will send new states and respond to client's requests.

+

Another type of event is ping, which can be sent by the client: {"event_type": "ping", "event": {}}. If the server is running, it will respond with pong: {"event_type": "pong", "event": {}}.

+
+Sending key events using Python +

For keypresses, set event_type to key and fill in the event structure with key and state, where key is the key from mapping and state is boolean that determines if the key is pressed or released:

+
# python, install websocket-client
+import websocket
+import ssl, time
+uri = "wss://10.0.0.7/api/ws?stream=0"
+headers = {"X-KVMD-User": "admin", "X-KVMD-Passwd": "admin"}
+ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE})
+ws.connect(uri, header=headers)
+# Key codes: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
+ws.send('{"event_type": "key", "event": {"key": "Enter", "state": true}}')
+time.sleep(0.05)
+ws.send('{"event_type": "key", "event": {"key": "Enter", "state": false}}')
+ws.close()
+
+
+
+

System functions

+

Get system info

+

Method: GET

+

Route: /api/info

+

Description: Returns the general information about the PiKVM device.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
fieldsstringoptionalReturn only specified categoriesauth, extras, fan, hw, meta, system
+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/info?fields=hw
+
+
+Example output +
{
+    "ok": true,
+    "result": {
+        "hw": {
+            "health": {
+                "cpu": {
+                    "percent": 2
+                },
+                "mem": {
+                    "available": 1568993280,
+                    "percent": 14.6,
+                    "total": 1836331008
+                },
+                "temp": {
+                    "cpu": 45.277
+                },
+                "throttling": {
+                    "ignore_past": false,
+                    "parsed_flags": {
+                        "freq_capped": {
+                            "now": false,
+                            "past": false
+                        },
+                        "throttled": {
+                            "now": false,
+                            "past": false
+                        },
+                        "undervoltage": {
+                            "now": false,
+                            "past": false
+                        }
+                    },
+                    "raw_flags": 0
+                }
+            },
+            "platform": {
+                "base": "Raspberry Pi 4 Model B Rev 1.5",
+                "board": "rpi4",
+                "model": "v3",
+                "serial": "10000000C8DA432D",
+                "type": "rpi",
+                "video": "hdmi"
+            }
+        }
+    }
+}  
+
+
+

Each category is represented by its own event in the websocket (info_hw_state, info_system_state, etc). The event content has the same format as the category content in the API.

+

Get system log

+

Method: GET

+

Route: /api/log

+

Description: Displays logs from all KVMD services as plain text.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
followbooleanoptionalTurns the request into long-polling mode and follow log messages in real timeEnable: 1, true, or yes. Disable: 0, false, or no
seekintegeroptionalRuns the log for the specified time in seconds≥0
+

Example of use: the following query returns commit messages for the last 1 hour and enables the long-polling mode:

+
$ curl -k -u admin:admin 'https://<pikvm-ip>/api/log?follow=1&seek=3600'
+
+
+Example output +
[2025-06-10 22:38:07 kvmd.service] --- kvmd.apps.kvmd.auth               INFO --- Authorized user 'admin' via auth service 'htpasswd'
+[2025-06-10 22:38:15 kvmd.service] --- kvmd.apps.kvmd.auth               INFO --- Authorized user 'admin' via auth service 'htpasswd'
+
+
+
+

HID

+

The PiKVM HID (Human Interface Device) API provides remote control capabilities for keyboard and mouse input devices. It allows users to perform the following operations:

+
    +
  • Get the device state and set/reset parameters.
  • +
  • Send keyboard shortcuts and text to be typed in the host system.
  • +
  • Send various mouse events: move to absolute coordinates and relatively, click virtual mouse buttons, and scroll the virtual mouse wheel.
  • +
+

Get devices state

+

Method: GET

+

Route: /api/hid

+

Description: Gets the current HID devices state.

+

Query parameters: none.

+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/hid
+
+
+Example output +
{
+    "ok": true,
+    "result": {
+        "busy": false,
+        "connected": null,
+        "enabled": true,
+        "jiggler": {
+            "active": false,
+            "enabled": true,
+            "interval": 60
+        },
+        "keyboard": {
+            "leds": {
+                "caps": false,
+                "num": false,
+                "scroll": false
+            },
+            "online": false,
+            "outputs": {
+                "active": "",
+                "available": []
+            }
+        },
+        "mouse": {
+            "absolute": true,
+            "online": false,
+            "outputs": {
+                "active": "usb",
+                "available": [
+                    "usb",
+                    "usb_rel"
+                ]
+            }
+        },
+        "online": true
+    }
+}
+
+
+

Set parameters

+

Method: POST

+

Route: /api/hid/set_params

+

Description: Configures HID device parameters, such as the type of emulated keyboard and mouse.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
keyboard_outputstringoptionalSets the type of the emulated keyboardusb, ps2, disabled
mouse_outputstringoptionalSets the type of the emulated mouseusb, usb_win98, usb_rel, ps2, disabled
jigglerbooleanoptionalEnable/disable mouse jiggler functionalitytrue
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/hid/set_params?jiggler=0
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+} 
+
+
+

Set the connected state

+

Method: POST

+

Route: /api/hid/set_connected

+

Description: Sets the HID devices connection state.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
connectedbooleanrequiredSets the connection stateEnable: 1, true, or yes. Disable: 0, false, or no
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/hid/set_connected?connected=0
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+} 
+
+
+

Reset devices' state

+

Method: POST

+

Route: /api/hid/reset

+

Description: Resets HID devices to their initial state.

+

Query parameters: none

+

Example of use:

+
$ curl -k -X POST -u admin:admin https://<pikvm-ip>/api/hid/reset
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}   
+
+
+

Get keyboard layouts

+

Method: GET

+

Route: /api/hid/keymaps

+

Description: Gets available keyboard layouts and the current defaults for use with POST /api/hid/print.

+

Query parameters: none

+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/hid/keymaps
+
+
+Example output +
{
+    "ok": true,
+    "result": {
+        "keymaps": {
+            "available": [
+                "ar",
+                "bepo",
+                "cz",
+                "da",
+                "de",
+                "de-ch",
+                "en-gb",
+                "en-us",
+                "en-us-altgr-intl",
+                "en-us-colemak",
+                "es",
+                "et",
+                "fi",
+                "fo",
+                "fr",
+                "fr-be",
+                "fr-ca",
+                "fr-ch",
+                "hr",
+                "hu",
+                "is",
+                "it",
+                "ja",
+                "lt",
+                "lv",
+                "mk",
+                "nl",
+                "no",
+                "pl",
+                "pt",
+                "pt-br",
+                "ru",
+                "sl",
+                "sv",
+                "th",
+                "tr"
+            ],
+            "default": "de"
+        }
+    }
+} 
+
+
+

Type text remotely

+

Method: POST

+

Route: /api/hid/print

+

Description: Transmits user-defined text to emulate typing it on the PiKVM by sequencing key presses.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
limitintegeroptionalMaximum characters to process0 = no limit. No maximum value. Default: 1024
keymapstringoptionalKeymap to use (defaults to system default)Any keymap listed in the output of GET /hid/keymaps
slowbooleanoptionalEnables slow typing mode (regular large intervals between key presses), false by defaultEnable: 1, true, or yes. Disable: 0, false, or no
delayfloatoptionalHow many seconds to delay the transmission of keys by in the slow mode. Defaults to 0.02 when slow is enabled, otherwise defaults to 00..5.0
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    -d "Einige Worte" \
+    https://<pikvm-ip>/api/hid/print?keymap=de
+
+
+Example output +
{
+"ok": true,
+"result": {}
+} 
+
+
+

Send a keyboard shortcut

+

Method: POST

+

Route: /api/hid/events/send_shortcut

+

Description: Sends a keyboard shortcut, or key combination, to be typed on the PiKVM.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
keysstringrequiredComma-separated list of key namesFor a full list of supported values, please see here. Use values from the web_name column
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/hid/events/send_shortcut?keys=ControlLeft,KeyL
+
+
+Example output +
{
+"ok": true,
+"result": {}
+}
+
+
+

Send a single key event

+

Method: POST

+

Route: /api/hid/events/send_key

+

Description: Transmits a command to emulate a single key press on the PiKVM.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
keystringrequiredKey identifier to sendFor a full list of supported values, please see here
statebooleanoptionalKey state: true for press, false for releaseEnable: 1, true, or yes. Disable: 0, false, or no
finishbooleanoptionalReleases non-modifier keys right after pressing them so that they don't get stuck when the connection is not stable. Defaults to falseEnable: 1, true, or yes. Disable: 0, false, or no
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/hid/events/send_key?key=Delete
+
+
+Example output +
{
+"ok": true,
+"result": {}
+}
+
+
+

Send mouse button events

+

Method: POST

+

Route: /api/hid/events/send_mouse_button

+

Description: Sends mouse button press/release events.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
buttonstringrequiredMouse button identifierleft, middle, right, up, down
statebooleanoptionalMouse button state: true for press, false for releaseEnable: 1, true, or yes. Disable: 0, false, or no
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/hid/events/send_mouse_button?button=left
+
+
+Example output +
{
+"ok": true,
+"result": {}
+}
+
+
+

Move the mouse pointer

+

Method: POST

+

Route: /api/hid/events/send_mouse_move

+

Description: Sends a command to move the mouse pointer to user-defined coordinates where 0,0 is the center of the screen. Only works if the mouse mode is set to absolute in the configuration.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
to_xintegerrequiredTarget X coordinateAny negative or positive integer value
to_yintegerrequiredTarget Y coordinateAny negative or positive integer value
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/hid/send_mouse_move?to_x=0&to_y=50'
+
+
+Example output +
{
+"ok": true,
+"result": {}
+}  
+
+
+

Move the mouse ppinter relatively

+

Method: POST

+

Route: /api/hid/events/send_mouse_relative

+

Description: Sends a command to move the mouse pointer by a relative offset in pixels. Only works if the mouse mode is set to absolute in the configuration.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
delta_xintegerrequiredHorizontal movement deltaAny negative or positive integer value
delta_yintegerrequiredVertical movement deltaAny negative or positive integer value
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/hid/send_mouse_relative?delta_x=20&delta_y=200'
+
+
+Example output +
{
+"ok": true,
+"result": {}
+}  
+
+
+

Send mouse wheel scroll events

+

Method: POST

+

Route: /api/hid/events/send_mouse_wheel

+

Description: Sends mouse wheel scroll events to be emulated on the host by PiKVM.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
delta_xintegerrequiredHorizontal scroll deltaAny negative or positive integer value
delta_yintegerrequiredVertical scroll deltaAny negative or positive integer value
+

Example of use: Sends mouse wheel scroll events.

+
$ curl -k -X POST \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/hid/send_mouse_wheel?delta_x=0&delta_y=200'
+
+
+Example output +
{
+"ok": true,
+"result": {}
+}  
+
+
+
+

ATX power management

+

The PiKVM ATX API provides control over ATX (Advanced Technology eXtended) power management functions. It allows users perform the following operations:

+
    +
  • Get the current ATX state.
  • +
  • Change the ATX state.
  • +
  • Send an ATX button press event.
  • +
+

Get ATX state

+

Method: GET

+

Route: /api/atx

+

Description: Shows the current ATX state

+

Query parameters: None.

+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/atx
+
+
+Example output +
{
+    "ok": true,
+    "result": {
+        "busy": false, // True if ATX is busy performing an operation and does not accept commands
+        "enabled": true,
+        "leds": {
+            "hdd": false,
+            "power": false
+        }
+    }
+}
+
+
+

Set ATX power

+

Method: POST

+

Route: /api/atx/power

+

Description: Changes the ATX power state to desired.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
actionstringoptionalSpecifies desired stateon - Turn on (do nothing in case PSU is already on). off - Turn off (aka soft-off), emulates click on the power button. off_hard - Perform long press on the power button (5+ seconds). reset_hard - Emulate pressing reset button (hardware hot reset)
waitbooleanoptionalSays if call should return immediately or just after finishing operation.Enable: 1, true, or yes. Disable: 0, false, or no
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/atx/power?action=on
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}
+
+
+

Click ATX button

+

Method: POST

+

Route: /api/atx/click

+

Description: Sends the ATX button press event.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
buttonstringoptionalSpecifies the desired PC case buttonpower - Short click on the power button. power_long - Long press on the power button (5+ seconds). reset - Short click on the reset button.
waitbooleanoptionalSays if call should return immediately or just after finishing operation.Enable: 1, true, or yes. Disable: 0, false, or no
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/atx/click?button=power
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}   
+
+
+
+

Mass Storage Drive

+

The PiKVM Mass Storage Drive API provides controls for remote management of disk images that can be mounted as virtual storage devices. It allows users perform the following operations:

+
    +
  • Get current MSD status and configuration
  • +
  • Upload, download, and delete disk images
  • +
  • Fetch disk images directly from URLs with progress streaming
  • +
  • Connect/disconnect virtual storages, enable CD-ROM and read-write modes
  • +
  • Set image names, access modes, and device type settings
  • +
+

Get MSD state

+

Method: GET

+

Route: /api/msd

+

Description: Retrieves the current state of the Mass Storage Device.

+

Query parameters: None.

+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/msd
+
+
+Example output +
{
+    "ok": true,
+    "result": {
+        "busy": false,
+        "drive": {
+            "cdrom": true,
+            "connected": false,
+            "image": null,
+            "rw": false
+        },
+        "enabled": true,
+        "online": true,
+        "storage": {
+            "downloading": null,
+            "images": {},
+            "parts": {
+                "": {
+                    "free": 24358789120,
+                    "size": 24375590912,
+                    "writable": true
+                }
+            },
+            "uploading": null
+        }
+    }
+}
+
+
+

Upload MSD image

+

Method: POST

+

Route: /api/msd/write

+

Description: uploads an ISO to the Mass Storage Device.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
imagestringrequiredSpecifies the name of the image. Binary data should be passed to the POST bodyfilename.iso
+

Example of use:

+
$ # create a test image
+$ dd if=/dev/zero of=test.iso bs=1M count=1
+
+$ # upload it to pikvm
+$ curl -v -X POST --data-binary @test.iso -k \
+    -u admin:admin \
+    https://<pikvm-ip>/api/msd/write?image=test.iso
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}   
+
+
+

Upload MSD image by URL

+

Method: POST

+

Route: /api/msd/write_remote

+

Description: Downloads an image from HTTP(S) URL to the MSD.

+
+

Note

+

This is a long-polling request. Do not interrupt the request until the download is complete, otherwise the download will stop.

+
+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
urlstringrequiredImage URLAny URL using HTTP(S)
imagestringoptionalImage nameAny alphanumeric name like image321.iso
timeoutintegeroptionalRemote request timeout, 10 seconds by default≥0
+

Example of use:

+
$ # create test image
+$ dd if=/dev/zero of=test.iso bs=1M count=1
+
+$ # upload it to pikvm
+$ curl -v -X POST -k \
+    -u admin:admin \
+    https://<pikvm-ip>/api/msd/write_remote?url=http://example.com/test.iso
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}   
+
+
+

Set MSD parameters

+

Method: POST

+

Route: /api/msd/set_params

+

Description: Changes the current image and/or set drive parameters.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
imagestringoptionalChange the current imagefilename.iso
cdrombooleanoptionalChange the media type to the CD-ROM or Flash.1 (CD-ROM) or 0 (Flash)
rwbooleanoptionalSets read-write or read-only mode. Ignored (always read-only) when cdrom=11 (read-write) or 0 (read-only)
+

Example of use:

+
$ curl -X POST -k \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/msd/set_params?image=test.iso&cdrom=1'
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}   
+
+
+

Control MSD

+

Method: POST

+

Route: /api/msd/set_connected

+

Description: Connects or disconnects the MSD to/from the host.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
connectedbooleanrequiredChanges the state1 connects the MSD, 0 disconnects it
+

Example of use:

+
$ curl -X POST -k \
+    -u admin:admin \
+    https://<pikvm-ip>/api/msd/set_connected?connected=1
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}   
+
+
+

Remove MSD image

+

Method: POST

+

Route: /api/msd/remove

+

Description: Removes the specified image.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
imagestringrequiredName of the image to removefilename.iso
+

Example of use:

+
$ curl -X POST -k \
+    -u admin:admin \
+    https://<pikvm-ip>/api/msd/remove?image=test.iso
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}   
+
+
+

Reset MSD

+

Method: POST

+

Route: /api/msd/reset

+

Description: Drops all the custom parameters you set before and resets the Mass Storage Device to its default state.

+

Query parameters: None.

+

Example of use:

+
$ curl -X POST -k \
+    -u admin:admin \
+    https://<pikvm-ip>/api/msd/reset
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}   
+
+
+
+

GPIO

+

This is a PiKVP API for controlling User GPIO (General Purpose Input/Output) pins. It allows users perform the following operations:

+
    +
  • Read GPIO states.
  • +
  • Switch pins on/off.
  • +
  • Send pulses to GPIO channels.
  • +
+

Get GPIO state

+

Method: GET

+

Route: /api/gpio

+

Description: Retrieves the current state of all GPIO channels.

+

Query parameters: None.

+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/gpio
+
+
+Example output +
{
+    "ok": true,
+    "result": {
+        "model": {
+            "scheme": {
+                "inputs": {},
+                "outputs": {
+                    "__v3_usb_breaker__": {
+                        "hw": {
+                            "driver": "__gpio__",
+                            "pin": "5"
+                        },
+                        "pulse": {
+                            "delay": 0.0,
+                            "max_delay": 0.0,
+                            "min_delay": 0.0
+                        },
+                        "switch": true
+                    }
+                }
+            },
+            "view": {
+                "header": {
+                    "title": [
+                        {
+                            "text": "GPIO",
+                            "type": "label"
+                        }
+                    ]
+                },
+                "table": []
+            }
+        },
+        "state": {
+            "inputs": {},
+            "outputs": {
+                "__v3_usb_breaker__": {
+                    "busy": false,
+                    "online": true,
+                    "state": true
+                }
+            }
+        }
+    }
+} 
+
+
+

Switch GPIO channel

+

Method: POST

+

Route: /gpio/switch

+

Description: Sets a GPIO channel to a specific state (on/off).

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
channelstringrequiredThe GPIO driver channelAlphanumeric channel name, e.g., __v3_usb_breaker__
statebooleanrequiredThe new switch state1 to switch on, 0 to switch off
waitbooleanoptionalDefines when a call should return1 return immediately, 0 return after finishing operation
+

Example of use:

+
# Switch GPIO channel led1 to OFF state without waiting
+$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/gpio/switch?channel=led1&state=0&wait=0
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}
+
+
+

Pulse GPIO channel

+

Method: POST

+

Route: /api/gpio/pulse

+

Description: Sends a pulse signal to a GPIO channel (briefly activates then deactivates). Only works for channels that support the pulse mode.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
channelstringrequiredThe GPIO driver channelAlphanumeric channel name, e.g., led1
delayfloatoptionalThe pulse time in secondsAny float number, 0 for default delay
waitbooleanoptionalDefines when a call should return1 return immediately, 0 return after finishing operation
+

Example of use:

+
# Send a pulse to GPIO channel led1 with 2 sec delay without waiting
+$ curl -k -X POST \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/gpio/pulse?channel=led1&delay=2.0&wait=0'
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+}
+
+
+
+

Streamer

+

The PiKVM Streamer API provides remote access to video stream capture and management functionality of PiKVM devices. It allows users perform the following operations:

+
    +
  • Capture screenshots.
  • +
  • Perform optical character recognition (OCR) on captured images.
  • +
  • Monitor the streamer's operational status.
  • +
+

Get streamer state

+

Method: GET

+

Route: /api/streamer

+

Description: Retrieves the current state of the streamer.

+

Query parameters: None

+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/streamer
+
+
+Example output +
{
+    "ok": true,
+    "result": {
+        "features": {
+            "h264": true,
+            "quality": true,
+            "resolution": false
+        },
+        "limits": {
+            "desired_fps": {
+                "max": 70,
+                "min": 0
+            },
+            "h264_bitrate": {
+                "max": 20000,
+                "min": 25
+            },
+            "h264_gop": {
+                "max": 60,
+                "min": 0
+            }
+        },
+        "params": {
+            "desired_fps": 40,
+            "h264_bitrate": 5000,
+            "h264_gop": 30,
+            "quality": 80
+        },
+        "snapshot": {
+            "saved": null
+        },
+        "streamer": {
+            "encoder": {
+                "quality": 80,
+                "type": "M2M-IMAGE"
+            },
+            "h264": {
+                "bitrate": 5000,
+                "fps": 60,
+                "gop": 30,
+                "online": true
+            },
+            "instance_id": "",
+            "sinks": {
+                "h264": {
+                    "has_clients": true
+                },
+                "jpeg": {
+                    "has_clients": false
+                }
+            },
+            "source": {
+                "captured_fps": 59,
+                "desired_fps": 40,
+                "online": true,
+                "resolution": {
+                    "height": 720,
+                    "width": 1280
+                }
+            },
+            "stream": {
+                "clients": 0,
+                "clients_stat": {},
+                "queued_fps": 0
+            }
+        }
+    }
+}  
+
+
+

Take snapshot

+

Method: GET

+

Route: /api/streamer/snapshot

+

Description: Captures a snapshot from the video stream. Can optionally perform OCR text recognition or generate a preview image. For optical character recognition, the coordinates origin starts at top left.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
savebooleanoptionalWhether to save the snapshot, default: falseEnable: 1, true, or yes. Disable: 0, false, or no
loadbooleanoptionalWhether to load an existing snapshot, default: falseEnable: 1, true, or yes. Disable: 0, false, or no
allow_offlinebooleanoptionalWhether to allow taking snapshots when offline, default: falseEnable: 1, true, or yes. Disable: 0, false, or no
ocrbooleanoptionalWhether to perform OCR text recognition on the snapshot, default: falseEnable: 1, true, or yes. Disable: 0, false, or no
ocr_langsstringoptionalComma-separated list of language codes for OCR recognitionTypically, a 3-letter code, such as eng for English or deu for German. Run pacman -Ss tesseract-data on PiKVM to get the full list
ocr_leftintegeroptionalX coordinate of the top left corner of the OCR region, default: -1≥0
ocr_topintegeroptionalY coordinate of the top left corner of the OCR region, default: -1≥0
ocr_rightintegeroptionalWidth of the OCR region, default: -1≥0
ocr_bottomintegeroptionalHeight of the OCR region, default: -1≥0
previewbooleanoptionalWhether to generate a preview image, default: falseEnable: 1, true, or yes. Disable: 0, false, or no
preview_max_widthintegeroptionalMaximum width for preview image, default: 0Any positive integer value
preview_max_heightintegeroptionalMaximum height for preview image, default: 0Any positive integer value
preview_qualityintegeroptionalJPEG quality for preview (valid stream quality value), default: 80Any integer value in the 0..100 range
+

Example of use: the following command will capture a snapshot of the current video stream and save it to a JPEG file.

+
$ curl -k \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/streamer/snapshot?save=1&preview_quality=95' \
+    --output=file.jpg
+
+
+Example output +
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
+                                 Dload  Upload   Total   Spent    Left  Speed
+100  107k  100  107k    0     0   619k      0 --:--:-- --:--:-- --:--:--  619k
+
+
+

Example of use: the following command will capture a region of the current video stream (left corner starts at the top left, extends 1000px to the right and 150px to the bottom), run it through Tesseract for optical character recognition (language defined as English), and output the recognized text into the console.

+
$ curl -k \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/streamer/snapshot?ocr=true&ocr_left=0&ocr_top=0&ocr_right=1000&ocr_bottom=150&ocr_langs=eng'
+
+

Responses:

+
    +
  • When ocr=true:
      +
    • Content-Type: text/plain
    • +
    • Body: Recognized text from the image
    • +
    +
  • +
  • When preview=true or default:
      +
    • Content-Type: image/jpeg
    • +
    • Body: JPEG image data (either preview or full snapshot)
    • +
    +
  • +
  • When snapshot unavailable:
      +
    • Status: 503 Service Unavailable
    • +
    • Error: UnavailableError
    • +
    +
  • +
+

Remove snapshot

+

Method: DELETE

+

Route: /api/streamer/snapshot

+

Description: Removes/deletes the current snapshot from memory.

+

Query parameters: None

+

Example of use:

+
$ curl -k -X DELETE \
+    -u admin:admin \
+    https://<pikvm-ip>/api/streamer/snapshot
+
+
+Example output +
{
+    "ok": true,
+    "result": {}
+} 
+
+
+

Get OCR state

+

Method: GET

+

Route: /api/streamer/ocr

+

Description: Retrieves the current state and configuration of the optical character recognition (OCR) service.

+

Query parameters: None

+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/streamer/ocr
+
+
+Example output +
{
+    "ok": true,
+    "result": {
+        "ocr": {
+            "enabled": true,
+            "langs": {
+                "available": [
+                    "eng",
+                    "osd"
+                ],
+                "default": [
+                    "eng"
+                ]
+            }
+        }
+    }
+}
+
+
+
+

Switch

+

The PiKVM Switch API provides handles to control the PiKVM Switch: get information, set active ports, and control beacons.

+

The API heavily relies on specifying ports on the PiKVM Switch. There are two ways to do that: with continuous numbering or with float numbers. Both options are equally valid and supported.

+
    +
  1. With continuous numbering, ports enumeration starts at 0 and ends at 19, because you can create up to 20 ports by adding more PiKVM Switch devices to the first Switch's downlink.
  2. +
  3. If you use a float value, the integer part specifies the number of the unit in the downlink, while the fractional part specifies the number of the port on that unit.
  4. +
+

Get Switch state

+

Method: GET

+

Route: /api/switch

+

Description: Returns the information about the PiKVM Switch state.

+

Query parameters: None.

+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/switch
+
+
+Example output +
FIXME
+
+
+

Set active port (previous)

+

Method: POST

+

Route: /api/switch/set_active_prev

+

Description: Switches to the previous active port.

+

Query parameters: None.

+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/switch/set_active_prev
+
+
+Example output +
FIXME
+
+
+

Set active port (next)

+

Method: POST

+

Route: /api/switch/set_active_next

+

Description: Switches to the next active port.

+

Query parameters: None.

+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/switch/set_active_next
+
+
+Example output +
FIXME
+
+
+

Set active port (specific)

+

Method: POST

+

Route: /api/switch/set_active

+

Description: Switches to a specific port.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
portfloatrequiredSpecifies the port numberInteger in the 0..19 range or float (0,0 through 4,3)
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/switch/set_active?port=2,2
+
+
+Example output +
FIXME
+
+
+

Set beacon

+

Method: POST

+

Route: /api/switch/set_beacon

+

Description: Controls beacon lights on ports or uplink/downlink units.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
statebooleanrequiredTurn beacon on/offEnable: 1, true, or yes. Disable: 0, false, or no
portfloatoptionalSpecify the port beaconInteger in the 0..19 range or float (0,0 through 4,3)
uplinkintegeroptionalNumber of the uplink beacon, same as the portInteger in the 0..19 range or float (0,0 through 4,3)
downlinkintegeroptionalNumber of the downlink beacon, same as the portInteger in the 0..19 range or float (0,0 through 4,3)
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/switch/set_beacon
+
+
+Example output +
FIXME
+
+
+

Set port parameters

+

Method: POST

+

Route: /api/switch/set_port_params

+

Description: Configures parameters for a specific port.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
portfloatrequiredSpecifies the port number0..19
edid_idstringoptionalEDID identifier (allows default value)Alphanumeric string like ca3d7114-79ca-47fc-80b4-b80ac63fc329
dummybooleanoptionalWhen enabled, the switch will pretend the host has a display attachedEnable: 1, true, or yes. Disable: 0, false, or no
namestringoptionalString port name, none set by defaultAny combination of ASCII letters and numbers
atx_click_power_delayfloatoptionalATX power click delay value0..10
atx_click_power_long_delayfloatoptionalATX long power click delay value0..10
atx_click_reset_delayfloatoptionalATX reset click delay value0..10
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/switch/set_port_params?port=2&name=PORT3'
+
+
+Example output +
FIXME
+
+
+

Set beacon color

+

Method: POST

+

Route: /api/switch/set_colors

+

Description: Sets the beacon color for the PiKVM Switch and all switches in the downlink (where applicable).

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
beaconhexrequiredSets color, brightness, and blink interval (ms)A valid hex value (see example below)
+

Example of use: Let's set the beacon to be orange at 75% of full brightness, blinking with an interval of 40ms.

+
$ curl -k -X POST \
+    -u admin:admin \
+    -d "FFA500:BF:0028" \
+    https://<pikvm-ip>/api/switch/set_colors
+
+
+Example output +
FIXME
+
+
+

Reboot the device

+

Method: POST

+

Route: /api/switch/reset

+

Description: Reboots the PiKVM Switch with an option to enter the reflashing mode after the reboot.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
unitintegerrequiredSpecifies the unit number0..4
bootloaderbooleanoptionalWhether to enter the reflashing mode after rebooting, defaults to falseEnable: 1, true, or yes. Disable: 0, false, or no
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/switch/reset?unit=0&bootloader=1'
+
+
+Example output +
FIXME
+
+
+

Create a new EDID configuration

+

Method: POST

+

Route: /api/switch/edids/create

+

Description: Creates a new EDID configuration from user-specified EDID name and data.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
namestringrequiredEDID nameAlphanumeric name (see example below)
datastringrequiredEDID dataHexadecimal string (see example below)
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/switch/edids/create?name=Gigabyte-GA-H77-DS3H&data=00FFFFFFFFFFFF0052628888008888881C150103800000780AEE91A3544C99260F505425400001000100010001000100010001010101D51B0050500019400820B80080001000001EEC2C80A070381A403020350040442100001E000000FC0050492D4B564D20566964656F0A000000FD00323D0F2E0F0000000000000000014D02030400DE0D20A03058122030203400F0B400000018E01500A04000163030203400000000000018B41400A050D011203020350080D810000018AB22A0A050841A3030203600B00E1100001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045'
+
+
+Example output +
FIXME
+
+
+

Change EDID configuration

+

Method: POST

+

Route: /api/switch/edids/change

+

Description: Modifies an existing EDID configuration.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
idstringrequiredEDID identifierAlphanumeric id (see example below)
namestringoptionalNew EDID nameAlphanumeric name (see example below)
datastringoptionalNew EDID dataHexadecimal string (see example below)
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/switch/edids/change?id=ca3d7114-79ca-47fc-80b4-b80ac63fc329&name=Gigabyte-GA-H77-DS3H&data=00FFFFFFFFFFFF0052628888008888881C150103800000780AEE91A3544C99260F505425400001000100010001000100010001010101D51B0050500019400820B80080001000001EEC2C80A070381A403020350040442100001E000000FC0050492D4B564D20566964656F0A000000FD00323D0F2E0F0000000000000000014D02030400DE0D20A03058122030203400F0B400000018E01500A04000163030203400000000000018B41400A050D011203020350080D810000018AB22A0A050841A3030203600B00E1100001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045'
+
+
+Example output +
FIXME
+
+
+

Remove EDID configuration

+

Method: POST

+

Route: /api/switch/edids/remove

+

Description: Deletes an EDID configuration.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
idstringrequiredEDID identifierAlphanumeric id (see example below)
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    https://<pikvm-ip>/api/switch/edids/remove?id=ca3d7114-79ca-47fc-80b4-b80ac63fc329
+
+
+Example output +
FIXME
+
+
+

ATX Power Control

+

Method: POST

+

Route: /api/switch/atx/power

+

Description: Controls ATX power states for a specific port.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
portfloatrequiredSpecifies the port number0..19
actionstringrequiredPower actionon - Power on, off - Power off, off_hard - Hard power off, reset_hard - Hard reset
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/switch/atx/power?port=0&action=reset_hard'
+
+
+Example output +
FIXME
+
+
+

ATX Button Click

+

Method: POST

+

Route: /api/switch/atx/click

+

Description: Simulates ATX button clicks for a specific port.

+

Query parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeOptionalityDescriptionAcceptable values
portfloatrequiredSpecifies the port number0..19
buttonstringrequiredPower actionpower - Power button click, power_long - Long power button press, reset - Reset button click
+

Example of use:

+
$ curl -k -X POST \
+    -u admin:admin \
+    'https://<pikvm-ip>/api/switch/atx/click?port=0&button=power_long'
+
+
+Example output +
FIXME
+
+
+
+

Redfish

+

The PiKVM Redfish API implements the industry-standard DMTF Redfish specification for remote server control. It allows you to monitor and control the power of the target system.

+

Most endpoints require authentication using your PiKVM credentials. You can interact with the API using standard HTTP clients, curl, or the specialized Redfish tools.

+

Root service discovery

+

Method: GET

+

Route: /api/redfish/v1

+

Description: Returns the basic Redfish service information and links to available resources. Doesn't require authentication.

+

Query parameters: None.

+

Example of use:

+
$ curl -k https://<pikvm-ip>/api/redfish/v1
+
+
+Example output +
{
+    "@odata.id": "/redfish/v1",
+    "@odata.type": "#ServiceRoot.v1_6_0.ServiceRoot",
+    "Id": "RootService",
+    "Name": "Root Service",
+    "RedfishVersion": "1.6.0",
+    "Systems": {
+        "@odata.id": "/redfish/v1/Systems"
+    }
+}
+
+
+

Systems collection

+

Method: GET

+

Route: /api/redfish/v1/Systems

+

Description: Returns collection of available computer systems.

+

Query parameters: None.

+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/redfish/v1/Systems
+
+
+Example output +
{
+    "@odata.id": "/redfish/v1/Systems",
+    "@odata.type": "#ComputerSystemCollection.ComputerSystemCollection",
+    "Members": [
+        {
+            "@odata.id": "/redfish/v1/Systems/0"
+        }
+    ],
+    "Members@odata.count": 1,
+    "Name": "Computer System Collection"
+}
+
+
+

Individual system information

+

Method: GET

+

Route: /api/redfish/v1/Systems/0

+

Description: Returns detailed information about the specific system, including power state, hostname, and available actions.

+

Query parameters: None.

+

Example of use:

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/redfish/v1/Systems/0
+
+
+Example output +
{
+    "@odata.id": "/redfish/v1/Systems/0",
+    "@odata.type": "#ComputerSystem.v1_10_0.ComputerSystem",
+    "Actions": {
+        "#ComputerSystem.Reset": {
+            "ResetType@Redfish.AllowableValues": [
+                "On",
+                "ForceOff",
+                "GracefulShutdown",
+                "ForceRestart",
+                "ForceOn",
+                "PushPowerButton"
+            ],
+            "target": "/redfish/v1/Systems/0/Actions/ComputerSystem.Reset"
+        },
+        "#ComputerSystem.SetDefaultBootOrder": {
+            "target": "/redfish/v1/Systems/0/Actions/ComputerSystem.SetDefaultBootOrder"
+        }
+    },
+    "Boot": {
+        "BootSourceOverrideEnabled": "Disabled",
+        "BootSourceOverrideTarget": null
+    },
+    "HostName": "pikvm",
+    "Id": "0",
+    "PowerState": "Off"
+}
+
+
+

System configuration update

+

Method: PATCH

+

Route: /api/redfish/v1/Systems/0

+

Description: This handle was added to aid in scenarios where installing OKD (Kubernetes) using installer-provisioned infrastructure involves expecting two fields to be returned and the patch request to return a 204. Hence, this handle is currently a no-op that just returns success.

+

Query parameters: None

+

Example of use:

+
$ curl -k -X PATCH -u admin:admin https://<pikvm-ip>/api/redfish/v1/Systems/0
+
+

There will be zero output for this command by design.

+

Responses:

+ + + + + + + + + + + + + +
CodeDescription
204Returns success
+

System power control

+

Method: POST

+

Route: /api/redfish/v1/Systems/0/Actions/ComputerSystem.Reset

+

Description: Performs power control actions on the system.

+

Query parameters: This handles expects JSON with ResetType in the request body and one of the following values:

+
    +
  • On - Power on
  • +
  • ForceOff - Hard power off
  • +
  • GracefulShutdown - Graceful power off
  • +
  • ForceRestart - Hard reset
  • +
  • ForceOn - Force power on
  • +
  • PushPowerButton - Simulate power button press
  • +
+

Example of use:

+
$ curl -k -X POST \
+    -H "Content-Type: application/json" \
+    -u admin:admin \
+    -d '{"ResetType": "ForceRestart"}' \
+    https://<pikvm-ip>/api/redfish/v1/Systems/0/Actions/ComputerSystem.Reset
+
+

There will be zero output for this command by design.

+

Responses:

+ + + + + + + + + + + + + + + + + +
CodeDescription
204Success
400Invalid or missing ResetType
+
+

Misc

+

Get Prometheus metrics

+

The GET /api/export/prometheus/metrics handle returns the Prometheus metrics. Also see here for details.

+
$ curl -k -u admin:admin https://<pikvm-ip>/api/export/prometheus/metrics
+
+
+

Video

+

PiKVM has 3 different ways to receive video and audio, depending on the device. +This is also reflected in the web interface.

+

| Mode |

+

Get raw H.264 video stream

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/arduino_hid/arduino_serial_hid.jpg b/arduino_hid/arduino_serial_hid.jpg new file mode 100644 index 00000000..f17f1b7e Binary files /dev/null and b/arduino_hid/arduino_serial_hid.jpg differ diff --git a/arduino_hid/arduino_spi_hid.png b/arduino_hid/arduino_spi_hid.png new file mode 100644 index 00000000..26ca5efc Binary files /dev/null and b/arduino_hid/arduino_spi_hid.png differ diff --git a/arduino_hid/arduino_spi_hid_bb.jpg b/arduino_hid/arduino_spi_hid_bb.jpg new file mode 100644 index 00000000..b5eadc6c Binary files /dev/null and b/arduino_hid/arduino_spi_hid_bb.jpg differ diff --git a/arduino_hid/arduino_spi_hid_rpi.jpg b/arduino_hid/arduino_spi_hid_rpi.jpg new file mode 100644 index 00000000..3e7099bc Binary files /dev/null and b/arduino_hid/arduino_spi_hid_rpi.jpg differ diff --git a/arduino_hid/index.html b/arduino_hid/index.html new file mode 100644 index 00000000..0023bf74 --- /dev/null +++ b/arduino_hid/index.html @@ -0,0 +1,3073 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Arduino HID - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

Arduino HID

+ +
+

Legacy warning

+

This page describes the legacy keyboard and mouse emulator used in old DIY builds. +There is no point using it today because there is a more modern and better replacement for the new Pico HID. +This one can also serve as an in-place compatible replacement for the Arduino HID in the old build.

+
+
+

Serial HID

+
+

PiKVM V3 note

+

Use the SPI HID for V3. Otherwise, you won't be able to use the Serial console.

+
+

USB keyboard and mouse

+
    +
  1. +
    +Get some parts +
      +
    • Arduino Pro Micro (based on an ATMega32u4).
    • +
    • Logic level shifter.
    • +
    • 1x NPN transistor (almost any NPN transistor: 2n2222 or similar).
    • +
    • 1x 390 Ohm resistor.
    • +
    • A breadboard and wires.
    • +
    +
    +
  2. +
  3. +
    +Build the Arduino HID according to the scheme +

    +
    +
  4. +
  5. +

    Power up PiKVM and switch it to RW-mode using command rw.

    +
  6. +
  7. +

    Add these lines to /etc/kvmd/override.yaml:

    +
    kvmd:
    +    hid:
    +        type: serial
    +        reset_pin: 4
    +        device: /dev/kvmd-hid
    +
    +
  8. +
  9. +

    Create file /etc/udev/rules.d/99-kvmd-extra.rules:

    +
    KERNEL=="ttyAMA0", SYMLINK+="kvmd-hid"
    +
    +
  10. +
  11. +

    Run systemctl disable getty@ttyAMA0.service.

    +
  12. +
  13. +

    Remove console=ttyAMA0,115200or console=serial0,115200 and kgdboc=ttyAMA0,115200 or kgdboc=serial0,115200 from /boot/cmdline.txt.

    +
  14. +
  15. +

    Flash the Arduino HID.

    +
  16. +
  17. +

    Perform reboot.

    +
  18. +
+

PS/2 keyboard

+

Using the PS/2 firmware currently have some limitations:

+
    +
  • The possibility of using the switchable USB HID is excluded.
  • +
  • PS/2 mouse is not supported right now (but it will).
  • +
+

Both of these problems will be solved in the nearest future and the two different firmware versions will be combined into one universal one.

+

To select the PS/2 firmware, follow the instructions for the USB, but with one exception:

+
+Before make you will need to edit file platformio-avr.ini +

Open the file and find these lines:

+
[_common]
+build_flags =
+    -DHID_PS2_KBD_CLOCK_PIN=7
+    -DHID_PS2_KBD_DATA_PIN=5
+    -DHID_USB_CHECK_ENDPOINT
+# ----- The default config with dynamic switching -----
+    -DHID_DYNAMIC
+    -DHID_WITH_USB
+    -DHID_SET_USB_KBD
+    -DHID_SET_USB_MOUSE_ABS
+# ----- PS2 keyboard only -----
+#   -DHID_WITH_PS2
+#   -DHID_SET_PS2_KBD
+# ----- PS2 keyboard + USB absolute mouse -----
+#   -DHID_WITH_USB
+#   -DHID_WITH_PS2
+#   -DHID_SET_PS2_KBD
+#   -DHID_SET_USB_MOUSE_ABS
+# ----- PS2 keyboard + USB relative mouse -----
+#   -DHID_WITH_USB
+#   -DHID_WITH_PS2
+#   -DHID_SET_PS2_KBD
+#   -DHID_SET_USB_MOUSE_REL
+
+

By default, the firmware works with USB HID and supports dynamic mode switching. You can choose one of the other modes by commenting some lines and uncommenting others. This example to use a USB mouse and PS/2 keyboard:

+
...
+# ----- The default config with dynamic switching -----
+#   -DHID_DYNAMIC
+#   -DHID_WITH_USB
+#   -DHID_SET_USB_KBD
+#   -DHID_SET_USB_MOUSE_ABS
+# ----- PS2 keyboard only -----
+...
+# ----- PS2 keyboard + USB absolute mouse -----
+    -DHID_WITH_USB
+    -DHID_WITH_PS2
+    -DHID_SET_PS2_KBD
+    -DHID_SET_USB_MOUSE_ABS
+# ----- PS2 keyboard + USB relative mouse -----
+...
+
+
+

Next, connect Arduino pins to the female PS/2 port of your motherboard. Choose the purple port. If your motherboard only have one port, it's probably universal and can be used either for the keyboard or for the mouse. Most likely, it is painted in two colors: green and purple. You can use it either.

+
+Follow the diagram + + + + + + + + + + + + + +
Female PS/2 port (front view)Pinout
drawingArduino pin 7 <-> PS/2 CLOCK
Arduino pin 5 <-> PS/2 DATA
Arduino GND pin <-> PS/2 GND
+
+

Warning

+

Connect VIN pin of Arduino to any Raspberry's 5v pin for PS/2 only device. But you don't need to connect the Arduino VIN pin if you connected USB (Arduino will get power through it).

+
+
+
+

SPI HID

+

Using an SPI connection, an Arduino Micro (not Pro) or compatible can be flashed from the Pi and used as an HID keyboard and mouse. Unlike UART, SPI does not share pins with Bluetooth on the Raspberry Pi so the Bluetooth radio does not need to be disabled.

+

Diagram of the Arduino SPI wiring for HID keyboard and mouse.

+

Before powering either device, double-check the connections. The following should be wired from the Pi to either the level shifter or the Arduino. While the Arduino tolerates 3.3V logic input, 5V outputs from the Arduino can damage or destroy the Raspberry Pi and must not be connected directly to 3.3V GPIO pins directly.

+

Parts list

+

There are very few parts needed besides the Raspberry Pi to build the solution. Some parts may be purchased with or without headers, if headers are not pre-soldered, it may be necessary to order some breakaway header strips and solder them to the boards prior to assembly unless the wires will be soldered directly to the boards.

+
    +
  • Raspberry Pi Zero W or Pi 4 are the most popular boards for this solution, pre-soldered headers recommended
  • +
  • Arduino Micro (or compatible) microcontroller board with pre-soldered headers recommended
  • +
  • Logic Level Converter. This may be RX/TX, Bidirectional, or Single Supply
  • +
  • 1x PNP transistor (2n2907 or equivalent). Note this is different from the one suggested in the Serial HID docs above, that is an NPN while this is a PNP.
  • +
  • 1x 390 ohm resistor
  • +
  • Dupont wires (female to male pin) recommended for breadboard or other suitable means of making the connections
  • +
  • Optional: Breakaway headers for the logic level converter
  • +
  • Optional: Breadboard large enough to accommodate the parts
  • +
  • Optional: Header pins for connection to a breadboard
  • +
+
+

Note

+

A smaller "Pro Micro" board is available in a 3.3V model but the SS connection (RX_LED) is not available as a separate pin or solderable hole. If using this board, a jumper wire can be soldered to the resistor for the RX_LED but there is risk of burning the resistor, the LED, the board, or other components in the process. Advantages of this board include not requiring a logic level converter and reduced breadboard or board space for building the solution.

+
+

List of connections to be made

+

For the primary functionality, most connections are made using a 4-channel bidirectional level shifter

+
    +
  • Pi 3v3 to LV on the level shifter
  • +
  • Pi Ground to LV GND
  • +
  • Arduino GND to HV GND
  • +
  • GPIO10 (MOSI) via the level shifter to MOSI on the Arduino
  • +
  • GPIO9 (MISO) via the level shifter to MISO on the Arduino
  • +
  • GPIO11 (SPIO_SCLK) via the level shifter to SCK on the Arduino
  • +
  • GPIO7 (SPIO_CE1_N) via the level shifter to SS (or RX_LED) on the Arduino
  • +
+

An additional circuit is used with a transistor to reset the HID for mode changes and for SPI programming as follows:

+
    +
  • GPIO25 to PNP base on transistor
  • +
  • PNP emitter to ground
  • +
  • PNP collector to RST on the Arduino
  • +
+

Pictures of this setup are also available in full resolution for download to assist for both the Raspberry Pi and the Arduino board. A smaller version of the images has been included on this page and can be downloaded.

+ + + + + + + + + + + + + +
Raspberry Pi CloseupBreadboard with Arduino
A closeup of the Raspberry Pi wired to the breadboard.Arduino on a breadboard fully wired to the Pi.
+

Programming assumes the Arduino is powered via USB, either from the connected host or the Pi itself. If the USB is not connected, 5 V may be provided by the Raspberry Pi GPIO but should be disconnected prior to connecting USB to the Arduino's USB port. The Raspberry Pi does not have backcurrent protection, a circuit using one or more Schottky diodes can be built to OR power from multiple sources but it's easier and more cost effective to avoid conflict and voltage differences between power supplies by leaving the 5 V wire disconnected.

+

Preparing the installation for SPI devices and programming

+

As of the latest package release, the kvmd service supports SPI. It should be sufficient to ensure the packages are up-to-date with the latest release, the programmer is installed, and the SPI device overlay is loaded at boot.

+
    +
  • Switch the filesystem to read-write mode with rw
  • +
  • Add dtoverlay=spi0-1cs to /boot/config.txt
  • +
  • Perform reboot.
  • +
+

Flashing the Arduino

+

Instructions on flashing the Arduino can be found on the page Flash the Arduino HID.

+

If programming fails, ensure the Arduino is powered and check the wiring again. If there is a misconfiguration, power off the Pi and the Arduino, correct the wiring, and try again. Note it is not recommended or required to supply 5V power from the Raspberry Pi if the Arduino is USB powered, if the issue appears to be power related it may be removed from the solution and replaced with a powered USB connection if it will aid in troubleshooting but check all other wires first to ensure there are no shorts.

+

After you have double and triple-checked your wiring (in particular make sure the pins you are using on the Pi are correct, the documentation uses the GPIO pin labels, NOT the sequential pin numbers from 1-40. A good pinout reference is @Gadgetoid's version, you might try flashing the Arduino by holding down the RESET button on the chip while running make install. If this works, then at least you know your SPI wiring is correct.

+

Wiring problems are a common issue but there could be other reasons for programming not to complete. While it is not possible to list every possible problem and solution here, there is an active user community with others familiar with the solution and willing to help.

+

Enable the SPI configuration and restart kvmd

+

Once the installation has completed, all that should remain is to add the following configuration to /etc/kvmd/override.yaml and restart the kvmd service. If the first line exists due to existing overrides, omit that line and either add or update the hid section as appropriate.

+
kvmd:
+    hid:
+        type: spi
+        chip: 0
+        bus: 0
+        sw_cs_pin: 7
+        reset_pin: 25
+        reset_inverted: true
+
+

After saving the changes to /etc/kvmd/override.yaml, restart kvmd and clear your browser cache. The command to restart kvmd is

+
# systemctl restart kvmd
+
+

If your device is still in read-write mode, ro will put the SD back in read-only mode.

+
+

Fixing the USB absolute mouse on Windows 98

+

Due to an ancient buggy driver, the USB absolute mouse on Windows 98 moves only within the upper-left quarter of the screen. To fix this, just recompile the firmware with uncommented flag -DHID_WITH_USB_WIN98 in platformio-avr.ini.

+ + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/arduino_hid/ps2_kbd.png b/arduino_hid/ps2_kbd.png new file mode 100644 index 00000000..97f03d7d Binary files /dev/null and b/arduino_hid/ps2_kbd.png differ diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 00000000..1cf13b9f Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/javascripts/bundle.f55a23d4.min.js b/assets/javascripts/bundle.f55a23d4.min.js new file mode 100644 index 00000000..01a46ad8 --- /dev/null +++ b/assets/javascripts/bundle.f55a23d4.min.js @@ -0,0 +1,16 @@ +"use strict";(()=>{var Wi=Object.create;var gr=Object.defineProperty;var Vi=Object.getOwnPropertyDescriptor;var Di=Object.getOwnPropertyNames,Vt=Object.getOwnPropertySymbols,zi=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,ao=Object.prototype.propertyIsEnumerable;var io=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,$=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&io(e,r,t[r]);if(Vt)for(var r of Vt(t))ao.call(t,r)&&io(e,r,t[r]);return e};var so=(e,t)=>{var r={};for(var o in e)yr.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(e!=null&&Vt)for(var o of Vt(e))t.indexOf(o)<0&&ao.call(e,o)&&(r[o]=e[o]);return r};var xr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Ni=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Di(t))!yr.call(e,n)&&n!==r&&gr(e,n,{get:()=>t[n],enumerable:!(o=Vi(t,n))||o.enumerable});return e};var Lt=(e,t,r)=>(r=e!=null?Wi(zi(e)):{},Ni(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var co=(e,t,r)=>new Promise((o,n)=>{var i=p=>{try{s(r.next(p))}catch(c){n(c)}},a=p=>{try{s(r.throw(p))}catch(c){n(c)}},s=p=>p.done?o(p.value):Promise.resolve(p.value).then(i,a);s((r=r.apply(e,t)).next())});var lo=xr((Er,po)=>{(function(e,t){typeof Er=="object"&&typeof po!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(Er,(function(){"use strict";function e(r){var o=!0,n=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(k){return!!(k&&k!==document&&k.nodeName!=="HTML"&&k.nodeName!=="BODY"&&"classList"in k&&"contains"in k.classList)}function p(k){var ft=k.type,qe=k.tagName;return!!(qe==="INPUT"&&a[ft]&&!k.readOnly||qe==="TEXTAREA"&&!k.readOnly||k.isContentEditable)}function c(k){k.classList.contains("focus-visible")||(k.classList.add("focus-visible"),k.setAttribute("data-focus-visible-added",""))}function l(k){k.hasAttribute("data-focus-visible-added")&&(k.classList.remove("focus-visible"),k.removeAttribute("data-focus-visible-added"))}function f(k){k.metaKey||k.altKey||k.ctrlKey||(s(r.activeElement)&&c(r.activeElement),o=!0)}function u(k){o=!1}function d(k){s(k.target)&&(o||p(k.target))&&c(k.target)}function y(k){s(k.target)&&(k.target.classList.contains("focus-visible")||k.target.hasAttribute("data-focus-visible-added"))&&(n=!0,window.clearTimeout(i),i=window.setTimeout(function(){n=!1},100),l(k.target))}function L(k){document.visibilityState==="hidden"&&(n&&(o=!0),X())}function X(){document.addEventListener("mousemove",J),document.addEventListener("mousedown",J),document.addEventListener("mouseup",J),document.addEventListener("pointermove",J),document.addEventListener("pointerdown",J),document.addEventListener("pointerup",J),document.addEventListener("touchmove",J),document.addEventListener("touchstart",J),document.addEventListener("touchend",J)}function ee(){document.removeEventListener("mousemove",J),document.removeEventListener("mousedown",J),document.removeEventListener("mouseup",J),document.removeEventListener("pointermove",J),document.removeEventListener("pointerdown",J),document.removeEventListener("pointerup",J),document.removeEventListener("touchmove",J),document.removeEventListener("touchstart",J),document.removeEventListener("touchend",J)}function J(k){k.target.nodeName&&k.target.nodeName.toLowerCase()==="html"||(o=!1,ee())}document.addEventListener("keydown",f,!0),document.addEventListener("mousedown",u,!0),document.addEventListener("pointerdown",u,!0),document.addEventListener("touchstart",u,!0),document.addEventListener("visibilitychange",L,!0),X(),r.addEventListener("focus",d,!0),r.addEventListener("blur",y,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)}))});var qr=xr((dy,On)=>{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var $a=/["'&<>]/;On.exports=Pa;function Pa(e){var t=""+e,r=$a.exec(t);if(!r)return t;var o,n="",i=0,a=0;for(i=r.index;i{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Rt=="object"&&typeof Yr=="object"?Yr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Rt=="object"?Rt.ClipboardJS=r():t.ClipboardJS=r()})(Rt,function(){return(function(){var e={686:(function(o,n,i){"use strict";i.d(n,{default:function(){return Ui}});var a=i(279),s=i.n(a),p=i(370),c=i.n(p),l=i(817),f=i.n(l);function u(D){try{return document.execCommand(D)}catch(A){return!1}}var d=function(A){var M=f()(A);return u("cut"),M},y=d;function L(D){var A=document.documentElement.getAttribute("dir")==="rtl",M=document.createElement("textarea");M.style.fontSize="12pt",M.style.border="0",M.style.padding="0",M.style.margin="0",M.style.position="absolute",M.style[A?"right":"left"]="-9999px";var F=window.pageYOffset||document.documentElement.scrollTop;return M.style.top="".concat(F,"px"),M.setAttribute("readonly",""),M.value=D,M}var X=function(A,M){var F=L(A);M.container.appendChild(F);var V=f()(F);return u("copy"),F.remove(),V},ee=function(A){var M=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},F="";return typeof A=="string"?F=X(A,M):A instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(A==null?void 0:A.type)?F=X(A.value,M):(F=f()(A),u("copy")),F},J=ee;function k(D){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?k=function(M){return typeof M}:k=function(M){return M&&typeof Symbol=="function"&&M.constructor===Symbol&&M!==Symbol.prototype?"symbol":typeof M},k(D)}var ft=function(){var A=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},M=A.action,F=M===void 0?"copy":M,V=A.container,Y=A.target,$e=A.text;if(F!=="copy"&&F!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(Y!==void 0)if(Y&&k(Y)==="object"&&Y.nodeType===1){if(F==="copy"&&Y.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(F==="cut"&&(Y.hasAttribute("readonly")||Y.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if($e)return J($e,{container:V});if(Y)return F==="cut"?y(Y):J(Y,{container:V})},qe=ft;function Fe(D){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Fe=function(M){return typeof M}:Fe=function(M){return M&&typeof Symbol=="function"&&M.constructor===Symbol&&M!==Symbol.prototype?"symbol":typeof M},Fe(D)}function ki(D,A){if(!(D instanceof A))throw new TypeError("Cannot call a class as a function")}function no(D,A){for(var M=0;M0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof V.action=="function"?V.action:this.defaultAction,this.target=typeof V.target=="function"?V.target:this.defaultTarget,this.text=typeof V.text=="function"?V.text:this.defaultText,this.container=Fe(V.container)==="object"?V.container:document.body}},{key:"listenClick",value:function(V){var Y=this;this.listener=c()(V,"click",function($e){return Y.onClick($e)})}},{key:"onClick",value:function(V){var Y=V.delegateTarget||V.currentTarget,$e=this.action(Y)||"copy",Wt=qe({action:$e,container:this.container,target:this.target(Y),text:this.text(Y)});this.emit(Wt?"success":"error",{action:$e,text:Wt,trigger:Y,clearSelection:function(){Y&&Y.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(V){return vr("action",V)}},{key:"defaultTarget",value:function(V){var Y=vr("target",V);if(Y)return document.querySelector(Y)}},{key:"defaultText",value:function(V){return vr("text",V)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(V){var Y=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return J(V,Y)}},{key:"cut",value:function(V){return y(V)}},{key:"isSupported",value:function(){var V=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],Y=typeof V=="string"?[V]:V,$e=!!document.queryCommandSupported;return Y.forEach(function(Wt){$e=$e&&!!document.queryCommandSupported(Wt)}),$e}}]),M})(s()),Ui=Fi}),828:(function(o){var n=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,p){for(;s&&s.nodeType!==n;){if(typeof s.matches=="function"&&s.matches(p))return s;s=s.parentNode}}o.exports=a}),438:(function(o,n,i){var a=i(828);function s(l,f,u,d,y){var L=c.apply(this,arguments);return l.addEventListener(u,L,y),{destroy:function(){l.removeEventListener(u,L,y)}}}function p(l,f,u,d,y){return typeof l.addEventListener=="function"?s.apply(null,arguments):typeof u=="function"?s.bind(null,document).apply(null,arguments):(typeof l=="string"&&(l=document.querySelectorAll(l)),Array.prototype.map.call(l,function(L){return s(L,f,u,d,y)}))}function c(l,f,u,d){return function(y){y.delegateTarget=a(y.target,f),y.delegateTarget&&d.call(l,y)}}o.exports=p}),879:(function(o,n){n.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},n.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||n.node(i[0]))},n.string=function(i){return typeof i=="string"||i instanceof String},n.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}}),370:(function(o,n,i){var a=i(879),s=i(438);function p(u,d,y){if(!u&&!d&&!y)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(y))throw new TypeError("Third argument must be a Function");if(a.node(u))return c(u,d,y);if(a.nodeList(u))return l(u,d,y);if(a.string(u))return f(u,d,y);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(u,d,y){return u.addEventListener(d,y),{destroy:function(){u.removeEventListener(d,y)}}}function l(u,d,y){return Array.prototype.forEach.call(u,function(L){L.addEventListener(d,y)}),{destroy:function(){Array.prototype.forEach.call(u,function(L){L.removeEventListener(d,y)})}}}function f(u,d,y){return s(document.body,u,d,y)}o.exports=p}),817:(function(o){function n(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var p=window.getSelection(),c=document.createRange();c.selectNodeContents(i),p.removeAllRanges(),p.addRange(c),a=p.toString()}return a}o.exports=n}),279:(function(o){function n(){}n.prototype={on:function(i,a,s){var p=this.e||(this.e={});return(p[i]||(p[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var p=this;function c(){p.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),p=0,c=s.length;for(p;p0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function z(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var o=r.call(e),n,i=[],a;try{for(;(t===void 0||t-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(s){a={error:s}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(a)throw a.error}}return i}function q(e,t,r){if(r||arguments.length===2)for(var o=0,n=t.length,i;o1||p(d,L)})},y&&(n[d]=y(n[d])))}function p(d,y){try{c(o[d](y))}catch(L){u(i[0][3],L)}}function c(d){d.value instanceof nt?Promise.resolve(d.value.v).then(l,f):u(i[0][2],d)}function l(d){p("next",d)}function f(d){p("throw",d)}function u(d,y){d(y),i.shift(),i.length&&p(i[0][0],i[0][1])}}function uo(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof he=="function"?he(e):e[Symbol.iterator](),r={},o("next"),o("throw"),o("return"),r[Symbol.asyncIterator]=function(){return this},r);function o(i){r[i]=e[i]&&function(a){return new Promise(function(s,p){a=e[i](a),n(s,p,a.done,a.value)})}}function n(i,a,s,p){Promise.resolve(p).then(function(c){i({value:c,done:s})},a)}}function H(e){return typeof e=="function"}function ut(e){var t=function(o){Error.call(o),o.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var zt=ut(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(o,n){return n+1+") "+o.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Qe(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ue=(function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,o,n,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=he(a),p=s.next();!p.done;p=s.next()){var c=p.value;c.remove(this)}}catch(L){t={error:L}}finally{try{p&&!p.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var l=this.initialTeardown;if(H(l))try{l()}catch(L){i=L instanceof zt?L.errors:[L]}var f=this._finalizers;if(f){this._finalizers=null;try{for(var u=he(f),d=u.next();!d.done;d=u.next()){var y=d.value;try{ho(y)}catch(L){i=i!=null?i:[],L instanceof zt?i=q(q([],z(i)),z(L.errors)):i.push(L)}}}catch(L){o={error:L}}finally{try{d&&!d.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}}if(i)throw new zt(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)ho(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Qe(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Qe(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=(function(){var t=new e;return t.closed=!0,t})(),e})();var Tr=Ue.EMPTY;function Nt(e){return e instanceof Ue||e&&"closed"in e&&H(e.remove)&&H(e.add)&&H(e.unsubscribe)}function ho(e){H(e)?e():e.unsubscribe()}var Pe={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var dt={setTimeout:function(e,t){for(var r=[],o=2;o0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var o=this,n=this,i=n.hasError,a=n.isStopped,s=n.observers;return i||a?Tr:(this.currentObservers=null,s.push(r),new Ue(function(){o.currentObservers=null,Qe(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var o=this,n=o.hasError,i=o.thrownError,a=o.isStopped;n?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new j;return r.source=this,r},t.create=function(r,o){return new To(r,o)},t})(j);var To=(function(e){oe(t,e);function t(r,o){var n=e.call(this)||this;return n.destination=r,n.source=o,n}return t.prototype.next=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.next)===null||n===void 0||n.call(o,r)},t.prototype.error=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.error)===null||n===void 0||n.call(o,r)},t.prototype.complete=function(){var r,o;(o=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||o===void 0||o.call(r)},t.prototype._subscribe=function(r){var o,n;return(n=(o=this.source)===null||o===void 0?void 0:o.subscribe(r))!==null&&n!==void 0?n:Tr},t})(g);var _r=(function(e){oe(t,e);function t(r){var o=e.call(this)||this;return o._value=r,o}return Object.defineProperty(t.prototype,"value",{get:function(){return this.getValue()},enumerable:!1,configurable:!0}),t.prototype._subscribe=function(r){var o=e.prototype._subscribe.call(this,r);return!o.closed&&r.next(this._value),o},t.prototype.getValue=function(){var r=this,o=r.hasError,n=r.thrownError,i=r._value;if(o)throw n;return this._throwIfClosed(),i},t.prototype.next=function(r){e.prototype.next.call(this,this._value=r)},t})(g);var _t={now:function(){return(_t.delegate||Date).now()},delegate:void 0};var At=(function(e){oe(t,e);function t(r,o,n){r===void 0&&(r=1/0),o===void 0&&(o=1/0),n===void 0&&(n=_t);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=o,i._timestampProvider=n,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=o===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,o),i}return t.prototype.next=function(r){var o=this,n=o.isStopped,i=o._buffer,a=o._infiniteTimeWindow,s=o._timestampProvider,p=o._windowTime;n||(i.push(r),!a&&i.push(s.now()+p)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var o=this._innerSubscribe(r),n=this,i=n._infiniteTimeWindow,a=n._buffer,s=a.slice(),p=0;p0?e.prototype.schedule.call(this,r,o):(this.delay=o,this.state=r,this.scheduler.flush(this),this)},t.prototype.execute=function(r,o){return o>0||this.closed?e.prototype.execute.call(this,r,o):this._execute(r,o)},t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!=null&&n>0||n==null&&this.delay>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.flush(this),0)},t})(gt);var Lo=(function(e){oe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t})(yt);var kr=new Lo(Oo);var Mo=(function(e){oe(t,e);function t(r,o){var n=e.call(this,r,o)||this;return n.scheduler=r,n.work=o,n}return t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!==null&&n>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.actions.push(this),r._scheduled||(r._scheduled=vt.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,o,n){var i;if(n===void 0&&(n=0),n!=null?n>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,o,n);var a=r.actions;o!=null&&o===r._scheduled&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==o&&(vt.cancelAnimationFrame(o),r._scheduled=void 0)},t})(gt);var _o=(function(e){oe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var o;r?o=r.id:(o=this._scheduled,this._scheduled=void 0);var n=this.actions,i;r=r||n.shift();do if(i=r.execute(r.state,r.delay))break;while((r=n[0])&&r.id===o&&n.shift());if(this._active=!1,i){for(;(r=n[0])&&r.id===o&&n.shift();)r.unsubscribe();throw i}},t})(yt);var me=new _o(Mo);var S=new j(function(e){return e.complete()});function Kt(e){return e&&H(e.schedule)}function Hr(e){return e[e.length-1]}function Xe(e){return H(Hr(e))?e.pop():void 0}function ke(e){return Kt(Hr(e))?e.pop():void 0}function Yt(e,t){return typeof Hr(e)=="number"?e.pop():t}var xt=(function(e){return e&&typeof e.length=="number"&&typeof e!="function"});function Bt(e){return H(e==null?void 0:e.then)}function Gt(e){return H(e[bt])}function Jt(e){return Symbol.asyncIterator&&H(e==null?void 0:e[Symbol.asyncIterator])}function Xt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Zi(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Zt=Zi();function er(e){return H(e==null?void 0:e[Zt])}function tr(e){return fo(this,arguments,function(){var r,o,n,i;return Dt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,nt(r.read())];case 3:return o=a.sent(),n=o.value,i=o.done,i?[4,nt(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,nt(n)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function rr(e){return H(e==null?void 0:e.getReader)}function U(e){if(e instanceof j)return e;if(e!=null){if(Gt(e))return ea(e);if(xt(e))return ta(e);if(Bt(e))return ra(e);if(Jt(e))return Ao(e);if(er(e))return oa(e);if(rr(e))return na(e)}throw Xt(e)}function ea(e){return new j(function(t){var r=e[bt]();if(H(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function ta(e){return new j(function(t){for(var r=0;r=2;return function(o){return o.pipe(e?b(function(n,i){return e(n,i,o)}):le,Te(1),r?Ve(t):Qo(function(){return new nr}))}}function jr(e){return e<=0?function(){return S}:E(function(t,r){var o=[];t.subscribe(T(r,function(n){o.push(n),e=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new g}:t,o=e.resetOnError,n=o===void 0?!0:o,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,p=s===void 0?!0:s;return function(c){var l,f,u,d=0,y=!1,L=!1,X=function(){f==null||f.unsubscribe(),f=void 0},ee=function(){X(),l=u=void 0,y=L=!1},J=function(){var k=l;ee(),k==null||k.unsubscribe()};return E(function(k,ft){d++,!L&&!y&&X();var qe=u=u!=null?u:r();ft.add(function(){d--,d===0&&!L&&!y&&(f=Ur(J,p))}),qe.subscribe(ft),!l&&d>0&&(l=new at({next:function(Fe){return qe.next(Fe)},error:function(Fe){L=!0,X(),f=Ur(ee,n,Fe),qe.error(Fe)},complete:function(){y=!0,X(),f=Ur(ee,a),qe.complete()}}),U(k).subscribe(l))})(c)}}function Ur(e,t){for(var r=[],o=2;oe.next(document)),e}function P(e,t=document){return Array.from(t.querySelectorAll(e))}function R(e,t=document){let r=fe(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function fe(e,t=document){return t.querySelector(e)||void 0}function Ie(){var e,t,r,o;return(o=(r=(t=(e=document.activeElement)==null?void 0:e.shadowRoot)==null?void 0:t.activeElement)!=null?r:document.activeElement)!=null?o:void 0}var wa=O(h(document.body,"focusin"),h(document.body,"focusout")).pipe(_e(1),Q(void 0),m(()=>Ie()||document.body),G(1));function et(e){return wa.pipe(m(t=>e.contains(t)),K())}function Ht(e,t){return C(()=>O(h(e,"mouseenter").pipe(m(()=>!0)),h(e,"mouseleave").pipe(m(()=>!1))).pipe(t?kt(r=>Le(+!r*t)):le,Q(e.matches(":hover"))))}function Jo(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)Jo(e,r)}function x(e,t,...r){let o=document.createElement(e);if(t)for(let n of Object.keys(t))typeof t[n]!="undefined"&&(typeof t[n]!="boolean"?o.setAttribute(n,t[n]):o.setAttribute(n,""));for(let n of r)Jo(o,n);return o}function sr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function wt(e){let t=x("script",{src:e});return C(()=>(document.head.appendChild(t),O(h(t,"load"),h(t,"error").pipe(v(()=>$r(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(m(()=>{}),_(()=>document.head.removeChild(t)),Te(1))))}var Xo=new g,Ta=C(()=>typeof ResizeObserver=="undefined"?wt("https://unpkg.com/resize-observer-polyfill"):I(void 0)).pipe(m(()=>new ResizeObserver(e=>e.forEach(t=>Xo.next(t)))),v(e=>O(Ye,I(e)).pipe(_(()=>e.disconnect()))),G(1));function ce(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){let t=e;for(;t.clientWidth===0&&t.parentElement;)t=t.parentElement;return Ta.pipe(w(r=>r.observe(t)),v(r=>Xo.pipe(b(o=>o.target===t),_(()=>r.unobserve(t)))),m(()=>ce(e)),Q(ce(e)))}function Tt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function cr(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}function Zo(e){let t=[],r=e.parentElement;for(;r;)(e.clientWidth>r.clientWidth||e.clientHeight>r.clientHeight)&&t.push(r),r=(e=r).parentElement;return t.length===0&&t.push(document.documentElement),t}function De(e){return{x:e.offsetLeft,y:e.offsetTop}}function en(e){let t=e.getBoundingClientRect();return{x:t.x+window.scrollX,y:t.y+window.scrollY}}function tn(e){return O(h(window,"load"),h(window,"resize")).pipe(Me(0,me),m(()=>De(e)),Q(De(e)))}function pr(e){return{x:e.scrollLeft,y:e.scrollTop}}function ze(e){return O(h(e,"scroll"),h(window,"scroll"),h(window,"resize")).pipe(Me(0,me),m(()=>pr(e)),Q(pr(e)))}var rn=new g,Sa=C(()=>I(new IntersectionObserver(e=>{for(let t of e)rn.next(t)},{threshold:0}))).pipe(v(e=>O(Ye,I(e)).pipe(_(()=>e.disconnect()))),G(1));function tt(e){return Sa.pipe(w(t=>t.observe(e)),v(t=>rn.pipe(b(({target:r})=>r===e),_(()=>t.unobserve(e)),m(({isIntersecting:r})=>r))))}function on(e,t=16){return ze(e).pipe(m(({y:r})=>{let o=ce(e),n=Tt(e);return r>=n.height-o.height-t}),K())}var lr={drawer:R("[data-md-toggle=drawer]"),search:R("[data-md-toggle=search]")};function nn(e){return lr[e].checked}function Je(e,t){lr[e].checked!==t&&lr[e].click()}function Ne(e){let t=lr[e];return h(t,"change").pipe(m(()=>t.checked),Q(t.checked))}function Oa(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function La(){return O(h(window,"compositionstart").pipe(m(()=>!0)),h(window,"compositionend").pipe(m(()=>!1))).pipe(Q(!1))}function an(){let e=h(window,"keydown").pipe(b(t=>!(t.metaKey||t.ctrlKey)),m(t=>({mode:nn("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),b(({mode:t,type:r})=>{if(t==="global"){let o=Ie();if(typeof o!="undefined")return!Oa(o,r)}return!0}),pe());return La().pipe(v(t=>t?S:e))}function ye(){return new URL(location.href)}function lt(e,t=!1){if(B("navigation.instant")&&!t){let r=x("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function sn(){return new g}function cn(){return location.hash.slice(1)}function pn(e){let t=x("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Ma(e){return O(h(window,"hashchange"),e).pipe(m(cn),Q(cn()),b(t=>t.length>0),G(1))}function ln(e){return Ma(e).pipe(m(t=>fe(`[id="${t}"]`)),b(t=>typeof t!="undefined"))}function $t(e){let t=matchMedia(e);return ir(r=>t.addListener(()=>r(t.matches))).pipe(Q(t.matches))}function mn(){let e=matchMedia("print");return O(h(window,"beforeprint").pipe(m(()=>!0)),h(window,"afterprint").pipe(m(()=>!1))).pipe(Q(e.matches))}function zr(e,t){return e.pipe(v(r=>r?t():S))}function Nr(e,t){return new j(r=>{let o=new XMLHttpRequest;return o.open("GET",`${e}`),o.responseType="blob",o.addEventListener("load",()=>{o.status>=200&&o.status<300?(r.next(o.response),r.complete()):r.error(new Error(o.statusText))}),o.addEventListener("error",()=>{r.error(new Error("Network error"))}),o.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(o.addEventListener("progress",n=>{var i;if(n.lengthComputable)t.progress$.next(n.loaded/n.total*100);else{let a=(i=o.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(n.loaded/+a*100)}}),t.progress$.next(5)),o.send(),()=>o.abort()})}function je(e,t){return Nr(e,t).pipe(v(r=>r.text()),m(r=>JSON.parse(r)),G(1))}function fn(e,t){let r=new DOMParser;return Nr(e,t).pipe(v(o=>o.text()),m(o=>r.parseFromString(o,"text/html")),G(1))}function un(e,t){let r=new DOMParser;return Nr(e,t).pipe(v(o=>o.text()),m(o=>r.parseFromString(o,"text/xml")),G(1))}function dn(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function hn(){return O(h(window,"scroll",{passive:!0}),h(window,"resize",{passive:!0})).pipe(m(dn),Q(dn()))}function bn(){return{width:innerWidth,height:innerHeight}}function vn(){return h(window,"resize",{passive:!0}).pipe(m(bn),Q(bn()))}function gn(){return N([hn(),vn()]).pipe(m(([e,t])=>({offset:e,size:t})),G(1))}function mr(e,{viewport$:t,header$:r}){let o=t.pipe(te("size")),n=N([o,r]).pipe(m(()=>De(e)));return N([r,t,n]).pipe(m(([{height:i},{offset:a,size:s},{x:p,y:c}])=>({offset:{x:a.x-p,y:a.y-c+i},size:s})))}function _a(e){return h(e,"message",t=>t.data)}function Aa(e){let t=new g;return t.subscribe(r=>e.postMessage(r)),t}function yn(e,t=new Worker(e)){let r=_a(t),o=Aa(t),n=new g;n.subscribe(o);let i=o.pipe(Z(),ie(!0));return n.pipe(Z(),Re(r.pipe(W(i))),pe())}var Ca=R("#__config"),St=JSON.parse(Ca.textContent);St.base=`${new URL(St.base,ye())}`;function xe(){return St}function B(e){return St.features.includes(e)}function Ee(e,t){return typeof t!="undefined"?St.translations[e].replace("#",t.toString()):St.translations[e]}function Se(e,t=document){return R(`[data-md-component=${e}]`,t)}function ae(e,t=document){return P(`[data-md-component=${e}]`,t)}function ka(e){let t=R(".md-typeset > :first-child",e);return h(t,"click",{once:!0}).pipe(m(()=>R(".md-typeset",e)),m(r=>({hash:__md_hash(r.innerHTML)})))}function xn(e){if(!B("announce.dismiss")||!e.childElementCount)return S;if(!e.hidden){let t=R(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return C(()=>{let t=new g;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),ka(e).pipe(w(r=>t.next(r)),_(()=>t.complete()),m(r=>$({ref:e},r)))})}function Ha(e,{target$:t}){return t.pipe(m(r=>({hidden:r!==e})))}function En(e,t){let r=new g;return r.subscribe(({hidden:o})=>{e.hidden=o}),Ha(e,t).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))}function Pt(e,t){return t==="inline"?x("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"})):x("div",{class:"md-tooltip",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"}))}function wn(...e){return x("div",{class:"md-tooltip2",role:"tooltip"},x("div",{class:"md-tooltip2__inner md-typeset"},e))}function Tn(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return x("aside",{class:"md-annotation",tabIndex:0},Pt(t),x("a",{href:r,class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}else return x("aside",{class:"md-annotation",tabIndex:0},Pt(t),x("span",{class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}function Sn(e){return x("button",{class:"md-clipboard md-icon",title:Ee("clipboard.copy"),"data-clipboard-target":`#${e} > code`})}var Ln=Lt(qr());function Qr(e,t){let r=t&2,o=t&1,n=Object.keys(e.terms).filter(p=>!e.terms[p]).reduce((p,c)=>[...p,x("del",null,(0,Ln.default)(c))," "],[]).slice(0,-1),i=xe(),a=new URL(e.location,i.base);B("search.highlight")&&a.searchParams.set("h",Object.entries(e.terms).filter(([,p])=>p).reduce((p,[c])=>`${p} ${c}`.trim(),""));let{tags:s}=xe();return x("a",{href:`${a}`,class:"md-search-result__link",tabIndex:-1},x("article",{class:"md-search-result__article md-typeset","data-md-score":e.score.toFixed(2)},r>0&&x("div",{class:"md-search-result__icon md-icon"}),r>0&&x("h1",null,e.title),r<=0&&x("h2",null,e.title),o>0&&e.text.length>0&&e.text,e.tags&&x("nav",{class:"md-tags"},e.tags.map(p=>{let c=s?p in s?`md-tag-icon md-tag--${s[p]}`:"md-tag-icon":"";return x("span",{class:`md-tag ${c}`},p)})),o>0&&n.length>0&&x("p",{class:"md-search-result__terms"},Ee("search.result.term.missing"),": ",...n)))}function Mn(e){let t=e[0].score,r=[...e],o=xe(),n=r.findIndex(l=>!`${new URL(l.location,o.base)}`.includes("#")),[i]=r.splice(n,1),a=r.findIndex(l=>l.scoreQr(l,1)),...p.length?[x("details",{class:"md-search-result__more"},x("summary",{tabIndex:-1},x("div",null,p.length>0&&p.length===1?Ee("search.result.more.one"):Ee("search.result.more.other",p.length))),...p.map(l=>Qr(l,1)))]:[]];return x("li",{class:"md-search-result__item"},c)}function _n(e){return x("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>x("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?sr(r):r)))}function Kr(e){let t=`tabbed-control tabbed-control--${e}`;return x("div",{class:t,hidden:!0},x("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function An(e){return x("div",{class:"md-typeset__scrollwrap"},x("div",{class:"md-typeset__table"},e))}function Ra(e){var o;let t=xe(),r=new URL(`../${e.version}/`,t.base);return x("li",{class:"md-version__item"},x("a",{href:`${r}`,class:"md-version__link"},e.title,((o=t.version)==null?void 0:o.alias)&&e.aliases.length>0&&x("span",{class:"md-version__alias"},e.aliases[0])))}function Cn(e,t){var o;let r=xe();return e=e.filter(n=>{var i;return!((i=n.properties)!=null&&i.hidden)}),x("div",{class:"md-version"},x("button",{class:"md-version__current","aria-label":Ee("select.version")},t.title,((o=r.version)==null?void 0:o.alias)&&t.aliases.length>0&&x("span",{class:"md-version__alias"},t.aliases[0])),x("ul",{class:"md-version__list"},e.map(Ra)))}var Ia=0;function ja(e){let t=N([et(e),Ht(e)]).pipe(m(([o,n])=>o||n),K()),r=C(()=>Zo(e)).pipe(ne(ze),pt(1),He(t),m(()=>en(e)));return t.pipe(Ae(o=>o),v(()=>N([t,r])),m(([o,n])=>({active:o,offset:n})),pe())}function Fa(e,t){let{content$:r,viewport$:o}=t,n=`__tooltip2_${Ia++}`;return C(()=>{let i=new g,a=new _r(!1);i.pipe(Z(),ie(!1)).subscribe(a);let s=a.pipe(kt(c=>Le(+!c*250,kr)),K(),v(c=>c?r:S),w(c=>c.id=n),pe());N([i.pipe(m(({active:c})=>c)),s.pipe(v(c=>Ht(c,250)),Q(!1))]).pipe(m(c=>c.some(l=>l))).subscribe(a);let p=a.pipe(b(c=>c),re(s,o),m(([c,l,{size:f}])=>{let u=e.getBoundingClientRect(),d=u.width/2;if(l.role==="tooltip")return{x:d,y:8+u.height};if(u.y>=f.height/2){let{height:y}=ce(l);return{x:d,y:-16-y}}else return{x:d,y:16+u.height}}));return N([s,i,p]).subscribe(([c,{offset:l},f])=>{c.style.setProperty("--md-tooltip-host-x",`${l.x}px`),c.style.setProperty("--md-tooltip-host-y",`${l.y}px`),c.style.setProperty("--md-tooltip-x",`${f.x}px`),c.style.setProperty("--md-tooltip-y",`${f.y}px`),c.classList.toggle("md-tooltip2--top",f.y<0),c.classList.toggle("md-tooltip2--bottom",f.y>=0)}),a.pipe(b(c=>c),re(s,(c,l)=>l),b(c=>c.role==="tooltip")).subscribe(c=>{let l=ce(R(":scope > *",c));c.style.setProperty("--md-tooltip-width",`${l.width}px`),c.style.setProperty("--md-tooltip-tail","0px")}),a.pipe(K(),ve(me),re(s)).subscribe(([c,l])=>{l.classList.toggle("md-tooltip2--active",c)}),N([a.pipe(b(c=>c)),s]).subscribe(([c,l])=>{l.role==="dialog"?(e.setAttribute("aria-controls",n),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",n)}),a.pipe(b(c=>!c)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),ja(e).pipe(w(c=>i.next(c)),_(()=>i.complete()),m(c=>$({ref:e},c)))})}function mt(e,{viewport$:t},r=document.body){return Fa(e,{content$:new j(o=>{let n=e.title,i=wn(n);return o.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",n)}}),viewport$:t})}function Ua(e,t){let r=C(()=>N([tn(e),ze(t)])).pipe(m(([{x:o,y:n},i])=>{let{width:a,height:s}=ce(e);return{x:o-i.x+a/2,y:n-i.y+s/2}}));return et(e).pipe(v(o=>r.pipe(m(n=>({active:o,offset:n})),Te(+!o||1/0))))}function kn(e,t,{target$:r}){let[o,n]=Array.from(e.children);return C(()=>{let i=new g,a=i.pipe(Z(),ie(!0));return i.subscribe({next({offset:s}){e.style.setProperty("--md-tooltip-x",`${s.x}px`),e.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),tt(e).pipe(W(a)).subscribe(s=>{e.toggleAttribute("data-md-visible",s)}),O(i.pipe(b(({active:s})=>s)),i.pipe(_e(250),b(({active:s})=>!s))).subscribe({next({active:s}){s?e.prepend(o):o.remove()},complete(){e.prepend(o)}}),i.pipe(Me(16,me)).subscribe(({active:s})=>{o.classList.toggle("md-tooltip--active",s)}),i.pipe(pt(125,me),b(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:s})=>s)).subscribe({next(s){s?e.style.setProperty("--md-tooltip-0",`${-s}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),h(n,"click").pipe(W(a),b(s=>!(s.metaKey||s.ctrlKey))).subscribe(s=>{s.stopPropagation(),s.preventDefault()}),h(n,"mousedown").pipe(W(a),re(i)).subscribe(([s,{active:p}])=>{var c;if(s.button!==0||s.metaKey||s.ctrlKey)s.preventDefault();else if(p){s.preventDefault();let l=e.parentElement.closest(".md-annotation");l instanceof HTMLElement?l.focus():(c=Ie())==null||c.blur()}}),r.pipe(W(a),b(s=>s===o),Ge(125)).subscribe(()=>e.focus()),Ua(e,t).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))})}function Wa(e){return e.tagName==="CODE"?P(".c, .c1, .cm",e):[e]}function Va(e){let t=[];for(let r of Wa(e)){let o=[],n=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=n.nextNode();i;i=n.nextNode())o.push(i);for(let i of o){let a;for(;a=/(\(\d+\))(!)?/.exec(i.textContent);){let[,s,p]=a;if(typeof p=="undefined"){let c=i.splitText(a.index);i=c.splitText(s.length),t.push(c)}else{i.textContent=s,t.push(i);break}}}}return t}function Hn(e,t){t.append(...Array.from(e.childNodes))}function fr(e,t,{target$:r,print$:o}){let n=t.closest("[id]"),i=n==null?void 0:n.id,a=new Map;for(let s of Va(t)){let[,p]=s.textContent.match(/\((\d+)\)/);fe(`:scope > li:nth-child(${p})`,e)&&(a.set(p,Tn(p,i)),s.replaceWith(a.get(p)))}return a.size===0?S:C(()=>{let s=new g,p=s.pipe(Z(),ie(!0)),c=[];for(let[l,f]of a)c.push([R(".md-typeset",f),R(`:scope > li:nth-child(${l})`,e)]);return o.pipe(W(p)).subscribe(l=>{e.hidden=!l,e.classList.toggle("md-annotation-list",l);for(let[f,u]of c)l?Hn(f,u):Hn(u,f)}),O(...[...a].map(([,l])=>kn(l,t,{target$:r}))).pipe(_(()=>s.complete()),pe())})}function $n(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return $n(t)}}function Pn(e,t){return C(()=>{let r=$n(e);return typeof r!="undefined"?fr(r,e,t):S})}var Rn=Lt(Br());var Da=0;function In(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return In(t)}}function za(e){return ge(e).pipe(m(({width:t})=>({scrollable:Tt(e).width>t})),te("scrollable"))}function jn(e,t){let{matches:r}=matchMedia("(hover)"),o=C(()=>{let n=new g,i=n.pipe(jr(1));n.subscribe(({scrollable:c})=>{c&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let a=[];if(Rn.default.isSupported()&&(e.closest(".copy")||B("content.code.copy")&&!e.closest(".no-copy"))){let c=e.closest("pre");c.id=`__code_${Da++}`;let l=Sn(c.id);c.insertBefore(l,e),B("content.tooltips")&&a.push(mt(l,{viewport$}))}let s=e.closest(".highlight");if(s instanceof HTMLElement){let c=In(s);if(typeof c!="undefined"&&(s.classList.contains("annotate")||B("content.code.annotate"))){let l=fr(c,e,t);a.push(ge(s).pipe(W(i),m(({width:f,height:u})=>f&&u),K(),v(f=>f?l:S)))}}return P(":scope > span[id]",e).length&&e.classList.add("md-code__content"),za(e).pipe(w(c=>n.next(c)),_(()=>n.complete()),m(c=>$({ref:e},c)),Re(...a))});return B("content.lazy")?tt(e).pipe(b(n=>n),Te(1),v(()=>o)):o}function Na(e,{target$:t,print$:r}){let o=!0;return O(t.pipe(m(n=>n.closest("details:not([open])")),b(n=>e===n),m(()=>({action:"open",reveal:!0}))),r.pipe(b(n=>n||!o),w(()=>o=e.open),m(n=>({action:n?"open":"close"}))))}function Fn(e,t){return C(()=>{let r=new g;return r.subscribe(({action:o,reveal:n})=>{e.toggleAttribute("open",o==="open"),n&&e.scrollIntoView()}),Na(e,t).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}var Un=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.flowchartTitleText{fill:var(--md-mermaid-label-fg-color)}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel p,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel p{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color)}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}.classDiagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs marker.marker.composition.class path,defs marker.marker.dependency.class path,defs marker.marker.extension.class path{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs marker.marker.aggregation.class path{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}.statediagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}[id^=entity] path,[id^=entity] rect{fill:var(--md-default-bg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs .marker.oneOrMore.er *,defs .marker.onlyOne.er *,defs .marker.zeroOrMore.er *,defs .marker.zeroOrOne.er *{stroke:var(--md-mermaid-edge-color)!important}text:not([class]):last-child{fill:var(--md-mermaid-label-fg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var Gr,Qa=0;function Ka(){return typeof mermaid=="undefined"||mermaid instanceof Element?wt("https://unpkg.com/mermaid@11/dist/mermaid.min.js"):I(void 0)}function Wn(e){return e.classList.remove("mermaid"),Gr||(Gr=Ka().pipe(w(()=>mermaid.initialize({startOnLoad:!1,themeCSS:Un,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),m(()=>{}),G(1))),Gr.subscribe(()=>co(null,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${Qa++}`,r=x("div",{class:"mermaid"}),o=e.textContent,{svg:n,fn:i}=yield mermaid.render(t,o),a=r.attachShadow({mode:"closed"});a.innerHTML=n,e.replaceWith(r),i==null||i(a)})),Gr.pipe(m(()=>({ref:e})))}var Vn=x("table");function Dn(e){return e.replaceWith(Vn),Vn.replaceWith(An(e)),I({ref:e})}function Ya(e){let t=e.find(r=>r.checked)||e[0];return O(...e.map(r=>h(r,"change").pipe(m(()=>R(`label[for="${r.id}"]`))))).pipe(Q(R(`label[for="${t.id}"]`)),m(r=>({active:r})))}function zn(e,{viewport$:t,target$:r}){let o=R(".tabbed-labels",e),n=P(":scope > input",e),i=Kr("prev");e.append(i);let a=Kr("next");return e.append(a),C(()=>{let s=new g,p=s.pipe(Z(),ie(!0));N([s,ge(e),tt(e)]).pipe(W(p),Me(1,me)).subscribe({next([{active:c},l]){let f=De(c),{width:u}=ce(c);e.style.setProperty("--md-indicator-x",`${f.x}px`),e.style.setProperty("--md-indicator-width",`${u}px`);let d=pr(o);(f.xd.x+l.width)&&o.scrollTo({left:Math.max(0,f.x-16),behavior:"smooth"})},complete(){e.style.removeProperty("--md-indicator-x"),e.style.removeProperty("--md-indicator-width")}}),N([ze(o),ge(o)]).pipe(W(p)).subscribe(([c,l])=>{let f=Tt(o);i.hidden=c.x<16,a.hidden=c.x>f.width-l.width-16}),O(h(i,"click").pipe(m(()=>-1)),h(a,"click").pipe(m(()=>1))).pipe(W(p)).subscribe(c=>{let{width:l}=ce(o);o.scrollBy({left:l*c,behavior:"smooth"})}),r.pipe(W(p),b(c=>n.includes(c))).subscribe(c=>c.click()),o.classList.add("tabbed-labels--linked");for(let c of n){let l=R(`label[for="${c.id}"]`);l.replaceChildren(x("a",{href:`#${l.htmlFor}`,tabIndex:-1},...Array.from(l.childNodes))),h(l.firstElementChild,"click").pipe(W(p),b(f=>!(f.metaKey||f.ctrlKey)),w(f=>{f.preventDefault(),f.stopPropagation()})).subscribe(()=>{history.replaceState({},"",`#${l.htmlFor}`),l.click()})}return B("content.tabs.link")&&s.pipe(Ce(1),re(t)).subscribe(([{active:c},{offset:l}])=>{let f=c.innerText.trim();if(c.hasAttribute("data-md-switching"))c.removeAttribute("data-md-switching");else{let u=e.offsetTop-l.y;for(let y of P("[data-tabs]"))for(let L of P(":scope > input",y)){let X=R(`label[for="${L.id}"]`);if(X!==c&&X.innerText.trim()===f){X.setAttribute("data-md-switching",""),L.click();break}}window.scrollTo({top:e.offsetTop-u});let d=__md_get("__tabs")||[];__md_set("__tabs",[...new Set([f,...d])])}}),s.pipe(W(p)).subscribe(()=>{for(let c of P("audio, video",e))c.offsetWidth&&c.autoplay?c.play().catch(()=>{}):c.pause()}),Ya(n).pipe(w(c=>s.next(c)),_(()=>s.complete()),m(c=>$({ref:e},c)))}).pipe(Ke(se))}function Nn(e,{viewport$:t,target$:r,print$:o}){return O(...P(".annotate:not(.highlight)",e).map(n=>Pn(n,{target$:r,print$:o})),...P("pre:not(.mermaid) > code",e).map(n=>jn(n,{target$:r,print$:o})),...P("pre.mermaid",e).map(n=>Wn(n)),...P("table:not([class])",e).map(n=>Dn(n)),...P("details",e).map(n=>Fn(n,{target$:r,print$:o})),...P("[data-tabs]",e).map(n=>zn(n,{viewport$:t,target$:r})),...P("[title]",e).filter(()=>B("content.tooltips")).map(n=>mt(n,{viewport$:t})))}function Ba(e,{alert$:t}){return t.pipe(v(r=>O(I(!0),I(!1).pipe(Ge(2e3))).pipe(m(o=>({message:r,active:o})))))}function qn(e,t){let r=R(".md-typeset",e);return C(()=>{let o=new g;return o.subscribe(({message:n,active:i})=>{e.classList.toggle("md-dialog--active",i),r.textContent=n}),Ba(e,t).pipe(w(n=>o.next(n)),_(()=>o.complete()),m(n=>$({ref:e},n)))})}var Ga=0;function Ja(e,t){document.body.append(e);let{width:r}=ce(e);e.style.setProperty("--md-tooltip-width",`${r}px`),e.remove();let o=cr(t),n=typeof o!="undefined"?ze(o):I({x:0,y:0}),i=O(et(t),Ht(t)).pipe(K());return N([i,n]).pipe(m(([a,s])=>{let{x:p,y:c}=De(t),l=ce(t),f=t.closest("table");return f&&t.parentElement&&(p+=f.offsetLeft+t.parentElement.offsetLeft,c+=f.offsetTop+t.parentElement.offsetTop),{active:a,offset:{x:p-s.x+l.width/2-r/2,y:c-s.y+l.height+8}}}))}function Qn(e){let t=e.title;if(!t.length)return S;let r=`__tooltip_${Ga++}`,o=Pt(r,"inline"),n=R(".md-typeset",o);return n.innerHTML=t,C(()=>{let i=new g;return i.subscribe({next({offset:a}){o.style.setProperty("--md-tooltip-x",`${a.x}px`),o.style.setProperty("--md-tooltip-y",`${a.y}px`)},complete(){o.style.removeProperty("--md-tooltip-x"),o.style.removeProperty("--md-tooltip-y")}}),O(i.pipe(b(({active:a})=>a)),i.pipe(_e(250),b(({active:a})=>!a))).subscribe({next({active:a}){a?(e.insertAdjacentElement("afterend",o),e.setAttribute("aria-describedby",r),e.removeAttribute("title")):(o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t))},complete(){o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t)}}),i.pipe(Me(16,me)).subscribe(({active:a})=>{o.classList.toggle("md-tooltip--active",a)}),i.pipe(pt(125,me),b(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:a})=>a)).subscribe({next(a){a?o.style.setProperty("--md-tooltip-0",`${-a}px`):o.style.removeProperty("--md-tooltip-0")},complete(){o.style.removeProperty("--md-tooltip-0")}}),Ja(o,e).pipe(w(a=>i.next(a)),_(()=>i.complete()),m(a=>$({ref:e},a)))}).pipe(Ke(se))}function Xa({viewport$:e}){if(!B("header.autohide"))return I(!1);let t=e.pipe(m(({offset:{y:n}})=>n),Be(2,1),m(([n,i])=>[nMath.abs(i-n.y)>100),m(([,[n]])=>n),K()),o=Ne("search");return N([e,o]).pipe(m(([{offset:n},i])=>n.y>400&&!i),K(),v(n=>n?r:I(!1)),Q(!1))}function Kn(e,t){return C(()=>N([ge(e),Xa(t)])).pipe(m(([{height:r},o])=>({height:r,hidden:o})),K((r,o)=>r.height===o.height&&r.hidden===o.hidden),G(1))}function Yn(e,{header$:t,main$:r}){return C(()=>{let o=new g,n=o.pipe(Z(),ie(!0));o.pipe(te("active"),He(t)).subscribe(([{active:a},{hidden:s}])=>{e.classList.toggle("md-header--shadow",a&&!s),e.hidden=s});let i=ue(P("[title]",e)).pipe(b(()=>B("content.tooltips")),ne(a=>Qn(a)));return r.subscribe(o),t.pipe(W(n),m(a=>$({ref:e},a)),Re(i.pipe(W(n))))})}function Za(e,{viewport$:t,header$:r}){return mr(e,{viewport$:t,header$:r}).pipe(m(({offset:{y:o}})=>{let{height:n}=ce(e);return{active:n>0&&o>=n}}),te("active"))}function Bn(e,t){return C(()=>{let r=new g;r.subscribe({next({active:n}){e.classList.toggle("md-header__title--active",n)},complete(){e.classList.remove("md-header__title--active")}});let o=fe(".md-content h1");return typeof o=="undefined"?S:Za(o,t).pipe(w(n=>r.next(n)),_(()=>r.complete()),m(n=>$({ref:e},n)))})}function Gn(e,{viewport$:t,header$:r}){let o=r.pipe(m(({height:i})=>i),K()),n=o.pipe(v(()=>ge(e).pipe(m(({height:i})=>({top:e.offsetTop,bottom:e.offsetTop+i})),te("bottom"))));return N([o,n,t]).pipe(m(([i,{top:a,bottom:s},{offset:{y:p},size:{height:c}}])=>(c=Math.max(0,c-Math.max(0,a-p,i)-Math.max(0,c+p-s)),{offset:a-i,height:c,active:a-i<=p})),K((i,a)=>i.offset===a.offset&&i.height===a.height&&i.active===a.active))}function es(e){let t=__md_get("__palette")||{index:e.findIndex(o=>matchMedia(o.getAttribute("data-md-color-media")).matches)},r=Math.max(0,Math.min(t.index,e.length-1));return I(...e).pipe(ne(o=>h(o,"change").pipe(m(()=>o))),Q(e[r]),m(o=>({index:e.indexOf(o),color:{media:o.getAttribute("data-md-color-media"),scheme:o.getAttribute("data-md-color-scheme"),primary:o.getAttribute("data-md-color-primary"),accent:o.getAttribute("data-md-color-accent")}})),G(1))}function Jn(e){let t=P("input",e),r=x("meta",{name:"theme-color"});document.head.appendChild(r);let o=x("meta",{name:"color-scheme"});document.head.appendChild(o);let n=$t("(prefers-color-scheme: light)");return C(()=>{let i=new g;return i.subscribe(a=>{if(document.body.setAttribute("data-md-color-switching",""),a.color.media==="(prefers-color-scheme)"){let s=matchMedia("(prefers-color-scheme: light)"),p=document.querySelector(s.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");a.color.scheme=p.getAttribute("data-md-color-scheme"),a.color.primary=p.getAttribute("data-md-color-primary"),a.color.accent=p.getAttribute("data-md-color-accent")}for(let[s,p]of Object.entries(a.color))document.body.setAttribute(`data-md-color-${s}`,p);for(let s=0;sa.key==="Enter"),re(i,(a,s)=>s)).subscribe(({index:a})=>{a=(a+1)%t.length,t[a].click(),t[a].focus()}),i.pipe(m(()=>{let a=Se("header"),s=window.getComputedStyle(a);return o.content=s.colorScheme,s.backgroundColor.match(/\d+/g).map(p=>(+p).toString(16).padStart(2,"0")).join("")})).subscribe(a=>r.content=`#${a}`),i.pipe(ve(se)).subscribe(()=>{document.body.removeAttribute("data-md-color-switching")}),es(t).pipe(W(n.pipe(Ce(1))),ct(),w(a=>i.next(a)),_(()=>i.complete()),m(a=>$({ref:e},a)))})}function Xn(e,{progress$:t}){return C(()=>{let r=new g;return r.subscribe(({value:o})=>{e.style.setProperty("--md-progress-value",`${o}`)}),t.pipe(w(o=>r.next({value:o})),_(()=>r.complete()),m(o=>({ref:e,value:o})))})}var Jr=Lt(Br());function ts(e){e.setAttribute("data-md-copying","");let t=e.closest("[data-copy]"),r=t?t.getAttribute("data-copy"):e.innerText;return e.removeAttribute("data-md-copying"),r.trimEnd()}function Zn({alert$:e}){Jr.default.isSupported()&&new j(t=>{new Jr.default("[data-clipboard-target], [data-clipboard-text]",{text:r=>r.getAttribute("data-clipboard-text")||ts(R(r.getAttribute("data-clipboard-target")))}).on("success",r=>t.next(r))}).pipe(w(t=>{t.trigger.focus()}),m(()=>Ee("clipboard.copied"))).subscribe(e)}function ei(e,t){return e.protocol=t.protocol,e.hostname=t.hostname,e}function rs(e,t){let r=new Map;for(let o of P("url",e)){let n=R("loc",o),i=[ei(new URL(n.textContent),t)];r.set(`${i[0]}`,i);for(let a of P("[rel=alternate]",o)){let s=a.getAttribute("href");s!=null&&i.push(ei(new URL(s),t))}}return r}function ur(e){return un(new URL("sitemap.xml",e)).pipe(m(t=>rs(t,new URL(e))),de(()=>I(new Map)))}function os(e,t){if(!(e.target instanceof Element))return S;let r=e.target.closest("a");if(r===null)return S;if(r.target||e.metaKey||e.ctrlKey)return S;let o=new URL(r.href);return o.search=o.hash="",t.has(`${o}`)?(e.preventDefault(),I(new URL(r.href))):S}function ti(e){let t=new Map;for(let r of P(":scope > *",e.head))t.set(r.outerHTML,r);return t}function ri(e){for(let t of P("[href], [src]",e))for(let r of["href","src"]){let o=t.getAttribute(r);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){t[r]=t[r];break}}return I(e)}function ns(e){for(let o of["[data-md-component=announce]","[data-md-component=container]","[data-md-component=header-topic]","[data-md-component=outdated]","[data-md-component=logo]","[data-md-component=skip]",...B("navigation.tabs.sticky")?["[data-md-component=tabs]"]:[]]){let n=fe(o),i=fe(o,e);typeof n!="undefined"&&typeof i!="undefined"&&n.replaceWith(i)}let t=ti(document);for(let[o,n]of ti(e))t.has(o)?t.delete(o):document.head.appendChild(n);for(let o of t.values()){let n=o.getAttribute("name");n!=="theme-color"&&n!=="color-scheme"&&o.remove()}let r=Se("container");return We(P("script",r)).pipe(v(o=>{let n=e.createElement("script");if(o.src){for(let i of o.getAttributeNames())n.setAttribute(i,o.getAttribute(i));return o.replaceWith(n),new j(i=>{n.onload=()=>i.complete()})}else return n.textContent=o.textContent,o.replaceWith(n),S}),Z(),ie(document))}function oi({location$:e,viewport$:t,progress$:r}){let o=xe();if(location.protocol==="file:")return S;let n=ur(o.base);I(document).subscribe(ri);let i=h(document.body,"click").pipe(He(n),v(([p,c])=>os(p,c)),pe()),a=h(window,"popstate").pipe(m(ye),pe());i.pipe(re(t)).subscribe(([p,{offset:c}])=>{history.replaceState(c,""),history.pushState(null,"",p)}),O(i,a).subscribe(e);let s=e.pipe(te("pathname"),v(p=>fn(p,{progress$:r}).pipe(de(()=>(lt(p,!0),S)))),v(ri),v(ns),pe());return O(s.pipe(re(e,(p,c)=>c)),s.pipe(v(()=>e),te("hash")),e.pipe(K((p,c)=>p.pathname===c.pathname&&p.hash===c.hash),v(()=>i),w(()=>history.back()))).subscribe(p=>{var c,l;history.state!==null||!p.hash?window.scrollTo(0,(l=(c=history.state)==null?void 0:c.y)!=null?l:0):(history.scrollRestoration="auto",pn(p.hash),history.scrollRestoration="manual")}),e.subscribe(()=>{history.scrollRestoration="manual"}),h(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}),t.pipe(te("offset"),_e(100)).subscribe(({offset:p})=>{history.replaceState(p,"")}),s}var ni=Lt(qr());function ii(e){let t=e.separator.split("|").map(n=>n.replace(/(\(\?[!=<][^)]+\))/g,"").length===0?"\uFFFD":n).join("|"),r=new RegExp(t,"img"),o=(n,i,a)=>`${i}${a}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").replace(/&/g,"&").trim();let i=new RegExp(`(^|${e.separator}|)(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return a=>(0,ni.default)(a).replace(i,o).replace(/<\/mark>(\s+)]*>/img,"$1")}}function It(e){return e.type===1}function dr(e){return e.type===3}function ai(e,t){let r=yn(e);return O(I(location.protocol!=="file:"),Ne("search")).pipe(Ae(o=>o),v(()=>t)).subscribe(({config:o,docs:n})=>r.next({type:0,data:{config:o,docs:n,options:{suggest:B("search.suggest")}}})),r}function si(e){var l;let{selectedVersionSitemap:t,selectedVersionBaseURL:r,currentLocation:o,currentBaseURL:n}=e,i=(l=Xr(n))==null?void 0:l.pathname;if(i===void 0)return;let a=ss(o.pathname,i);if(a===void 0)return;let s=ps(t.keys());if(!t.has(s))return;let p=Xr(a,s);if(!p||!t.has(p.href))return;let c=Xr(a,r);if(c)return c.hash=o.hash,c.search=o.search,c}function Xr(e,t){try{return new URL(e,t)}catch(r){return}}function ss(e,t){if(e.startsWith(t))return e.slice(t.length)}function cs(e,t){let r=Math.min(e.length,t.length),o;for(o=0;oS)),o=r.pipe(m(n=>{let[,i]=t.base.match(/([^/]+)\/?$/);return n.find(({version:a,aliases:s})=>a===i||s.includes(i))||n[0]}));r.pipe(m(n=>new Map(n.map(i=>[`${new URL(`../${i.version}/`,t.base)}`,i]))),v(n=>h(document.body,"click").pipe(b(i=>!i.metaKey&&!i.ctrlKey),re(o),v(([i,a])=>{if(i.target instanceof Element){let s=i.target.closest("a");if(s&&!s.target&&n.has(s.href)){let p=s.href;return!i.target.closest(".md-version")&&n.get(p)===a?S:(i.preventDefault(),I(new URL(p)))}}return S}),v(i=>ur(i).pipe(m(a=>{var s;return(s=si({selectedVersionSitemap:a,selectedVersionBaseURL:i,currentLocation:ye(),currentBaseURL:t.base}))!=null?s:i})))))).subscribe(n=>lt(n,!0)),N([r,o]).subscribe(([n,i])=>{R(".md-header__topic").appendChild(Cn(n,i))}),e.pipe(v(()=>o)).subscribe(n=>{var s;let i=new URL(t.base),a=__md_get("__outdated",sessionStorage,i);if(a===null){a=!0;let p=((s=t.version)==null?void 0:s.default)||"latest";Array.isArray(p)||(p=[p]);e:for(let c of p)for(let l of n.aliases.concat(n.version))if(new RegExp(c,"i").test(l)){a=!1;break e}__md_set("__outdated",a,sessionStorage,i)}if(a)for(let p of ae("outdated"))p.hidden=!1})}function ls(e,{worker$:t}){let{searchParams:r}=ye();r.has("q")&&(Je("search",!0),e.value=r.get("q"),e.focus(),Ne("search").pipe(Ae(i=>!i)).subscribe(()=>{let i=ye();i.searchParams.delete("q"),history.replaceState({},"",`${i}`)}));let o=et(e),n=O(t.pipe(Ae(It)),h(e,"keyup"),o).pipe(m(()=>e.value),K());return N([n,o]).pipe(m(([i,a])=>({value:i,focus:a})),G(1))}function pi(e,{worker$:t}){let r=new g,o=r.pipe(Z(),ie(!0));N([t.pipe(Ae(It)),r],(i,a)=>a).pipe(te("value")).subscribe(({value:i})=>t.next({type:2,data:i})),r.pipe(te("focus")).subscribe(({focus:i})=>{i&&Je("search",i)}),h(e.form,"reset").pipe(W(o)).subscribe(()=>e.focus());let n=R("header [for=__search]");return h(n,"click").subscribe(()=>e.focus()),ls(e,{worker$:t}).pipe(w(i=>r.next(i)),_(()=>r.complete()),m(i=>$({ref:e},i)),G(1))}function li(e,{worker$:t,query$:r}){let o=new g,n=on(e.parentElement).pipe(b(Boolean)),i=e.parentElement,a=R(":scope > :first-child",e),s=R(":scope > :last-child",e);Ne("search").subscribe(l=>{s.setAttribute("role",l?"list":"presentation"),s.hidden=!l}),o.pipe(re(r),Wr(t.pipe(Ae(It)))).subscribe(([{items:l},{value:f}])=>{switch(l.length){case 0:a.textContent=f.length?Ee("search.result.none"):Ee("search.result.placeholder");break;case 1:a.textContent=Ee("search.result.one");break;default:let u=sr(l.length);a.textContent=Ee("search.result.other",u)}});let p=o.pipe(w(()=>s.innerHTML=""),v(({items:l})=>O(I(...l.slice(0,10)),I(...l.slice(10)).pipe(Be(4),Dr(n),v(([f])=>f)))),m(Mn),pe());return p.subscribe(l=>s.appendChild(l)),p.pipe(ne(l=>{let f=fe("details",l);return typeof f=="undefined"?S:h(f,"toggle").pipe(W(o),m(()=>f))})).subscribe(l=>{l.open===!1&&l.offsetTop<=i.scrollTop&&i.scrollTo({top:l.offsetTop})}),t.pipe(b(dr),m(({data:l})=>l)).pipe(w(l=>o.next(l)),_(()=>o.complete()),m(l=>$({ref:e},l)))}function ms(e,{query$:t}){return t.pipe(m(({value:r})=>{let o=ye();return o.hash="",r=r.replace(/\s+/g,"+").replace(/&/g,"%26").replace(/=/g,"%3D"),o.search=`q=${r}`,{url:o}}))}function mi(e,t){let r=new g,o=r.pipe(Z(),ie(!0));return r.subscribe(({url:n})=>{e.setAttribute("data-clipboard-text",e.href),e.href=`${n}`}),h(e,"click").pipe(W(o)).subscribe(n=>n.preventDefault()),ms(e,t).pipe(w(n=>r.next(n)),_(()=>r.complete()),m(n=>$({ref:e},n)))}function fi(e,{worker$:t,keyboard$:r}){let o=new g,n=Se("search-query"),i=O(h(n,"keydown"),h(n,"focus")).pipe(ve(se),m(()=>n.value),K());return o.pipe(He(i),m(([{suggest:s},p])=>{let c=p.split(/([\s-]+)/);if(s!=null&&s.length&&c[c.length-1]){let l=s[s.length-1];l.startsWith(c[c.length-1])&&(c[c.length-1]=l)}else c.length=0;return c})).subscribe(s=>e.innerHTML=s.join("").replace(/\s/g," ")),r.pipe(b(({mode:s})=>s==="search")).subscribe(s=>{switch(s.type){case"ArrowRight":e.innerText.length&&n.selectionStart===n.value.length&&(n.value=e.innerText);break}}),t.pipe(b(dr),m(({data:s})=>s)).pipe(w(s=>o.next(s)),_(()=>o.complete()),m(()=>({ref:e})))}function ui(e,{index$:t,keyboard$:r}){let o=xe();try{let n=ai(o.search,t),i=Se("search-query",e),a=Se("search-result",e);h(e,"click").pipe(b(({target:p})=>p instanceof Element&&!!p.closest("a"))).subscribe(()=>Je("search",!1)),r.pipe(b(({mode:p})=>p==="search")).subscribe(p=>{let c=Ie();switch(p.type){case"Enter":if(c===i){let l=new Map;for(let f of P(":first-child [href]",a)){let u=f.firstElementChild;l.set(f,parseFloat(u.getAttribute("data-md-score")))}if(l.size){let[[f]]=[...l].sort(([,u],[,d])=>d-u);f.click()}p.claim()}break;case"Escape":case"Tab":Je("search",!1),i.blur();break;case"ArrowUp":case"ArrowDown":if(typeof c=="undefined")i.focus();else{let l=[i,...P(":not(details) > [href], summary, details[open] [href]",a)],f=Math.max(0,(Math.max(0,l.indexOf(c))+l.length+(p.type==="ArrowUp"?-1:1))%l.length);l[f].focus()}p.claim();break;default:i!==Ie()&&i.focus()}}),r.pipe(b(({mode:p})=>p==="global")).subscribe(p=>{switch(p.type){case"f":case"s":case"/":i.focus(),i.select(),p.claim();break}});let s=pi(i,{worker$:n});return O(s,li(a,{worker$:n,query$:s})).pipe(Re(...ae("search-share",e).map(p=>mi(p,{query$:s})),...ae("search-suggest",e).map(p=>fi(p,{worker$:n,keyboard$:r}))))}catch(n){return e.hidden=!0,Ye}}function di(e,{index$:t,location$:r}){return N([t,r.pipe(Q(ye()),b(o=>!!o.searchParams.get("h")))]).pipe(m(([o,n])=>ii(o.config)(n.searchParams.get("h"))),m(o=>{var a;let n=new Map,i=document.createNodeIterator(e,NodeFilter.SHOW_TEXT);for(let s=i.nextNode();s;s=i.nextNode())if((a=s.parentElement)!=null&&a.offsetHeight){let p=s.textContent,c=o(p);c.length>p.length&&n.set(s,c)}for(let[s,p]of n){let{childNodes:c}=x("span",null,p);s.replaceWith(...Array.from(c))}return{ref:e,nodes:n}}))}function fs(e,{viewport$:t,main$:r}){let o=e.closest(".md-grid"),n=o.offsetTop-o.parentElement.offsetTop;return N([r,t]).pipe(m(([{offset:i,height:a},{offset:{y:s}}])=>(a=a+Math.min(n,Math.max(0,s-i))-n,{height:a,locked:s>=i+n})),K((i,a)=>i.height===a.height&&i.locked===a.locked))}function Zr(e,o){var n=o,{header$:t}=n,r=so(n,["header$"]);let i=R(".md-sidebar__scrollwrap",e),{y:a}=De(i);return C(()=>{let s=new g,p=s.pipe(Z(),ie(!0)),c=s.pipe(Me(0,me));return c.pipe(re(t)).subscribe({next([{height:l},{height:f}]){i.style.height=`${l-2*a}px`,e.style.top=`${f}px`},complete(){i.style.height="",e.style.top=""}}),c.pipe(Ae()).subscribe(()=>{for(let l of P(".md-nav__link--active[href]",e)){if(!l.clientHeight)continue;let f=l.closest(".md-sidebar__scrollwrap");if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=ce(f);f.scrollTo({top:u-d/2})}}}),ue(P("label[tabindex]",e)).pipe(ne(l=>h(l,"click").pipe(ve(se),m(()=>l),W(p)))).subscribe(l=>{let f=R(`[id="${l.htmlFor}"]`);R(`[aria-labelledby="${l.id}"]`).setAttribute("aria-expanded",`${f.checked}`)}),fs(e,r).pipe(w(l=>s.next(l)),_(()=>s.complete()),m(l=>$({ref:e},l)))})}function hi(e,t){if(typeof t!="undefined"){let r=`https://api.github.com/repos/${e}/${t}`;return st(je(`${r}/releases/latest`).pipe(de(()=>S),m(o=>({version:o.tag_name})),Ve({})),je(r).pipe(de(()=>S),m(o=>({stars:o.stargazers_count,forks:o.forks_count})),Ve({}))).pipe(m(([o,n])=>$($({},o),n)))}else{let r=`https://api.github.com/users/${e}`;return je(r).pipe(m(o=>({repositories:o.public_repos})),Ve({}))}}function bi(e,t){let r=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return st(je(`${r}/releases/permalink/latest`).pipe(de(()=>S),m(({tag_name:o})=>({version:o})),Ve({})),je(r).pipe(de(()=>S),m(({star_count:o,forks_count:n})=>({stars:o,forks:n})),Ve({}))).pipe(m(([o,n])=>$($({},o),n)))}function vi(e){let t=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);if(t){let[,r,o]=t;return hi(r,o)}if(t=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i),t){let[,r,o]=t;return bi(r,o)}return S}var us;function ds(e){return us||(us=C(()=>{let t=__md_get("__source",sessionStorage);if(t)return I(t);if(ae("consent").length){let o=__md_get("__consent");if(!(o&&o.github))return S}return vi(e.href).pipe(w(o=>__md_set("__source",o,sessionStorage)))}).pipe(de(()=>S),b(t=>Object.keys(t).length>0),m(t=>({facts:t})),G(1)))}function gi(e){let t=R(":scope > :last-child",e);return C(()=>{let r=new g;return r.subscribe(({facts:o})=>{t.appendChild(_n(o)),t.classList.add("md-source__repository--active")}),ds(e).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}function hs(e,{viewport$:t,header$:r}){return ge(document.body).pipe(v(()=>mr(e,{header$:r,viewport$:t})),m(({offset:{y:o}})=>({hidden:o>=10})),te("hidden"))}function yi(e,t){return C(()=>{let r=new g;return r.subscribe({next({hidden:o}){e.hidden=o},complete(){e.hidden=!1}}),(B("navigation.tabs.sticky")?I({hidden:!1}):hs(e,t)).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}function bs(e,{viewport$:t,header$:r}){let o=new Map,n=P(".md-nav__link",e);for(let s of n){let p=decodeURIComponent(s.hash.substring(1)),c=fe(`[id="${p}"]`);typeof c!="undefined"&&o.set(s,c)}let i=r.pipe(te("height"),m(({height:s})=>{let p=Se("main"),c=R(":scope > :first-child",p);return s+.8*(c.offsetTop-p.offsetTop)}),pe());return ge(document.body).pipe(te("height"),v(s=>C(()=>{let p=[];return I([...o].reduce((c,[l,f])=>{for(;p.length&&o.get(p[p.length-1]).tagName>=f.tagName;)p.pop();let u=f.offsetTop;for(;!u&&f.parentElement;)f=f.parentElement,u=f.offsetTop;let d=f.offsetParent;for(;d;d=d.offsetParent)u+=d.offsetTop;return c.set([...p=[...p,l]].reverse(),u)},new Map))}).pipe(m(p=>new Map([...p].sort(([,c],[,l])=>c-l))),He(i),v(([p,c])=>t.pipe(Fr(([l,f],{offset:{y:u},size:d})=>{let y=u+d.height>=Math.floor(s.height);for(;f.length;){let[,L]=f[0];if(L-c=u&&!y)f=[l.pop(),...f];else break}return[l,f]},[[],[...p]]),K((l,f)=>l[0]===f[0]&&l[1]===f[1])))))).pipe(m(([s,p])=>({prev:s.map(([c])=>c),next:p.map(([c])=>c)})),Q({prev:[],next:[]}),Be(2,1),m(([s,p])=>s.prev.length{let i=new g,a=i.pipe(Z(),ie(!0));if(i.subscribe(({prev:s,next:p})=>{for(let[c]of p)c.classList.remove("md-nav__link--passed"),c.classList.remove("md-nav__link--active");for(let[c,[l]]of s.entries())l.classList.add("md-nav__link--passed"),l.classList.toggle("md-nav__link--active",c===s.length-1)}),B("toc.follow")){let s=O(t.pipe(_e(1),m(()=>{})),t.pipe(_e(250),m(()=>"smooth")));i.pipe(b(({prev:p})=>p.length>0),He(o.pipe(ve(se))),re(s)).subscribe(([[{prev:p}],c])=>{let[l]=p[p.length-1];if(l.offsetHeight){let f=cr(l);if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=ce(f);f.scrollTo({top:u-d/2,behavior:c})}}})}return B("navigation.tracking")&&t.pipe(W(a),te("offset"),_e(250),Ce(1),W(n.pipe(Ce(1))),ct({delay:250}),re(i)).subscribe(([,{prev:s}])=>{let p=ye(),c=s[s.length-1];if(c&&c.length){let[l]=c,{hash:f}=new URL(l.href);p.hash!==f&&(p.hash=f,history.replaceState({},"",`${p}`))}else p.hash="",history.replaceState({},"",`${p}`)}),bs(e,{viewport$:t,header$:r}).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))})}function vs(e,{viewport$:t,main$:r,target$:o}){let n=t.pipe(m(({offset:{y:a}})=>a),Be(2,1),m(([a,s])=>a>s&&s>0),K()),i=r.pipe(m(({active:a})=>a));return N([i,n]).pipe(m(([a,s])=>!(a&&s)),K(),W(o.pipe(Ce(1))),ie(!0),ct({delay:250}),m(a=>({hidden:a})))}function Ei(e,{viewport$:t,header$:r,main$:o,target$:n}){let i=new g,a=i.pipe(Z(),ie(!0));return i.subscribe({next({hidden:s}){e.hidden=s,s?(e.setAttribute("tabindex","-1"),e.blur()):e.removeAttribute("tabindex")},complete(){e.style.top="",e.hidden=!0,e.removeAttribute("tabindex")}}),r.pipe(W(a),te("height")).subscribe(({height:s})=>{e.style.top=`${s+16}px`}),h(e,"click").subscribe(s=>{s.preventDefault(),window.scrollTo({top:0})}),vs(e,{viewport$:t,main$:o,target$:n}).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))}function wi({document$:e,viewport$:t}){e.pipe(v(()=>P(".md-ellipsis")),ne(r=>tt(r).pipe(W(e.pipe(Ce(1))),b(o=>o),m(()=>r),Te(1))),b(r=>r.offsetWidth{let o=r.innerText,n=r.closest("a")||r;return n.title=o,B("content.tooltips")?mt(n,{viewport$:t}).pipe(W(e.pipe(Ce(1))),_(()=>n.removeAttribute("title"))):S})).subscribe(),B("content.tooltips")&&e.pipe(v(()=>P(".md-status")),ne(r=>mt(r,{viewport$:t}))).subscribe()}function Ti({document$:e,tablet$:t}){e.pipe(v(()=>P(".md-toggle--indeterminate")),w(r=>{r.indeterminate=!0,r.checked=!1}),ne(r=>h(r,"change").pipe(Vr(()=>r.classList.contains("md-toggle--indeterminate")),m(()=>r))),re(t)).subscribe(([r,o])=>{r.classList.remove("md-toggle--indeterminate"),o&&(r.checked=!1)})}function gs(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}function Si({document$:e}){e.pipe(v(()=>P("[data-md-scrollfix]")),w(t=>t.removeAttribute("data-md-scrollfix")),b(gs),ne(t=>h(t,"touchstart").pipe(m(()=>t)))).subscribe(t=>{let r=t.scrollTop;r===0?t.scrollTop=1:r+t.offsetHeight===t.scrollHeight&&(t.scrollTop=r-1)})}function Oi({viewport$:e,tablet$:t}){N([Ne("search"),t]).pipe(m(([r,o])=>r&&!o),v(r=>I(r).pipe(Ge(r?400:100))),re(e)).subscribe(([r,{offset:{y:o}}])=>{if(r)document.body.setAttribute("data-md-scrolllock",""),document.body.style.top=`-${o}px`;else{let n=-1*parseInt(document.body.style.top,10);document.body.removeAttribute("data-md-scrolllock"),document.body.style.top="",n&&window.scrollTo(0,n)}})}Object.entries||(Object.entries=function(e){let t=[];for(let r of Object.keys(e))t.push([r,e[r]]);return t});Object.values||(Object.values=function(e){let t=[];for(let r of Object.keys(e))t.push(e[r]);return t});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(e,t){typeof e=="object"?(this.scrollLeft=e.left,this.scrollTop=e.top):(this.scrollLeft=e,this.scrollTop=t)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...e){let t=this.parentNode;if(t){e.length===0&&t.removeChild(this);for(let r=e.length-1;r>=0;r--){let o=e[r];typeof o=="string"?o=document.createTextNode(o):o.parentNode&&o.parentNode.removeChild(o),r?t.insertBefore(this.previousSibling,o):t.replaceChild(o,this)}}}));function ys(){return location.protocol==="file:"?wt(`${new URL("search/search_index.js",eo.base)}`).pipe(m(()=>__index),G(1)):je(new URL("search/search_index.json",eo.base))}document.documentElement.classList.remove("no-js");document.documentElement.classList.add("js");var ot=Go(),Ft=sn(),Ot=ln(Ft),to=an(),Oe=gn(),hr=$t("(min-width: 60em)"),Mi=$t("(min-width: 76.25em)"),_i=mn(),eo=xe(),Ai=document.forms.namedItem("search")?ys():Ye,ro=new g;Zn({alert$:ro});var oo=new g;B("navigation.instant")&&oi({location$:Ft,viewport$:Oe,progress$:oo}).subscribe(ot);var Li;((Li=eo.version)==null?void 0:Li.provider)==="mike"&&ci({document$:ot});O(Ft,Ot).pipe(Ge(125)).subscribe(()=>{Je("drawer",!1),Je("search",!1)});to.pipe(b(({mode:e})=>e==="global")).subscribe(e=>{switch(e.type){case"p":case",":let t=fe("link[rel=prev]");typeof t!="undefined"&<(t);break;case"n":case".":let r=fe("link[rel=next]");typeof r!="undefined"&<(r);break;case"Enter":let o=Ie();o instanceof HTMLLabelElement&&o.click()}});wi({viewport$:Oe,document$:ot});Ti({document$:ot,tablet$:hr});Si({document$:ot});Oi({viewport$:Oe,tablet$:hr});var rt=Kn(Se("header"),{viewport$:Oe}),jt=ot.pipe(m(()=>Se("main")),v(e=>Gn(e,{viewport$:Oe,header$:rt})),G(1)),xs=O(...ae("consent").map(e=>En(e,{target$:Ot})),...ae("dialog").map(e=>qn(e,{alert$:ro})),...ae("palette").map(e=>Jn(e)),...ae("progress").map(e=>Xn(e,{progress$:oo})),...ae("search").map(e=>ui(e,{index$:Ai,keyboard$:to})),...ae("source").map(e=>gi(e))),Es=C(()=>O(...ae("announce").map(e=>xn(e)),...ae("content").map(e=>Nn(e,{viewport$:Oe,target$:Ot,print$:_i})),...ae("content").map(e=>B("search.highlight")?di(e,{index$:Ai,location$:Ft}):S),...ae("header").map(e=>Yn(e,{viewport$:Oe,header$:rt,main$:jt})),...ae("header-title").map(e=>Bn(e,{viewport$:Oe,header$:rt})),...ae("sidebar").map(e=>e.getAttribute("data-md-type")==="navigation"?zr(Mi,()=>Zr(e,{viewport$:Oe,header$:rt,main$:jt})):zr(hr,()=>Zr(e,{viewport$:Oe,header$:rt,main$:jt}))),...ae("tabs").map(e=>yi(e,{viewport$:Oe,header$:rt})),...ae("toc").map(e=>xi(e,{viewport$:Oe,header$:rt,main$:jt,target$:Ot})),...ae("top").map(e=>Ei(e,{viewport$:Oe,header$:rt,main$:jt,target$:Ot})))),Ci=ot.pipe(v(()=>Es),Re(xs),G(1));Ci.subscribe();window.document$=ot;window.location$=Ft;window.target$=Ot;window.keyboard$=to;window.viewport$=Oe;window.tablet$=hr;window.screen$=Mi;window.print$=_i;window.alert$=ro;window.progress$=oo;window.component$=Ci;})(); +//# sourceMappingURL=bundle.f55a23d4.min.js.map + diff --git a/assets/javascripts/bundle.f55a23d4.min.js.map b/assets/javascripts/bundle.f55a23d4.min.js.map new file mode 100644 index 00000000..e3de73ff --- /dev/null +++ b/assets/javascripts/bundle.f55a23d4.min.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["node_modules/focus-visible/dist/focus-visible.js", "node_modules/escape-html/index.js", "node_modules/clipboard/dist/clipboard.js", "src/templates/assets/javascripts/bundle.ts", "node_modules/tslib/tslib.es6.mjs", "node_modules/rxjs/src/internal/util/isFunction.ts", "node_modules/rxjs/src/internal/util/createErrorClass.ts", "node_modules/rxjs/src/internal/util/UnsubscriptionError.ts", "node_modules/rxjs/src/internal/util/arrRemove.ts", "node_modules/rxjs/src/internal/Subscription.ts", "node_modules/rxjs/src/internal/config.ts", "node_modules/rxjs/src/internal/scheduler/timeoutProvider.ts", "node_modules/rxjs/src/internal/util/reportUnhandledError.ts", "node_modules/rxjs/src/internal/util/noop.ts", "node_modules/rxjs/src/internal/NotificationFactories.ts", "node_modules/rxjs/src/internal/util/errorContext.ts", "node_modules/rxjs/src/internal/Subscriber.ts", "node_modules/rxjs/src/internal/symbol/observable.ts", "node_modules/rxjs/src/internal/util/identity.ts", "node_modules/rxjs/src/internal/util/pipe.ts", "node_modules/rxjs/src/internal/Observable.ts", "node_modules/rxjs/src/internal/util/lift.ts", "node_modules/rxjs/src/internal/operators/OperatorSubscriber.ts", "node_modules/rxjs/src/internal/scheduler/animationFrameProvider.ts", "node_modules/rxjs/src/internal/util/ObjectUnsubscribedError.ts", "node_modules/rxjs/src/internal/Subject.ts", "node_modules/rxjs/src/internal/BehaviorSubject.ts", "node_modules/rxjs/src/internal/scheduler/dateTimestampProvider.ts", "node_modules/rxjs/src/internal/ReplaySubject.ts", "node_modules/rxjs/src/internal/scheduler/Action.ts", "node_modules/rxjs/src/internal/scheduler/intervalProvider.ts", "node_modules/rxjs/src/internal/scheduler/AsyncAction.ts", "node_modules/rxjs/src/internal/Scheduler.ts", "node_modules/rxjs/src/internal/scheduler/AsyncScheduler.ts", "node_modules/rxjs/src/internal/scheduler/async.ts", "node_modules/rxjs/src/internal/scheduler/QueueAction.ts", "node_modules/rxjs/src/internal/scheduler/QueueScheduler.ts", "node_modules/rxjs/src/internal/scheduler/queue.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameAction.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameScheduler.ts", "node_modules/rxjs/src/internal/scheduler/animationFrame.ts", "node_modules/rxjs/src/internal/observable/empty.ts", "node_modules/rxjs/src/internal/util/isScheduler.ts", "node_modules/rxjs/src/internal/util/args.ts", "node_modules/rxjs/src/internal/util/isArrayLike.ts", "node_modules/rxjs/src/internal/util/isPromise.ts", "node_modules/rxjs/src/internal/util/isInteropObservable.ts", "node_modules/rxjs/src/internal/util/isAsyncIterable.ts", "node_modules/rxjs/src/internal/util/throwUnobservableError.ts", "node_modules/rxjs/src/internal/symbol/iterator.ts", "node_modules/rxjs/src/internal/util/isIterable.ts", "node_modules/rxjs/src/internal/util/isReadableStreamLike.ts", "node_modules/rxjs/src/internal/observable/innerFrom.ts", "node_modules/rxjs/src/internal/util/executeSchedule.ts", "node_modules/rxjs/src/internal/operators/observeOn.ts", "node_modules/rxjs/src/internal/operators/subscribeOn.ts", "node_modules/rxjs/src/internal/scheduled/scheduleObservable.ts", "node_modules/rxjs/src/internal/scheduled/schedulePromise.ts", "node_modules/rxjs/src/internal/scheduled/scheduleArray.ts", "node_modules/rxjs/src/internal/scheduled/scheduleIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleAsyncIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleReadableStreamLike.ts", "node_modules/rxjs/src/internal/scheduled/scheduled.ts", "node_modules/rxjs/src/internal/observable/from.ts", "node_modules/rxjs/src/internal/observable/of.ts", "node_modules/rxjs/src/internal/observable/throwError.ts", "node_modules/rxjs/src/internal/util/EmptyError.ts", "node_modules/rxjs/src/internal/util/isDate.ts", "node_modules/rxjs/src/internal/operators/map.ts", "node_modules/rxjs/src/internal/util/mapOneOrManyArgs.ts", "node_modules/rxjs/src/internal/util/argsArgArrayOrObject.ts", "node_modules/rxjs/src/internal/util/createObject.ts", "node_modules/rxjs/src/internal/observable/combineLatest.ts", "node_modules/rxjs/src/internal/operators/mergeInternals.ts", "node_modules/rxjs/src/internal/operators/mergeMap.ts", "node_modules/rxjs/src/internal/operators/mergeAll.ts", "node_modules/rxjs/src/internal/operators/concatAll.ts", "node_modules/rxjs/src/internal/observable/concat.ts", "node_modules/rxjs/src/internal/observable/defer.ts", "node_modules/rxjs/src/internal/observable/fromEvent.ts", "node_modules/rxjs/src/internal/observable/fromEventPattern.ts", "node_modules/rxjs/src/internal/observable/timer.ts", "node_modules/rxjs/src/internal/observable/merge.ts", "node_modules/rxjs/src/internal/observable/never.ts", "node_modules/rxjs/src/internal/util/argsOrArgArray.ts", "node_modules/rxjs/src/internal/operators/filter.ts", "node_modules/rxjs/src/internal/observable/zip.ts", "node_modules/rxjs/src/internal/operators/audit.ts", "node_modules/rxjs/src/internal/operators/auditTime.ts", "node_modules/rxjs/src/internal/operators/bufferCount.ts", "node_modules/rxjs/src/internal/operators/catchError.ts", "node_modules/rxjs/src/internal/operators/scanInternals.ts", "node_modules/rxjs/src/internal/operators/combineLatest.ts", "node_modules/rxjs/src/internal/operators/combineLatestWith.ts", "node_modules/rxjs/src/internal/operators/debounce.ts", "node_modules/rxjs/src/internal/operators/debounceTime.ts", "node_modules/rxjs/src/internal/operators/defaultIfEmpty.ts", "node_modules/rxjs/src/internal/operators/take.ts", "node_modules/rxjs/src/internal/operators/ignoreElements.ts", "node_modules/rxjs/src/internal/operators/mapTo.ts", "node_modules/rxjs/src/internal/operators/delayWhen.ts", "node_modules/rxjs/src/internal/operators/delay.ts", "node_modules/rxjs/src/internal/operators/distinctUntilChanged.ts", "node_modules/rxjs/src/internal/operators/distinctUntilKeyChanged.ts", "node_modules/rxjs/src/internal/operators/throwIfEmpty.ts", "node_modules/rxjs/src/internal/operators/endWith.ts", "node_modules/rxjs/src/internal/operators/finalize.ts", "node_modules/rxjs/src/internal/operators/first.ts", "node_modules/rxjs/src/internal/operators/takeLast.ts", "node_modules/rxjs/src/internal/operators/merge.ts", "node_modules/rxjs/src/internal/operators/mergeWith.ts", "node_modules/rxjs/src/internal/operators/repeat.ts", "node_modules/rxjs/src/internal/operators/scan.ts", "node_modules/rxjs/src/internal/operators/share.ts", "node_modules/rxjs/src/internal/operators/shareReplay.ts", "node_modules/rxjs/src/internal/operators/skip.ts", "node_modules/rxjs/src/internal/operators/skipUntil.ts", "node_modules/rxjs/src/internal/operators/startWith.ts", "node_modules/rxjs/src/internal/operators/switchMap.ts", "node_modules/rxjs/src/internal/operators/takeUntil.ts", "node_modules/rxjs/src/internal/operators/takeWhile.ts", "node_modules/rxjs/src/internal/operators/tap.ts", "node_modules/rxjs/src/internal/operators/throttle.ts", "node_modules/rxjs/src/internal/operators/throttleTime.ts", "node_modules/rxjs/src/internal/operators/withLatestFrom.ts", "node_modules/rxjs/src/internal/operators/zip.ts", "node_modules/rxjs/src/internal/operators/zipWith.ts", "src/templates/assets/javascripts/browser/document/index.ts", "src/templates/assets/javascripts/browser/element/_/index.ts", "src/templates/assets/javascripts/browser/element/focus/index.ts", "src/templates/assets/javascripts/browser/element/hover/index.ts", "src/templates/assets/javascripts/utilities/h/index.ts", "src/templates/assets/javascripts/utilities/round/index.ts", "src/templates/assets/javascripts/browser/script/index.ts", "src/templates/assets/javascripts/browser/element/size/_/index.ts", "src/templates/assets/javascripts/browser/element/size/content/index.ts", "src/templates/assets/javascripts/browser/element/offset/_/index.ts", "src/templates/assets/javascripts/browser/element/offset/content/index.ts", "src/templates/assets/javascripts/browser/element/visibility/index.ts", "src/templates/assets/javascripts/browser/toggle/index.ts", "src/templates/assets/javascripts/browser/keyboard/index.ts", "src/templates/assets/javascripts/browser/location/_/index.ts", "src/templates/assets/javascripts/browser/location/hash/index.ts", "src/templates/assets/javascripts/browser/media/index.ts", "src/templates/assets/javascripts/browser/request/index.ts", "src/templates/assets/javascripts/browser/viewport/offset/index.ts", "src/templates/assets/javascripts/browser/viewport/size/index.ts", "src/templates/assets/javascripts/browser/viewport/_/index.ts", "src/templates/assets/javascripts/browser/viewport/at/index.ts", "src/templates/assets/javascripts/browser/worker/index.ts", "src/templates/assets/javascripts/_/index.ts", "src/templates/assets/javascripts/components/_/index.ts", "src/templates/assets/javascripts/components/announce/index.ts", "src/templates/assets/javascripts/components/consent/index.ts", "src/templates/assets/javascripts/templates/tooltip/index.tsx", "src/templates/assets/javascripts/templates/annotation/index.tsx", "src/templates/assets/javascripts/templates/clipboard/index.tsx", "src/templates/assets/javascripts/templates/search/index.tsx", "src/templates/assets/javascripts/templates/source/index.tsx", "src/templates/assets/javascripts/templates/tabbed/index.tsx", "src/templates/assets/javascripts/templates/table/index.tsx", "src/templates/assets/javascripts/templates/version/index.tsx", "src/templates/assets/javascripts/components/tooltip2/index.ts", "src/templates/assets/javascripts/components/content/annotation/_/index.ts", "src/templates/assets/javascripts/components/content/annotation/list/index.ts", "src/templates/assets/javascripts/components/content/annotation/block/index.ts", "src/templates/assets/javascripts/components/content/code/_/index.ts", "src/templates/assets/javascripts/components/content/details/index.ts", "src/templates/assets/javascripts/components/content/mermaid/index.css", "src/templates/assets/javascripts/components/content/mermaid/index.ts", "src/templates/assets/javascripts/components/content/table/index.ts", "src/templates/assets/javascripts/components/content/tabs/index.ts", "src/templates/assets/javascripts/components/content/_/index.ts", "src/templates/assets/javascripts/components/dialog/index.ts", "src/templates/assets/javascripts/components/tooltip/index.ts", "src/templates/assets/javascripts/components/header/_/index.ts", "src/templates/assets/javascripts/components/header/title/index.ts", "src/templates/assets/javascripts/components/main/index.ts", "src/templates/assets/javascripts/components/palette/index.ts", "src/templates/assets/javascripts/components/progress/index.ts", "src/templates/assets/javascripts/integrations/clipboard/index.ts", "src/templates/assets/javascripts/integrations/sitemap/index.ts", "src/templates/assets/javascripts/integrations/instant/index.ts", "src/templates/assets/javascripts/integrations/search/highlighter/index.ts", "src/templates/assets/javascripts/integrations/search/worker/message/index.ts", "src/templates/assets/javascripts/integrations/search/worker/_/index.ts", "src/templates/assets/javascripts/integrations/version/findurl/index.ts", "src/templates/assets/javascripts/integrations/version/index.ts", "src/templates/assets/javascripts/components/search/query/index.ts", "src/templates/assets/javascripts/components/search/result/index.ts", "src/templates/assets/javascripts/components/search/share/index.ts", "src/templates/assets/javascripts/components/search/suggest/index.ts", "src/templates/assets/javascripts/components/search/_/index.ts", "src/templates/assets/javascripts/components/search/highlight/index.ts", "src/templates/assets/javascripts/components/sidebar/index.ts", "src/templates/assets/javascripts/components/source/facts/github/index.ts", "src/templates/assets/javascripts/components/source/facts/gitlab/index.ts", "src/templates/assets/javascripts/components/source/facts/_/index.ts", "src/templates/assets/javascripts/components/source/_/index.ts", "src/templates/assets/javascripts/components/tabs/index.ts", "src/templates/assets/javascripts/components/toc/index.ts", "src/templates/assets/javascripts/components/top/index.ts", "src/templates/assets/javascripts/patches/ellipsis/index.ts", "src/templates/assets/javascripts/patches/indeterminate/index.ts", "src/templates/assets/javascripts/patches/scrollfix/index.ts", "src/templates/assets/javascripts/patches/scrolllock/index.ts", "src/templates/assets/javascripts/polyfills/index.ts"], + "sourcesContent": ["(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. \u00AF\\_(\u30C4)_/\u00AF\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n", "/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n", "/*!\n * clipboard.js v2.0.11\n * https://clipboardjs.com/\n *\n * Licensed MIT \u00A9 Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function() { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 686:\n/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"default\": function() { return /* binding */ clipboard; }\n});\n\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(279);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(370);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(817);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n;// CONCATENATED MODULE: ./src/common/command.js\n/**\n * Executes a given operation type.\n * @param {String} type\n * @return {Boolean}\n */\nfunction command(type) {\n try {\n return document.execCommand(type);\n } catch (err) {\n return false;\n }\n}\n;// CONCATENATED MODULE: ./src/actions/cut.js\n\n\n/**\n * Cut action wrapper.\n * @param {String|HTMLElement} target\n * @return {String}\n */\n\nvar ClipboardActionCut = function ClipboardActionCut(target) {\n var selectedText = select_default()(target);\n command('cut');\n return selectedText;\n};\n\n/* harmony default export */ var actions_cut = (ClipboardActionCut);\n;// CONCATENATED MODULE: ./src/common/create-fake-element.js\n/**\n * Creates a fake textarea element with a value.\n * @param {String} value\n * @return {HTMLElement}\n */\nfunction createFakeElement(value) {\n var isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS\n\n fakeElement.style.fontSize = '12pt'; // Reset box model\n\n fakeElement.style.border = '0';\n fakeElement.style.padding = '0';\n fakeElement.style.margin = '0'; // Move element out of screen horizontally\n\n fakeElement.style.position = 'absolute';\n fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically\n\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n fakeElement.style.top = \"\".concat(yPosition, \"px\");\n fakeElement.setAttribute('readonly', '');\n fakeElement.value = value;\n return fakeElement;\n}\n;// CONCATENATED MODULE: ./src/actions/copy.js\n\n\n\n/**\n * Create fake copy action wrapper using a fake element.\n * @param {String} target\n * @param {Object} options\n * @return {String}\n */\n\nvar fakeCopyAction = function fakeCopyAction(value, options) {\n var fakeElement = createFakeElement(value);\n options.container.appendChild(fakeElement);\n var selectedText = select_default()(fakeElement);\n command('copy');\n fakeElement.remove();\n return selectedText;\n};\n/**\n * Copy action wrapper.\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @return {String}\n */\n\n\nvar ClipboardActionCopy = function ClipboardActionCopy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n var selectedText = '';\n\n if (typeof target === 'string') {\n selectedText = fakeCopyAction(target, options);\n } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {\n // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n selectedText = fakeCopyAction(target.value, options);\n } else {\n selectedText = select_default()(target);\n command('copy');\n }\n\n return selectedText;\n};\n\n/* harmony default export */ var actions_copy = (ClipboardActionCopy);\n;// CONCATENATED MODULE: ./src/actions/default.js\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n\n\n/**\n * Inner function which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n * @param {Object} options\n */\n\nvar ClipboardActionDefault = function ClipboardActionDefault() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Defines base properties passed from constructor.\n var _options$action = options.action,\n action = _options$action === void 0 ? 'copy' : _options$action,\n container = options.container,\n target = options.target,\n text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.\n\n if (action !== 'copy' && action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n } // Sets the `target` property using an element that will be have its content copied.\n\n\n if (target !== undefined) {\n if (target && _typeof(target) === 'object' && target.nodeType === 1) {\n if (action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n } // Define selection strategy based on `text` property.\n\n\n if (text) {\n return actions_copy(text, {\n container: container\n });\n } // Defines which selection strategy based on `target` property.\n\n\n if (target) {\n return action === 'cut' ? actions_cut(target) : actions_copy(target, {\n container: container\n });\n }\n};\n\n/* harmony default export */ var actions_default = (ClipboardActionDefault);\n;// CONCATENATED MODULE: ./src/clipboard.js\nfunction clipboard_typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return clipboard_typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\nfunction getAttributeValue(suffix, element) {\n var attribute = \"data-clipboard-\".concat(suffix);\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\n\nvar Clipboard = /*#__PURE__*/function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n var _super = _createSuper(Clipboard);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n var _this;\n\n _classCallCheck(this, Clipboard);\n\n _this = _super.call(this);\n\n _this.resolveOptions(options);\n\n _this.listenClick(trigger);\n\n return _this;\n }\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: \"resolveOptions\",\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: \"listenClick\",\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: \"onClick\",\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n var action = this.action(trigger) || 'copy';\n var text = actions_default({\n action: action,\n container: this.container,\n target: this.target(trigger),\n text: this.text(trigger)\n }); // Fires an event based on the copy operation result.\n\n this.emit(text ? 'success' : 'error', {\n action: action,\n text: text,\n trigger: trigger,\n clearSelection: function clearSelection() {\n if (trigger) {\n trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n });\n }\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultAction\",\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultTarget\",\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n /**\n * Allow fire programmatically a copy action\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @returns Text copied.\n */\n\n }, {\n key: \"defaultText\",\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: \"destroy\",\n value: function destroy() {\n this.listener.destroy();\n }\n }], [{\n key: \"copy\",\n value: function copy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n return actions_copy(target, options);\n }\n /**\n * Allow fire programmatically a cut action\n * @param {String|HTMLElement} target\n * @returns Text cutted.\n */\n\n }, {\n key: \"cut\",\n value: function cut(target) {\n return actions_cut(target);\n }\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: \"isSupported\",\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n return support;\n }\n }]);\n\n return Clipboard;\n}((tiny_emitter_default()));\n\n/* harmony default export */ var clipboard = (Clipboard);\n\n/***/ }),\n\n/***/ 828:\n/***/ (function(module) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n\n/***/ 438:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar closest = __webpack_require__(828);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n\n/***/ 879:\n/***/ (function(__unused_webpack_module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n\n/***/ 370:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar is = __webpack_require__(879);\nvar delegate = __webpack_require__(438);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n\n/***/ 817:\n/***/ (function(module) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n\n/***/ 279:\n/***/ (function(module) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(__webpack_module_cache__[moduleId]) {\n/******/ \t\t\treturn __webpack_module_cache__[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t!function() {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = function(module) {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\tfunction() { return module['default']; } :\n/******/ \t\t\t\tfunction() { return module; };\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t!function() {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = function(exports, definition) {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t!function() {\n/******/ \t\t__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }\n/******/ \t}();\n/******/ \t\n/************************************************************************/\n/******/ \t// module exports must be returned from runtime so entry inlining is disabled\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(686);\n/******/ })()\n.default;\n});", "/*\n * Copyright (c) 2016-2025 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"focus-visible\"\n\nimport {\n EMPTY,\n NEVER,\n Observable,\n Subject,\n defer,\n delay,\n filter,\n map,\n merge,\n mergeWith,\n shareReplay,\n switchMap\n} from \"rxjs\"\n\nimport { configuration, feature } from \"./_\"\nimport {\n at,\n getActiveElement,\n getOptionalElement,\n requestJSON,\n setLocation,\n setToggle,\n watchDocument,\n watchKeyboard,\n watchLocation,\n watchLocationTarget,\n watchMedia,\n watchPrint,\n watchScript,\n watchViewport\n} from \"./browser\"\nimport {\n getComponentElement,\n getComponentElements,\n mountAnnounce,\n mountBackToTop,\n mountConsent,\n mountContent,\n mountDialog,\n mountHeader,\n mountHeaderTitle,\n mountPalette,\n mountProgress,\n mountSearch,\n mountSearchHiglight,\n mountSidebar,\n mountSource,\n mountTableOfContents,\n mountTabs,\n watchHeader,\n watchMain\n} from \"./components\"\nimport {\n SearchIndex,\n setupClipboardJS,\n setupInstantNavigation,\n setupVersionSelector\n} from \"./integrations\"\nimport {\n patchEllipsis,\n patchIndeterminate,\n patchScrollfix,\n patchScrolllock\n} from \"./patches\"\nimport \"./polyfills\"\n\n/* ----------------------------------------------------------------------------\n * Functions - @todo refactor\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch search index\n *\n * @returns Search index observable\n */\nfunction fetchSearchIndex(): Observable {\n if (location.protocol === \"file:\") {\n return watchScript(\n `${new URL(\"search/search_index.js\", config.base)}`\n )\n .pipe(\n // @ts-ignore - @todo fix typings\n map(() => __index),\n shareReplay(1)\n )\n } else {\n return requestJSON(\n new URL(\"search/search_index.json\", config.base)\n )\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Application\n * ------------------------------------------------------------------------- */\n\n/* Yay, JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Set up navigation observables and subjects */\nconst document$ = watchDocument()\nconst location$ = watchLocation()\nconst target$ = watchLocationTarget(location$)\nconst keyboard$ = watchKeyboard()\n\n/* Set up media observables */\nconst viewport$ = watchViewport()\nconst tablet$ = watchMedia(\"(min-width: 60em)\")\nconst screen$ = watchMedia(\"(min-width: 76.25em)\")\nconst print$ = watchPrint()\n\n/* Retrieve search index, if search is enabled */\nconst config = configuration()\nconst index$ = document.forms.namedItem(\"search\")\n ? fetchSearchIndex()\n : NEVER\n\n/* Set up Clipboard.js integration */\nconst alert$ = new Subject()\nsetupClipboardJS({ alert$ })\n\n/* Set up progress indicator */\nconst progress$ = new Subject()\n\n/* Set up instant navigation, if enabled */\nif (feature(\"navigation.instant\"))\n setupInstantNavigation({ location$, viewport$, progress$ })\n .subscribe(document$)\n\n/* Set up version selector */\nif (config.version?.provider === \"mike\")\n setupVersionSelector({ document$ })\n\n/* Always close drawer and search on navigation */\nmerge(location$, target$)\n .pipe(\n delay(125)\n )\n .subscribe(() => {\n setToggle(\"drawer\", false)\n setToggle(\"search\", false)\n })\n\n/* Set up global keyboard handlers */\nkeyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\")\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getOptionalElement(\"link[rel=prev]\")\n if (typeof prev !== \"undefined\")\n setLocation(prev)\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getOptionalElement(\"link[rel=next]\")\n if (typeof next !== \"undefined\")\n setLocation(next)\n break\n\n /* Expand navigation, see https://bit.ly/3ZjG5io */\n case \"Enter\":\n const active = getActiveElement()\n if (active instanceof HTMLLabelElement)\n active.click()\n }\n })\n\n/* Set up patches */\npatchEllipsis({ viewport$, document$ })\npatchIndeterminate({ document$, tablet$ })\npatchScrollfix({ document$ })\npatchScrolllock({ viewport$, tablet$ })\n\n/* Set up header and main area observable */\nconst header$ = watchHeader(getComponentElement(\"header\"), { viewport$ })\nconst main$ = document$\n .pipe(\n map(() => getComponentElement(\"main\")),\n switchMap(el => watchMain(el, { viewport$, header$ })),\n shareReplay(1)\n )\n\n/* Set up control component observables */\nconst control$ = merge(\n\n /* Consent */\n ...getComponentElements(\"consent\")\n .map(el => mountConsent(el, { target$ })),\n\n /* Dialog */\n ...getComponentElements(\"dialog\")\n .map(el => mountDialog(el, { alert$ })),\n\n /* Color palette */\n ...getComponentElements(\"palette\")\n .map(el => mountPalette(el)),\n\n /* Progress bar */\n ...getComponentElements(\"progress\")\n .map(el => mountProgress(el, { progress$ })),\n\n /* Search */\n ...getComponentElements(\"search\")\n .map(el => mountSearch(el, { index$, keyboard$ })),\n\n /* Repository information */\n ...getComponentElements(\"source\")\n .map(el => mountSource(el))\n)\n\n/* Set up content component observables */\nconst content$ = defer(() => merge(\n\n /* Announcement bar */\n ...getComponentElements(\"announce\")\n .map(el => mountAnnounce(el)),\n\n /* Content */\n ...getComponentElements(\"content\")\n .map(el => mountContent(el, { viewport$, target$, print$ })),\n\n /* Search highlighting */\n ...getComponentElements(\"content\")\n .map(el => feature(\"search.highlight\")\n ? mountSearchHiglight(el, { index$, location$ })\n : EMPTY\n ),\n\n /* Header */\n ...getComponentElements(\"header\")\n .map(el => mountHeader(el, { viewport$, header$, main$ })),\n\n /* Header title */\n ...getComponentElements(\"header-title\")\n .map(el => mountHeaderTitle(el, { viewport$, header$ })),\n\n /* Sidebar */\n ...getComponentElements(\"sidebar\")\n .map(el => el.getAttribute(\"data-md-type\") === \"navigation\"\n ? at(screen$, () => mountSidebar(el, { viewport$, header$, main$ }))\n : at(tablet$, () => mountSidebar(el, { viewport$, header$, main$ }))\n ),\n\n /* Navigation tabs */\n ...getComponentElements(\"tabs\")\n .map(el => mountTabs(el, { viewport$, header$ })),\n\n /* Table of contents */\n ...getComponentElements(\"toc\")\n .map(el => mountTableOfContents(el, {\n viewport$, header$, main$, target$\n })),\n\n /* Back-to-top button */\n ...getComponentElements(\"top\")\n .map(el => mountBackToTop(el, { viewport$, header$, main$, target$ }))\n))\n\n/* Set up component observables */\nconst component$ = document$\n .pipe(\n switchMap(() => content$),\n mergeWith(control$),\n shareReplay(1)\n )\n\n/* Subscribe to all components */\ncomponent$.subscribe()\n\n/* ----------------------------------------------------------------------------\n * Exports\n * ------------------------------------------------------------------------- */\n\nwindow.document$ = document$ /* Document observable */\nwindow.location$ = location$ /* Location subject */\nwindow.target$ = target$ /* Location target observable */\nwindow.keyboard$ = keyboard$ /* Keyboard observable */\nwindow.viewport$ = viewport$ /* Viewport observable */\nwindow.tablet$ = tablet$ /* Media tablet observable */\nwindow.screen$ = screen$ /* Media screen observable */\nwindow.print$ = print$ /* Media print observable */\nwindow.alert$ = alert$ /* Alert subject */\nwindow.progress$ = progress$ /* Progress indicator subject */\nwindow.component$ = component$ /* Component observable */\n", "/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\n\nvar extendStatics = function(d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n }\n return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n var _, done = false;\n for (var i = decorators.length - 1; i >= 0; i--) {\n var context = {};\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n if (kind === \"accessor\") {\n if (result === void 0) continue;\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n if (_ = accept(result.get)) descriptor.get = _;\n if (_ = accept(result.set)) descriptor.set = _;\n if (_ = accept(result.init)) initializers.unshift(_);\n }\n else if (_ = accept(result)) {\n if (kind === \"field\") initializers.unshift(_);\n else descriptor[key] = _;\n }\n }\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\n done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n var useValue = arguments.length > 2;\n for (var i = 0; i < initializers.length; i++) {\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n }\n return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n}\n\nexport function __generator(thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n for (var ar = [], i = 0; i < arguments.length; i++)\n ar = ar.concat(__read(arguments[i]));\n return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n var i, p;\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n};\n\nexport function __importStar(mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n}\n\nexport function __importDefault(mod) {\n return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n if (value !== null && value !== void 0) {\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n var dispose, inner;\n if (async) {\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n dispose = value[Symbol.asyncDispose];\n }\n if (dispose === void 0) {\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n dispose = value[Symbol.dispose];\n if (async) inner = dispose;\n }\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\n env.stack.push({ value: value, dispose: dispose, async: async });\n }\n else if (async) {\n env.stack.push({ async: true });\n }\n return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n function fail(e) {\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n env.hasError = true;\n }\n var r, s = 0;\n function next() {\n while (r = env.stack.pop()) {\n try {\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\n if (r.dispose) {\n var result = r.dispose.call(r.value);\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n }\n else s |= 1;\n }\n catch (e) {\n fail(e);\n }\n }\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\n if (env.hasError) throw env.error;\n }\n return next();\n}\n\nexport default {\n __extends,\n __assign,\n __rest,\n __decorate,\n __param,\n __metadata,\n __awaiter,\n __generator,\n __createBinding,\n __exportStar,\n __values,\n __read,\n __spread,\n __spreadArrays,\n __spreadArray,\n __await,\n __asyncGenerator,\n __asyncDelegator,\n __asyncValues,\n __makeTemplateObject,\n __importStar,\n __importDefault,\n __classPrivateFieldGet,\n __classPrivateFieldSet,\n __classPrivateFieldIn,\n __addDisposableResource,\n __disposeResources,\n};\n", "/**\n * Returns true if the object is a function.\n * @param value The value to check\n */\nexport function isFunction(value: any): value is (...args: any[]) => any {\n return typeof value === 'function';\n}\n", "/**\n * Used to create Error subclasses until the community moves away from ES5.\n *\n * This is because compiling from TypeScript down to ES5 has issues with subclassing Errors\n * as well as other built-in types: https://github.com/Microsoft/TypeScript/issues/12123\n *\n * @param createImpl A factory function to create the actual constructor implementation. The returned\n * function should be a named function that calls `_super` internally.\n */\nexport function createErrorClass(createImpl: (_super: any) => any): T {\n const _super = (instance: any) => {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n\n const ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface UnsubscriptionError extends Error {\n readonly errors: any[];\n}\n\nexport interface UnsubscriptionErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (errors: any[]): UnsubscriptionError;\n}\n\n/**\n * An error thrown when one or more errors have occurred during the\n * `unsubscribe` of a {@link Subscription}.\n */\nexport const UnsubscriptionError: UnsubscriptionErrorCtor = createErrorClass(\n (_super) =>\n function UnsubscriptionErrorImpl(this: any, errors: (Error | string)[]) {\n _super(this);\n this.message = errors\n ? `${errors.length} errors occurred during unsubscription:\n${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n ')}`\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n }\n);\n", "/**\n * Removes an item from an array, mutating it.\n * @param arr The array to remove the item from\n * @param item The item to remove\n */\nexport function arrRemove(arr: T[] | undefined | null, item: T) {\n if (arr) {\n const index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { SubscriptionLike, TeardownLogic, Unsubscribable } from './types';\nimport { arrRemove } from './util/arrRemove';\n\n/**\n * Represents a disposable resource, such as the execution of an Observable. A\n * Subscription has one important method, `unsubscribe`, that takes no argument\n * and just disposes the resource held by the subscription.\n *\n * Additionally, subscriptions may be grouped together through the `add()`\n * method, which will attach a child Subscription to the current Subscription.\n * When a Subscription is unsubscribed, all its children (and its grandchildren)\n * will be unsubscribed as well.\n */\nexport class Subscription implements SubscriptionLike {\n public static EMPTY = (() => {\n const empty = new Subscription();\n empty.closed = true;\n return empty;\n })();\n\n /**\n * A flag to indicate whether this Subscription has already been unsubscribed.\n */\n public closed = false;\n\n private _parentage: Subscription[] | Subscription | null = null;\n\n /**\n * The list of registered finalizers to execute upon unsubscription. Adding and removing from this\n * list occurs in the {@link #add} and {@link #remove} methods.\n */\n private _finalizers: Exclude[] | null = null;\n\n /**\n * @param initialTeardown A function executed first as part of the finalization\n * process that is kicked off when {@link #unsubscribe} is called.\n */\n constructor(private initialTeardown?: () => void) {}\n\n /**\n * Disposes the resources held by the subscription. May, for instance, cancel\n * an ongoing Observable execution or cancel any other type of work that\n * started when the Subscription was created.\n */\n unsubscribe(): void {\n let errors: any[] | undefined;\n\n if (!this.closed) {\n this.closed = true;\n\n // Remove this from it's parents.\n const { _parentage } = this;\n if (_parentage) {\n this._parentage = null;\n if (Array.isArray(_parentage)) {\n for (const parent of _parentage) {\n parent.remove(this);\n }\n } else {\n _parentage.remove(this);\n }\n }\n\n const { initialTeardown: initialFinalizer } = this;\n if (isFunction(initialFinalizer)) {\n try {\n initialFinalizer();\n } catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n\n const { _finalizers } = this;\n if (_finalizers) {\n this._finalizers = null;\n for (const finalizer of _finalizers) {\n try {\n execFinalizer(finalizer);\n } catch (err) {\n errors = errors ?? [];\n if (err instanceof UnsubscriptionError) {\n errors = [...errors, ...err.errors];\n } else {\n errors.push(err);\n }\n }\n }\n }\n\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n }\n\n /**\n * Adds a finalizer to this subscription, so that finalization will be unsubscribed/called\n * when this subscription is unsubscribed. If this subscription is already {@link #closed},\n * because it has already been unsubscribed, then whatever finalizer is passed to it\n * will automatically be executed (unless the finalizer itself is also a closed subscription).\n *\n * Closed Subscriptions cannot be added as finalizers to any subscription. Adding a closed\n * subscription to a any subscription will result in no operation. (A noop).\n *\n * Adding a subscription to itself, or adding `null` or `undefined` will not perform any\n * operation at all. (A noop).\n *\n * `Subscription` instances that are added to this instance will automatically remove themselves\n * if they are unsubscribed. Functions and {@link Unsubscribable} objects that you wish to remove\n * will need to be removed manually with {@link #remove}\n *\n * @param teardown The finalization logic to add to this subscription.\n */\n add(teardown: TeardownLogic): void {\n // Only add the finalizer if it's not undefined\n // and don't add a subscription to itself.\n if (teardown && teardown !== this) {\n if (this.closed) {\n // If this subscription is already closed,\n // execute whatever finalizer is handed to it automatically.\n execFinalizer(teardown);\n } else {\n if (teardown instanceof Subscription) {\n // We don't add closed subscriptions, and we don't add the same subscription\n // twice. Subscription unsubscribe is idempotent.\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._finalizers = this._finalizers ?? []).push(teardown);\n }\n }\n }\n\n /**\n * Checks to see if a this subscription already has a particular parent.\n * This will signal that this subscription has already been added to the parent in question.\n * @param parent the parent to check for\n */\n private _hasParent(parent: Subscription) {\n const { _parentage } = this;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n }\n\n /**\n * Adds a parent to this subscription so it can be removed from the parent if it\n * unsubscribes on it's own.\n *\n * NOTE: THIS ASSUMES THAT {@link _hasParent} HAS ALREADY BEEN CHECKED.\n * @param parent The parent subscription to add\n */\n private _addParent(parent: Subscription) {\n const { _parentage } = this;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n }\n\n /**\n * Called on a child when it is removed via {@link #remove}.\n * @param parent The parent to remove\n */\n private _removeParent(parent: Subscription) {\n const { _parentage } = this;\n if (_parentage === parent) {\n this._parentage = null;\n } else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n }\n\n /**\n * Removes a finalizer from this subscription that was previously added with the {@link #add} method.\n *\n * Note that `Subscription` instances, when unsubscribed, will automatically remove themselves\n * from every other `Subscription` they have been added to. This means that using the `remove` method\n * is not a common thing and should be used thoughtfully.\n *\n * If you add the same finalizer instance of a function or an unsubscribable object to a `Subscription` instance\n * more than once, you will need to call `remove` the same number of times to remove all instances.\n *\n * All finalizer instances are removed to free up memory upon unsubscription.\n *\n * @param teardown The finalizer to remove from this subscription\n */\n remove(teardown: Exclude): void {\n const { _finalizers } = this;\n _finalizers && arrRemove(_finalizers, teardown);\n\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n }\n}\n\nexport const EMPTY_SUBSCRIPTION = Subscription.EMPTY;\n\nexport function isSubscription(value: any): value is Subscription {\n return (\n value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe))\n );\n}\n\nfunction execFinalizer(finalizer: Unsubscribable | (() => void)) {\n if (isFunction(finalizer)) {\n finalizer();\n } else {\n finalizer.unsubscribe();\n }\n}\n", "import { Subscriber } from './Subscriber';\nimport { ObservableNotification } from './types';\n\n/**\n * The {@link GlobalConfig} object for RxJS. It is used to configure things\n * like how to react on unhandled errors.\n */\nexport const config: GlobalConfig = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n\n/**\n * The global configuration object for RxJS, used to configure things\n * like how to react on unhandled errors. Accessible via {@link config}\n * object.\n */\nexport interface GlobalConfig {\n /**\n * A registration point for unhandled errors from RxJS. These are errors that\n * cannot were not handled by consuming code in the usual subscription path. For\n * example, if you have this configured, and you subscribe to an observable without\n * providing an error handler, errors from that subscription will end up here. This\n * will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onUnhandledError: ((err: any) => void) | null;\n\n /**\n * A registration point for notifications that cannot be sent to subscribers because they\n * have completed, errored or have been explicitly unsubscribed. By default, next, complete\n * and error notifications sent to stopped subscribers are noops. However, sometimes callers\n * might want a different behavior. For example, with sources that attempt to report errors\n * to stopped subscribers, a caller can configure RxJS to throw an unhandled error instead.\n * This will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onStoppedNotification: ((notification: ObservableNotification, subscriber: Subscriber) => void) | null;\n\n /**\n * The promise constructor used by default for {@link Observable#toPromise toPromise} and {@link Observable#forEach forEach}\n * methods.\n *\n * @deprecated As of version 8, RxJS will no longer support this sort of injection of a\n * Promise constructor. If you need a Promise implementation other than native promises,\n * please polyfill/patch Promise as you see appropriate. Will be removed in v8.\n */\n Promise?: PromiseConstructorLike;\n\n /**\n * If true, turns on synchronous error rethrowing, which is a deprecated behavior\n * in v6 and higher. This behavior enables bad patterns like wrapping a subscribe\n * call in a try/catch block. It also enables producer interference, a nasty bug\n * where a multicast can be broken for all observers by a downstream consumer with\n * an unhandled error. DO NOT USE THIS FLAG UNLESS IT'S NEEDED TO BUY TIME\n * FOR MIGRATION REASONS.\n *\n * @deprecated As of version 8, RxJS will no longer support synchronous throwing\n * of unhandled errors. All errors will be thrown on a separate call stack to prevent bad\n * behaviors described above. Will be removed in v8.\n */\n useDeprecatedSynchronousErrorHandling: boolean;\n\n /**\n * If true, enables an as-of-yet undocumented feature from v5: The ability to access\n * `unsubscribe()` via `this` context in `next` functions created in observers passed\n * to `subscribe`.\n *\n * This is being removed because the performance was severely problematic, and it could also cause\n * issues when types other than POJOs are passed to subscribe as subscribers, as they will likely have\n * their `this` context overwritten.\n *\n * @deprecated As of version 8, RxJS will no longer support altering the\n * context of next functions provided as part of an observer to Subscribe. Instead,\n * you will have access to a subscription or a signal or token that will allow you to do things like\n * unsubscribe and test closed status. Will be removed in v8.\n */\n useDeprecatedNextContext: boolean;\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetTimeoutFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearTimeoutFunction = (handle: TimerHandle) => void;\n\ninterface TimeoutProvider {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n delegate:\n | {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n }\n | undefined;\n}\n\nexport const timeoutProvider: TimeoutProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setTimeout(handler: () => void, timeout?: number, ...args) {\n const { delegate } = timeoutProvider;\n if (delegate?.setTimeout) {\n return delegate.setTimeout(handler, timeout, ...args);\n }\n return setTimeout(handler, timeout, ...args);\n },\n clearTimeout(handle) {\n const { delegate } = timeoutProvider;\n return (delegate?.clearTimeout || clearTimeout)(handle as any);\n },\n delegate: undefined,\n};\n", "import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\n\n/**\n * Handles an error on another job either with the user-configured {@link onUnhandledError},\n * or by throwing it on that new job so it can be picked up by `window.onerror`, `process.on('error')`, etc.\n *\n * This should be called whenever there is an error that is out-of-band with the subscription\n * or when an error hits a terminal boundary of the subscription and no error handler was provided.\n *\n * @param err the error to report\n */\nexport function reportUnhandledError(err: any) {\n timeoutProvider.setTimeout(() => {\n const { onUnhandledError } = config;\n if (onUnhandledError) {\n // Execute the user-configured error handler.\n onUnhandledError(err);\n } else {\n // Throw so it is picked up by the runtime's uncaught error mechanism.\n throw err;\n }\n });\n}\n", "/* tslint:disable:no-empty */\nexport function noop() { }\n", "import { CompleteNotification, NextNotification, ErrorNotification } from './types';\n\n/**\n * A completion object optimized for memory use and created to be the\n * same \"shape\" as other notifications in v8.\n * @internal\n */\nexport const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined) as CompleteNotification)();\n\n/**\n * Internal use only. Creates an optimized error notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function errorNotification(error: any): ErrorNotification {\n return createNotification('E', undefined, error) as any;\n}\n\n/**\n * Internal use only. Creates an optimized next notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function nextNotification(value: T) {\n return createNotification('N', value, undefined) as NextNotification;\n}\n\n/**\n * Ensures that all notifications created internally have the same \"shape\" in v8.\n *\n * TODO: This is only exported to support a crazy legacy test in `groupBy`.\n * @internal\n */\nexport function createNotification(kind: 'N' | 'E' | 'C', value: any, error: any) {\n return {\n kind,\n value,\n error,\n };\n}\n", "import { config } from '../config';\n\nlet context: { errorThrown: boolean; error: any } | null = null;\n\n/**\n * Handles dealing with errors for super-gross mode. Creates a context, in which\n * any synchronously thrown errors will be passed to {@link captureError}. Which\n * will record the error such that it will be rethrown after the call back is complete.\n * TODO: Remove in v8\n * @param cb An immediately executed function.\n */\nexport function errorContext(cb: () => void) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n const isRoot = !context;\n if (isRoot) {\n context = { errorThrown: false, error: null };\n }\n cb();\n if (isRoot) {\n const { errorThrown, error } = context!;\n context = null;\n if (errorThrown) {\n throw error;\n }\n }\n } else {\n // This is the general non-deprecated path for everyone that\n // isn't crazy enough to use super-gross mode (useDeprecatedSynchronousErrorHandling)\n cb();\n }\n}\n\n/**\n * Captures errors only in super-gross mode.\n * @param err the error to capture\n */\nexport function captureError(err: any) {\n if (config.useDeprecatedSynchronousErrorHandling && context) {\n context.errorThrown = true;\n context.error = err;\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { Observer, ObservableNotification } from './types';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nimport { captureError } from './util/errorContext';\n\n/**\n * Implements the {@link Observer} interface and extends the\n * {@link Subscription} class. While the {@link Observer} is the public API for\n * consuming the values of an {@link Observable}, all Observers get converted to\n * a Subscriber, in order to provide Subscription-like capabilities such as\n * `unsubscribe`. Subscriber is a common type in RxJS, and crucial for\n * implementing operators, but it is rarely used as a public API.\n */\nexport class Subscriber extends Subscription implements Observer {\n /**\n * A static factory for a Subscriber, given a (potentially partial) definition\n * of an Observer.\n * @param next The `next` callback of an Observer.\n * @param error The `error` callback of an\n * Observer.\n * @param complete The `complete` callback of an\n * Observer.\n * @return A Subscriber wrapping the (partially defined)\n * Observer represented by the given arguments.\n * @deprecated Do not use. Will be removed in v8. There is no replacement for this\n * method, and there is no reason to be creating instances of `Subscriber` directly.\n * If you have a specific use case, please file an issue.\n */\n static create(next?: (x?: T) => void, error?: (e?: any) => void, complete?: () => void): Subscriber {\n return new SafeSubscriber(next, error, complete);\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected isStopped: boolean = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected destination: Subscriber | Observer; // this `any` is the escape hatch to erase extra type param (e.g. R)\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * There is no reason to directly create an instance of Subscriber. This type is exported for typings reasons.\n */\n constructor(destination?: Subscriber | Observer) {\n super();\n if (destination) {\n this.destination = destination;\n // Automatically chain subscriptions together here.\n // if destination is a Subscription, then it is a Subscriber.\n if (isSubscription(destination)) {\n destination.add(this);\n }\n } else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `next` from\n * the Observable, with a value. The Observable may call this method 0 or more\n * times.\n * @param value The `next` value.\n */\n next(value: T): void {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n } else {\n this._next(value!);\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `error` from\n * the Observable, with an attached `Error`. Notifies the Observer that\n * the Observable has experienced an error condition.\n * @param err The `error` exception.\n */\n error(err?: any): void {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n } else {\n this.isStopped = true;\n this._error(err);\n }\n }\n\n /**\n * The {@link Observer} callback to receive a valueless notification of type\n * `complete` from the Observable. Notifies the Observer that the Observable\n * has finished sending push-based notifications.\n */\n complete(): void {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n } else {\n this.isStopped = true;\n this._complete();\n }\n }\n\n unsubscribe(): void {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n this.destination = null!;\n }\n }\n\n protected _next(value: T): void {\n this.destination.next(value);\n }\n\n protected _error(err: any): void {\n try {\n this.destination.error(err);\n } finally {\n this.unsubscribe();\n }\n }\n\n protected _complete(): void {\n try {\n this.destination.complete();\n } finally {\n this.unsubscribe();\n }\n }\n}\n\n/**\n * This bind is captured here because we want to be able to have\n * compatibility with monoid libraries that tend to use a method named\n * `bind`. In particular, a library called Monio requires this.\n */\nconst _bind = Function.prototype.bind;\n\nfunction bind any>(fn: Fn, thisArg: any): Fn {\n return _bind.call(fn, thisArg);\n}\n\n/**\n * Internal optimization only, DO NOT EXPOSE.\n * @internal\n */\nclass ConsumerObserver implements Observer {\n constructor(private partialObserver: Partial>) {}\n\n next(value: T): void {\n const { partialObserver } = this;\n if (partialObserver.next) {\n try {\n partialObserver.next(value);\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n\n error(err: any): void {\n const { partialObserver } = this;\n if (partialObserver.error) {\n try {\n partialObserver.error(err);\n } catch (error) {\n handleUnhandledError(error);\n }\n } else {\n handleUnhandledError(err);\n }\n }\n\n complete(): void {\n const { partialObserver } = this;\n if (partialObserver.complete) {\n try {\n partialObserver.complete();\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n}\n\nexport class SafeSubscriber extends Subscriber {\n constructor(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((e?: any) => void) | null,\n complete?: (() => void) | null\n ) {\n super();\n\n let partialObserver: Partial>;\n if (isFunction(observerOrNext) || !observerOrNext) {\n // The first argument is a function, not an observer. The next\n // two arguments *could* be observers, or they could be empty.\n partialObserver = {\n next: (observerOrNext ?? undefined) as ((value: T) => void) | undefined,\n error: error ?? undefined,\n complete: complete ?? undefined,\n };\n } else {\n // The first argument is a partial observer.\n let context: any;\n if (this && config.useDeprecatedNextContext) {\n // This is a deprecated path that made `this.unsubscribe()` available in\n // next handler functions passed to subscribe. This only exists behind a flag\n // now, as it is *very* slow.\n context = Object.create(observerOrNext);\n context.unsubscribe = () => this.unsubscribe();\n partialObserver = {\n next: observerOrNext.next && bind(observerOrNext.next, context),\n error: observerOrNext.error && bind(observerOrNext.error, context),\n complete: observerOrNext.complete && bind(observerOrNext.complete, context),\n };\n } else {\n // The \"normal\" path. Just use the partial observer directly.\n partialObserver = observerOrNext;\n }\n }\n\n // Wrap the partial observer to ensure it's a full observer, and\n // make sure proper error handling is accounted for.\n this.destination = new ConsumerObserver(partialObserver);\n }\n}\n\nfunction handleUnhandledError(error: any) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n captureError(error);\n } else {\n // Ideal path, we report this as an unhandled error,\n // which is thrown on a new call stack.\n reportUnhandledError(error);\n }\n}\n\n/**\n * An error handler used when no error handler was supplied\n * to the SafeSubscriber -- meaning no error handler was supplied\n * do the `subscribe` call on our observable.\n * @param err The error to handle\n */\nfunction defaultErrorHandler(err: any) {\n throw err;\n}\n\n/**\n * A handler for notifications that cannot be sent to a stopped subscriber.\n * @param notification The notification being sent.\n * @param subscriber The stopped subscriber.\n */\nfunction handleStoppedNotification(notification: ObservableNotification, subscriber: Subscriber) {\n const { onStoppedNotification } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\n\n/**\n * The observer used as a stub for subscriptions where the user did not\n * pass any arguments to `subscribe`. Comes with the default error handling\n * behavior.\n */\nexport const EMPTY_OBSERVER: Readonly> & { closed: true } = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n", "/**\n * Symbol.observable or a string \"@@observable\". Used for interop\n *\n * @deprecated We will no longer be exporting this symbol in upcoming versions of RxJS.\n * Instead polyfill and use Symbol.observable directly *or* use https://www.npmjs.com/package/symbol-observable\n */\nexport const observable: string | symbol = (() => (typeof Symbol === 'function' && Symbol.observable) || '@@observable')();\n", "/**\n * This function takes one parameter and just returns it. Simply put,\n * this is like `(x: T): T => x`.\n *\n * ## Examples\n *\n * This is useful in some cases when using things like `mergeMap`\n *\n * ```ts\n * import { interval, take, map, range, mergeMap, identity } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(5));\n *\n * const result$ = source$.pipe(\n * map(i => range(i)),\n * mergeMap(identity) // same as mergeMap(x => x)\n * );\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * Or when you want to selectively apply an operator\n *\n * ```ts\n * import { interval, take, identity } from 'rxjs';\n *\n * const shouldLimit = () => Math.random() < 0.5;\n *\n * const source$ = interval(1000);\n *\n * const result$ = source$.pipe(shouldLimit() ? take(5) : identity);\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * @param x Any value that is returned by this function\n * @returns The value passed as the first parameter to this function\n */\nexport function identity(x: T): T {\n return x;\n}\n", "import { identity } from './identity';\nimport { UnaryFunction } from '../types';\n\nexport function pipe(): typeof identity;\nexport function pipe(fn1: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction, fn3: UnaryFunction): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction,\n ...fns: UnaryFunction[]\n): UnaryFunction;\n\n/**\n * pipe() can be called on one or more functions, each of which can take one argument (\"UnaryFunction\")\n * and uses it to return a value.\n * It returns a function that takes one argument, passes it to the first UnaryFunction, and then\n * passes the result to the next one, passes that result to the next one, and so on. \n */\nexport function pipe(...fns: Array>): UnaryFunction {\n return pipeFromArray(fns);\n}\n\n/** @internal */\nexport function pipeFromArray(fns: Array>): UnaryFunction {\n if (fns.length === 0) {\n return identity as UnaryFunction;\n }\n\n if (fns.length === 1) {\n return fns[0];\n }\n\n return function piped(input: T): R {\n return fns.reduce((prev: any, fn: UnaryFunction) => fn(prev), input as any);\n };\n}\n", "import { Operator } from './Operator';\nimport { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription, Subscription } from './Subscription';\nimport { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A representation of any set of values over any amount of time. This is the most basic building block\n * of RxJS.\n */\nexport class Observable implements Subscribable {\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n source: Observable | undefined;\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n operator: Operator | undefined;\n\n /**\n * @param subscribe The function that is called when the Observable is\n * initially subscribed to. This function is given a Subscriber, to which new values\n * can be `next`ed, or an `error` method can be called to raise an error, or\n * `complete` can be called to notify of a successful completion.\n */\n constructor(subscribe?: (this: Observable, subscriber: Subscriber) => TeardownLogic) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n\n // HACK: Since TypeScript inherits static properties too, we have to\n // fight against TypeScript here so Subject can have a different static create signature\n /**\n * Creates a new Observable by calling the Observable constructor\n * @param subscribe the subscriber function to be passed to the Observable constructor\n * @return A new observable.\n * @deprecated Use `new Observable()` instead. Will be removed in v8.\n */\n static create: (...args: any[]) => any = (subscribe?: (subscriber: Subscriber) => TeardownLogic) => {\n return new Observable(subscribe);\n };\n\n /**\n * Creates a new Observable, with this Observable instance as the source, and the passed\n * operator defined as the new observable's operator.\n * @param operator the operator defining the operation to take on the observable\n * @return A new observable with the Operator applied.\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * If you have implemented an operator using `lift`, it is recommended that you create an\n * operator by simply returning `new Observable()` directly. See \"Creating new operators from\n * scratch\" section here: https://rxjs.dev/guide/operators\n */\n lift(operator?: Operator): Observable {\n const observable = new Observable();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n\n subscribe(observerOrNext?: Partial> | ((value: T) => void)): Subscription;\n /** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */\n subscribe(next?: ((value: T) => void) | null, error?: ((error: any) => void) | null, complete?: (() => void) | null): Subscription;\n /**\n * Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.\n *\n * Use it when you have all these Observables, but still nothing is happening.\n *\n * `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It\n * might be for example a function that you passed to Observable's constructor, but most of the time it is\n * a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means\n * that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often\n * the thought.\n *\n * Apart from starting the execution of an Observable, this method allows you to listen for values\n * that an Observable emits, as well as for when it completes or errors. You can achieve this in two\n * of the following ways.\n *\n * The first way is creating an object that implements {@link Observer} interface. It should have methods\n * defined by that interface, but note that it should be just a regular JavaScript object, which you can create\n * yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do\n * not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also\n * that your object does not have to implement all methods. If you find yourself creating a method that doesn't\n * do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,\n * it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,\n * use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or\n * `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide\n * an `error` method to avoid missing thrown errors.\n *\n * The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.\n * This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent\n * of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,\n * if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,\n * since `subscribe` recognizes these functions by where they were placed in function call. When it comes\n * to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.\n *\n * You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events\n * and you also handled emissions internally by using operators (e.g. using `tap`).\n *\n * Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.\n * This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean\n * up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback\n * provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.\n *\n * Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.\n * It is an Observable itself that decides when these functions will be called. For example {@link of}\n * by default emits all its values synchronously. Always check documentation for how given Observable\n * will behave when subscribed and if its default behavior can be modified with a `scheduler`.\n *\n * #### Examples\n *\n * Subscribe with an {@link guide/observer Observer}\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * const sumObserver = {\n * sum: 0,\n * next(value) {\n * console.log('Adding: ' + value);\n * this.sum = this.sum + value;\n * },\n * error() {\n * // We actually could just remove this method,\n * // since we do not really care about errors right now.\n * },\n * complete() {\n * console.log('Sum equals: ' + this.sum);\n * }\n * };\n *\n * of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.\n * .subscribe(sumObserver);\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Subscribe with functions ({@link deprecations/subscribe-arguments deprecated})\n *\n * ```ts\n * import { of } from 'rxjs'\n *\n * let sum = 0;\n *\n * of(1, 2, 3).subscribe(\n * value => {\n * console.log('Adding: ' + value);\n * sum = sum + value;\n * },\n * undefined,\n * () => console.log('Sum equals: ' + sum)\n * );\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Cancel a subscription\n *\n * ```ts\n * import { interval } from 'rxjs';\n *\n * const subscription = interval(1000).subscribe({\n * next(num) {\n * console.log(num)\n * },\n * complete() {\n * // Will not be called, even when cancelling subscription.\n * console.log('completed!');\n * }\n * });\n *\n * setTimeout(() => {\n * subscription.unsubscribe();\n * console.log('unsubscribed!');\n * }, 2500);\n *\n * // Logs:\n * // 0 after 1s\n * // 1 after 2s\n * // 'unsubscribed!' after 2.5s\n * ```\n *\n * @param observerOrNext Either an {@link Observer} with some or all callback methods,\n * or the `next` handler that is called for each value emitted from the subscribed Observable.\n * @param error A handler for a terminal event resulting from an error. If no error handler is provided,\n * the error will be thrown asynchronously as unhandled.\n * @param complete A handler for a terminal event resulting from successful completion.\n * @return A subscription reference to the registered handlers.\n */\n subscribe(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((error: any) => void) | null,\n complete?: (() => void) | null\n ): Subscription {\n const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n\n errorContext(() => {\n const { operator, source } = this;\n subscriber.add(\n operator\n ? // We're dealing with a subscription in the\n // operator chain to one of our lifted operators.\n operator.call(subscriber, source)\n : source\n ? // If `source` has a value, but `operator` does not, something that\n // had intimate knowledge of our API, like our `Subject`, must have\n // set it. We're going to just call `_subscribe` directly.\n this._subscribe(subscriber)\n : // In all other cases, we're likely wrapping a user-provided initializer\n // function, so we need to catch errors and handle them appropriately.\n this._trySubscribe(subscriber)\n );\n });\n\n return subscriber;\n }\n\n /** @internal */\n protected _trySubscribe(sink: Subscriber): TeardownLogic {\n try {\n return this._subscribe(sink);\n } catch (err) {\n // We don't need to return anything in this case,\n // because it's just going to try to `add()` to a subscription\n // above.\n sink.error(err);\n }\n }\n\n /**\n * Used as a NON-CANCELLABLE means of subscribing to an observable, for use with\n * APIs that expect promises, like `async/await`. You cannot unsubscribe from this.\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * #### Example\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(4));\n *\n * async function getTotal() {\n * let total = 0;\n *\n * await source$.forEach(value => {\n * total += value;\n * console.log('observable -> ' + value);\n * });\n *\n * return total;\n * }\n *\n * getTotal().then(\n * total => console.log('Total: ' + total)\n * );\n *\n * // Expected:\n * // 'observable -> 0'\n * // 'observable -> 1'\n * // 'observable -> 2'\n * // 'observable -> 3'\n * // 'Total: 6'\n * ```\n *\n * @param next A handler for each value emitted by the observable.\n * @return A promise that either resolves on observable completion or\n * rejects with the handled error.\n */\n forEach(next: (value: T) => void): Promise;\n\n /**\n * @param next a handler for each value emitted by the observable\n * @param promiseCtor a constructor function used to instantiate the Promise\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n * @deprecated Passing a Promise constructor will no longer be available\n * in upcoming versions of RxJS. This is because it adds weight to the library, for very\n * little benefit. If you need this functionality, it is recommended that you either\n * polyfill Promise, or you create an adapter to convert the returned native promise\n * to whatever promise implementation you wanted. Will be removed in v8.\n */\n forEach(next: (value: T) => void, promiseCtor: PromiseConstructorLike): Promise;\n\n forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n const subscriber = new SafeSubscriber({\n next: (value) => {\n try {\n next(value);\n } catch (err) {\n reject(err);\n subscriber.unsubscribe();\n }\n },\n error: reject,\n complete: resolve,\n });\n this.subscribe(subscriber);\n }) as Promise;\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): TeardownLogic {\n return this.source?.subscribe(subscriber);\n }\n\n /**\n * An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable\n * @return This instance of the observable.\n */\n [Symbol_observable]() {\n return this;\n }\n\n /* tslint:disable:max-line-length */\n pipe(): Observable;\n pipe(op1: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction,\n ...operations: OperatorFunction[]\n ): Observable;\n /* tslint:enable:max-line-length */\n\n /**\n * Used to stitch together functional operators into a chain.\n *\n * ## Example\n *\n * ```ts\n * import { interval, filter, map, scan } from 'rxjs';\n *\n * interval(1000)\n * .pipe(\n * filter(x => x % 2 === 0),\n * map(x => x + x),\n * scan((acc, x) => acc + x)\n * )\n * .subscribe(x => console.log(x));\n * ```\n *\n * @return The Observable result of all the operators having been called\n * in the order they were passed in.\n */\n pipe(...operations: OperatorFunction[]): Observable {\n return pipeFromArray(operations)(this);\n }\n\n /* tslint:disable:max-line-length */\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: typeof Promise): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: PromiseConstructorLike): Promise;\n /* tslint:enable:max-line-length */\n\n /**\n * Subscribe to this Observable and get a Promise resolving on\n * `complete` with the last emission (if any).\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * @param [promiseCtor] a constructor function used to instantiate\n * the Promise\n * @return A Promise that resolves with the last value emit, or\n * rejects on an error. If there were no emissions, Promise\n * resolves with undefined.\n * @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise\n */\n toPromise(promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n let value: T | undefined;\n this.subscribe(\n (x: T) => (value = x),\n (err: any) => reject(err),\n () => resolve(value)\n );\n }) as Promise;\n }\n}\n\n/**\n * Decides between a passed promise constructor from consuming code,\n * A default configured promise constructor, and the native promise\n * constructor and returns it. If nothing can be found, it will throw\n * an error.\n * @param promiseCtor The optional promise constructor to passed by consuming code\n */\nfunction getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) {\n return promiseCtor ?? config.Promise ?? Promise;\n}\n\nfunction isObserver(value: any): value is Observer {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\n\nfunction isSubscriber(value: any): value is Subscriber {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n", "import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { OperatorFunction } from '../types';\nimport { isFunction } from './isFunction';\n\n/**\n * Used to determine if an object is an Observable with a lift function.\n */\nexport function hasLift(source: any): source is { lift: InstanceType['lift'] } {\n return isFunction(source?.lift);\n}\n\n/**\n * Creates an `OperatorFunction`. Used to define operators throughout the library in a concise way.\n * @param init The logic to connect the liftedSource to the subscriber at the moment of subscription.\n */\nexport function operate(\n init: (liftedSource: Observable, subscriber: Subscriber) => (() => void) | void\n): OperatorFunction {\n return (source: Observable) => {\n if (hasLift(source)) {\n return source.lift(function (this: Subscriber, liftedSource: Observable) {\n try {\n return init(liftedSource, this);\n } catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n", "import { Subscriber } from '../Subscriber';\n\n/**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional teardown logic here. This will only be called on teardown if the\n * subscriber itself is not already closed. This is called after all other teardown logic is executed.\n */\nexport function createOperatorSubscriber(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n onFinalize?: () => void\n): Subscriber {\n return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);\n}\n\n/**\n * A generic helper for allowing operators to be created with a Subscriber and\n * use closures to capture necessary state from the operator function itself.\n */\nexport class OperatorSubscriber extends Subscriber {\n /**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional finalization logic here. This will only be called on finalization if the\n * subscriber itself is not already closed. This is called after all other finalization logic is executed.\n * @param shouldUnsubscribe An optional check to see if an unsubscribe call should truly unsubscribe.\n * NOTE: This currently **ONLY** exists to support the strange behavior of {@link groupBy}, where unsubscription\n * to the resulting observable does not actually disconnect from the source if there are active subscriptions\n * to any grouped observable. (DO NOT EXPOSE OR USE EXTERNALLY!!!)\n */\n constructor(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n private onFinalize?: () => void,\n private shouldUnsubscribe?: () => boolean\n ) {\n // It's important - for performance reasons - that all of this class's\n // members are initialized and that they are always initialized in the same\n // order. This will ensure that all OperatorSubscriber instances have the\n // same hidden class in V8. This, in turn, will help keep the number of\n // hidden classes involved in property accesses within the base class as\n // low as possible. If the number of hidden classes involved exceeds four,\n // the property accesses will become megamorphic and performance penalties\n // will be incurred - i.e. inline caches won't be used.\n //\n // The reasons for ensuring all instances have the same hidden class are\n // further discussed in this blog post from Benedikt Meurer:\n // https://benediktmeurer.de/2018/03/23/impact-of-polymorphism-on-component-based-frameworks-like-react/\n super(destination);\n this._next = onNext\n ? function (this: OperatorSubscriber, value: T) {\n try {\n onNext(value);\n } catch (err) {\n destination.error(err);\n }\n }\n : super._next;\n this._error = onError\n ? function (this: OperatorSubscriber, err: any) {\n try {\n onError(err);\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._error;\n this._complete = onComplete\n ? function (this: OperatorSubscriber) {\n try {\n onComplete();\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._complete;\n }\n\n unsubscribe() {\n if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {\n const { closed } = this;\n super.unsubscribe();\n // Execute additional teardown if we have any and we didn't already do so.\n !closed && this.onFinalize?.();\n }\n }\n}\n", "import { Subscription } from '../Subscription';\n\ninterface AnimationFrameProvider {\n schedule(callback: FrameRequestCallback): Subscription;\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n delegate:\n | {\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n }\n | undefined;\n}\n\nexport const animationFrameProvider: AnimationFrameProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n schedule(callback) {\n let request = requestAnimationFrame;\n let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame;\n const { delegate } = animationFrameProvider;\n if (delegate) {\n request = delegate.requestAnimationFrame;\n cancel = delegate.cancelAnimationFrame;\n }\n const handle = request((timestamp) => {\n // Clear the cancel function. The request has been fulfilled, so\n // attempting to cancel the request upon unsubscription would be\n // pointless.\n cancel = undefined;\n callback(timestamp);\n });\n return new Subscription(() => cancel?.(handle));\n },\n requestAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args);\n },\n cancelAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args);\n },\n delegate: undefined,\n};\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface ObjectUnsubscribedError extends Error {}\n\nexport interface ObjectUnsubscribedErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (): ObjectUnsubscribedError;\n}\n\n/**\n * An error thrown when an action is invalid because the object has been\n * unsubscribed.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n *\n * @class ObjectUnsubscribedError\n */\nexport const ObjectUnsubscribedError: ObjectUnsubscribedErrorCtor = createErrorClass(\n (_super) =>\n function ObjectUnsubscribedErrorImpl(this: any) {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n }\n);\n", "import { Operator } from './Operator';\nimport { Observable } from './Observable';\nimport { Subscriber } from './Subscriber';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { Observer, SubscriptionLike, TeardownLogic } from './types';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A Subject is a special type of Observable that allows values to be\n * multicasted to many Observers. Subjects are like EventEmitters.\n *\n * Every Subject is an Observable and an Observer. You can subscribe to a\n * Subject, and you can call next to feed values as well as error and complete.\n */\nexport class Subject extends Observable implements SubscriptionLike {\n closed = false;\n\n private currentObservers: Observer[] | null = null;\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n observers: Observer[] = [];\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n isStopped = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n hasError = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n thrownError: any = null;\n\n /**\n * Creates a \"subject\" by basically gluing an observer to an observable.\n *\n * @deprecated Recommended you do not use. Will be removed at some point in the future. Plans for replacement still under discussion.\n */\n static create: (...args: any[]) => any = (destination: Observer, source: Observable): AnonymousSubject => {\n return new AnonymousSubject(destination, source);\n };\n\n constructor() {\n // NOTE: This must be here to obscure Observable's constructor.\n super();\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n lift(operator: Operator): Observable {\n const subject = new AnonymousSubject(this, this);\n subject.operator = operator as any;\n return subject as any;\n }\n\n /** @internal */\n protected _throwIfClosed() {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n }\n\n next(value: T) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n if (!this.currentObservers) {\n this.currentObservers = Array.from(this.observers);\n }\n for (const observer of this.currentObservers) {\n observer.next(value);\n }\n }\n });\n }\n\n error(err: any) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.hasError = this.isStopped = true;\n this.thrownError = err;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.error(err);\n }\n }\n });\n }\n\n complete() {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.isStopped = true;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.complete();\n }\n }\n });\n }\n\n unsubscribe() {\n this.isStopped = this.closed = true;\n this.observers = this.currentObservers = null!;\n }\n\n get observed() {\n return this.observers?.length > 0;\n }\n\n /** @internal */\n protected _trySubscribe(subscriber: Subscriber): TeardownLogic {\n this._throwIfClosed();\n return super._trySubscribe(subscriber);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n }\n\n /** @internal */\n protected _innerSubscribe(subscriber: Subscriber) {\n const { hasError, isStopped, observers } = this;\n if (hasError || isStopped) {\n return EMPTY_SUBSCRIPTION;\n }\n this.currentObservers = null;\n observers.push(subscriber);\n return new Subscription(() => {\n this.currentObservers = null;\n arrRemove(observers, subscriber);\n });\n }\n\n /** @internal */\n protected _checkFinalizedStatuses(subscriber: Subscriber) {\n const { hasError, thrownError, isStopped } = this;\n if (hasError) {\n subscriber.error(thrownError);\n } else if (isStopped) {\n subscriber.complete();\n }\n }\n\n /**\n * Creates a new Observable with this Subject as the source. You can do this\n * to create custom Observer-side logic of the Subject and conceal it from\n * code that uses the Observable.\n * @return Observable that this Subject casts to.\n */\n asObservable(): Observable {\n const observable: any = new Observable();\n observable.source = this;\n return observable;\n }\n}\n\nexport class AnonymousSubject extends Subject {\n constructor(\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n public destination?: Observer,\n source?: Observable\n ) {\n super();\n this.source = source;\n }\n\n next(value: T) {\n this.destination?.next?.(value);\n }\n\n error(err: any) {\n this.destination?.error?.(err);\n }\n\n complete() {\n this.destination?.complete?.();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n return this.source?.subscribe(subscriber) ?? EMPTY_SUBSCRIPTION;\n }\n}\n", "import { Subject } from './Subject';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\n\n/**\n * A variant of Subject that requires an initial value and emits its current\n * value whenever it is subscribed to.\n */\nexport class BehaviorSubject extends Subject {\n constructor(private _value: T) {\n super();\n }\n\n get value(): T {\n return this.getValue();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n const subscription = super._subscribe(subscriber);\n !subscription.closed && subscriber.next(this._value);\n return subscription;\n }\n\n getValue(): T {\n const { hasError, thrownError, _value } = this;\n if (hasError) {\n throw thrownError;\n }\n this._throwIfClosed();\n return _value;\n }\n\n next(value: T): void {\n super.next((this._value = value));\n }\n}\n", "import { TimestampProvider } from '../types';\n\ninterface DateTimestampProvider extends TimestampProvider {\n delegate: TimestampProvider | undefined;\n}\n\nexport const dateTimestampProvider: DateTimestampProvider = {\n now() {\n // Use the variable rather than `this` so that the function can be called\n // without being bound to the provider.\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n", "import { Subject } from './Subject';\nimport { TimestampProvider } from './types';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * A variant of {@link Subject} that \"replays\" old values to new subscribers by emitting them when they first subscribe.\n *\n * `ReplaySubject` has an internal buffer that will store a specified number of values that it has observed. Like `Subject`,\n * `ReplaySubject` \"observes\" values by having them passed to its `next` method. When it observes a value, it will store that\n * value for a time determined by the configuration of the `ReplaySubject`, as passed to its constructor.\n *\n * When a new subscriber subscribes to the `ReplaySubject` instance, it will synchronously emit all values in its buffer in\n * a First-In-First-Out (FIFO) manner. The `ReplaySubject` will also complete, if it has observed completion; and it will\n * error if it has observed an error.\n *\n * There are two main configuration items to be concerned with:\n *\n * 1. `bufferSize` - This will determine how many items are stored in the buffer, defaults to infinite.\n * 2. `windowTime` - The amount of time to hold a value in the buffer before removing it from the buffer.\n *\n * Both configurations may exist simultaneously. So if you would like to buffer a maximum of 3 values, as long as the values\n * are less than 2 seconds old, you could do so with a `new ReplaySubject(3, 2000)`.\n *\n * ### Differences with BehaviorSubject\n *\n * `BehaviorSubject` is similar to `new ReplaySubject(1)`, with a couple of exceptions:\n *\n * 1. `BehaviorSubject` comes \"primed\" with a single value upon construction.\n * 2. `ReplaySubject` will replay values, even after observing an error, where `BehaviorSubject` will not.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n * @see {@link shareReplay}\n */\nexport class ReplaySubject extends Subject {\n private _buffer: (T | number)[] = [];\n private _infiniteTimeWindow = true;\n\n /**\n * @param _bufferSize The size of the buffer to replay on subscription\n * @param _windowTime The amount of time the buffered items will stay buffered\n * @param _timestampProvider An object with a `now()` method that provides the current timestamp. This is used to\n * calculate the amount of time something has been buffered.\n */\n constructor(\n private _bufferSize = Infinity,\n private _windowTime = Infinity,\n private _timestampProvider: TimestampProvider = dateTimestampProvider\n ) {\n super();\n this._infiniteTimeWindow = _windowTime === Infinity;\n this._bufferSize = Math.max(1, _bufferSize);\n this._windowTime = Math.max(1, _windowTime);\n }\n\n next(value: T): void {\n const { isStopped, _buffer, _infiniteTimeWindow, _timestampProvider, _windowTime } = this;\n if (!isStopped) {\n _buffer.push(value);\n !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);\n }\n this._trimBuffer();\n super.next(value);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._trimBuffer();\n\n const subscription = this._innerSubscribe(subscriber);\n\n const { _infiniteTimeWindow, _buffer } = this;\n // We use a copy here, so reentrant code does not mutate our array while we're\n // emitting it to a new subscriber.\n const copy = _buffer.slice();\n for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i] as T);\n }\n\n this._checkFinalizedStatuses(subscriber);\n\n return subscription;\n }\n\n private _trimBuffer() {\n const { _bufferSize, _timestampProvider, _buffer, _infiniteTimeWindow } = this;\n // If we don't have an infinite buffer size, and we're over the length,\n // use splice to truncate the old buffer values off. Note that we have to\n // double the size for instances where we're not using an infinite time window\n // because we're storing the values and the timestamps in the same array.\n const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;\n _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);\n\n // Now, if we're not in an infinite time window, remove all values where the time is\n // older than what is allowed.\n if (!_infiniteTimeWindow) {\n const now = _timestampProvider.now();\n let last = 0;\n // Search the array for the first timestamp that isn't expired and\n // truncate the buffer up to that point.\n for (let i = 1; i < _buffer.length && (_buffer[i] as number) <= now; i += 2) {\n last = i;\n }\n last && _buffer.splice(0, last + 1);\n }\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Subscription } from '../Subscription';\nimport { SchedulerAction } from '../types';\n\n/**\n * A unit of work to be executed in a `scheduler`. An action is typically\n * created from within a {@link SchedulerLike} and an RxJS user does not need to concern\n * themselves about creating and manipulating an Action.\n *\n * ```ts\n * class Action extends Subscription {\n * new (scheduler: Scheduler, work: (state?: T) => void);\n * schedule(state?: T, delay: number = 0): Subscription;\n * }\n * ```\n */\nexport class Action extends Subscription {\n constructor(scheduler: Scheduler, work: (this: SchedulerAction, state?: T) => void) {\n super();\n }\n /**\n * Schedules this action on its parent {@link SchedulerLike} for execution. May be passed\n * some context object, `state`. May happen at some point in the future,\n * according to the `delay` parameter, if specified.\n * @param state Some contextual data that the `work` function uses when called by the\n * Scheduler.\n * @param delay Time to wait before executing the work, where the time unit is implicit\n * and defined by the Scheduler.\n * @return A subscription in order to be able to unsubscribe the scheduled work.\n */\n public schedule(state?: T, delay: number = 0): Subscription {\n return this;\n }\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetIntervalFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearIntervalFunction = (handle: TimerHandle) => void;\n\ninterface IntervalProvider {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n delegate:\n | {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n }\n | undefined;\n}\n\nexport const intervalProvider: IntervalProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setInterval(handler: () => void, timeout?: number, ...args) {\n const { delegate } = intervalProvider;\n if (delegate?.setInterval) {\n return delegate.setInterval(handler, timeout, ...args);\n }\n return setInterval(handler, timeout, ...args);\n },\n clearInterval(handle) {\n const { delegate } = intervalProvider;\n return (delegate?.clearInterval || clearInterval)(handle as any);\n },\n delegate: undefined,\n};\n", "import { Action } from './Action';\nimport { SchedulerAction } from '../types';\nimport { Subscription } from '../Subscription';\nimport { AsyncScheduler } from './AsyncScheduler';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncAction extends Action {\n public id: TimerHandle | undefined;\n public state?: T;\n // @ts-ignore: Property has no initializer and is not definitely assigned\n public delay: number;\n protected pending: boolean = false;\n\n constructor(protected scheduler: AsyncScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (this.closed) {\n return this;\n }\n\n // Always replace the current state with the new state.\n this.state = state;\n\n const id = this.id;\n const scheduler = this.scheduler;\n\n //\n // Important implementation note:\n //\n // Actions only execute once by default, unless rescheduled from within the\n // scheduled callback. This allows us to implement single and repeat\n // actions via the same code path, without adding API surface area, as well\n // as mimic traditional recursion but across asynchronous boundaries.\n //\n // However, JS runtimes and timers distinguish between intervals achieved by\n // serial `setTimeout` calls vs. a single `setInterval` call. An interval of\n // serial `setTimeout` calls can be individually delayed, which delays\n // scheduling the next `setTimeout`, and so on. `setInterval` attempts to\n // guarantee the interval callback will be invoked more precisely to the\n // interval period, regardless of load.\n //\n // Therefore, we use `setInterval` to schedule single and repeat actions.\n // If the action reschedules itself with the same delay, the interval is not\n // canceled. If the action doesn't reschedule, or reschedules with a\n // different delay, the interval will be canceled after scheduled callback\n // execution.\n //\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n\n // Set the pending flag indicating that this action has been scheduled, or\n // has recursively rescheduled itself.\n this.pending = true;\n\n this.delay = delay;\n // If this action has already an async Id, don't request a new one.\n this.id = this.id ?? this.requestAsyncId(scheduler, this.id, delay);\n\n return this;\n }\n\n protected requestAsyncId(scheduler: AsyncScheduler, _id?: TimerHandle, delay: number = 0): TimerHandle {\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n }\n\n protected recycleAsyncId(_scheduler: AsyncScheduler, id?: TimerHandle, delay: number | null = 0): TimerHandle | undefined {\n // If this action is rescheduled with the same delay time, don't clear the interval id.\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n // Otherwise, if the action's delay time is different from the current delay,\n // or the action has been rescheduled before it's executed, clear the interval id\n if (id != null) {\n intervalProvider.clearInterval(id);\n }\n\n return undefined;\n }\n\n /**\n * Immediately executes this action and the `work` it contains.\n */\n public execute(state: T, delay: number): any {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n\n this.pending = false;\n const error = this._execute(state, delay);\n if (error) {\n return error;\n } else if (this.pending === false && this.id != null) {\n // Dequeue if the action didn't reschedule itself. Don't call\n // unsubscribe(), because the action could reschedule later.\n // For example:\n // ```\n // scheduler.schedule(function doWork(counter) {\n // /* ... I'm a busy worker bee ... */\n // var originalAction = this;\n // /* wait 100ms before rescheduling the action */\n // setTimeout(function () {\n // originalAction.schedule(counter + 1);\n // }, 100);\n // }, 1000);\n // ```\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n }\n\n protected _execute(state: T, _delay: number): any {\n let errored: boolean = false;\n let errorValue: any;\n try {\n this.work(state);\n } catch (e) {\n errored = true;\n // HACK: Since code elsewhere is relying on the \"truthiness\" of the\n // return here, we can't have it return \"\" or 0 or false.\n // TODO: Clean this up when we refactor schedulers mid-version-8 or so.\n errorValue = e ? e : new Error('Scheduled action threw falsy error');\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n }\n\n unsubscribe() {\n if (!this.closed) {\n const { id, scheduler } = this;\n const { actions } = scheduler;\n\n this.work = this.state = this.scheduler = null!;\n this.pending = false;\n\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n\n this.delay = null!;\n super.unsubscribe();\n }\n }\n}\n", "import { Action } from './scheduler/Action';\nimport { Subscription } from './Subscription';\nimport { SchedulerLike, SchedulerAction } from './types';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * An execution context and a data structure to order tasks and schedule their\n * execution. Provides a notion of (potentially virtual) time, through the\n * `now()` getter method.\n *\n * Each unit of work in a Scheduler is called an `Action`.\n *\n * ```ts\n * class Scheduler {\n * now(): number;\n * schedule(work, delay?, state?): Subscription;\n * }\n * ```\n *\n * @deprecated Scheduler is an internal implementation detail of RxJS, and\n * should not be used directly. Rather, create your own class and implement\n * {@link SchedulerLike}. Will be made internal in v8.\n */\nexport class Scheduler implements SchedulerLike {\n public static now: () => number = dateTimestampProvider.now;\n\n constructor(private schedulerActionCtor: typeof Action, now: () => number = Scheduler.now) {\n this.now = now;\n }\n\n /**\n * A getter method that returns a number representing the current time\n * (at the time this function was called) according to the scheduler's own\n * internal clock.\n * @return A number that represents the current time. May or may not\n * have a relation to wall-clock time. May or may not refer to a time unit\n * (e.g. milliseconds).\n */\n public now: () => number;\n\n /**\n * Schedules a function, `work`, for execution. May happen at some point in\n * the future, according to the `delay` parameter, if specified. May be passed\n * some context object, `state`, which will be passed to the `work` function.\n *\n * The given arguments will be processed an stored as an Action object in a\n * queue of actions.\n *\n * @param work A function representing a task, or some unit of work to be\n * executed by the Scheduler.\n * @param delay Time to wait before executing the work, where the time unit is\n * implicit and defined by the Scheduler itself.\n * @param state Some contextual data that the `work` function uses when called\n * by the Scheduler.\n * @return A subscription in order to be able to unsubscribe the scheduled work.\n */\n public schedule(work: (this: SchedulerAction, state?: T) => void, delay: number = 0, state?: T): Subscription {\n return new this.schedulerActionCtor(this, work).schedule(state, delay);\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Action } from './Action';\nimport { AsyncAction } from './AsyncAction';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncScheduler extends Scheduler {\n public actions: Array> = [];\n /**\n * A flag to indicate whether the Scheduler is currently executing a batch of\n * queued actions.\n * @internal\n */\n public _active: boolean = false;\n /**\n * An internal ID used to track the latest asynchronous task such as those\n * coming from `setTimeout`, `setInterval`, `requestAnimationFrame`, and\n * others.\n * @internal\n */\n public _scheduled: TimerHandle | undefined;\n\n constructor(SchedulerAction: typeof Action, now: () => number = Scheduler.now) {\n super(SchedulerAction, now);\n }\n\n public flush(action: AsyncAction): void {\n const { actions } = this;\n\n if (this._active) {\n actions.push(action);\n return;\n }\n\n let error: any;\n this._active = true;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions.shift()!)); // exhaust the scheduler queue\n\n this._active = false;\n\n if (error) {\n while ((action = actions.shift()!)) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\n/**\n *\n * Async Scheduler\n *\n * Schedule task as if you used setTimeout(task, duration)\n *\n * `async` scheduler schedules tasks asynchronously, by putting them on the JavaScript\n * event loop queue. It is best used to delay tasks in time or to schedule tasks repeating\n * in intervals.\n *\n * If you just want to \"defer\" task, that is to perform it right after currently\n * executing synchronous code ends (commonly achieved by `setTimeout(deferredTask, 0)`),\n * better choice will be the {@link asapScheduler} scheduler.\n *\n * ## Examples\n * Use async scheduler to delay task\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * const task = () => console.log('it works!');\n *\n * asyncScheduler.schedule(task, 2000);\n *\n * // After 2 seconds logs:\n * // \"it works!\"\n * ```\n *\n * Use async scheduler to repeat task in intervals\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * function task(state) {\n * console.log(state);\n * this.schedule(state + 1, 1000); // `this` references currently executing Action,\n * // which we reschedule with new state and delay\n * }\n *\n * asyncScheduler.schedule(task, 3000, 0);\n *\n * // Logs:\n * // 0 after 3s\n * // 1 after 4s\n * // 2 after 5s\n * // 3 after 6s\n * ```\n */\n\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\n\n/**\n * @deprecated Renamed to {@link asyncScheduler}. Will be removed in v8.\n */\nexport const async = asyncScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { Subscription } from '../Subscription';\nimport { QueueScheduler } from './QueueScheduler';\nimport { SchedulerAction } from '../types';\nimport { TimerHandle } from './timerHandle';\n\nexport class QueueAction extends AsyncAction {\n constructor(protected scheduler: QueueScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (delay > 0) {\n return super.schedule(state, delay);\n }\n this.delay = delay;\n this.state = state;\n this.scheduler.flush(this);\n return this;\n }\n\n public execute(state: T, delay: number): any {\n return delay > 0 || this.closed ? super.execute(state, delay) : this._execute(state, delay);\n }\n\n protected requestAsyncId(scheduler: QueueScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n\n if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n\n // Otherwise flush the scheduler starting with this action.\n scheduler.flush(this);\n\n // HACK: In the past, this was returning `void`. However, `void` isn't a valid\n // `TimerHandle`, and generally the return value here isn't really used. So the\n // compromise is to return `0` which is both \"falsy\" and a valid `TimerHandle`,\n // as opposed to refactoring every other instanceo of `requestAsyncId`.\n return 0;\n }\n}\n", "import { AsyncScheduler } from './AsyncScheduler';\n\nexport class QueueScheduler extends AsyncScheduler {\n}\n", "import { QueueAction } from './QueueAction';\nimport { QueueScheduler } from './QueueScheduler';\n\n/**\n *\n * Queue Scheduler\n *\n * Put every next task on a queue, instead of executing it immediately\n *\n * `queue` scheduler, when used with delay, behaves the same as {@link asyncScheduler} scheduler.\n *\n * When used without delay, it schedules given task synchronously - executes it right when\n * it is scheduled. However when called recursively, that is when inside the scheduled task,\n * another task is scheduled with queue scheduler, instead of executing immediately as well,\n * that task will be put on a queue and wait for current one to finish.\n *\n * This means that when you execute task with `queue` scheduler, you are sure it will end\n * before any other task scheduled with that scheduler will start.\n *\n * ## Examples\n * Schedule recursively first, then do something\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(() => {\n * queueScheduler.schedule(() => console.log('second')); // will not happen now, but will be put on a queue\n *\n * console.log('first');\n * });\n *\n * // Logs:\n * // \"first\"\n * // \"second\"\n * ```\n *\n * Reschedule itself recursively\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(function(state) {\n * if (state !== 0) {\n * console.log('before', state);\n * this.schedule(state - 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * console.log('after', state);\n * }\n * }, 0, 3);\n *\n * // In scheduler that runs recursively, you would expect:\n * // \"before\", 3\n * // \"before\", 2\n * // \"before\", 1\n * // \"after\", 1\n * // \"after\", 2\n * // \"after\", 3\n *\n * // But with queue it logs:\n * // \"before\", 3\n * // \"after\", 3\n * // \"before\", 2\n * // \"after\", 2\n * // \"before\", 1\n * // \"after\", 1\n * ```\n */\n\nexport const queueScheduler = new QueueScheduler(QueueAction);\n\n/**\n * @deprecated Renamed to {@link queueScheduler}. Will be removed in v8.\n */\nexport const queue = queueScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\nimport { SchedulerAction } from '../types';\nimport { animationFrameProvider } from './animationFrameProvider';\nimport { TimerHandle } from './timerHandle';\n\nexport class AnimationFrameAction extends AsyncAction {\n constructor(protected scheduler: AnimationFrameScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n protected requestAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay is greater than 0, request as an async action.\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n // Push the action to the end of the scheduler queue.\n scheduler.actions.push(this);\n // If an animation frame has already been requested, don't request another\n // one. If an animation frame hasn't been requested yet, request one. Return\n // the current animation frame request id.\n return scheduler._scheduled || (scheduler._scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n }\n\n protected recycleAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n if (delay != null ? delay > 0 : this.delay > 0) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n // If the scheduler queue has no remaining actions with the same async id,\n // cancel the requested animation frame and set the scheduled flag to\n // undefined so the next AnimationFrameAction will request its own.\n const { actions } = scheduler;\n if (id != null && id === scheduler._scheduled && actions[actions.length - 1]?.id !== id) {\n animationFrameProvider.cancelAnimationFrame(id as number);\n scheduler._scheduled = undefined;\n }\n // Return undefined so the action knows to request a new async id if it's rescheduled.\n return undefined;\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\nexport class AnimationFrameScheduler extends AsyncScheduler {\n public flush(action?: AsyncAction): void {\n this._active = true;\n // The async id that effects a call to flush is stored in _scheduled.\n // Before executing an action, it's necessary to check the action's async\n // id to determine whether it's supposed to be executed in the current\n // flush.\n // Previous implementations of this method used a count to determine this,\n // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n // are removed from the actions array and that can shift actions that are\n // scheduled to be executed in a subsequent flush into positions at which\n // they are executed within the current flush.\n let flushId;\n if (action) {\n flushId = action.id;\n } else {\n flushId = this._scheduled;\n this._scheduled = undefined;\n }\n\n const { actions } = this;\n let error: any;\n action = action || actions.shift()!;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n this._active = false;\n\n if (error) {\n while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AnimationFrameAction } from './AnimationFrameAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\n\n/**\n *\n * Animation Frame Scheduler\n *\n * Perform task when `window.requestAnimationFrame` would fire\n *\n * When `animationFrame` scheduler is used with delay, it will fall back to {@link asyncScheduler} scheduler\n * behaviour.\n *\n * Without delay, `animationFrame` scheduler can be used to create smooth browser animations.\n * It makes sure scheduled task will happen just before next browser content repaint,\n * thus performing animations as efficiently as possible.\n *\n * ## Example\n * Schedule div height animation\n * ```ts\n * // html:
\n * import { animationFrameScheduler } from 'rxjs';\n *\n * const div = document.querySelector('div');\n *\n * animationFrameScheduler.schedule(function(height) {\n * div.style.height = height + \"px\";\n *\n * this.schedule(height + 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * }, 0, 0);\n *\n * // You will see a div element growing in height\n * ```\n */\n\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\n\n/**\n * @deprecated Renamed to {@link animationFrameScheduler}. Will be removed in v8.\n */\nexport const animationFrame = animationFrameScheduler;\n", "import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\n\n/**\n * A simple Observable that emits no items to the Observer and immediately\n * emits a complete notification.\n *\n * Just emits 'complete', and nothing else.\n *\n * ![](empty.png)\n *\n * A simple Observable that only emits the complete notification. It can be used\n * for composing with other Observables, such as in a {@link mergeMap}.\n *\n * ## Examples\n *\n * Log complete notification\n *\n * ```ts\n * import { EMPTY } from 'rxjs';\n *\n * EMPTY.subscribe({\n * next: () => console.log('Next'),\n * complete: () => console.log('Complete!')\n * });\n *\n * // Outputs\n * // Complete!\n * ```\n *\n * Emit the number 7, then complete\n *\n * ```ts\n * import { EMPTY, startWith } from 'rxjs';\n *\n * const result = EMPTY.pipe(startWith(7));\n * result.subscribe(x => console.log(x));\n *\n * // Outputs\n * // 7\n * ```\n *\n * Map and flatten only odd numbers to the sequence `'a'`, `'b'`, `'c'`\n *\n * ```ts\n * import { interval, mergeMap, of, EMPTY } from 'rxjs';\n *\n * const interval$ = interval(1000);\n * const result = interval$.pipe(\n * mergeMap(x => x % 2 === 1 ? of('a', 'b', 'c') : EMPTY),\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following to the console:\n * // x is equal to the count on the interval, e.g. (0, 1, 2, 3, ...)\n * // x will occur every 1000ms\n * // if x % 2 is equal to 1, print a, b, c (each on its own)\n * // if x % 2 is not equal to 1, nothing will be output\n * ```\n *\n * @see {@link Observable}\n * @see {@link NEVER}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const EMPTY = new Observable((subscriber) => subscriber.complete());\n\n/**\n * @param scheduler A {@link SchedulerLike} to use for scheduling\n * the emission of the complete notification.\n * @deprecated Replaced with the {@link EMPTY} constant or {@link scheduled} (e.g. `scheduled([], scheduler)`). Will be removed in v8.\n */\nexport function empty(scheduler?: SchedulerLike) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\n\nfunction emptyScheduled(scheduler: SchedulerLike) {\n return new Observable((subscriber) => scheduler.schedule(() => subscriber.complete()));\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport function isScheduler(value: any): value is SchedulerLike {\n return value && isFunction(value.schedule);\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\n\nfunction last(arr: T[]): T | undefined {\n return arr[arr.length - 1];\n}\n\nexport function popResultSelector(args: any[]): ((...args: unknown[]) => unknown) | undefined {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\n\nexport function popScheduler(args: any[]): SchedulerLike | undefined {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\n\nexport function popNumber(args: any[], defaultValue: number): number {\n return typeof last(args) === 'number' ? args.pop()! : defaultValue;\n}\n", "export const isArrayLike = ((x: any): x is ArrayLike => x && typeof x.length === 'number' && typeof x !== 'function');", "import { isFunction } from \"./isFunction\";\n\n/**\n * Tests to see if the object is \"thennable\".\n * @param value the object to test\n */\nexport function isPromise(value: any): value is PromiseLike {\n return isFunction(value?.then);\n}\n", "import { InteropObservable } from '../types';\nimport { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being Observable (but not necessary an Rx Observable) */\nexport function isInteropObservable(input: any): input is InteropObservable {\n return isFunction(input[Symbol_observable]);\n}\n", "import { isFunction } from './isFunction';\n\nexport function isAsyncIterable(obj: any): obj is AsyncIterable {\n return Symbol.asyncIterator && isFunction(obj?.[Symbol.asyncIterator]);\n}\n", "/**\n * Creates the TypeError to throw if an invalid object is passed to `from` or `scheduled`.\n * @param input The object that was passed.\n */\nexport function createInvalidObservableTypeError(input: any) {\n // TODO: We should create error codes that can be looked up, so this can be less verbose.\n return new TypeError(\n `You provided ${\n input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`\n } where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`\n );\n}\n", "export function getSymbolIterator(): symbol {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator' as any;\n }\n\n return Symbol.iterator;\n}\n\nexport const iterator = getSymbolIterator();\n", "import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being an Iterable */\nexport function isIterable(input: any): input is Iterable {\n return isFunction(input?.[Symbol_iterator]);\n}\n", "import { ReadableStreamLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport async function* readableStreamLikeToAsyncGenerator(readableStream: ReadableStreamLike): AsyncGenerator {\n const reader = readableStream.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n return;\n }\n yield value!;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nexport function isReadableStreamLike(obj: any): obj is ReadableStreamLike {\n // We don't want to use instanceof checks because they would return\n // false for instances from another Realm, like an

+

Other changes:

+
+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/04/17/kvmd-2-53-web-terminal-in-web-ui-window/index.html b/blog/2021/04/17/kvmd-2-53-web-terminal-in-web-ui-window/index.html new file mode 100644 index 00000000..c095be02 --- /dev/null +++ b/blog/2021/04/17/kvmd-2-53-web-terminal-in-web-ui-window/index.html @@ -0,0 +1,2790 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 2.53: Web terminal in a web UI window - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 2.53: Web terminal in a web UI window

+ +

You can now have the web terminal in a window above the video stream if you like. The focus works a little strange, but it is quite functional and even supports changing the size.

+ + +

Web terminal in a window

+

Another recent change is that you can now select the keyboard layout of the target machine in the paste-as-keys menu, so this solves the problem of German, British, and other layouts.

+

Select the keyboard layout of the target machine in the paste-as-keys menu

+

And a few more changes:

+
    +
  • You can disable confirmation in the paste-as-keys menu
  • +
  • Full-screen mode now works in Safari on Mac.
  • +
  • Some minor UI fixes and improvements.
  • +
+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/04/23/kvmd-2-55-arduino-hid-improvements/index.html b/blog/2021/04/23/kvmd-2-55-arduino-hid-improvements/index.html new file mode 100644 index 00000000..1657d895 --- /dev/null +++ b/blog/2021/04/23/kvmd-2-55-arduino-hid-improvements/index.html @@ -0,0 +1,2783 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 2.55: Arduino HID imrpovements - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 2.55: Arduino HID imrpovements

+ +

This release delivers a significant improvement of the Arduino HID when you control a computer with a MacOS.

+ + +

Now you don't need to spam the Command+R or Option keys on boot to hope to get to the UEFI menu or Recovery mode—just hold down the shortcut on boot, as on a real keyboard, and everything will work.

+

We also improved the behavior of the stream window: now it will not try to establish a connection several times due to a race on a slow channel, but works more stably. This is part of the work on future H.264 support—cleaning the ancient Augean stables.

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/05/09/kvmd-2-65-ezcoo-fix-for-usb3/index.html b/blog/2021/05/09/kvmd-2-65-ezcoo-fix-for-usb3/index.html new file mode 100644 index 00000000..943c99e4 --- /dev/null +++ b/blog/2021/05/09/kvmd-2-65-ezcoo-fix-for-usb3/index.html @@ -0,0 +1,2783 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 2.65: Ezcoo fix for USB 3.0 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 2.65: Ezcoo fix for USB 3.0

+ +

If you bought an Ezcoo switch for USB 3.0, then in order for it to work with Pi-KVM, you need to upgrade to the new version and add one option to the config.

+ + +

The fact is that the Ezcoo guys for some reason changed the management protocol. The update adds support for this.

+

Ah, and if you're wondering where the rest of the versions disappeared between release 2.59 and 2.65, then these were some things for the upcoming H.264 support 🙂

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/05/20/kvmd-2-71-massive-internal-changes/index.html b/blog/2021/05/20/kvmd-2-71-massive-internal-changes/index.html new file mode 100644 index 00000000..fae3c938 --- /dev/null +++ b/blog/2021/05/20/kvmd-2-71-massive-internal-changes/index.html @@ -0,0 +1,2799 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 2.71: Massive internal changes - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 2.71: Massive internal changes

+ +

This is a very important release. In addition to new features and fixes, a large number of internal changes have been made for the upcoming H264/WebRTC support.

+ + +

As usual, I tested everything very carefully, but anyway. If you notice anything strange (for example, with the stream), let me know.

+
    +
  • +

    Added module for new managed KVM switch Tesmart (as an Ezcoo alternative): https://github.com/pikvm/pikvm/blob/master/pages/tesmart.md. It can be used in a same way from Web UI.

    +
  • +
  • +

    Fixed the Bluetooth HID emulation module.

    +
  • +
  • +

    Improved text insertion via the Web UI: typographic quotes are now replaced with ASCII quotes. Many sites where scripts can be copied from like to break quotes, so I decided to make life a little easier for sysadmins.

    +
  • +
  • +

    Due to a bug in systemd/udev, port binding for USB HDMI is disabled. This is temporary for now, but I'm considering getting rid of it altogether, because no one seems to be using multiple video devices on the Pi-KVM.

    +
  • +
  • +

    Redesigned the System menu in the Web UI to make it more compact, as due to H264 and v3 there will be a lot of new settings.

    +
  • +
+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/05/30/store-update/index.html b/blog/2021/05/30/store-update/index.html new file mode 100644 index 00000000..a9ff50de --- /dev/null +++ b/blog/2021/05/30/store-update/index.html @@ -0,0 +1,2758 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Store update - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

Store update

+ +

There is good and bad news about our store.

+ + +

A couple of days ago, we tried to make test sales and faced a huge number of refusals when making payments. In most cases, US and European banks consider the payment to Russia to be a fraudulent operation. There's nothing we can do about it. Well, it's probably well deserved, given the stories about Russian hackers.

+

Obviously, we can't sell our devices under these conditions, so we decided to sell most of the batch to wholesale suppliers in the US. These are two good stores that sell Raspberry Pi and accessories for them. The advantage of this approach is that it will be easier for you to buy it, if you want to add some things (Raspberry, memory card, cables, if you don't have one) and you will get delivery faster than from Russia. Minus - it will be a little more expensive.

+

The second batch will be sold through resellers for retail. To companies we will sell directly with deliveries via DHL.

+

So I'm doing customs clearance this week. Most likely, this will be delayed for another three weeks, taking into account the delivery to the reseller.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/06/08/kvmd-2-83-uploading-large-images/index.html b/blog/2021/06/08/kvmd-2-83-uploading-large-images/index.html new file mode 100644 index 00000000..d8b6410b --- /dev/null +++ b/blog/2021/06/08/kvmd-2-83-uploading-large-images/index.html @@ -0,0 +1,2784 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 2.83: Uploading large images - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 2.83: Uploading large images

+ +

We have improved the behavior of mass storage when uploading large images.

+ + +

Previously, the progress bar could be displayed incorrectly due to the features of different browsers (for example, chrome on some win 10), so now the download progress is calculated on the server side and transmitted to the client.

+

We also recently accelerated the uploading of images to Mass Storage by two to three times.

+

Work continues on the implementation of H264 and WebRTC. Presumably, the release will be within a week.

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/06/10/kvmd-3-0-big-h264-release/index.html b/blog/2021/06/10/kvmd-3-0-big-h264-release/index.html new file mode 100644 index 00000000..b85793ae --- /dev/null +++ b/blog/2021/06/10/kvmd-3-0-big-h264-release/index.html @@ -0,0 +1,2780 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.0: The big H.264 release! - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.0: The big H.264 release!

+ +

I'm happy to introduce you to a feature I've been working on for the last six months. Now, instead of using bold MJPEG for video, you can use fast WebRTC with H.264.

+ + +

This allows you to significantly reduce traffic consumption and improve the responsiveness of Pi-KVM on bad networks, and all in the regular Web UI! The MJPEG and H.264 modes are left to choose from and you can switch them at any time using the menu.

+

It was a huge job, as I had to understand the intricacies of WebRTC functioning, integrate it with uStreamer, develop a way to automatically configure the WebRTC gateway, and so on.

+

To try the new super video mode, upgrade your system (rw; pacman -Syu; reboot) and read the simple user guide.

+

Please note that right now H.264 is only available for Raspberry Pi 4 with CSI bridge.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/07/04/kvmd-3-7-some-v3-news/index.html b/blog/2021/07/04/kvmd-3-7-some-v3-news/index.html new file mode 100644 index 00000000..c121ba3f --- /dev/null +++ b/blog/2021/07/04/kvmd-3-7-some-v3-news/index.html @@ -0,0 +1,2796 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.7 + Some V3 news - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.7 + Some V3 news

+ +

This release comes with several improvements, we also have some V3 news for you.

+ + +
    +
  • +

    Now the video mode is saved in the browser. If you have chosen WebRTC by default, then it will remain the same for this browser.

    +
  • +
  • +

    The Yen key in the Japanese keyboard now works.

    +
  • +
  • +

    Added a link to the configuration documentation and possible problems with WebRTC (right next to the mode switch).

    +
  • +
  • +

    The OS images on the site will be updated in the near future. Now the size of rootfs has been increased from 4 to 6 gigabytes to avoid problems with updates. The size of the partition in old images on already installed OS will not be increased.

    +
  • +
+

To update:

+
rw
+pacman -Syu
+reboot 
+
+

As for the first batch of v3: it was delayed at russian customs. Let's wish health to these wonderful people. I'll deal with it. Btw the second batch is planned for September. There will be no such problems with this since it will be produced in China.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/07/10/kvmd-3-8-epic-apple-fix/index.html b/blog/2021/07/10/kvmd-3-8-epic-apple-fix/index.html new file mode 100644 index 00000000..1a9c1a99 --- /dev/null +++ b/blog/2021/07/10/kvmd-3-8-epic-apple-fix/index.html @@ -0,0 +1,2796 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.8: The Epic Apple fix! - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.8: The Epic Apple fix!

+ +

For a long time, Pi-KVM had several problems related to the mouse and keyboard on Apple. Previously, you could not use the mouse in the boot menu, and recovery mode also required you to connect the mouse, despite the fact that the cursor was functioning. Because of these bugs, it was impossible to fully remotely control your Mac. Now all this is fixed!

+ + +
    +
  • +

    For an Intel-based Mac, you can use the Arduino HID to enter different boot menus (Option or Cmd+R). In boot manager, a relative mouse now works, and in recovery mode, both relative and absolute work.

    +
  • +
  • +

    For Mac with M1, you can use default OTG HID. You will no longer be shown a screen with an absurd requirement to connect another mouse in recovery mode.

    +
  • +
+

Since this problem was hidden somewhere inside the Apple drivers, I needed to buy a hardware USB protocol analyzer to understand how to get around it (because Mac is a closed source and there is no other way to find out what is happening there). Fixing this cost me almost $1500. So if it will be useful to someone, you can support me with a donation, because developing Pi-KVM software as Open Source is my main and only job.

+ +

To update:

+
rw
+pacman -Syu
+reboot 
+
+

And don't forget reflash your Arduino HID!

+

Epic Mac fix

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/07/14/kvmd-3-9-paste-as-keys-update/index.html b/blog/2021/07/14/kvmd-3-9-paste-as-keys-update/index.html new file mode 100644 index 00000000..a607b020 --- /dev/null +++ b/blog/2021/07/14/kvmd-3-9-paste-as-keys-update/index.html @@ -0,0 +1,2782 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.9: Paste-as-Keys update - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.9: Paste-as-Keys update

+ +

For the Paste-as-Keys function, the state of the confirmation switch and the selected keymap are saved. You asked for it—I did it.

+ + +

Also, after solving the problems with HID on Apple, I sent patches to the upstream HID library. I know of at least one other project for which these problems were a thorn. Let's hope that we will make life easier for people 🙂

+

To update:

+
rw
+pacman -Syu
+reboot 
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/07/17/kvmd-3-11-for-workgroups/index.html b/blog/2021/07/17/kvmd-3-11-for-workgroups/index.html new file mode 100644 index 00000000..2c25733a --- /dev/null +++ b/blog/2021/07/17/kvmd-3-11-for-workgroups/index.html @@ -0,0 +1,2784 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.11 For Workgroups - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.11 For Workgroups

+ +

More new features in this new release.

+ + +

Now Wake-on-LAN can be configured not for one, but for a whole list of hosts. Now you can use this as another method of managing multiple hosts connected to an HDMI switch: https://github.com/pikvm/pikvm/blob/master/pages/wol.md

+

This change required a complete rewrite of the WoL subsystem, which has now become a pseudo-GPIO driver. Your old settings in override.yaml will work and the button for one host is still in the System menu, since I took care of backward compatibility, but the /api/wol handle has been removed, you need to use the GPIO API instead it (if anyone has used it at all).

+

We also made some improvements in the interface. The interval between hotkeys was increased to 100 milliseconds (since 50 was sometimes not enough for reliable operation), the shortcuts menu was separated from the paste menu in preparation for the implementation of custom keyboard shortcuts.

+

To update:

+
rw
+pacman -Syu
+reboot 
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/08/02/kvmd-3-13-upload-images-by-url-dual-mouse-mode/index.html b/blog/2021/08/02/kvmd-3-13-upload-images-by-url-dual-mouse-mode/index.html new file mode 100644 index 00000000..6245e550 --- /dev/null +++ b/blog/2021/08/02/kvmd-3-13-upload-images-by-url-dual-mouse-mode/index.html @@ -0,0 +1,2795 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.13: Upload images by URL + dual mouse mode - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.13: Upload images by URL + dual mouse mode

+ +

Two new great features!

+ + +
    +
  • +

    Now you can tell Pi-KVM to download the image for mass storage from the HTTP(S) URL, and not just upload from your local computer. The new MSD API has also become more convenient if you are a curl guru.

    +
  • +
  • +

    For v2/v3/OTG, you will no longer have to choose between relative and absolute mouse, you will be able to use both modes and switch between them without changing the config and reboot. This is very convenient if your BIOS does not understand the absolute mouse and only wants a relative one, while the absolute one is more convenient for everyday work in the OS. This dual mouse mode is disabled by default for compatibility reasons (perhaps, especially buggy bioses may not support two mice at once), to enable it, after updating, add to /etc/kvmd/override.yaml:

    +
  • +
+
kvmd:
+    hid:
+        mouse_alt:
+            device: /dev/kvmd-hid-mouse-alt
+
+

Turn off the relative mode for the mouse in the config if it was enabled earlier. And make sure that you merged files /etc/udev/99-kvmd.rules.pacnew with /etc/udev/99-kvmd.rules.

+

To update:

+
rw
+pacman -Syu
+reboot 
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/08/08/big-testing-request/index.html b/blog/2021/08/08/big-testing-request/index.html new file mode 100644 index 00000000..1f8ef233 --- /dev/null +++ b/blog/2021/08/08/big-testing-request/index.html @@ -0,0 +1,2762 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Big testing request - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

Big testing request

+ +

I have a very important request. We are preparing for a big update that will improve compatibility with BIOS and UEFI on many devices, and I need as many people as possible to check out the new build of the kernel and core packages.

+ + +

How to test:

+
    +
  1. Switch filesystem to RW-mode using the rw command.
  2. +
  3. Open the /etc/pacman.conf file for editing and go to its end.
  4. +
  5. Change the repository URL like this (add testing component path): Server = https://pikvm.org/repos/testing/rpi4-arm. Don't change the last component (rpi4-arm, zerow-arm, etc).
  6. +
  7. Run pacman -Syu && reboot
  8. +
+

Please make sure that everything works as usual, I mean video and USB. I am particularly interested in the CSI bridge.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/08/12/kvmd-3-14-epic-apple-fix-vol2/index.html b/blog/2021/08/12/kvmd-3-14-epic-apple-fix-vol2/index.html new file mode 100644 index 00000000..39928cfd --- /dev/null +++ b/blog/2021/08/12/kvmd-3-14-epic-apple-fix-vol2/index.html @@ -0,0 +1,2788 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.14: The Epic Apple fix, Vol.2 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.14: The Epic Apple fix, Vol.2

+ +

I continue to eliminate ancient bugs from USB. So great news for Apple and v2/v3/OTG users: you no longer need to use the Arduino HID to get into the Boot Menu or Recovery Mode.

+ + +

It took a long and thoughtful study, but now this problem has been resolved. In addition, compatibility with some strange HP and DELL motherboards has improved, so if you didn't have a keyboard there before, now it has all the chances to work! Note: wakeup from suspend using keyboard has not yet worked, but it's a matter of time.

+

Before updating: If you used testing repository, cancel this and use the usual settings.

+

To update:

+
rw
+pacman -Syu
+reboot 
+
+

You will also need my own stable kernel build (if you are using a very old image and have not installed it, in new images it is out of the box):

+
    +
  1. Check if it is installed: pacman -Q | grep pikvm-os-raspberrypi
  2. +
  3. If this command didn't show you anything, install my kernel
  4. +
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/08/17/kvmd-3-18-sensitivity-adjustment-for-relative-mouse/index.html b/blog/2021/08/17/kvmd-3-18-sensitivity-adjustment-for-relative-mouse/index.html new file mode 100644 index 00000000..f9746684 --- /dev/null +++ b/blog/2021/08/17/kvmd-3-18-sensitivity-adjustment-for-relative-mouse/index.html @@ -0,0 +1,2792 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.18: Sensitivity adjustment for relative mouse - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.18: Sensitivity adjustment for relative mouse

+ +

There are several improvements in this release.

+ + +
    +
  • +

    The relative mouse now has a sensitivity adjustment. The setting is remembered in the browser.

    +
  • +
  • +

    We added a PWM and Servo module for GPIO. Now you can control servos using the GPIO menu.

    +
  • +
  • +

    The most important change! We added the absolute mouse compatibility mode for Windows 98 for both OTG and Arduino HID.

    +
  • +
+

To update:

+
rw
+pacman -Syu
+reboot 
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/08/31/kvmd-3-23-keyboard-mouse-wakeup/index.html b/blog/2021/08/31/kvmd-3-23-keyboard-mouse-wakeup/index.html new file mode 100644 index 00000000..0b22b445 --- /dev/null +++ b/blog/2021/08/31/kvmd-3-23-keyboard-mouse-wakeup/index.html @@ -0,0 +1,2789 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.23 + kernel fix: keyboard/mouse wakeup - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.23 + kernel fix: keyboard/mouse wakeup

+ +

Previously, when using v2+/OTG on Pi4 and ZeroW, you could not wake up the host if it was in suspend. Now this problem is solved.

+ + +

At the moment, this feature is experimental and disabled by default, since it was implemented blindly without documentation for the USB controller (no one gave it to me lol). It would be great if as many people as possible test it and tell if everything works fine.

+

Although the feature is experimental, the update must be safe.

+

To update you will need our own stable kernel build (if you are using a very old image and have not installed it, in new images it is out of the box):

+
    +
  1. Check if it is installed: pacman -Q | grep pikvm-os-raspberrypi
  2. +
  3. If this command didn't show you anything, install our kernel (⁠news⁠)
  4. +
  5. After reboot, make this: rw; pacman -Syu; reboot
  6. +
  7. To enable wakeup feature edit /etc/kvmd/override.yaml and add this:
  8. +
+

otg:
+    remote_wakeup: true
+
+... and reboot
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/09/26/kvmd-3-26-philips-hue-gpio-plugin/index.html b/blog/2021/09/26/kvmd-3-26-philips-hue-gpio-plugin/index.html new file mode 100644 index 00000000..6d15e3b4 --- /dev/null +++ b/blog/2021/09/26/kvmd-3-26-philips-hue-gpio-plugin/index.html @@ -0,0 +1,2795 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.26: Philips Hue GPIO plugin - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.26: Philips Hue GPIO plugin

+ +

This releases comes with several new features and improvements.

+ + +
    +
  • +

    Started rebranding Pi-KVM -> PiKVM. Everyone is constantly confused about how to write it correctly, so we will write the name in one word. And it's easier to google, too.

    +
  • +
  • +

    Added Philips Hue GPIO plugin for smartplugs and lamps. We also changed the GPIO HTTP API accordingly: pin numbers are strings now, which is a requirement for named pins.

    +
  • +
  • +

    ATX and GPIO actions are now also recorded in macros.

    +
  • +
  • +

    The IPMI GPIO plugin no longer calls ipmitool twice when a button is clicked in the interface.

    +
  • +
+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/10/03/kvmd-3-27-mouse-polling-rate/index.html b/blog/2021/10/03/kvmd-3-27-mouse-polling-rate/index.html new file mode 100644 index 00000000..b8fd2b7c --- /dev/null +++ b/blog/2021/10/03/kvmd-3-27-mouse-polling-rate/index.html @@ -0,0 +1,2788 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.27: Mouse polling rate - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.27: Mouse polling rate

+ +

The new version ships with a new feature: configurable mouse polling rate.

+ + +

Previously it was a fixed 100ms, now it can be reduced to 10ms, so on good communication channels it makes the mouse more responsive.

+

Other changes:

+
    +
  • Added tests to check whether the browser supports WebRTC/H.264.
  • +
  • Added a GPIO driver for a new KVM switch XK-HK4401.
  • +
+

To update:

+
rw
+pacman -Syu
+reboot
+
+

We also fixed the use of new Tailscale versions. Install the tailscale-pikvm package.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/10/19/kvmd-3-33-new-wifi-configuration-method/index.html b/blog/2021/10/19/kvmd-3-33-new-wifi-configuration-method/index.html new file mode 100644 index 00000000..b6580654 --- /dev/null +++ b/blog/2021/10/19/kvmd-3-33-new-wifi-configuration-method/index.html @@ -0,0 +1,2789 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.33: New Wi-Fi configuration method - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.33: New Wi-Fi configuration method

+ +

Starting from today, the old way to configure Wi-Fi using netctl is deprecated. Instead, it is proposed to use a more native way with systemd-networkd, which is already used to configure Ethernet.

+ + +

To update:

+
rw
+pacman -Syu
+reboot
+
+

All new OS images will use this feature. In addition, I have prepared documentation for you on how to set up wifi in a new way: https://docs.pikvm.org/wifi

+

Additionally, even if you don't use Wi-Fi, do this:

+
rw
+systemctl disable pikvm-bootconfig
+rm /etc/systemd/system/pikvm-bootconfig.service /usr/local/bin/_pikvm-bootconfig.sh
+systemctl enable kvmd-bootconfig
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/10/24/kvmd-3-36-custom-command-button/index.html b/blog/2021/10/24/kvmd-3-36-custom-command-button/index.html new file mode 100644 index 00000000..fe00b571 --- /dev/null +++ b/blog/2021/10/24/kvmd-3-36-custom-command-button/index.html @@ -0,0 +1,2783 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.36: Custom command button in the menu - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.36: Custom command button in the menu

+ +

We have just implemented the long-awaited feature—adding a custom command button to the menu.

+ + +

I don't know why this is necessary, but it's been asked so often, so why not do it. To use it, you will need a pseudo-GPIO CMD driver. See this help page for details.

+

We also improved the behavior of stream quality sliders on Firefox.

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2021/2021-04-13/fullscreen-mode.mp4 b/blog/2021/2021-04-13/fullscreen-mode.mp4 new file mode 100644 index 00000000..17d04203 Binary files /dev/null and b/blog/2021/2021-04-13/fullscreen-mode.mp4 differ diff --git a/blog/2021/2021-04-17/paste-as-keys-keyboard-layout.webp b/blog/2021/2021-04-17/paste-as-keys-keyboard-layout.webp new file mode 100644 index 00000000..bcb1b15f Binary files /dev/null and b/blog/2021/2021-04-17/paste-as-keys-keyboard-layout.webp differ diff --git a/blog/2021/2021-04-17/web-terminal-window.webp b/blog/2021/2021-04-17/web-terminal-window.webp new file mode 100644 index 00000000..c5b454fe Binary files /dev/null and b/blog/2021/2021-04-17/web-terminal-window.webp differ diff --git a/blog/2021/2021-07-10/epic-mac-fix.webp b/blog/2021/2021-07-10/epic-mac-fix.webp new file mode 100644 index 00000000..b86a1c0e Binary files /dev/null and b/blog/2021/2021-07-10/epic-mac-fix.webp differ diff --git a/blog/2022/01/08/kvmd-3-53-oled-and-fan-updates-for-v3/index.html b/blog/2022/01/08/kvmd-3-53-oled-and-fan-updates-for-v3/index.html new file mode 100644 index 00000000..4266a34a --- /dev/null +++ b/blog/2022/01/08/kvmd-3-53-oled-and-fan-updates-for-v3/index.html @@ -0,0 +1,2783 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.53: OLED and fan updates for V3 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.53: OLED and fan updates for V3

+ +

The new KVMD update ships with a few major OLED changes.

+ + +

First off, the OLED screen now displays the temperature, CPU and memory usage. You can control that with a new kvmd-oled tool. American users can now turn on the temperature display in Fahrenheit, see Step 5 in the quickstart guide for details.

+

The next new feature is kvmd-fan. This new utility implements automatic fan speed control depending on temperature.

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/02/11/zero-w-1-and-rpi-1-end-of-life/index.html b/blog/2022/02/11/zero-w-1-and-rpi-1-end-of-life/index.html new file mode 100644 index 00000000..e8cb5eb2 --- /dev/null +++ b/blog/2022/02/11/zero-w-1-and-rpi-1-end-of-life/index.html @@ -0,0 +1,2764 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Zero W 1 and RPi 1 end-of-life - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

Zero W 1 and RPi 1 end-of-life

+ +

Since Arch Linux ARM has discontinued support for the ARMv6 architecture , we are discontinuing support for PiKVM based on Zero W and RPi 1, because we don't have the ability to maintain our own fork of the whole distro for this architecture.

+ + +

It is proposed to use Zero W 2 and RPi 2 for supported replacement. I know this will upset a lot of users, but there's nothing we can do about it right now. The current plan is as follows:

+
    +
  1. +

    We will build the last image with the current packages for Zero W 1. It will not receive updates, but will continue to work as before.

    +
  2. +
  3. +

    In the long term, we plan to create a package repository for Raspbian. When this happens, support for Zero W 1 and RPi 1 will be returned, but not for the Arch Linux ARM, but for the Raspbian / Raspberry Pi OS.

    +
  4. +
+

RPi 2 and the rest of the devices continue to be supported as before.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/02/21/kvmd-3-55-copying-text-from-target-machine/index.html b/blog/2022/02/21/kvmd-3-55-copying-text-from-target-machine/index.html new file mode 100644 index 00000000..bf803cf6 --- /dev/null +++ b/blog/2022/02/21/kvmd-3-55-copying-text-from-target-machine/index.html @@ -0,0 +1,2786 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.55: Copying text FROM the target machine - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.55: Copying text FROM the target machine

+ +

Introducing a new big feature—the ability to copy text from a managed machine to the clipboard.

+ + +

As you know, the clipboard inside the machine is a system feature and has no hardware connection with PiKVM. Therefore, in order to copy the text, we made it possible to recognize the selected image on the screen using the Tesseract OCR library, which converts it into text.

+

+

Image recognition works locally on your Raspberry Pi and does not use any Skynet clouds. In addition, recognition works ONLY on your demand, that is, the OCR library does not see the image until you give it to it explicitly, so if you are afraid to raise an evil AI, then you can relax.

+

For reasons of concern about paranoids, OCR library are not installed by default yet 🙂

+
rw
+pacman -Syu
+pacman --assume-installed tessdata -S tesseract tesseract-data-eng
+reboot
+
+

Install any OCR language by searching it in pacman -Ss tesseract-data.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/03/06/new-testing-branch-available/index.html b/blog/2022/03/06/new-testing-branch-available/index.html new file mode 100644 index 00000000..12851d11 --- /dev/null +++ b/blog/2022/03/06/new-testing-branch-available/index.html @@ -0,0 +1,2762 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + New testing branch available - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

New testing branch available

+ +

A few months ago, due to the release of Bullseye, the usual video encoding method used in PiKVM stopped working in the new kernel. OpenMAX and MMAL were deprecated and uStreamer has ben rewrited to use new M2M encoder. Now the work is almost completed and everything seems to be working fine.

+ + +

I am asking all interested users of v0, v2 and v3 to test this update before I make it available to everyone. Rememer: this is an experimental update, so don't install it unless you're ready to do a reflash.

+

To install:

+
rw
+sed -i -e 's|repos/arch/|repos/arch-testing/|g' /etc/pacman.conf
+pacman -Syu
+reboot
+
+

Please report any problems to #⁠dev on Discord. Also let me know if everything is working fine. I am interested in testing on RPi3, RPi4 and Zero2W boards with HDMI-CSI bridge or v3 HAT.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/04/01/kvmd-3-73-experimental-dynamic-usb-configuration/index.html b/blog/2022/04/01/kvmd-3-73-experimental-dynamic-usb-configuration/index.html new file mode 100644 index 00000000..6bbb0600 --- /dev/null +++ b/blog/2022/04/01/kvmd-3-73-experimental-dynamic-usb-configuration/index.html @@ -0,0 +1,2797 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.73: Experimental dynamic USB configuration - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.73: Experimental dynamic USB configuration

+ +

First of all, although the release is experimental, it is NOT unstable. The new utility does not affect the performance of the system in any way if you do not use.

+ + +

So, the idea is that now you can change the configuration of the USB emulator on the fly. For example, you can temporarily turn off the mouse or mass storage or USB network (if you have it configured) without restarting, and then turn it on again:

+
[root@pikvm ~]# kvmd-otgconf
++ hid.usb0  # Keyboard
++ hid.usb1  # Absolute Mouse
++ mass_storage.usb0  # Mass Storage Drive
+[root@pikvm ~]# kvmd-otgconf --disable-function mass_storage.usb0
++ hid.usb0  # Keyboard
++ hid.usb1  # Absolute Mouse
+- mass_storage.usb0  # Mass Storage Drive
+[root@pikvm ~]# kvmd-otgconf --enable-function mass_storage.usb0
++ hid.usb0  # Keyboard
++ hid.usb1  # Absolute Mouse
++ mass_storage.usb0  # Mass Storage Drive
+
+

Disabling the function means that the host will not see it in USB.

+

Important: Due to the imperfections of the kernel modules, in rare cases, a dynamic configuration change can lead to a kernel panic and reboot, so use this carefully. I will fix the kernel at some point.

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/05/03/now-you-can-buy-a-pre-assambled-pikvm-v3-with-case/index.html b/blog/2022/05/03/now-you-can-buy-a-pre-assambled-pikvm-v3-with-case/index.html new file mode 100644 index 00000000..9e92cf30 --- /dev/null +++ b/blog/2022/05/03/now-you-can-buy-a-pre-assambled-pikvm-v3-with-case/index.html @@ -0,0 +1,2762 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Now you can buy a pre-assambled PiKVM v3 with case - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

Now you can buy a pre-assambled PiKVM v3 with case

+ +

A “Pre-Assembled” version of PiKVM has just been released!

+ + +

It includes the PiKVM board, a Raspberry Pi 4B 2GB, and a pre-programmed 32GB SanDisk card. Each unit has been carefully built and tested ❤️

+

Preassembled PiKVM V3

+

A limited quantity is available for this launch. We are expecting a high demand and will be doing our best to keep up! It’s already in stock at PiShop.us and PiShop.ca and will be soon available at other resellers.

+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/06/09/kvmd-3-101-audio-on-pikvm-v3/index.html b/blog/2022/06/09/kvmd-3-101-audio-on-pikvm-v3/index.html new file mode 100644 index 00000000..e7684576 --- /dev/null +++ b/blog/2022/06/09/kvmd-3-101-audio-on-pikvm-v3/index.html @@ -0,0 +1,2779 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.101: PiKVM V3 + Audio = ❤️ - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.101: PiKVM V3 + Audio = ❤️

+ +

This moment has come! We are finally ready to provide audio for testing by all V3 users.

+ + +

Audio on PiKVM v3

+

Right now everything is working pretty stable, so if you really wanted to watch a movie on KVM or something like that—this is your chance!

+

To start using audio, follow the simple instructions here: https://docs.pikvm.org/audio.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/06/11/introducing-new-tool-kvmd-edidconf/index.html b/blog/2022/06/11/introducing-new-tool-kvmd-edidconf/index.html new file mode 100644 index 00000000..616e9673 --- /dev/null +++ b/blog/2022/06/11/introducing-new-tool-kvmd-edidconf/index.html @@ -0,0 +1,2758 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Introducing a new tool — `kvmd-edidconf` - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

Introducing a new tool — `kvmd-edidconf`

+ +

For the happy owners of V2 and V3, we now offer a new utility, kvmd-edidconf. It will help you configure EDID (the display metadata) and provide import/export for EDID modification using advanced editors such as AW EDID Editor.

+ + +

For example, with its help, you can easily change the manufacturer and model of the virtual display without external editor apps, if you want PiKVM to mimic real hardware:

+
$ kvmd-edidconf --set-mfc-id=LNX --set-monitor-name=PiKVM
+
+

See the full documentation here: https://docs.pikvm.org/edid.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/06/24/kvmd-3-116-lets-encrypt-certificates/index.html b/blog/2022/06/24/kvmd-3-116-lets-encrypt-certificates/index.html new file mode 100644 index 00000000..e0c41530 --- /dev/null +++ b/blog/2022/06/24/kvmd-3-116-lets-encrypt-certificates/index.html @@ -0,0 +1,2780 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.116: Let's Encrypt certificates - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.116: Let's Encrypt certificates

+ +

Usually Let's Encrypt certificates are issued and updated automatically using Certbot, however, since PiKVM uses a read-only file system, special tools around Certbot are required to work with certificates.

+ + +

Now you can use it out of box. PiKVM will ensure that they are automatically renewed without affecting the root file system. Check out the documentation: https://docs.pikvm.org/letsencrypt/.

+

Here is what we recently changed to allow for this.

+

As you know, the file system uses read-only mode by default. However, sometimes user scripts (updating some certificates, keys, or something else) need to save some data to the memory card.

+

New versions of PiKVM after 20 June 2022 provide a small 256 Mb storage partition for this and a convenient tools of automatically managing it. The storage will always be in read-only mode, and will be writable only if requested. This is super handy if you want to make a cron job or a systemd timer. For details, please see here: https://docs.pikvm.org/pst/.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/07/03/small-request-for-v3-and-diy-builds-with-csi-bridge-owners/index.html b/blog/2022/07/03/small-request-for-v3-and-diy-builds-with-csi-bridge-owners/index.html new file mode 100644 index 00000000..ed1ed5cc --- /dev/null +++ b/blog/2022/07/03/small-request-for-v3-and-diy-builds-with-csi-bridge-owners/index.html @@ -0,0 +1,2764 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + A small request for V3 and DIY builds with CSI bridge owners - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

A small request for V3 and DIY builds with CSI bridge owners

+ +

We want to change some default values in the EDID (information about the virtual display) so that it looks not like Toshiba-H2C, but like PiKVM, and also change the vendor code.

+ + +

If you have a minute, please change the EDID settings and test the PiKVM virtual display in your BIOS and OS.

+

Preparations:

+
rw
+pacman -Syu
+kvmd-edidconf --set-mfc-id=LNX --set-monitor-name=PiKVM
+reboot
+
+

After this, check OS and BIOS. The current paranoid hypothesis is that perhaps some ugly BIOSes may rely on the manufacturer's code for monitor Plug-n-Playing.

+

Expected behavior: PiKVM video capture work as before without any problems. If something goes wrong, you can undo all the changes.

+

Please, if you have completed the testing and everything is fine, click the UP! under the message. If something doesn't work, please report to ⁠the #dev channel on Discord.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/07/24/kvmd-3-126-writable-flash-drive-storage/index.html b/blog/2022/07/24/kvmd-3-126-writable-flash-drive-storage/index.html new file mode 100644 index 00000000..8353d986 --- /dev/null +++ b/blog/2022/07/24/kvmd-3-126-writable-flash-drive-storage/index.html @@ -0,0 +1,2783 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.126: Writable flash drive storage - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.126: Writable flash drive storage

+ +

Now you can upload the flash drive image to MSD, write some files to it, or even install entire OS to the PiKVM MSD drive (I don't know why, but you can), and download the image back. Use the new feature wisely.

+ + +

Okay, here is an obvious question: is it possible to download not the entire image, but one file from it? This will be implemented later. For now, only the entire image.

+

Another recent change affects V3 and CSI bridges owners. I changed the display name from Toshiba-H2C to PiKVM and the manufacturer id from TSB to LNX. You may need to specify the preferred monitor resolution in your OS again. If you used a custom EDID (for example, turned on the sound), then nothing will change for you.

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/10/07/kvmd-3-152-android-and-ios-tablets-support/index.html b/blog/2022/10/07/kvmd-3-152-android-and-ios-tablets-support/index.html new file mode 100644 index 00000000..614857d9 --- /dev/null +++ b/blog/2022/10/07/kvmd-3-152-android-and-ios-tablets-support/index.html @@ -0,0 +1,2792 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.152: Android and iOS tablets support - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.152: Android and iOS tablets support

+ +

Several latest releases of KVMD come with improved support for web UI running on tablets.

+ + +
    +
  • We now have working mouse buttons and mobile keyboard for Apple tablets running iOS.
  • +
  • We also fixed Shift key in iOS JUMP and bVNC clients and fixed key confusion in Apple Magic International Keyboard.
  • +
  • The mobile interface is now available for Android tablets. Maybe not perfect, but it works.
  • +
+

Some of the other changes are:

+
    +
  • Workaround for paste-as-keys for en/em dashes.
  • +
  • Improved OCR.
  • +
  • Kernel updated to 5.15.68.
  • +
+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/11/03/kvmd-3-159-significant-vnc-improvement/index.html b/blog/2022/11/03/kvmd-3-159-significant-vnc-improvement/index.html new file mode 100644 index 00000000..019098ed --- /dev/null +++ b/blog/2022/11/03/kvmd-3-159-significant-vnc-improvement/index.html @@ -0,0 +1,2791 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.159: Significant VNC improvement - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.159: Significant VNC improvement

+ +

The VNC server has learned how to transmit video asynchronously to make it fast and smooth. Now, FPS can grow about twice, it will be especially noticeable with poor internet quality.

+ + +

Some of the other recent changes:

+
    +
  • Fixed H.264 stream corruption (it was a kernel bug).
  • +
  • Fixed the bug where the web interface considered a laptop with a touchscreen to be a mobile device.
  • +
  • Made it possible to use icon leds for GPIO menu title like this:
  • +
+
title: ["#KVM", "#PC1", pc1led, "#PC2", pc2led]
+
+

Here is how it looks:

+

LED for GPIO

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/11/06/kvmd-3-163-ustreamer-5-30-no-keyframes-mode/index.html b/blog/2022/11/06/kvmd-3-163-ustreamer-5-30-no-keyframes-mode/index.html new file mode 100644 index 00000000..2ba92a6a --- /dev/null +++ b/blog/2022/11/06/kvmd-3-163-ustreamer-5-30-no-keyframes-mode/index.html @@ -0,0 +1,2809 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.163 + uStreamer 5.30: No-Keyframes mode - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.163 + uStreamer 5.30: No-Keyframes mode

+ +

This is the second part of an experiment to improve the video streaming.

+ + +

There is such a thing in H.264—keyframes. In a normal situation, they are sent approximately once per second in order to ensure the stability of the video. If you were faced with the fact that your stream turned black, and then started working again after a couple of seconds, then you had a flow failure, but the keyframe fixed this.

+

So, the keyframe is our friend. But keyframes contain an entire frame of the screen, and unlike intermediate frames, which fill the entire remaining stream, they have a huge size. Next comes blah-blah-blah about WebRTC theory and flow correction algorithms in browsers, but in general, if we disable keyframes and send them only when the flow fails, you can make the stream faster, smoother and consuming less traffic.

+

You can test this mode in the new update. I've added the H.264 gop parameter that adjusts the interval between keyframes.

+

The H.264 gop parameter

+

If you reduce it to zero, then keyframes will be sent only in exceptional cases. This mode is best suited for slow wired channels, but I will be interested in how well it will work in wireless communication.

+

I would appreciate if someone would test this and share their experience for me in ⁠dev 🙏

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/12/15/the-pikvm-v4-kickstarter-campaign-is-on/index.html b/blog/2022/12/15/the-pikvm-v4-kickstarter-campaign-is-on/index.html new file mode 100644 index 00000000..288ebccd --- /dev/null +++ b/blog/2022/12/15/the-pikvm-v4-kickstarter-campaign-is-on/index.html @@ -0,0 +1,2786 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + The PiKVM V4 Kickstarter campaign is on! - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

The PiKVM V4 Kickstarter campaign is on!

+ +

We've been working on this for a long time! The new PiKVM V4 is even more powerful, more convenient and more feature-rich!

+ + +
    +
  • We have two new devicesV4 Mini and V4 Plus. They have different hardware features.
  • +
  • Both are based on Compute Module 4.
  • +
  • Two new video modes support added: 1920×1080@60Hz and 1920×1200@60Hz. This improves the UEFI/BIOS compatibility.
  • +
  • V4 Mini has a fanless design and efficient power consumption.
  • +
  • V4 Plus has a super-quiet cooling system with a custom-designed heatsink and intelligent fan controller.
  • +
  • Both devices are ready-made: CM4 included, as well as a case, screen, and even micro SD. Uh, and they are already assembled!
  • +
+

...and a lot of other nifty stuff ⚡

+

Visit our Kickstarter page: https://www.kickstarter.com/projects/mdevaev/pikvm-v4

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2022/2022-02-21/copy-text-from-target-machine.webm b/blog/2022/2022-02-21/copy-text-from-target-machine.webm new file mode 100644 index 00000000..667a9c68 Binary files /dev/null and b/blog/2022/2022-02-21/copy-text-from-target-machine.webm differ diff --git a/blog/2022/2022-05-03/v3-preassembled.webp b/blog/2022/2022-05-03/v3-preassembled.webp new file mode 100644 index 00000000..352cf91c Binary files /dev/null and b/blog/2022/2022-05-03/v3-preassembled.webp differ diff --git a/blog/2022/2022-06-09/pikvm-v3-audio.webp b/blog/2022/2022-06-09/pikvm-v3-audio.webp new file mode 100644 index 00000000..79c8e0b4 Binary files /dev/null and b/blog/2022/2022-06-09/pikvm-v3-audio.webp differ diff --git a/blog/2022/2022-11-03/gpio-led.webp b/blog/2022/2022-11-03/gpio-led.webp new file mode 100644 index 00000000..3158d136 Binary files /dev/null and b/blog/2022/2022-11-03/gpio-led.webp differ diff --git a/blog/2022/2022-11-06/h264-gop.webp b/blog/2022/2022-11-06/h264-gop.webp new file mode 100644 index 00000000..bef5c781 Binary files /dev/null and b/blog/2022/2022-11-06/h264-gop.webp differ diff --git a/blog/2023/01/23/kvmd-3-196-2fa-support/index.html b/blog/2023/01/23/kvmd-3-196-2fa-support/index.html new file mode 100644 index 00000000..65f8249b --- /dev/null +++ b/blog/2023/01/23/kvmd-3-196-2fa-support/index.html @@ -0,0 +1,2784 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.196: 2FA support - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.196: 2FA support

+ +

Many have asked for this, so now you have the opportunity to increase the security of your PiKVM.

+ + +

By the way, this is a great chance to see how the QR code is rendered in the terminal using ASCII 😄

+

Have fun: https://docs.pikvm.org/auth/#two-factor-authentication

+

2FA support in the web UI

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2023/03/05/kvmd-3-203-changes-in-msd/index.html b/blog/2023/03/05/kvmd-3-203-changes-in-msd/index.html new file mode 100644 index 00000000..9e5b7333 --- /dev/null +++ b/blog/2023/03/05/kvmd-3-203-changes-in-msd/index.html @@ -0,0 +1,2791 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.203: Changes in MSD - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.203: Changes in MSD

+ +

This is an infrastructure release. The internal structure of the MSD image storage has changed.

+ + +

Metadata and image directories have been merged into one:

+

Old:

+
/var/lib/kvmd/msd/images/foobar.iso
+/var/lib/kvmd/msd/meta/foobar.iso.complete
+
+

New:

+
/var/lib/kvmd/msd/foobar.iso
+/var/lib/kvmd/msd/.__foobar.iso.complete
+
+

If you use a standard configuration (or even MSD on a separate flash drive), the migration will be seamless for you. All you need is just to update and reboot, the files will be moved automatically. The change was needed for future MSD-over-network support.

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2023/03/21/kvmd-3-206-nfs-storage-for-virtual-media/index.html b/blog/2023/03/21/kvmd-3-206-nfs-storage-for-virtual-media/index.html new file mode 100644 index 00000000..1a151e51 --- /dev/null +++ b/blog/2023/03/21/kvmd-3-206-nfs-storage-for-virtual-media/index.html @@ -0,0 +1,2789 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.206: NFS storage for virtual media - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.206: NFS storage for virtual media

+ +

Now you can create NFS share for a common images storage for your PiKVMs fleet. The images will be available on all devices.

+ + +

Here is the documentation for the new feature: https://docs.pikvm.org/msd/#nfs-storage

+

This release also comes with Mass Storage Device API (/api/msd and and WebSocket event msd_state) changes required for NFS support:

+
    +
  • Removed the features field. The flags in it don't make sense since we dropped relay msd a year ago (does anyone even know what it is?)
  • +
  • Removed the storage.free and storage.size fields. Instead, use storage.parts[""].free and storage.parts[""].size. The new mechanism provides MSD placement on several local/NFS partitions at the same time. "" means the default partition.
  • +
  • Removed the storage.images[...].name field. Use the object key instead.
  • +
+

For those who use only Web UI or VNC, nothing changes.

+

To update:

+
rw
+pacman -Syu
+reboot
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2023/06/04/kvmd-3-225-performance-update/index.html b/blog/2023/06/04/kvmd-3-225-performance-update/index.html new file mode 100644 index 00000000..c4cbf59d --- /dev/null +++ b/blog/2023/06/04/kvmd-3-225-performance-update/index.html @@ -0,0 +1,2793 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.225: Performance update - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.225: Performance update

+ +

This is a performance update that improves multiple aspects of PiKVM OS.

+ + +
    +
  • Added a new very effective mouse events protocol.
  • +
  • Tuned some OS settings, so you will get a faster mass-storage image uploading.
  • +
  • Actually, there are many more things that I have fixed and improved, but it's too boring to describe them.
  • +
+

To update:

+
rw
+pacman -Syu
+reboot
+
+

We would appreciate wider testing. There are two important parameters in Web UI that affect the latency. Try them out:

+
    +
  • H.264 gop in the same location.
  • +
  • Mouse polling interval in the System menu;
  • +
+

Try to reduce it to tis minimum values (0 and 10 ms respectively). This should reduce latency and increase responsiveness. If you don't have a very reliable network (you're using VPN, or your host is a thousand kilometers away from you)—check whether the mouse will work well and whether the video will not be interrupted often.

+

It is important for me to know this, because if everything is fine, I will change the default values. Let me know if you encounter any problems with the described parameters.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2023/07/30/diy-pikvm-v0-based-on-arduino-hid-becomes-legacy/index.html b/blog/2023/07/30/diy-pikvm-v0-based-on-arduino-hid-becomes-legacy/index.html new file mode 100644 index 00000000..c7123ae7 --- /dev/null +++ b/blog/2023/07/30/diy-pikvm-v0-based-on-arduino-hid-becomes-legacy/index.html @@ -0,0 +1,2762 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + DIY PiKVM V0 based on Arduino HID becomes legacy - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

DIY PiKVM V0 based on Arduino HID becomes legacy

+ +

I'm planning to replace V0 with a new V1 soon, which will be based on Raspberry Pico.

+ + +

Here is what it boils down to:

+
    +
  • No more transistors and level shifters for USB emulation, now only wires are needed.
  • +
  • Full-fledged PS/2 keyboard and mouse support for connoisseurs of antiquity.
  • +
  • Pico is much cheaper than Arduino.
  • +
+

Old DIY devices will continue to be supported, but the instructions will be marked as legacy. +If you have any suggestions for the new Pico HID, please write to the #⁠dev channel on Discord.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2023/08/19/kvmd-3-249-easier-uploading-over-ssh/index.html b/blog/2023/08/19/kvmd-3-249-easier-uploading-over-ssh/index.html new file mode 100644 index 00000000..744a6c29 --- /dev/null +++ b/blog/2023/08/19/kvmd-3-249-easier-uploading-over-ssh/index.html @@ -0,0 +1,2784 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.249: easier uploading over SSH - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.249: easier uploading over SSH

+ +

In addition to many minor improvements from the previous announcement, an important change has occurred in the new release for those who use advanced Mass Storage emulation features.

+ + +

Now, when uploading an image via SSH, you no longer need to create a .complete file, since a manually placed image will be considered complete by default. This should simplify the operation of NFS shares for images and simplify console use.

+

Before updating, delete all your broken images. In theory, you should not have them, since PiKVM deletes it on uploading error, but anyway.

+

To update:

+
rw
+pacman -Syu
+reboot
+
+

PS: A little bit about the state of things: PiKVM is an open source product and full-time work for several people, thanks to which we can maintain the proper level of quality and security. As you can see, even after the release of V3 and V4, we do not abandon the development of DIY devices and port all possible features there.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2023/08/23/ustreamer-5-42-reduced-stream-latency/index.html b/blog/2023/08/23/ustreamer-5-42-reduced-stream-latency/index.html new file mode 100644 index 00000000..b9f2b39a --- /dev/null +++ b/blog/2023/08/23/ustreamer-5-42-reduced-stream-latency/index.html @@ -0,0 +1,2778 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + uStreamer 5.42: Reduced stream latency! - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

uStreamer 5.42: Reduced stream latency!

+ +

While I was working on HDMI passthrough for V4 Plus (I didn't forget what we promised!), I found a way to reduce the stream latency.

+ + +

Now 1080p stream with H.264 can reach ~110ms on LAN. That is, -50ms compared to the previous result.

+

BTW all PiKVMs, including V3 and DIY builds, will receive this update.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2023/10/23/kvmd-3-265-mouse-jiggler/index.html b/blog/2023/10/23/kvmd-3-265-mouse-jiggler/index.html new file mode 100644 index 00000000..538d54e8 --- /dev/null +++ b/blog/2023/10/23/kvmd-3-265-mouse-jiggler/index.html @@ -0,0 +1,2782 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.265: Mouse Jiggler! - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.265: Mouse Jiggler!

+ +

This is a feature that many users have been asking for for a long time. So, mouse jiggler will allow you to prevent the monitor from falling asleep if it was turned on.

+ + +

It performs short mouse movements every minute until you use PiKVM. Works with both mouse modes: absolute and relative. In addition, being enabled, it does not interfere with normal work with PiKVM: it will only interfere when you are not interacting with a virtual keyboard or mouse. The time of inactivity is counted from your last actions.

+

To update (see previous post):

+
curl https://files.pikvm.org/update-os.sh | bash
+
+

Or rw; pacman -Syu; reboot, if you have already updated the OS using the script earlier.

+

Howto enable it: https://docs.pikvm.org/mouse_jiggler/

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2023/10/24/pikvm-just-got-full-ps2-support/index.html b/blog/2023/10/24/pikvm-just-got-full-ps2-support/index.html new file mode 100644 index 00000000..6b9d2128 --- /dev/null +++ b/blog/2023/10/24/pikvm-just-got-full-ps2-support/index.html @@ -0,0 +1,2757 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + PiKVM just got full PS/2 support - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

PiKVM just got full PS/2 support

+ +

Previously, to support PS/2 keyboards (only), it was necessary to assemble a complex circuit on Arduino. With the transition to Raspberry Pi Pico, we finally have full support for both keyboard and mouse. The design has been greatly simplified, and is now compatible with V4 Plus.

+ + +

PS/2 support

+

HOWTO: https://docs.pikvm.org/pico_hid_bridge/

+

Let me know if you need a native support of the Sun SPARCstation Keyboard & Mouse!

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2023/12/03/introducing-the-new-diy-pikvm-v1-build/index.html b/blog/2023/12/03/introducing-the-new-diy-pikvm-v1-build/index.html new file mode 100644 index 00000000..69a48659 --- /dev/null +++ b/blog/2023/12/03/introducing-the-new-diy-pikvm-v1-build/index.html @@ -0,0 +1,2768 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Introducing the new DIY PiKVM V1 build - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

Introducing the new DIY PiKVM V1 build

+ +

We've been working for a while to unify DIY builds and simplify instructions. The result was a new DIY platform V1, which replaced V0.

+ + +
    +
  • The old Arduino HID was replaced by a new one based on the Raspberry Pi Pico.
  • +
  • The Pico HID uses an SPI connection and leaves the UART on the Raspberry free so that you can connect a USB-TTL adapter and use a serial console. Hurray!
  • +
  • Also, the new HID has full PS/2 mouse support, not just the keyboard, as before.
  • +
  • It is much easier and faster to make than the old V0 build with Arduino.
  • +
  • Among other things, now we're providing ready-made OS images for all DIYs. You will no longer have to build them yourself.
  • +
+

From this day on, V0 on Arduino is declared obsolete and consigned to oblivion. Instructions for its assembly are no longer available, except for the Arduino HID page. If you need an Arduino HID for anything, use the new Pico HID. The Pico HID is also capable of working as an in-place replacement for the Arduino HID, in case you need to replace it on your old V0.

+

OS images and updates for V0 will still be coming out. That is, V0 support will be continued. We only deprecate the instructions.

+

The assembly instructions for the PiKVM V2 have also been updated—this is greatly simplified and systematized.

+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2023/2023-01-23/2fa.webp b/blog/2023/2023-01-23/2fa.webp new file mode 100644 index 00000000..dcf38f77 Binary files /dev/null and b/blog/2023/2023-01-23/2fa.webp differ diff --git a/blog/2023/2023-10-24/pico_hid_bridge_ps2.webp b/blog/2023/2023-10-24/pico_hid_bridge_ps2.webp new file mode 100644 index 00000000..6c8b5d20 Binary files /dev/null and b/blog/2023/2023-10-24/pico_hid_bridge_ps2.webp differ diff --git a/blog/2024/02/03/kvmd-3-301-generated-nginx-configs/index.html b/blog/2024/02/03/kvmd-3-301-generated-nginx-configs/index.html new file mode 100644 index 00000000..2b82f5be --- /dev/null +++ b/blog/2024/02/03/kvmd-3-301-generated-nginx-configs/index.html @@ -0,0 +1,2786 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.301: Generated Nginx configs - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.301: Generated Nginx configs

+ +

Starting from this version, the /etc/kvmd/nginx.conf config will be replaced with the /etc/kvmd/nginx.conf.mako template, which will be rendered to /run/kvmd/nginx.conf taking into account the /etc/kvmd/override.yaml parameters and network configurations.

+ + +

This will make it very easy to turn off IPv6, HTTPS on and off and change ports using the standard override mechanism, like this:

+
nginx:
+    https:
+        enabled: false
+
+

If you had any changes in nginx.conf (for example, you previously disabled HTTPS manually), your Nginx configuration will roll back to the default, and HTTPS will be enabled again. To disable it, use the snippet above.

+

This will not affect the settings of certificates and Letsencrypt, nothing will break here. If you have not changed Nginx configs, you have nothing to worry about at all and the migration will be seamless.

+

To update:

+
$ curl https://files.pikvm.org/update-os.sh | bash
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2024/02/15/kvmd-3-304-video-quality-and-compatibility-improvements/index.html b/blog/2024/02/15/kvmd-3-304-video-quality-and-compatibility-improvements/index.html new file mode 100644 index 00000000..dbfb0817 --- /dev/null +++ b/blog/2024/02/15/kvmd-3-304-video-quality-and-compatibility-improvements/index.html @@ -0,0 +1,2840 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.304: Video quality and compatibility improvements - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.304: Video quality and compatibility improvements

+ +

In this release, you will get many improvements regarding video quality and EDID.

+ + +

PiKVM V4

+
    +
  • Default resolution is 1920×1080@60Hz.
  • +
  • Added native support of 1920×1200@60Hz!
  • +
  • Fixed broken audio on Linux hosts.
  • +
+

PiKVM V3

+
    +
  • Default resolution now is 1280×720@60Hz, it should improve BIOS compatibility.
  • +
  • Supported resolutions up to 1920×1080@50Hz.
  • +
  • Fixed broken audio on Linux hosts.
  • +
+

For V4 + V3 + DIY based on CSI bridges

+
    +
  • The color rendering quality has been significantly improved. Now the colors are bright and juicy, and not overexposed, see the attached picture.
  • +
  • Presumably, this release should put an end to shamanic dancing with EDID settings for different BIOSes.
  • +
  • Added several new supported resolutions like 1600×YYYY.
  • +
  • kvmd-edidconf --set-audio=1 now allows you to automatically add audio blocks for PiKVM, which are required by some particularly finicky OS.
  • +
+

To update:

+
$ curl https://files.pikvm.org/update-os.sh | bash
+
+

Important: if you are using a custom EDID, you will need to manually replace it with a new one after update. For example: rw; kvmd-edidconf --restore-default=v4plus; reboot (available: v0, v1, v2, v3, v4mini and v4plus)

+

Before/After

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2024/02/16/kvmd-3-305-new-option-to-hide-the-blue-dot/index.html b/blog/2024/02/16/kvmd-3-305-new-option-to-hide-the-blue-dot/index.html new file mode 100644 index 00000000..36c855d8 --- /dev/null +++ b/blog/2024/02/16/kvmd-3-305-new-option-to-hide-the-blue-dot/index.html @@ -0,0 +1,2778 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.305: New option to hide the blue dot - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.305: New option to hide the blue dot

+ +

Now you can disable the blue mouse dot.

+ + +

New display orientation options

+

But I still don't recommend doing this, because using the blue dot you can not wait for the real cursor. Click events are instantly transmitted to where the blue dot points, not the lagging real cursor.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2024/02/23/hdmi-passthrough-on pikvm-v4-plus/index.html b/blog/2024/02/23/hdmi-passthrough-on pikvm-v4-plus/index.html new file mode 100644 index 00000000..2fe3341c --- /dev/null +++ b/blog/2024/02/23/hdmi-passthrough-on pikvm-v4-plus/index.html @@ -0,0 +1,2755 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + HDMI passthrough on PiKVM V4 Plus - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

HDMI passthrough on PiKVM V4 Plus

+ +

We promised it at the start and finally it's almost done. The V4 Plus will get an HDMI passthrough on one of its outputs. Right now It's working on my desk, and it's pretty good: 1080p 60 fps with vertical sync, perfect 24 bit color and zero-latency.

+ + +

The first versions will pass the video if the online stream in the Web UI or VNC is not active. This is necessary to reduce all possible delays. I will finalize this in the future. I plan to release a public beta in the next week or two. In fact, it might happen sooner if I catch a wave.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2024/03/06/kvmd-ustreamer-performance-update/index.html b/blog/2024/03/06/kvmd-ustreamer-performance-update/index.html new file mode 100644 index 00000000..b4a6399d --- /dev/null +++ b/blog/2024/03/06/kvmd-ustreamer-performance-update/index.html @@ -0,0 +1,2806 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD + uStreamer performance update - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD + uStreamer performance update

+ +

Today I have prepared a great update for you. After few weeks of research, I managed to increase the video performance slightly reduce the latency for all CSI devices (PiKVM V4, V3 and CSI-based V2).

+ + +

In H.264 mode (WebUI and VNC), you will get stable 30fps on 1080p and 60fps on 720p +In MJPEG mode it just works a little faster.

+

To update:

+
# pikvm-update`
+
+

If this command is not available, please use:

+
# curl https://files.pikvm.org/update-os.sh | bash`
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2024/03/17/kvmd-3-319-display-orientation-options/index.html b/blog/2024/03/17/kvmd-3-319-display-orientation-options/index.html new file mode 100644 index 00000000..6ec8ae8c --- /dev/null +++ b/blog/2024/03/17/kvmd-3-319-display-orientation-options/index.html @@ -0,0 +1,2784 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.319: Display orientation options for H.264 stream - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.319: Display orientation options for H.264 stream

+ +

For the H.264 stream, there are now options to rotate the virtual screen.

+ + +

Rotation is done in 90° increments. The toggles are in the System menu in the web UI.

+

New display orientation options

+

To update:

+
# pikvm-update`
+
+

If this command is not available, please use:

+
# curl https://files.pikvm.org/update-os.sh | bash`
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2024/04/16/kvmd-3-333-hdmi-passthrough-now-available-on-v4-plus/index.html b/blog/2024/04/16/kvmd-3-333-hdmi-passthrough-now-available-on-v4-plus/index.html new file mode 100644 index 00000000..1fb3e1db --- /dev/null +++ b/blog/2024/04/16/kvmd-3-333-hdmi-passthrough-now-available-on-v4-plus/index.html @@ -0,0 +1,2781 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 3.333: HDMI passthrough now available on V4 Plus - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 3.333: HDMI passthrough now available on V4 Plus

+ +

After a long and thorny path of research, we are pleased to present the promised HDMI passthrough feature for PiKVM V4 Plus.

+ + +

+

The new feature allows you to connect PiKVM between the host and local display. PiKVM will not interfere with the normal operation of the display and passes the video signal through itself until you need remote access. In this case, PiKVM will copy the video stream to the Web UI or VNC.

+

But the most important thing is that the video will still be available on the local display at the same time as the stream! And of course it's zero-latency for the local display, with VSync support.

+

How-to: https://docs.pikvm.org/pass

+

Also, I'm glad that this release got a beautiful number, and I was finally able to make the Evangelion reference, which I forgot to do for 3.33 :)

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2024/08/19/kvmd-4-4-stable-hdmi-passthrough-on-v4-plus/index.html b/blog/2024/08/19/kvmd-4-4-stable-hdmi-passthrough-on-v4-plus/index.html new file mode 100644 index 00000000..db474f8a --- /dev/null +++ b/blog/2024/08/19/kvmd-4-4-stable-hdmi-passthrough-on-v4-plus/index.html @@ -0,0 +1,2778 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 4.4: HDMI passthrough on V4 Plus is stable now - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 4.4: HDMI passthrough on V4 Plus is stable now

+ +

Thanks to the work of the Raspberry kernel team, a bug related to incorrect colors in H.264 was finally fixed while working with passthrough.

+ + +

With the new release, this feature is now enabled by default, and you will get great juicy colors both in the stream and on the external physical monitor. See the documentation for details on setting this up.

+

Updating PiKVM OS

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2024/12/20/announcing-pikvm-switch-multiport-extender/index.html b/blog/2024/12/20/announcing-pikvm-switch-multiport-extender/index.html new file mode 100644 index 00000000..53da921a --- /dev/null +++ b/blog/2024/12/20/announcing-pikvm-switch-multiport-extender/index.html @@ -0,0 +1,2769 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Announcing PiKVM Switch Multiport Extender - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

Announcing PiKVM Switch Multiport Extender

+ +

The PiKVM team is excited to present its new PiKVM Switch Multiport Extender - the most full-featured switch for PiKVM devices. After much anticipation, the PiKVM Switch is now available for order! The switch allows you to connect up to four target hosts to a single PiKVM and provides full control over them.

+ + +

PiKVM Switch

+
    +
  • ATX control on each port.
  • +
  • Per-port EDID configuration.
  • +
  • HDMI dummy plug functionality.
  • +
  • True Plug-n-Play with no need for override.yaml setups and complete control via Web UI.
  • +
  • Multifunctional RGB LEDs with beacon mode and customizable color schemes.
  • +
  • Firmware update directly from PiKVM and ready for future hardware extensions.
  • +
  • Compatible with V4 Plus, V3 and DIY devices based on Pi2-Pi4 except Zero and V4 Mini.
  • +
+

And now the best part: the switches can be chained! Need four ports? Get a PiKVM Switch Multiport Extender. As your server fleet expands to eight, simply add another switch and link it to the first one. Need even more? No worries — connect up to five switches and enjoy 20 fully functional ports on your PiKVM. Say goodbye to replacing your entire KVM system!

+

You can order PiKVM Switch Multiport Extender from our international store.

+

Canadian customers can place an order at PiShop.ca.

+

See also the detailed technical descriptions and documentation on docs.pikvm.org.

+

The first batch will start shipping at the end of December 2024, and the second batch will be at the end of January 2025.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2024/12/25/kvmd-4-29-h264-over-http/index.html b/blog/2024/12/25/kvmd-4-29-h264-over-http/index.html new file mode 100644 index 00000000..ea77dfb2 --- /dev/null +++ b/blog/2024/12/25/kvmd-4-29-h264-over-http/index.html @@ -0,0 +1,2782 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 4.29: H.264 over HTTP - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 4.29: H.264 over HTTP

+ +

I know that some people have a problem using H.264 and WebRTC with firewalls, NAT, Tailscale and other things. Until recently, the only alternative was MJPEG, which consumes a lot of traffic. So I was constantly researching whether something could be done about it, and finally found a way.

+

Starting with KVMD 4.29, in addition to WebRTC, a new method of direct transmission of H.264 over HTTP will be available to you. Is the Web UI working? Then direct video transmission will also work. This completely solves the problem of WebRTC unavailability.

+ + +

This new feature is available for free not only to PiKVM V4 and V3 users, but also to all DIY users with HDMI-CSI devices. Merry Christmas to everyone! 🥳

+

A little tip: use H.264 gop 0 in settings.

+

To update just run pikvm-update. As usual, I advise you not to upgrade without physical access to the device. Also, you should not update PiKVM if the amount of alcohol in the blood on the occasion of the holiday is not zero or at least does not correspond to the level of the peak Ballmer.

+

PS: Our work on the open development of PiKVM is possible only through sales of hardware and donations. So if you want to support us, please consider [buying(https://pikvm.org/buy/) our official PiKVM or a Switch.

+

H.264 over HTTP

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2024/2024-02-15/before-after.webp b/blog/2024/2024-02-15/before-after.webp new file mode 100644 index 00000000..1781b3c7 Binary files /dev/null and b/blog/2024/2024-02-15/before-after.webp differ diff --git a/blog/2024/2024-02-16/hide-blue-dot.webp b/blog/2024/2024-02-16/hide-blue-dot.webp new file mode 100644 index 00000000..afb0bfc7 Binary files /dev/null and b/blog/2024/2024-02-16/hide-blue-dot.webp differ diff --git a/blog/2024/2024-03-17/display-orientation.webp b/blog/2024/2024-03-17/display-orientation.webp new file mode 100644 index 00000000..ee3a01b4 Binary files /dev/null and b/blog/2024/2024-03-17/display-orientation.webp differ diff --git a/blog/2024/2024-04-16/hdmi-passthrough.webm b/blog/2024/2024-04-16/hdmi-passthrough.webm new file mode 100644 index 00000000..3f108e50 Binary files /dev/null and b/blog/2024/2024-04-16/hdmi-passthrough.webm differ diff --git a/blog/2024/2024-08-19/pikvm-os-update.webp b/blog/2024/2024-08-19/pikvm-os-update.webp new file mode 100644 index 00000000..9bebaff1 Binary files /dev/null and b/blog/2024/2024-08-19/pikvm-os-update.webp differ diff --git a/blog/2024/2024-12-20/pikvm-switch.webp b/blog/2024/2024-12-20/pikvm-switch.webp new file mode 100644 index 00000000..a4b82b00 Binary files /dev/null and b/blog/2024/2024-12-20/pikvm-switch.webp differ diff --git a/blog/2024/2024-12-25/h264.webp b/blog/2024/2024-12-25/h264.webp new file mode 100644 index 00000000..2e85232b Binary files /dev/null and b/blog/2024/2024-12-25/h264.webp differ diff --git a/blog/2025/01/12/switch-update- better-hdmi-compatibility/index.html b/blog/2025/01/12/switch-update- better-hdmi-compatibility/index.html new file mode 100644 index 00000000..d92b2066 --- /dev/null +++ b/blog/2025/01/12/switch-update- better-hdmi-compatibility/index.html @@ -0,0 +1,2757 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Switch update: better HDMI compatibility - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

Switch update: better HDMI compatibility

+ +

An announcement for happy PiKVM Switch owners. We have released a firmware update that improves compatibility with some HDMI sources + audio.

+ + +

You need to update the PiKVM OS using pikvm-update, and the firmware will be delivered with it. Next, follow the instructions in the Switch menu.

+

This is another cool feature of the PiKVM Switch: you don't need to take any complicated steps to update the firmware. A switch connected to PiKVM receives an update from PiKVM, and then updates all other switches in the chain automatically.

+

Firmware update running

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2025/01/20/kvmd-4-44-two-way-audio-with-microphone/index.html b/blog/2025/01/20/kvmd-4-44-two-way-audio-with-microphone/index.html new file mode 100644 index 00000000..ebc8b61c --- /dev/null +++ b/blog/2025/01/20/kvmd-4-44-two-way-audio-with-microphone/index.html @@ -0,0 +1,2778 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 4.44: Two-way audio with microphone - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 4.44: Two-way audio with microphone

+ +

PiKVM V3 and V4 Mini/Plus just got two-way audio with microphone! Now you can use voice applications remotely, or you can just emotionally tell the server what you think about it.

+ + +

+

How to: https://docs.pikvm.org/audio

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2025/01/24/kvmd-4-49-dvd-images-support/index.html b/blog/2025/01/24/kvmd-4-49-dvd-images-support/index.html new file mode 100644 index 00000000..c982560e --- /dev/null +++ b/blog/2025/01/24/kvmd-4-49-dvd-images-support/index.html @@ -0,0 +1,2780 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 4.49: DVD images support - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 4.49: DVD images support

+ +

Starting with KVMD 4.49, the old 2.2 GB CD limit is now removed.

+ + +

PiKVM just learned how to support large DVD images natively, which means that you no longer need Ventoy to prepare Flash images for PiKVM. You can even use the official Windows ISO to install the OS! Small ISO images will be handled as CD as before, but for big images PiKVM will switch emulation to DVD mode automatically.

+

No CD ISO limit

+

How to update: pikvm-update, as usual.

+

If you've been dreaming of getting DVD emulation, then your wish has been fulfilled 🙂

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2025/02/16/pikvm-switch-firmware-update/index.html b/blog/2025/02/16/pikvm-switch-firmware-update/index.html new file mode 100644 index 00000000..d4f3ee94 --- /dev/null +++ b/blog/2025/02/16/pikvm-switch-firmware-update/index.html @@ -0,0 +1,2790 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + PiKVM Switch firmware update - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

PiKVM Switch firmware update

+ +

At the request of Switch owners, we have improved the compatibility with DIY devices based on CSI bridge.

+ + +
    +
  • Fixed the problem of the HDMI backpowering.
  • +
  • Added compatibility mode if DIY PiKVM does not see the image through the switch.
  • +
+

As we promised, this is a new generation of multiport switches. It's so smart that we can fix any problems with it with a simple firmware update. No more "Oh crap, my " doesn't show any videos because of EDID 😭 " Okay, okay, we just really proud of the design, sorry 🙂

+ +

Where to buy:

+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2025/03/11/kvmd-4-65-adopt-display-identifiers-on-v4-plus/index.html b/blog/2025/03/11/kvmd-4-65-adopt-display-identifiers-on-v4-plus/index.html new file mode 100644 index 00000000..fad08b94 --- /dev/null +++ b/blog/2025/03/11/kvmd-4-65-adopt-display-identifiers-on-v4-plus/index.html @@ -0,0 +1,2782 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 4.65: Adopt display identifiers on V4 Plus - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 4.65: Adopt display identifiers on V4 Plus

+ +

PiKVM V4 Plus just got a new tool to read and adopt display identifiers like model and serial number from the physical monitor.

+ + +

Install the updated OS using pikvm-update, connect the desired display to OUT2 port and use follows:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# kvmd-edidconf --import-display-ids --apply
+[root@pikvm ~]# ro
+
+

V4 will read display identifiers and apply them to own EDID. The target host connected to PiKVM will recognize it as your display.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2025/05/18/kvmd-4-72-big-bunch-of-big-improvements/index.html b/blog/2025/05/18/kvmd-4-72-big-bunch-of-big-improvements/index.html new file mode 100644 index 00000000..060d29f7 --- /dev/null +++ b/blog/2025/05/18/kvmd-4-72-big-bunch-of-big-improvements/index.html @@ -0,0 +1,2853 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 4.72: A big bunch of big improvements - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 4.72: A big bunch of big improvements

+ +

This release has gathered a whole bunch of features that some users have been asking. And this is a big step forward in terms of usability.

+ + +

Web UI

+
    +
  • ⭐ The maximized window continues to be maximized when the browser is resized or the resolution of the remote host is changed. It's meaning the stream will always occupy the maximum workspace without having to constantly press the dot button to remove the black bars from above or below the stream.
  • +
  • ⭐ The text in the paste menu can now be sent using the hotkey Ctrl+Enter.
  • +
  • ⭐ Added two-finger scrolling on touch devices.
  • +
  • ⭐ The virtual keyboard supports the key lock mode by clicking the middle button. Hotkeys like REISUB are now much more convenient to enter. Long left or short right click for hold like right now, middle for lock.
  • +
  • Fixed the mouse positioning at the right and bottom edges of the screen.
  • +
  • Fixed incorrect scrolling inertia when changing the direction. The scrolling algorithm has been significantly improved.
  • +
  • Fixed the keys overlapping on the virtual keyboard on HiDPI screens.
  • +
+

VNC

+
    +
  • ⭐ Eliminated the mess with the clipboard. Now, to paste the text, you just need to copy it to the client PC, and then use the magic LeftAlt,LeftAlt,P hotkey (quickly in a row, without holding). No more accidental insertion when switching windows.
  • +
  • ⭐ Hotkeys for switching channels on the PiKVM Switch on any VNC client. If you have one or two switches, you can use LeftAlt,LeftAlt,1 (1-8) to switch between 8 channels. For three or more Switches, you need to use double numbers, like LeftAlt,LeftAlt,3,2 (unit 3, channel 2).
  • +
  • ⭐ VNC clients showing host information will now display the current active port of PiKVM Switch and KVM name.
  • +
  • VNCAuth no longer requires you to write the KVMD password in /etc/kvmd/vncpasswd and does not prevent you from using one-time passwords with KVMD. Now you can turn it on if you haven't done it before.
  • +
+

IPMI

+
    +
  • kvmd-ipmi no longer requires writing the KVMD password in /etc/kvmd/ipmipasswd and does not prevent you from using 2FA with KVMD. Now you can turn it on if you haven't done it before.
  • +
+

PiKVM Switch

+
    +
  • ⭐ Improved VNC integration (see the previous header).
  • +
  • Option to disable the dummy plug function.
  • +
+

To update:

+

pikvm-update

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2025/05/23/kvmd-4-74-local-usb-mouse-passthrough/index.html b/blog/2025/05/23/kvmd-4-74-local-usb-mouse-passthrough/index.html new file mode 100644 index 00000000..0679bf93 --- /dev/null +++ b/blog/2025/05/23/kvmd-4-74-local-usb-mouse-passthrough/index.html @@ -0,0 +1,2784 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 4.74: Local USB keyboard & mouse passthrough - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 4.74: Local USB keyboard & mouse passthrough

+ +

With this new mode, all USB keyboards and mice connected to PiKVM directly will be forwarded the host. If you're using PiKVM Switch, they will be forwarded via the Switch to the active selected host.

+ + +

There are several hotkeys available that are always active:

+
    +
  • LeftAlt, LeftAlt, K - (mnemonic KVM, quick hit) disable keyboard/mouse grabbing and allow them to use with PiKVM locally, for example, for the console operating.
  • +
  • LeftAlt, LeftAlt, H - (Host) - switch back to the passthrough mode and pass keyboard-mouse events to the host.
  • +
  • Switching the PiKVM Switch channels. If you have one or two switches, you can use LeftAlt, LeftAlt, 1 (1-8) to switch between 8 channels. For three or more Switches, you need to use double numbers, like LeftAlt, LeftAlt, 3, 2 (unit 3, channel 2).
  • +
+

Now you can set up your workplace so that all your input devices are connected via PiKVM, this is especially convenient with the V4 Plus, which can also passthrough a monitor. And if you use a switch, then you will no longer need to have a separate keyboard and mouse for local work. Your workplace behaves exactly the same locally as it does remotely.

+

To enable this feature, update OS with pikvm-update and run rw; systemctl enable --now kvmd-localhid; ro.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2025/05/27/kvmd-4-76-advanced-diagnostics-for-the-video-streams/index.html b/blog/2025/05/27/kvmd-4-76-advanced-diagnostics-for-the-video-streams/index.html new file mode 100644 index 00000000..87215001 --- /dev/null +++ b/blog/2025/05/27/kvmd-4-76-advanced-diagnostics-for-the-video-streams/index.html @@ -0,0 +1,2777 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 4.76: Advanced diagnostics for the video stream - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 4.76: Advanced diagnostics for the video stream

+ +

Now you will see the reason why there is no signal. We reliably distinguish the condition of the cable from the absence of a signal or unsupported video mode.

+ + +

Video stream diagnostics

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2025/09/30/kvmd-4-99-oled-display-improvements-on-v3-and-v4/index.html b/blog/2025/09/30/kvmd-4-99-oled-display-improvements-on-v3-and-v4/index.html new file mode 100644 index 00000000..75c67602 --- /dev/null +++ b/blog/2025/09/30/kvmd-4-99-oled-display-improvements-on-v3-and-v4/index.html @@ -0,0 +1,2777 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + KVMD 4.99: OLED display improvements on V3 and V4 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 4.99: OLED display improvements on V3 and V4

+ +
    +
  • Now the display shows the number of users who use PiKVM via the Web UI and VNC. This number is located next to the cute spinning stick that we all love so much.
  • +
  • If there is at least one user, the display brightness will be reduced to a minimum to prolong its life.
  • +
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2025/10/23/kvmd-4-107-configuration-changes/index.html b/blog/2025/10/23/kvmd-4-107-configuration-changes/index.html new file mode 100644 index 00000000..0332e5e0 --- /dev/null +++ b/blog/2025/10/23/kvmd-4-107-configuration-changes/index.html @@ -0,0 +1,2790 @@ + + + + + + + + + + + + + + + + + + + + + + + + KVMD 4.107: Configuration changes - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + + + + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + + + +

KVMD 4.107: Configuration changes

+ +

We have revamped the configuration system. If PiKVM customization concerns you, read on.

+ + +

Here are the main changes:

+
    +
  • +

    We have moved /etc/kvmd/main.yaml to /usr/lib/kvmd/, because it's a platform config that should never be changed.

    +
  • +
  • +

    We have deprecated and removed /etc/kvmd/logging.yaml. It contained some Python-specific logging settings that no one had ever changed. Getting rid of this artifact will simplify the configuration structure for some future improvements.

    +
  • +
  • +

    We have deprecated /etc/kvmd/auth.yaml. This is a legacy auth configuration that existed before /etc/kvmd/override.yaml was introduced, and has never been suggested for use even in the documentation. If you have ever customized your PiKVM with auth.yaml (likely not), your changes will be carefully moved to /etc/kvmd/override.d/..., and the source file is auth.yaml should be deleted manually. Please see here for details.

    +
  • +
  • +

    The !include directive in /etc/kvmd/override* and /etc/kvmd/meta.yaml configs is now deprecated and removed. Instead, you can place your partial config files into the /etc/kvmd/override.d directory, which is described in the documentation. Automatic migration is not possible here, and if you used !include for some reason, pikvm-update will tell you to remove this from the configuration before updating.

    +
  • +
+

Please note that if you stored all the configs only in override.d and override.yaml and did not use !include, the migration will be transparent for you.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/2025/2025-01-12/firmware-update.webp b/blog/2025/2025-01-12/firmware-update.webp new file mode 100644 index 00000000..7f6fe0e7 Binary files /dev/null and b/blog/2025/2025-01-12/firmware-update.webp differ diff --git a/blog/2025/2025-01-20/two-way-audio-with-mic.webm b/blog/2025/2025-01-20/two-way-audio-with-mic.webm new file mode 100644 index 00000000..dc952291 Binary files /dev/null and b/blog/2025/2025-01-20/two-way-audio-with-mic.webm differ diff --git a/blog/2025/2025-01-24/no-cd-iso-limit.webp b/blog/2025/2025-01-24/no-cd-iso-limit.webp new file mode 100644 index 00000000..ca324752 Binary files /dev/null and b/blog/2025/2025-01-24/no-cd-iso-limit.webp differ diff --git a/blog/2025/2025-05-27/video-stream-diagnostics.webp b/blog/2025/2025-05-27/video-stream-diagnostics.webp new file mode 100644 index 00000000..6cb92814 Binary files /dev/null and b/blog/2025/2025-05-27/video-stream-diagnostics.webp differ diff --git a/blog/archive/2020/index.html b/blog/archive/2020/index.html new file mode 100644 index 00000000..79aeffb4 --- /dev/null +++ b/blog/archive/2020/index.html @@ -0,0 +1,3298 @@ + + + + + + + + + + + + + + + + + + + + + + + + 2020 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2020

+
+ +
+
+ + + + +
+
+

Some news about v3

+

We have some news about v3. The prototypes are almost ready. Since the last release, they have included several changes and additional features.

+ + + + +
+
+ + + + + + + + + + + + + +
+
+ + + + +
+
+

Another test request for v2 users of RPi4 and ZeroW

+

I found a way to improve USB HID/Mass Storage compatibility with some motherboards. I would like to ask you to check if there are any problems because of this. If successful, if you didn't have MSD working, it may work after this change.

+ + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/archive/2020/page/2/index.html b/blog/archive/2020/page/2/index.html new file mode 100644 index 00000000..2e1bed99 --- /dev/null +++ b/blog/archive/2020/page/2/index.html @@ -0,0 +1,3296 @@ + + + + + + + + + + + + + + + + + + + + + + + + 2020 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2020

+
+ + + + + + + +
+
+ + + + +
+
+

KVMD 1.100: GPIO and USB relays

+

This release introduces a feature that I have been working on for a long time and that will significantly expand the functionality of Pi-KVM: the ability to use GPIO and USB relays.

+ + + + +
+
+ +
+
+ + + + +
+
+

Pi-KVM is now available on Raspberry Pi 1

+

In the last release, I added the ability to use this board. This is still unofficial and not reflected in the documentation, but you can already build the system using the build environment if you use the BOARD=rpi and PLATFORM=v0-hdmi or v0-hdmiusb parameters.

+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/archive/2020/page/3/index.html b/blog/archive/2020/page/3/index.html new file mode 100644 index 00000000..a9f1ff86 --- /dev/null +++ b/blog/archive/2020/page/3/index.html @@ -0,0 +1,3297 @@ + + + + + + + + + + + + + + + + + + + + + + + + 2020 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2020

+
+ + + + + + + +
+
+ + + + +
+
+

Security note for v2

+

After installation, Pi-KVM will be available via USB OTG from the managed server via the virtual serial console port.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 1.78: VNC improvements

+

Two important VNC improvements: client connections that have hung up are now terminated correctly using TCP_KEEPALIVE; applying the TCP_NODELAY parameter slightly improved responsiveness.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 1.75: Hardware health monitoring

+

Today's big release KVMD 1.75 includes several important features.

+

1) Hardware health monitoring. If your Pi-KVM suffers from overheating or lack of power, you will see the corresponding icons and messages in the interface. Don't ignore them! The problems, if any, are not caused by the update, they have always been there, but you have not seen them before, because they were hidden in the kernel logs.

+ + + + +
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/archive/2021/index.html b/blog/archive/2021/index.html new file mode 100644 index 00000000..5b75dc12 --- /dev/null +++ b/blog/archive/2021/index.html @@ -0,0 +1,3300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 2021 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2021

+
+ + + +
+
+ + + + +
+
+

KVMD 3.33: New Wi-Fi configuration method

+

Starting from today, the old way to configure Wi-Fi using netctl is deprecated. Instead, it is proposed to use a more native way with systemd-networkd, which is already used to configure Ethernet.

+ + + + +
+
+ + + + + + + + + +
+
+ + + + +
+
+

KVMD 3.14: The Epic Apple fix, Vol.2

+

I continue to eliminate ancient bugs from USB. So great news for Apple and v2/v3/OTG users: you no longer need to use the Arduino HID to get into the Boot Menu or Recovery Mode.

+ + + + +
+
+ +
+
+ + + + +
+
+

Big testing request

+

I have a very important request. We are preparing for a big update that will improve compatibility with BIOS and UEFI on many devices, and I need as many people as possible to check out the new build of the kernel and core packages.

+ + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/archive/2021/page/2/index.html b/blog/archive/2021/page/2/index.html new file mode 100644 index 00000000..da6ceddf --- /dev/null +++ b/blog/archive/2021/page/2/index.html @@ -0,0 +1,3298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 2021 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2021

+
+ +
+
+ + + + +
+
+

KVMD 3.9: Paste-as-Keys update

+

For the Paste-as-Keys function, the state of the confirmation switch and the selected keymap are saved. You asked for it—I did it.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 3.8: The Epic Apple fix!

+

For a long time, Pi-KVM had several problems related to the mouse and keyboard on Apple. Previously, you could not use the mouse in the boot menu, and recovery mode also required you to connect the mouse, despite the fact that the cursor was functioning. Because of these bugs, it was impossible to fully remotely control your Mac. Now all this is fixed!

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.0: The big H.264 release!

+

I'm happy to introduce you to a feature I've been working on for the last six months. Now, instead of using bold MJPEG for video, you can use fast WebRTC with H.264.

+ + + + +
+
+ + + + + +
+
+ + + + +
+
+

KVMD 2.71: Massive internal changes

+

This is a very important release. In addition to new features and fixes, a large number of internal changes have been made for the upcoming H264/WebRTC support.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 2.65: Ezcoo fix for USB 3.0

+

If you bought an Ezcoo switch for USB 3.0, then in order for it to work with Pi-KVM, you need to upgrade to the new version and add one option to the config.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 2.53: Web terminal in a web UI window

+

You can now have the web terminal in a window above the video stream if you like. The focus works a little strange, but it is quite functional and even supports changing the size.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/archive/2021/page/3/index.html b/blog/archive/2021/page/3/index.html new file mode 100644 index 00000000..316dbcde --- /dev/null +++ b/blog/archive/2021/page/3/index.html @@ -0,0 +1,2973 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 2021 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2021

+
+ + + +
+
+ + + + +
+
+

KVMD 2.31: Critical bug fix

+

In recent weeks, I have been mainly working on H264 and have achieved significant results ⁠h264_vnc_funding. A critical bug has been fixed in the kernel that prevents the H264 encoder from being enabled by default, so now everyone can try H264 for VNC for v2 and CSI bridge (only).

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 2.27: Critical bug fix

+

A lot of changes have accumulated since the last announced release. Mostly finally fixed wifi support on Zero and RPi4.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

uStreamer 3.0: H264 video recording

+

Currently, Pi-KVM uses MJPEG for video transmission. This is a simple and widely supported, but not very effective video format. In the near future, it is planned to support H264, and then switch to it as the main one.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/archive/2022/index.html b/blog/archive/2022/index.html new file mode 100644 index 00000000..68f8201a --- /dev/null +++ b/blog/archive/2022/index.html @@ -0,0 +1,3300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 2022 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2022

+
+ + + + + +
+
+ + + + +
+
+

KVMD 3.159: Significant VNC improvement

+

The VNC server has learned how to transmit video asynchronously to make it fast and smooth. Now, FPS can grow about twice, it will be especially noticeable with poor internet quality.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.126: Writable flash drive storage

+

Now you can upload the flash drive image to MSD, write some files to it, or even install entire OS to the PiKVM MSD drive (I don't know why, but you can), and download the image back. Use the new feature wisely.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.116: Let's Encrypt certificates

+

Usually Let's Encrypt certificates are issued and updated automatically using Certbot, however, since PiKVM uses a read-only file system, special tools around Certbot are required to work with certificates.

+ + + + +
+
+ +
+
+ + + + +
+
+

Introducing a new tool — kvmd-edidconf

+

For the happy owners of V2 and V3, we now offer a new utility, kvmd-edidconf. It will help you configure EDID (the display metadata) and provide import/export for EDID modification using advanced editors such as AW EDID Editor.

+ + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/archive/2022/page/2/index.html b/blog/archive/2022/page/2/index.html new file mode 100644 index 00000000..69e94a51 --- /dev/null +++ b/blog/archive/2022/page/2/index.html @@ -0,0 +1,2973 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 2022 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2022

+
+ + + +
+
+ + + + +
+
+

New testing branch available

+

A few months ago, due to the release of Bullseye, the usual video encoding method used in PiKVM stopped working in the new kernel. OpenMAX and MMAL were deprecated and uStreamer has ben rewrited to use new M2M encoder. Now the work is almost completed and everything seems to be working fine.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

Zero W 1 and RPi 1 end-of-life

+

Since Arch Linux ARM has discontinued support for the ARMv6 architecture , we are discontinuing support for PiKVM based on Zero W and RPi 1, because we don't have the ability to maintain our own fork of the whole distro for this architecture.

+ + + + +
+
+ + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/archive/2023/index.html b/blog/archive/2023/index.html new file mode 100644 index 00000000..70ce02c1 --- /dev/null +++ b/blog/archive/2023/index.html @@ -0,0 +1,3300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 2023 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2023

+
+ + + +
+
+ + + + +
+
+

PiKVM just got full PS/2 support

+

Previously, to support PS/2 keyboards (only), it was necessary to assemble a complex circuit on Arduino. With the transition to Raspberry Pi Pico, we finally have full support for both keyboard and mouse. The design has been greatly simplified, and is now compatible with V4 Plus.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 3.265: Mouse Jiggler!

+

This is a feature that many users have been asking for for a long time. So, mouse jiggler will allow you to prevent the monitor from falling asleep if it was turned on.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.249: easier uploading over SSH

+

In addition to many minor improvements from the previous announcement, an important change has occurred in the new release for those who use advanced Mass Storage emulation features.

+ + + + +
+
+ + + + + + + + + +
+
+ + + + +
+
+

KVMD 3.196: 2FA support

+

Many have asked for this, so now you have the opportunity to increase the security of your PiKVM.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/archive/2024/index.html b/blog/archive/2024/index.html new file mode 100644 index 00000000..08e7461c --- /dev/null +++ b/blog/archive/2024/index.html @@ -0,0 +1,3301 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 2024 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2024

+
+ +
+
+ + + + +
+
+

KVMD 4.29: H.264 over HTTP

+

I know that some people have a problem using H.264 and WebRTC with firewalls, NAT, Tailscale and other things. Until recently, the only alternative was MJPEG, which consumes a lot of traffic. So I was constantly researching whether something could be done about it, and finally found a way.

+

Starting with KVMD 4.29, in addition to WebRTC, a new method of direct transmission of H.264 over HTTP will be available to you. Is the Web UI working? Then direct video transmission will also work. This completely solves the problem of WebRTC unavailability.

+ + + + +
+
+ +
+
+ + + + +
+
+

Announcing PiKVM Switch Multiport Extender

+

The PiKVM team is excited to present its new PiKVM Switch Multiport Extender - the most full-featured switch for PiKVM devices. After much anticipation, the PiKVM Switch is now available for order! The switch allows you to connect up to four target hosts to a single PiKVM and provides full control over them.

+ + + + +
+
+ + + + + + + +
+
+ + + + +
+
+

KVMD + uStreamer performance update

+

Today I have prepared a great update for you. After few weeks of research, I managed to increase the video performance slightly reduce the latency for all CSI devices (PiKVM V4, V3 and CSI-based V2).

+ + + + +
+
+ +
+
+ + + + +
+
+

HDMI passthrough on PiKVM V4 Plus

+

We promised it at the start and finally it's almost done. The V4 Plus will get an HDMI passthrough on one of its outputs. Right now It's working on my desk, and it's pretty good: 1080p 60 fps with vertical sync, perfect 24 bit color and zero-latency.

+ + + + +
+
+ + + + + +
+
+ + + + +
+
+

KVMD 3.301: Generated Nginx configs

+

Starting from this version, the /etc/kvmd/nginx.conf config will be replaced with the /etc/kvmd/nginx.conf.mako template, which will be rendered to /run/kvmd/nginx.conf taking into account the /etc/kvmd/override.yaml parameters and network configurations.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/archive/2025/index.html b/blog/archive/2025/index.html new file mode 100644 index 00000000..10bc056a --- /dev/null +++ b/blog/archive/2025/index.html @@ -0,0 +1,3296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 2025 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

2025

+
+ + + +
+
+ + + + +
+
+

KVMD 4.99: OLED display improvements on V3 and V4

+
    +
  • Now the display shows the number of users who use PiKVM via the Web UI and VNC. This number is located next to the cute spinning stick that we all love so much.
  • +
  • If there is at least one user, the display brightness will be reduced to a minimum to prolong its life.
  • +
+ +
+
+ + + + + + + + + + + + + +
+
+ + + + +
+
+

KVMD 4.44: Two-way audio with microphone

+

PiKVM V3 and V4 Mini/Plus just got two-way audio with microphone! Now you can use voice applications remotely, or you can just emotionally tell the server what you think about it.

+ + + + +
+
+ + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/development/index.html b/blog/category/development/index.html new file mode 100644 index 00000000..5e429666 --- /dev/null +++ b/blog/category/development/index.html @@ -0,0 +1,3235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Development - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Development

+
+ +
+
+ + + + +
+
+

HDMI passthrough on PiKVM V4 Plus

+

We promised it at the start and finally it's almost done. The V4 Plus will get an HDMI passthrough on one of its outputs. Right now It's working on my desk, and it's pretty good: 1080p 60 fps with vertical sync, perfect 24 bit color and zero-latency.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

Introducing a new tool — kvmd-edidconf

+

For the happy owners of V2 and V3, we now offer a new utility, kvmd-edidconf. It will help you configure EDID (the display metadata) and provide import/export for EDID modification using advanced editors such as AW EDID Editor.

+ + + + +
+
+ +
+
+ + + + +
+
+

New testing branch available

+

A few months ago, due to the release of Bullseye, the usual video encoding method used in PiKVM stopped working in the new kernel. OpenMAX and MMAL were deprecated and uStreamer has ben rewrited to use new M2M encoder. Now the work is almost completed and everything seems to be working fine.

+ + + + +
+
+ +
+
+ + + + +
+
+

Big testing request

+

I have a very important request. We are preparing for a big update that will improve compatibility with BIOS and UEFI on many devices, and I need as many people as possible to check out the new build of the kernel and core packages.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

Another test request for v2 users of RPi4 and ZeroW

+

I found a way to improve USB HID/Mass Storage compatibility with some motherboards. I would like to ask you to check if there are any problems because of this. If successful, if you didn't have MSD working, it may work after this change.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

Security note for v2

+

After installation, Pi-KVM will be available via USB OTG from the managed server via the virtual serial console port.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/products/index.html b/blog/category/products/index.html new file mode 100644 index 00000000..3a40131d --- /dev/null +++ b/blog/category/products/index.html @@ -0,0 +1,3300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Products - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Products

+
+ +
+
+ + + + +
+
+

Announcing PiKVM Switch Multiport Extender

+

The PiKVM team is excited to present its new PiKVM Switch Multiport Extender - the most full-featured switch for PiKVM devices. After much anticipation, the PiKVM Switch is now available for order! The switch allows you to connect up to four target hosts to a single PiKVM and provides full control over them.

+ + + + +
+
+ + + + + +
+
+ + + + +
+
+

PiKVM just got full PS/2 support

+

Previously, to support PS/2 keyboards (only), it was necessary to assemble a complex circuit on Arduino. With the transition to Raspberry Pi Pico, we finally have full support for both keyboard and mouse. The design has been greatly simplified, and is now compatible with V4 Plus.

+ + + + +
+
+ + + + + + + +
+
+ + + + +
+
+

Zero W 1 and RPi 1 end-of-life

+

Since Arch Linux ARM has discontinued support for the ARMv6 architecture , we are discontinuing support for PiKVM based on Zero W and RPi 1, because we don't have the ability to maintain our own fork of the whole distro for this architecture.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

Some news about v3

+

We have some news about v3. The prototypes are almost ready. Since the last release, they have included several changes and additional features.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/products/page/2/index.html b/blog/category/products/page/2/index.html new file mode 100644 index 00000000..77246745 --- /dev/null +++ b/blog/category/products/page/2/index.html @@ -0,0 +1,2778 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Products - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+
+

Products

+
+ +
+
+ + + + +
+
+

Pi-KVM is now available on Raspberry Pi 1

+

In the last release, I added the ability to use this board. This is still unofficial and not reflected in the documentation, but you can already build the system using the build environment if you use the BOARD=rpi and PLATFORM=v0-hdmi or v0-hdmiusb parameters.

+ + + + +
+
+ + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/releases/index.html b/blog/category/releases/index.html new file mode 100644 index 00000000..18ae5b62 --- /dev/null +++ b/blog/category/releases/index.html @@ -0,0 +1,3296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Releases - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Releases

+
+ + + +
+
+ + + + +
+
+

KVMD 4.99: OLED display improvements on V3 and V4

+
    +
  • Now the display shows the number of users who use PiKVM via the Web UI and VNC. This number is located next to the cute spinning stick that we all love so much.
  • +
  • If there is at least one user, the display brightness will be reduced to a minimum to prolong its life.
  • +
+ +
+
+ + + + + + + + + + + + + +
+
+ + + + +
+
+

KVMD 4.44: Two-way audio with microphone

+

PiKVM V3 and V4 Mini/Plus just got two-way audio with microphone! Now you can use voice applications remotely, or you can just emotionally tell the server what you think about it.

+ + + + +
+
+ + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/releases/page/2/index.html b/blog/category/releases/page/2/index.html new file mode 100644 index 00000000..6830c9a0 --- /dev/null +++ b/blog/category/releases/page/2/index.html @@ -0,0 +1,3299 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Releases - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Releases

+
+ +
+
+ + + + +
+
+

KVMD 4.29: H.264 over HTTP

+

I know that some people have a problem using H.264 and WebRTC with firewalls, NAT, Tailscale and other things. Until recently, the only alternative was MJPEG, which consumes a lot of traffic. So I was constantly researching whether something could be done about it, and finally found a way.

+

Starting with KVMD 4.29, in addition to WebRTC, a new method of direct transmission of H.264 over HTTP will be available to you. Is the Web UI working? Then direct video transmission will also work. This completely solves the problem of WebRTC unavailability.

+ + + + +
+
+ + + + + +
+
+ + + + +
+
+

KVMD + uStreamer performance update

+

Today I have prepared a great update for you. After few weeks of research, I managed to increase the video performance slightly reduce the latency for all CSI devices (PiKVM V4, V3 and CSI-based V2).

+ + + + +
+
+ + + + + +
+
+ + + + +
+
+

KVMD 3.301: Generated Nginx configs

+

Starting from this version, the /etc/kvmd/nginx.conf config will be replaced with the /etc/kvmd/nginx.conf.mako template, which will be rendered to /run/kvmd/nginx.conf taking into account the /etc/kvmd/override.yaml parameters and network configurations.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 3.265: Mouse Jiggler!

+

This is a feature that many users have been asking for for a long time. So, mouse jiggler will allow you to prevent the monitor from falling asleep if it was turned on.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.249: easier uploading over SSH

+

In addition to many minor improvements from the previous announcement, an important change has occurred in the new release for those who use advanced Mass Storage emulation features.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/releases/page/3/index.html b/blog/category/releases/page/3/index.html new file mode 100644 index 00000000..2acbbb82 --- /dev/null +++ b/blog/category/releases/page/3/index.html @@ -0,0 +1,3298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Releases - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Releases

+
+ + + + + + + +
+
+ + + + +
+
+

KVMD 3.196: 2FA support

+

Many have asked for this, so now you have the opportunity to increase the security of your PiKVM.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.159: Significant VNC improvement

+

The VNC server has learned how to transmit video asynchronously to make it fast and smooth. Now, FPS can grow about twice, it will be especially noticeable with poor internet quality.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.126: Writable flash drive storage

+

Now you can upload the flash drive image to MSD, write some files to it, or even install entire OS to the PiKVM MSD drive (I don't know why, but you can), and download the image back. Use the new feature wisely.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 3.116: Let's Encrypt certificates

+

Usually Let's Encrypt certificates are issued and updated automatically using Certbot, however, since PiKVM uses a read-only file system, special tools around Certbot are required to work with certificates.

+ + + + +
+
+ + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/releases/page/4/index.html b/blog/category/releases/page/4/index.html new file mode 100644 index 00000000..bc33f7c6 --- /dev/null +++ b/blog/category/releases/page/4/index.html @@ -0,0 +1,3298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Releases - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Releases

+
+ + + + + + + + + +
+
+ + + + +
+
+

KVMD 3.33: New Wi-Fi configuration method

+

Starting from today, the old way to configure Wi-Fi using netctl is deprecated. Instead, it is proposed to use a more native way with systemd-networkd, which is already used to configure Ethernet.

+ + + + +
+
+ + + + + + + + + +
+
+ + + + +
+
+

KVMD 3.14: The Epic Apple fix, Vol.2

+

I continue to eliminate ancient bugs from USB. So great news for Apple and v2/v3/OTG users: you no longer need to use the Arduino HID to get into the Boot Menu or Recovery Mode.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/releases/page/5/index.html b/blog/category/releases/page/5/index.html new file mode 100644 index 00000000..841478ba --- /dev/null +++ b/blog/category/releases/page/5/index.html @@ -0,0 +1,3298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Releases - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Releases

+
+ + + + + +
+
+ + + + +
+
+

KVMD 3.9: Paste-as-Keys update

+

For the Paste-as-Keys function, the state of the confirmation switch and the selected keymap are saved. You asked for it—I did it.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 3.8: The Epic Apple fix!

+

For a long time, Pi-KVM had several problems related to the mouse and keyboard on Apple. Previously, you could not use the mouse in the boot menu, and recovery mode also required you to connect the mouse, despite the fact that the cursor was functioning. Because of these bugs, it was impossible to fully remotely control your Mac. Now all this is fixed!

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.0: The big H.264 release!

+

I'm happy to introduce you to a feature I've been working on for the last six months. Now, instead of using bold MJPEG for video, you can use fast WebRTC with H.264.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 2.71: Massive internal changes

+

This is a very important release. In addition to new features and fixes, a large number of internal changes have been made for the upcoming H264/WebRTC support.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 2.65: Ezcoo fix for USB 3.0

+

If you bought an Ezcoo switch for USB 3.0, then in order for it to work with Pi-KVM, you need to upgrade to the new version and add one option to the config.

+ + + + +
+
+ + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/releases/page/6/index.html b/blog/category/releases/page/6/index.html new file mode 100644 index 00000000..d36a0fa9 --- /dev/null +++ b/blog/category/releases/page/6/index.html @@ -0,0 +1,3298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Releases - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Releases

+
+ +
+
+ + + + +
+
+

KVMD 2.53: Web terminal in a web UI window

+

You can now have the web terminal in a window above the video stream if you like. The focus works a little strange, but it is quite functional and even supports changing the size.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 2.31: Critical bug fix

+

In recent weeks, I have been mainly working on H264 and have achieved significant results ⁠h264_vnc_funding. A critical bug has been fixed in the kernel that prevents the H264 encoder from being enabled by default, so now everyone can try H264 for VNC for v2 and CSI bridge (only).

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 2.27: Critical bug fix

+

A lot of changes have accumulated since the last announced release. Mostly finally fixed wifi support on Zero and RPi4.

+ + + + +
+
+ +
+
+ + + + +
+
+

uStreamer 3.0: H264 video recording

+

Currently, Pi-KVM uses MJPEG for video transmission. This is a simple and widely supported, but not very effective video format. In the near future, it is planned to support H264, and then switch to it as the main one.

+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/releases/page/7/index.html b/blog/category/releases/page/7/index.html new file mode 100644 index 00000000..bd15d37d --- /dev/null +++ b/blog/category/releases/page/7/index.html @@ -0,0 +1,3298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Releases - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Releases

+
+ + + + + + + + + + + +
+
+ + + + +
+
+

KVMD 1.100: GPIO and USB relays

+

This release introduces a feature that I have been working on for a long time and that will significantly expand the functionality of Pi-KVM: the ability to use GPIO and USB relays.

+ + + + +
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/category/releases/page/8/index.html b/blog/category/releases/page/8/index.html new file mode 100644 index 00000000..683de6e0 --- /dev/null +++ b/blog/category/releases/page/8/index.html @@ -0,0 +1,3234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Releases - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Releases

+
+ + + + + + + + + +
+
+ + + + +
+
+

KVMD 1.78: VNC improvements

+

Two important VNC improvements: client connections that have hung up are now terminated correctly using TCP_KEEPALIVE; applying the TCP_NODELAY parameter slightly improved responsiveness.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 1.75: Hardware health monitoring

+

Today's big release KVMD 1.75 includes several important features.

+

1) Hardware health monitoring. If your Pi-KVM suffers from overheating or lack of power, you will see the corresponding icons and messages in the interface. Don't ignore them! The problems, if any, are not caused by the update, they have always been there, but you have not seen them before, because they were hidden in the kernel logs.

+ + + + +
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/index.html b/blog/index.html new file mode 100644 index 00000000..ac65bc7e --- /dev/null +++ b/blog/index.html @@ -0,0 +1,3163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Blog - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Blog

+

Welcome to the PiKVM Blog. Here you'll find updates, tutorials, release notes, and insights into KVM-over-IP development.

+
+ + + +
+
+ + + + +
+
+

KVMD 4.99: OLED display improvements on V3 and V4

+
    +
  • Now the display shows the number of users who use PiKVM via the Web UI and VNC. This number is located next to the cute spinning stick that we all love so much.
  • +
  • If there is at least one user, the display brightness will be reduced to a minimum to prolong its life.
  • +
+ +
+
+ + + + + + + + + + + + + +
+
+ + + + +
+
+

KVMD 4.44: Two-way audio with microphone

+

PiKVM V3 and V4 Mini/Plus just got two-way audio with microphone! Now you can use voice applications remotely, or you can just emotionally tell the server what you think about it.

+ + + + +
+
+ + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/page/10/index.html b/blog/page/10/index.html new file mode 100644 index 00000000..4be817e7 --- /dev/null +++ b/blog/page/10/index.html @@ -0,0 +1,3167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Blog - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Blog

+
+ + + + + + + +
+
+ + + + +
+
+

Security note for v2

+

After installation, Pi-KVM will be available via USB OTG from the managed server via the virtual serial console port.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 1.78: VNC improvements

+

Two important VNC improvements: client connections that have hung up are now terminated correctly using TCP_KEEPALIVE; applying the TCP_NODELAY parameter slightly improved responsiveness.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 1.75: Hardware health monitoring

+

Today's big release KVMD 1.75 includes several important features.

+

1) Hardware health monitoring. If your Pi-KVM suffers from overheating or lack of power, you will see the corresponding icons and messages in the interface. Don't ignore them! The problems, if any, are not caused by the update, they have always been there, but you have not seen them before, because they were hidden in the kernel logs.

+ + + + +
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/page/2/index.html b/blog/page/2/index.html new file mode 100644 index 00000000..0488cdc8 --- /dev/null +++ b/blog/page/2/index.html @@ -0,0 +1,3167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Blog - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Blog

+
+ +
+
+ + + + +
+
+

KVMD 4.29: H.264 over HTTP

+

I know that some people have a problem using H.264 and WebRTC with firewalls, NAT, Tailscale and other things. Until recently, the only alternative was MJPEG, which consumes a lot of traffic. So I was constantly researching whether something could be done about it, and finally found a way.

+

Starting with KVMD 4.29, in addition to WebRTC, a new method of direct transmission of H.264 over HTTP will be available to you. Is the Web UI working? Then direct video transmission will also work. This completely solves the problem of WebRTC unavailability.

+ + + + +
+
+ +
+
+ + + + +
+
+

Announcing PiKVM Switch Multiport Extender

+

The PiKVM team is excited to present its new PiKVM Switch Multiport Extender - the most full-featured switch for PiKVM devices. After much anticipation, the PiKVM Switch is now available for order! The switch allows you to connect up to four target hosts to a single PiKVM and provides full control over them.

+ + + + +
+
+ + + + + + + +
+
+ + + + +
+
+

KVMD + uStreamer performance update

+

Today I have prepared a great update for you. After few weeks of research, I managed to increase the video performance slightly reduce the latency for all CSI devices (PiKVM V4, V3 and CSI-based V2).

+ + + + +
+
+ +
+
+ + + + +
+
+

HDMI passthrough on PiKVM V4 Plus

+

We promised it at the start and finally it's almost done. The V4 Plus will get an HDMI passthrough on one of its outputs. Right now It's working on my desk, and it's pretty good: 1080p 60 fps with vertical sync, perfect 24 bit color and zero-latency.

+ + + + +
+
+ + + + + +
+
+ + + + +
+
+

KVMD 3.301: Generated Nginx configs

+

Starting from this version, the /etc/kvmd/nginx.conf config will be replaced with the /etc/kvmd/nginx.conf.mako template, which will be rendered to /run/kvmd/nginx.conf taking into account the /etc/kvmd/override.yaml parameters and network configurations.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/page/3/index.html b/blog/page/3/index.html new file mode 100644 index 00000000..e36dff64 --- /dev/null +++ b/blog/page/3/index.html @@ -0,0 +1,3166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Blog - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Blog

+
+ + + +
+
+ + + + +
+
+

PiKVM just got full PS/2 support

+

Previously, to support PS/2 keyboards (only), it was necessary to assemble a complex circuit on Arduino. With the transition to Raspberry Pi Pico, we finally have full support for both keyboard and mouse. The design has been greatly simplified, and is now compatible with V4 Plus.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 3.265: Mouse Jiggler!

+

This is a feature that many users have been asking for for a long time. So, mouse jiggler will allow you to prevent the monitor from falling asleep if it was turned on.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.249: easier uploading over SSH

+

In addition to many minor improvements from the previous announcement, an important change has occurred in the new release for those who use advanced Mass Storage emulation features.

+ + + + +
+
+ + + + + + + + + +
+
+ + + + +
+
+

KVMD 3.196: 2FA support

+

Many have asked for this, so now you have the opportunity to increase the security of your PiKVM.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/page/4/index.html b/blog/page/4/index.html new file mode 100644 index 00000000..7cc7954a --- /dev/null +++ b/blog/page/4/index.html @@ -0,0 +1,3166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Blog - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Blog

+
+ + + + + +
+
+ + + + +
+
+

KVMD 3.159: Significant VNC improvement

+

The VNC server has learned how to transmit video asynchronously to make it fast and smooth. Now, FPS can grow about twice, it will be especially noticeable with poor internet quality.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.126: Writable flash drive storage

+

Now you can upload the flash drive image to MSD, write some files to it, or even install entire OS to the PiKVM MSD drive (I don't know why, but you can), and download the image back. Use the new feature wisely.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.116: Let's Encrypt certificates

+

Usually Let's Encrypt certificates are issued and updated automatically using Certbot, however, since PiKVM uses a read-only file system, special tools around Certbot are required to work with certificates.

+ + + + +
+
+ +
+
+ + + + +
+
+

Introducing a new tool — kvmd-edidconf

+

For the happy owners of V2 and V3, we now offer a new utility, kvmd-edidconf. It will help you configure EDID (the display metadata) and provide import/export for EDID modification using advanced editors such as AW EDID Editor.

+ + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/page/5/index.html b/blog/page/5/index.html new file mode 100644 index 00000000..9523dcaa --- /dev/null +++ b/blog/page/5/index.html @@ -0,0 +1,3166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Blog - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Blog

+
+ + + +
+
+ + + + +
+
+

New testing branch available

+

A few months ago, due to the release of Bullseye, the usual video encoding method used in PiKVM stopped working in the new kernel. OpenMAX and MMAL were deprecated and uStreamer has ben rewrited to use new M2M encoder. Now the work is almost completed and everything seems to be working fine.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

Zero W 1 and RPi 1 end-of-life

+

Since Arch Linux ARM has discontinued support for the ARMv6 architecture , we are discontinuing support for PiKVM based on Zero W and RPi 1, because we don't have the ability to maintain our own fork of the whole distro for this architecture.

+ + + + +
+
+ + + + + +
+
+ + + + +
+
+

KVMD 3.33: New Wi-Fi configuration method

+

Starting from today, the old way to configure Wi-Fi using netctl is deprecated. Instead, it is proposed to use a more native way with systemd-networkd, which is already used to configure Ethernet.

+ + + + +
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/page/6/index.html b/blog/page/6/index.html new file mode 100644 index 00000000..6bc7371b --- /dev/null +++ b/blog/page/6/index.html @@ -0,0 +1,3166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Blog - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Blog

+
+ + + +
+
+ + + + +
+
+

KVMD 3.14: The Epic Apple fix, Vol.2

+

I continue to eliminate ancient bugs from USB. So great news for Apple and v2/v3/OTG users: you no longer need to use the Arduino HID to get into the Boot Menu or Recovery Mode.

+ + + + +
+
+ +
+
+ + + + +
+
+

Big testing request

+

I have a very important request. We are preparing for a big update that will improve compatibility with BIOS and UEFI on many devices, and I need as many people as possible to check out the new build of the kernel and core packages.

+ + + + +
+
+ + + + + +
+
+ + + + +
+
+

KVMD 3.9: Paste-as-Keys update

+

For the Paste-as-Keys function, the state of the confirmation switch and the selected keymap are saved. You asked for it—I did it.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 3.8: The Epic Apple fix!

+

For a long time, Pi-KVM had several problems related to the mouse and keyboard on Apple. Previously, you could not use the mouse in the boot menu, and recovery mode also required you to connect the mouse, despite the fact that the cursor was functioning. Because of these bugs, it was impossible to fully remotely control your Mac. Now all this is fixed!

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 3.0: The big H.264 release!

+

I'm happy to introduce you to a feature I've been working on for the last six months. Now, instead of using bold MJPEG for video, you can use fast WebRTC with H.264.

+ + + + +
+
+ + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/page/7/index.html b/blog/page/7/index.html new file mode 100644 index 00000000..941c9e0e --- /dev/null +++ b/blog/page/7/index.html @@ -0,0 +1,3166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Blog - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Blog

+
+ + + +
+
+ + + + +
+
+

KVMD 2.71: Massive internal changes

+

This is a very important release. In addition to new features and fixes, a large number of internal changes have been made for the upcoming H264/WebRTC support.

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 2.65: Ezcoo fix for USB 3.0

+

If you bought an Ezcoo switch for USB 3.0, then in order for it to work with Pi-KVM, you need to upgrade to the new version and add one option to the config.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 2.53: Web terminal in a web UI window

+

You can now have the web terminal in a window above the video stream if you like. The focus works a little strange, but it is quite functional and even supports changing the size.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

KVMD 2.31: Critical bug fix

+

In recent weeks, I have been mainly working on H264 and have achieved significant results ⁠h264_vnc_funding. A critical bug has been fixed in the kernel that prevents the H264 encoder from being enabled by default, so now everyone can try H264 for VNC for v2 and CSI bridge (only).

+ + + + +
+
+ +
+
+ + + + +
+
+

KVMD 2.27: Critical bug fix

+

A lot of changes have accumulated since the last announced release. Mostly finally fixed wifi support on Zero and RPi4.

+ + + + +
+
+ + + +
+
+ + + + +
+
+

uStreamer 3.0: H264 video recording

+

Currently, Pi-KVM uses MJPEG for video transmission. This is a simple and widely supported, but not very effective video format. In the near future, it is planned to support H264, and then switch to it as the main one.

+ + + + +
+
+ + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/page/8/index.html b/blog/page/8/index.html new file mode 100644 index 00000000..5181863b --- /dev/null +++ b/blog/page/8/index.html @@ -0,0 +1,3166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Blog - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Blog

+
+ +
+
+ + + + +
+
+

Some news about v3

+

We have some news about v3. The prototypes are almost ready. Since the last release, they have included several changes and additional features.

+ + + + +
+
+ + + + + + + + + + + + + +
+
+ + + + +
+
+

Another test request for v2 users of RPi4 and ZeroW

+

I found a way to improve USB HID/Mass Storage compatibility with some motherboards. I would like to ask you to check if there are any problems because of this. If successful, if you didn't have MSD working, it may work after this change.

+ + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/page/9/index.html b/blog/page/9/index.html new file mode 100644 index 00000000..8dc5d0fd --- /dev/null +++ b/blog/page/9/index.html @@ -0,0 +1,3166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Blog - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+
+

Blog

+
+ + + + + + + +
+
+ + + + +
+
+

KVMD 1.100: GPIO and USB relays

+

This release introduces a feature that I have been working on for a long time and that will significantly expand the functionality of Pi-KVM: the ability to use GPIO and USB relays.

+ + + + +
+
+ +
+
+ + + + +
+
+

Pi-KVM is now available on Raspberry Pi 1

+

In the last release, I added the ability to use this board. This is still unofficial and not reflected in the documentation, but you can already build the system using the build environment if you use the BOARD=rpi and PLATFORM=v0-hdmi or v0-hdmiusb parameters.

+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bluetooth_hid/index.html b/bluetooth_hid/index.html new file mode 100644 index 00000000..493681ba --- /dev/null +++ b/bluetooth_hid/index.html @@ -0,0 +1,2765 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Bluetooth HID - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Bluetooth HID

+ +

PiKVM is able to emulate a Bluetooth keyboard & mouse. +This is not the main case of using PiKVM since you still need it to pair with a remote host, but can be used for something like mobile KVM.

+
+

Warning

+

Using Bluetooth HID requires additional configuration of the operating system. For v2+, this means losing the UART port, since it will be used by Bluetooth. Also, Bluetooth operation was tested only on RPi4 and v2+ platform. Other boards may require different system service settings. Making the required changes for BT to work will also disable normal KB/MOUSE functionality therefor this will need to be disabled before normal operation can occur.

+
+
+

Note

+

Bluetooth mouse can work only in relative mode. The reason is that many Bluetooth host drivers do not correctly implement HID descriptors. Horizontal scrolling is not supported for the same reason.

+
+

Configuring the OS

+
    +
  1. +

    Switch filesystem to RW-mode and install some packages:

    +
    # rw
    +# pacman -Syy   
    +# pacman -Su bluez bluez-utils raspberrypi-bluetooth
    +
    +
  2. +
  3. +

    Edit /boot/config.txt and comment these lines:

    +
    #enable_uart=1
    +#dtoverlay=disable-bt
    +
    +
  4. +
  5. +

    Create an empty directory /var/lib/bluetooth and add mountpoint to /etc/fstab:

    +
    # mkdir /var/lib/bluetooth
    +# echo 'tmpfs /var/lib/bluetooth tmpfs nodev,nosuid,mode=0755 0 0' >> /etc/fstab
    +
    +
  6. +
  7. +

    Override and enable the services:

    +
    # mkdir /etc/systemd/system/bluetooth.service.d
    +# cat << EOF > /etc/systemd/system/bluetooth.service.d/override.conf
    +[Service]
    +ExecStart=
    +ExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=*
    +EOF
    +# systemctl enable bluetooth
    +# systemctl enable raspberrypi-btuart
    +
    +
  8. +
  9. +

    Override kvmd service:

    +
    # mkdir /etc/systemd/system/kvmd.service.d
    +# cat << EOF > /etc/systemd/system/kvmd.service.d/override.conf
    +[Service]
    +AmbientCapabilities=CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SYS_ADMIN CAP_SETUID CAP_SETGID CAP_CHOWN
    +CapabilityBoundingSet=CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SYS_ADMIN CAP_SETUID CAP_SETGID CAP_CHOWN
    +EOF
    +
    +
  10. +
  11. +

    Add following lines to /etc/kvmd/override.yaml:

    +
    kvmd:
    +    hid:
    +        type: bt
    +
    +
  12. +
  13. +

    Perform reboot.

    +
  14. +
  15. +

    To reverse, uncomment lines from Step 2 and remove lines in Step 6, and reboot.

    +
  16. +
+

Using Bluetooth HID

+
    +
  • +

    After a reboot, the PiKVM will be ready for detection and pairing with no auth. You will see the PiKVM HID device.

    +
  • +
  • +

    Once the server is connected, PiKVM will no longer be discoverable and pairable to other clients until you unpair the server.

    +
  • +
  • +

    If something went wrong, use the web menu System -> Reset keyboard & mouse. This will cause unpair the device and switch the PiKVM to public mode before the first client is connected.

    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/building_os/index.html b/building_os/index.html new file mode 100644 index 00000000..405a210c --- /dev/null +++ b/building_os/index.html @@ -0,0 +1,2704 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Building PiKVM OS - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Building PiKVM OS

+ +

The assembly of PiKVM OS is carried out using a special build environment. +Here the minimum required for its use, imposed on the build machine:

+
    +
  • kernel >= 5.8
  • +
  • glibc >= 2.33
  • +
  • docker >= 19.03.13
  • +
  • git
  • +
+

Docker must work in privileged mode.

+
    +
  1. +

    When starting with a clean OS you need to install and configure Docker. An example for Ubuntu:

    +
    [user@localhost ~]$ sudo apt-get install git make curl binutils -y
    +[user@localhost ~]$ sudo apt-get install docker.io
    +[user@localhost ~]$ sudo usermod -aG docker $USER
    +
    +

    Re-login to apply the changes.

    +
  2. +
  3. +

    Checkout the build environment:

    +
    [user@localhost ~]$ git clone --depth=1 https://github.com/pikvm/os
    +[user@localhost ~]$ cd os
    +
    +
  4. +
  5. +

    Determine the target board and platform:

    +
      +
    • +

      Choose the board:

      +
        +
      • BOARD=rpi4 for Raspberry Pi 4.
      • +
      • BOARD=zero2w
      • +
      • BOARD=rpi3
      • +
      • BOARD=rpi2
      • +
      +
    • +
    • +

      Choose the platform:

      +
        +
      • PLATFORM=v4mini-hdmi for PiKVM V4 Mini.
      • +
      • PLATFORM=v4plus-hdmi for PiKVM V4 Plus.
      • +
      • PLATFORM=v3-hdmi for RPi4 and PiKVM V3 HAT.
      • +
      • PLATFORM=v2-hdmi for RPi3a+/RPi4 or Zero2W with HDMI-CSI bridge.
      • +
      • PLATFORM=v2-hdmiusb for RPi4 with HDMI-USB dongle.
      • +
      • PLATFORM=v1-hdmi for RPi2 or 3b+ with HDMI-CSI bridge and the Pico HID.
      • +
      • PLATFORM=v1-hdmiusb for RPi2 or 3b+ with HDMI-USB dongle and the Pico HID.
      • +
      +
    • +
    +
  6. +
  7. +

    Create the build config file config.mk for the target system and and the BOARD and PLATFORM variables. + You can also set some other parameters as you wish (see below). + Please note: if your password contains the # character, you must escape it using a backslash like ROOT_PASSWD = pass\#word.

    +
    # Base board
    +BOARD = rpi4
    +
    +# Hardware configuration
    +PLATFORM = v2-hdmi
    +
    +# Target hostname
    +HOSTNAME = pikvm
    +
    +# ru_RU, etc. UTF-8 only
    +LOCALE = en_US
    +
    +# See /usr/share/zoneinfo
    +TIMEZONE = Europe/Nicosia
    +
    +# For SSH root user
    +ROOT_PASSWD = rootpass
    +
    +# Web UI credentials: user=admin, password=adminpass
    +WEBUI_ADMIN_PASSWD = adminpass
    +
    +# IPMI credentials: user=admin, password=adminpass
    +IPMI_ADMIN_PASSWD = adminpass
    +
    +
  8. +
  9. +

    Build the OS. It may take about one hour depending on the Internet connection:

    +
    [user@localhost os]$ make os
    +
    +
    +

    Tip

    +

    If you get an error about failing to retrieving a file, please edit the Makefile and remove de3. from the repo URL.

    +
    +
  10. +
  11. +

    Create an image. It will be stored in the images directory as a file with *.img extension:

    +
    [user@localhost os]$ make image
    +
    +
  12. +
  13. +

    Flash the result image to SD card.

    +
  14. +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cheat_sheet/index.html b/cheat_sheet/index.html new file mode 100644 index 00000000..1051f6a6 --- /dev/null +++ b/cheat_sheet/index.html @@ -0,0 +1,14 @@ + + + + + + Redirecting... + + + + + +You're being redirected to a new destination. + + diff --git a/cheatsheet/index.html b/cheatsheet/index.html new file mode 100644 index 00000000..ba57bc35 --- /dev/null +++ b/cheatsheet/index.html @@ -0,0 +1,2922 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + PiKVM Cheat Sheet - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

PiKVM Cheat Sheet

+

Here are first steps guides for each PiKVM device:

+ +
+

Basics

+
+Performing commands with root privileges +

There are two ways to perform any command with root privileges.

+
    +
  1. +

    Gain root privileges, then perform any command.

    +

    [kvmd-webterm@pikvm ~]$ su -

    +

    After providing root account password, you will be able to run any commands as a root user as long as the session is running. Use it wisely. For example, if you need to reboot PiKVM, all you need to do is this:

    +

    [root@pikvm ~]# reboot

    +

    The use of su - applies to both SSH and web terminal sessions.

    +
  2. +
  3. +

    Use su -c followed by the command wrapped in apostrophes. This will perform the command with root privileges a single time, you will not gain permanent root access. This will For example, to reboot PiKVM, do this:

    +

    [kvmd-webterm@pikvm ~]$ su -c 'reboot'

    +

    The use of su -c applies to both SSH and web terminal sessions.

    +
  4. +
+
+
+Changing PiKVM Passwords +

PiKVM comes with the following default passwords:

+
    +
  • +

    Linux OS-level admin (SSH, console...):

    +
      +
    • Username: root
    • +
    • Password: root
    • +
    +
  • +
  • +

    KVM user (Web Interface, API, VNC...):

    +
      +
    • Username: admin
    • +
    • Password: admin
    • +
    • No 2FA code
    • +
    +
  • +
+

They are two separate accounts with independent passwords.

+

To change passwords, you will need to use the console access via SSH or the Web Terminal. +If you are using the Web Terminal, enter the su - command to get the root access (enter the root user password).

+
[root@pikvm ~]# rw
+[root@pikvm ~]# passwd root
+[root@pikvm ~]# kvmd-htpasswd set admin
+[root@pikvm ~]# ro
+
+

If you require additional user for the Web UI access, use the following:

+
[root@pikvm ~]# kvmd-htpasswd add <user> # Add a new user with password
+[root@pikvm ~]# kvmd-htpasswd del <user> # Remove/delete a user
+
+

Optionally you can enable the two-factor authentication for more security.

+

Changing the VNCAuth key and IPMI password at the first start of PiKVM is not required, +since these services are disabled by default. But it is here just so that you remember their existence.

+
+
+Configuring PiKVM OS +
+

Need more info? We have it!

+

The following is a brief guide to configuring PiKVM. +For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), +please refer to this page.

+
+

Most of the PiKVM configuration files are located in the /etc/kvmd directory.

+

The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. +To redefine system parameters use the file /etc/kvmd/override.yaml. +All other files that are also not recommended for editing have read-only permissions.

+

You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory +to split your customization into logical parts. +The override.yaml file definitions takes precedence over the override.d directory.

+

A complete list of all parameters can be viewed using the kvmd -m command.

+

Files with the *.yaml suffix uses the YAML syntax +and describes a parameter tree with key-value pairs of different types. +To define the parameters within one section, an indent of 4 spaces is used. +Comments starts with the # symbol.

+
+

Only 4 spaces should be used for indentation

+

Be careful when editing YAML and follow this rule. +Invalid indentation or tabs instead of spaces will cause an error when starting the services.

+
+

Sections under the same keys should be merged:

+
    +
  • +

    Wrong:

    +
    kvmd:
    +    gpio:
    +        drivers: ...
    +kvmd:
    +    gpio:
    +        scheme: ...
    +
    +
  • +
  • +

    Correct:

    +
    kvmd:
    +    gpio:
    +        drivers: ...
    +        scheme: ...
    +
    +
  • +
+

In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

+
+
+Updating PiKVM OS +

To update, run following commands under the root user:

+
[root@pikvm ~]# pikvm-update
+
+

If you encounter an error like:

+
[root@pikvm ~]# pikvm-update
+bash: pikvm-update: command not found
+
+

It's most likely you have an old OS release. You can update the OS as follows:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# pacman -Syy
+[root@pikvm ~]# pacman -S pikvm-os-updater
+[root@pikvm ~]# pikvm-update
+
+

Next time you will be able to use the usual method with pikvm-update.

+
+
+Connecting to PiKVM via SSH +

SSH is the most common remote access method in the Linux world. Normally, it should be possible to simply run ssh root@pikvm in a terminal window to connect to your PiKVM. However, this can fail for various reasons. In that case, you will have to connect using PiKVM's IP address.

+

To connect to PiKVM via SSH, do this:

+
    +
  1. +

    Discover PiKVM's IP address in the local network. There are several ways to do that:

    +
      +
    • Open the web interface of your router and find the list of issued IP addresses there.
    • +
    • Linux-only: install and run arp-scan: sudo arp-scan --localnet.
    • +
    • Linux, MacOS, Windows: Download and run Angry IP Scanner.
    • +
    • Windows PowerShell: Use the arp -a command.
    • +
    +

    In each case, look for the entry that says "Raspberry Pi Trading Ltd" and copy its IP address to the clipboard. Let's assume that the IP address is 192.168.0.100.

    +
  2. +
  3. +

    Run the SSH client to connect to PiKVM:

    +
      +
    • Linux, MacOS: Open any terminal application and run: ssh root@192.168.0.100.
    • +
    • Windows: Use PuTTY for this.
    • +
    +
  4. +
  5. +

    Submit your root user credentials. The default password is root. If you haven't changed it, you absolutely should do it.

    +
  6. +
  7. +

    You should now be able to see and interact with the serial port. All the system tools in PiKVM will be available in the terminal window. Once you are done, type exit and press Enter, or simply press Ctrl+d to terminate the session.

    +
  8. +
+
+
+Connecting to PiKVM via serial console +

A serial console is a convenient and fast way to connect to PiKVM when there is no network, or get boot logs and a console if something goes wrong.

+
    +
  1. +

    Connect to the physical universal asynchronous receiver / transmitter (UART) console from your host computer:

    +
      +
    • +

      On PiKVM V3 or V4, you have a built-in USB-UART adapter in your device. Just disconnect the OTG cable and place the USB-C end into the IOIOI port on V4 (or the CON port on V3). Place the USB-A end into the port you want serial to be accessed, typically done on the host. If you have a Windows host, you may need to install this driver, other operating systems may not need one.

      +
    • +
    • +

      On DIY PiKVM V1 or V2, you'll need to get the right TTY to USB cable, we recommend the RPi Debug Probe and follow existing RPi TTY serial setups.

      +
    • +
    +
  2. +
  3. +

    Install picocom on a Linux or a macOS host (available in Homebrew and MacPorts), or Putty on Windows.

    +
  4. +
  5. +

    Identify the port that your operating system exposes for connecting to the PiKVM.

    +
      +
    • +

      Windows: look this up in the Device Manager

      +
    • +
    • +

      Linux: open a terminal program, run sudo dmesg | grep ttyand look for a message like this:

      +
    • +
    +
    [14362.388405] usb 1-2: cp210x converter now attached to ttyUSB0
    +
    +

    This means you will need to use /dev/ttyUSB0.

    +
      +
    • macOS: open the terminal and list all USB serial devices with ls /dev/cu.usbserial-*. Look for a device that contains cu.usbserial, e.g. /dev/cu.usbserial-FT0RVWSW.
    • +
    +
  6. +
  7. +

    Connect via the serial port:

    +
      +
    • +

      Windows: select the COM port in Putty and use the 115200 baud rate, then connect.

      +
    • +
    • +

      Linux/macOS: open your terminal program and run sudo picocom -b 115200 $USB_SERIAL_DEVICE where $USB_SERIAL_DEVICE is the device you looked up, e.g. /dev/ttyUSB0 on Linux or /dev/cu.usbserial-FT0RVWSW on macOS.

      +
    • +
    +

    After running the command, press Enter to get to a login prompt.

    +
  8. +
  9. +

    Submit your root user credentials.

    +
  10. +
  11. +

    You should now be able to see and interact with the serial port. All the system tools in PiKVM will be available in the terminal window. Once you are done, press Ctrl+a and then immediately Ctrl+x to terminate the session.

    +
  12. +
+
+
+Shutting down PiKVM +

PiKVM defaults to using the system in read-only mode, so there is no need to explicitly shut it down. You can simply unplug the device from power.

+

If you absolutely need to use the shutdown command, please ensure the following requirements are met:

+
    +
  • This is not one of the DIY (V1 or V2) devices. If you shut down a DIY PiKVM, it will not power on until you physically reconnect the power cord.
  • +
  • You are not currently running a system update. If you are, you will likely corrupt the system.
  • +
  • You are not currently uploading a mass storage drive image. If you are, you will likely corrupt the system.
  • +
+

If all these requirements are met, do this:

+
[kvmd-webterm@pikvm ~]$ su -
+[root@pikvm ~]# shutdown -h now
+
+

PiKVM V3 and V4 will automatically reboot after several minutes of being halted. DIY PiKVM will need a power cord reconnection to become available again.

+
+
+

Getting User Support

+

If something doesn't work, check out our FAQ. Otherwise, head straight to our Support.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cloudflared/index.html b/cloudflared/index.html new file mode 100644 index 00000000..1b3705dd --- /dev/null +++ b/cloudflared/index.html @@ -0,0 +1,2803 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Cloudflare tunnels - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Cloudflare Tunnel

+ +
+

Warning

+

This is unofficial instructions proposed by the community. We don't officially support this and don't know what problems may arise when using cloudflared.

+
+

Cloudflare Tunnels can be used to access PiKVM over the internet securely using Cloudflare Zero Trust with Cloudflared. This is a convenient and free (for 50 users) tool for allowing access to web services running on your internal network without port forwarding or IPv4/IPv6 compatability issues. This document is provided as an example for accessing your PiKVM over the internet but you can also use Zerotier/Tailscale/Insert XYZ VPN service here. Basic support like whats shown below is provided as an example, any other setting or functionality needs to be redirected to the appropriate community.

+
+

If you get error 1033 / lookup localhost error

+

You might need to add 127.0.0.1 localhost into your /etc/hosts file

+
+

Prequisites

+
    +
  1. +

    A domain utilizing Cloudflare for DNS

    +
  2. +
  3. +

    A Cloudflare tunnel configured with an application created and secured by an access policy

    +
  4. +
  5. +

    Custom firewall rules configured in Cloudflare as needed

    +
  6. +
+

Cloudflare Tunnel Steps

+
    +
  1. +

    Login to Cloudflare and provision a tunnel using the steps here. Save the tunnel token as we will need this later. In most cases the target will be https://localhost

    +
  2. +
  3. +

    Create a self-hosted application with the URL matching one created in the previous step by following the steps here.

    +
  4. +
  5. +

    You will need to check the http options to disable SSL certificate verification under Tunnels -> Configure -> Public Hostname -> yourapplication.yourdomain -> Edit -> TLS Settings -> No TLS Verify as the PiKVM uses self-signed certificates.

    +
  6. +
  7. +

    Don't skip the access policies as this important to preventing randoms from the internet from gaining access to your PiKVM. Cloudflare offers a variety of login options with the simplest being One-time PINs that are emailed to you. NOTE: This external authentication will not replace the username/password for the PiKVM but instead supplement it acting as a first line of defense from the internet.

    +
  8. +
+

Installation on the PiKVM

+
    +
  1. +

    Use these commands to install Cloudflared:

    +
    # rw
    +# curl -L -o /usr/local/bin/cloudflared "$(curl -s "https://api.github.com/repos/cloudflare/cloudflared/releases/latest" | grep -e 'browser_download_url.*/cloudflared-linux-armhf"' | sed -e 's/[\ \":]//g' -e 's/browser_download_url//g' -e 's/\/\//:\/\//g')"
    +# chmod +x /usr/local/bin/cloudflared
    +# cloudflared version
    +
    +
  2. +
  3. +

    Update /etc/systemd/resolved.conf and set cloudflare nameservers.

    +
    # sudo vim /etc/systemd/resolved.conf
    +# Uncomment DNS line and set 'DNS=1.1.1.1 1.0.0.1'
    +# systemctl restart systemd-resolved
    +
    +
  4. +
  5. +

    Install the Cloudflare tunnel service to Cloudflared.

    +
    # sudo cloudflared service install SERVICE_TOKEN_HERE
    +
    +
  6. +
  7. +

    Ensure cloudflared service is enabled so it starts on boot.

    +
    # sudo systemctl enable cloudflared
    +
    +
  8. +
  9. +

    Open a web browser and attempt to connect to your tunnel.

    +
  10. +
  11. +

    Drop back in to read only mode

    +
    # ro
    +
    +
  12. +
  13. +

    Reboot pikvm and ensure your tunnel comes back up. This may take a few minutes.

    +
  14. +
+

Updating Cloudflared

+

Use these commands to update Cloudflared:

+
# rw
+# cloudflared update
+# ro
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/compliance/index.html b/compliance/index.html new file mode 100644 index 00000000..446aedf4 --- /dev/null +++ b/compliance/index.html @@ -0,0 +1,2615 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Compliance - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Compliance Information

+
+ + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/compliance/pikvm_ce_ukca.pdf b/compliance/pikvm_ce_ukca.pdf new file mode 100644 index 00000000..35c3405b Binary files /dev/null and b/compliance/pikvm_ce_ukca.pdf differ diff --git a/config/index.html b/config/index.html new file mode 100644 index 00000000..daedf16e --- /dev/null +++ b/config/index.html @@ -0,0 +1,2992 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Overriding system settings - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

Configuring PiKVM

+ +

PiKVM OS has various low-level settings you can customize: timeout for the kvmd daemon, default keymap for the emulated keyboard, scroll rate for VNC sessions, logs formatting, etc. To do that, you need to override default settings.

+
+

How overrides work in PiKVM OS

+

Main default settings are stored in /usr/lib/kvmd/main.yaml. However, you should never edit that file. To override these and other defaults, you need to edit /etc/kvmd/override.yaml instead.

+

PiKVM OS applies settings from main.yaml first and then applies anything it finds in override.yaml. This approach helps keeping defaults and customizations safely separate from each other.

+
+

How override.yaml is structured

+

The /etc/kvmd/override.yaml file has YAML syntax. All configurations are stored as key-value pairs.

+

Consider this example:

+
file: /etc/kvmd/ipmipasswd
+
+

Here, file is a key, or the name of a configuration entry, and /etc/kvmd/ipmipasswd is the value. Keys and values are separated by a semicolon.

+

YAML files can have nested key-value pairs:

+
ipmi:
+    auth:
+        file: /etc/kvmd/ipmipasswd
+
+

To nest key-value pairs correctly, use four spaces rather than tabulation for indentation.

+

There is no need to copy and paste an entire configuration tree of key-value pairs to change just one setting. For example, if you want to change just the kvmd timeout, you only need the timeout setting and its parent keys, kvmd and vnc:

+
vnc:
+    kvmd:
+        timeout: 7.0
+
+

An important rule is that sections under the same keys should be merged:

+
    +
  • +

    Wrong:

    +
    kvmd:
    +    gpio:
    +        drivers: ...
    +kvmd:
    +    gpio:
    +        scheme: ...
    +
    +
  • +
  • +

    Correct:

    +
    kvmd:
    +    gpio:
    +        drivers: ...
    +        scheme: ...
    +
    +
  • +
+

Anything that starts with # is considered a comment. This is useful when you need to document your customizations, e.g., write down the rationale for changing a particular default.

+

You can start new lines with comments if you need to write a longer explanation.

+
# 2025-05-08: changed the default timeout to 7.0 after some troubleshooting.
+vnc:
+    kvmd:
+        timeout: 7.0
+
+

You can also write inline comments like this:

+
vnc:
+    kvmd:
+        timeout: 7.0 #this seems to work better
+
+

Let's practice changing a default setting by switching to a German keyboard map by default. This is just an example to explain how overrides work.

+
+

Change file system access to read-write

+

For safety reasons, access to the file system of PiKVM OS is read-only by default. You need to temporarily change it to read-write to be able to save changes to the configuration file. To do it, use the rw command:

+
[root@pikvm ~]# rw
+
+
+

Identify the configuration entry

+

Before you start editing, you need to find the setting you will need to override. Run kvmd -m to look up configuration entries you can redefine. This command will print the entire list. We need the keymap setting somewhere in the kvmd group:

+

keymap in kvmd

+

So, the correct hierarchy is kvmd/hid/keymap, and the path to keymaps is /usr/share/kvmd/keymaps/.

+

List all keymaps in that directory:

+
[root@pikvm ~]# ls /usr/share/kvmd/keymaps/
+ar    cz  de     en-gb  en-us-altgr-intl  es  fi  fr     fr-ca  hr  is  ja  lv  nl  pl  pt-br  sl  th
+bepo  da  de-ch  en-us  en-us-colemak     et  fo  fr-be  fr-ch  hu  it  lt  mk  no  pt  ru     sv  tr
+
+

You will need de, which is a two-letter code for German.

+
+

Edit override.yaml

+

Now, let's open override.yaml for editing. PiKVM ships with both nano and vim. We generally recommend nano over vim for new users:

+
[root@pikvm ~]# nano /etc/kvmd/override.yaml
+
+

nano has a console user interface, so it displays the text file right in the terminal window:

+

override.yaml in nano

+

Scroll down to the bottom of the file (use Ctrl+End, PageDown, or ArrowDown keys). Type this:

+
kvmd:
+    hid:
+        keymap: /usr/share/kvmd/keymaps/de
+
+

Don't forget to indent each child key with four spaces.

+
+

Save the file

+

Now, you need to save the configuration file and exit. Nano displays hints on the most important keyboard shortcuts at the bottom of its window.

+

Save and exit

+

^ stands for Ctrl on Windows and Linux and for Cmd on macOS. M stands for Alt.

+

Press Ctrl+O to save the configuration file and then Ctrl+X to quit nano.

+
+

Validate the configuration

+

Before attempting to make your changes take effect, you should always validate override.yaml. To do that, run kvmd -m. If there are any syntax errors, kvmd will complain about them.

+

For example, if you accidentally used a semicolon instead of a colon between the key and the value like this:

+
keymap; /usr/share/kvmd/keymaps/de
+
+

kvmd -m will display this message instead of outputting all configuration entries:

+
ConfigError: The node 'vnc' must be a dictionary
+
+

If you see any errors in the output, fix them and run kvmd -m again to verify that the error is gone.

+

Note that kvmd -m does not validate configuration entries for correct key names. So if your changes don't work, that's #1 thing to check for when troubleshooting.

+
+

Change access to read-only

+

Before you go to the next step, change the file system access mode to read-only. To do that, run the ro command:

+
[root@pikvm kvmd-webterm]# ro
+
+
+

Reboot your PiKVM

+

There are close to a dozen various system daemons that depend on configuration settings. The easiest way to apply your changes is to simply reboot your PiKVM:

+
[root@pikvm ~]# reboot
+
+

Once the device restarts, your changes take effect.

+
+

Keeping customizations atomic

+

When you apply massive customizations, it may help separating changes into several files to keep them manageable.

+

To do that, create these YAML files inside the /etc/kvmd/override.d/ directory. KVMD will apply all configurations in the following order: main.yaml -> legacy auth.yaml -> override.d -> override.yaml. Inside the override.d directory, KVMD will apply YAML files in alphabetical order, so please pay attention to how you name them.

+

We recommend sticking with a particular file-naming scheme, e.g. 0000-vendor-otg-serial.yaml. We do reserve -vendor- and -pikvm- prefixes for our own future needs, though.

+

Once you completed the customization and validated newly created/edited files, reboot your PiKVM for the changes to take effect.

+
+

Legacy notes

+
    +
  • +

    Older installations may have used the outdated /etc/kvmd/auth.yaml for authorization settings. + It existed even before the introduction of /etc/override* mechanism. + It has never been recommended for use in this documentation and should contain only the string {}, meaning an empty configuration.

    +

    However, if you have used it, you should move your configuration from /etc/kvmd/auth.yaml +somewhere in /etc/kvmd/override.d or even /etc/kvmd/override.yaml, +and then delete the source file /etc/kvmd/auth.yaml.

    +

    For example, if the /etc/kvmd/auth.yaml contained the following text:

    +
    enabled: false
    +
    +

    You can move it to /etc/kvmd/override.d/9999-auth.yaml and change the nesting of the parameters as follows:

    +
    kvmd:
    +    auth:
    +        enabled: false
    +
    +
  • +
  • +

    Early YAML configurations could contain the !include directive, which loaded the content of another file to the appropriate level. + It still works, but has been deprecated and should not be used. Support will be removed in the future.

    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/kvmd-hid-keymap.png b/config/kvmd-hid-keymap.png new file mode 100644 index 00000000..e7b38334 Binary files /dev/null and b/config/kvmd-hid-keymap.png differ diff --git a/config/nano-start.png b/config/nano-start.png new file mode 100644 index 00000000..32662a2f Binary files /dev/null and b/config/nano-start.png differ diff --git a/config/save-exit.png b/config/save-exit.png new file mode 100644 index 00000000..ef9d93d4 Binary files /dev/null and b/config/save-exit.png differ diff --git a/driver/win/pikvm-rndis5.inf b/driver/win/pikvm-rndis5.inf new file mode 100644 index 00000000..4727cf40 --- /dev/null +++ b/driver/win/pikvm-rndis5.inf @@ -0,0 +1,45 @@ +; Remote NDIS device setup file for PIKVM + +[Version] +Signature = "$Windows NT$" +Class = Net +ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} +Provider = "PIKVM" +DriverVer =01/17/2021,6.0.6000.16385 + +[Manufacturer] +"PIKVM" = RndisDevices,NTx86,NTamd64,NTia64 + +[RndisDevices.NTx86] +%RndisDevice% = RNDIS.NT.5.1, USB\VID_1D6B&PID_0104&MI_00 + +[RndisDevices.NTamd64] +%RndisDevice% = RNDIS.NT.5.1, USB\VID_1D6B&PID_0104&MI_00 + +[RndisDevices.NTia64] +%RndisDevice% = RNDIS.NT.5.1, USB\VID_1D6B&PID_0104&MI_00 + +[ControlFlags] +ExcludeFromSelect=* + +[RNDIS.NT.5.1] +Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI +BusType = 15 +include = netrndis.inf +needs = Usb_Rndis.ndi +AddReg = Rndis_AddReg_Vista + +[RNDIS.NT.5.1.Services] +include = netrndis.inf +needs = Usb_Rndis.ndi.Services + +[RNDIS_AddReg_Vista] +HKR, NDI\params\VistaProperty, ParamDesc, 0, "PIKVM" +HKR, NDI\params\VistaProperty, type, 0, "edit" +HKR, NDI\params\VistaProperty, LimitText, 0, "12" +HKR, NDI\params\VistaProperty, UpperCase, 0, "1" +HKR, NDI\params\VistaProperty, default, 0, " " +HKR, NDI\params\VistaProperty, optional, 0, "1" + +[Strings] +RndisDevice = "PIKVM RNDIS Ethernet" diff --git a/edid/index.html b/edid/index.html new file mode 100644 index 00000000..63b616f0 --- /dev/null +++ b/edid/index.html @@ -0,0 +1,3082 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + EDID - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

Tuning HDMI EDID

+ +
+

Info

+

This applies to PiKVM V3, V4 and DIY based on CSI bridge. +It is impossible to change the EDID for the HDMI-USB dongle.

+
+

The EDID provides an information about the video modes supported by the video capture device. +In the case of PiKVM, this is an HDMI CSI bridge. +Usually, you don't need to change this, since the default configuration is quite flexible, +but sometimes, for example for strange UEFIs/BIOSes, this may be necessary +(a story).

+
+

Basics

+

The EDID is stored on the PiKVM in the file /etc/kvmd/tc358743-edid.hex in HEX format. +When booting PiKVM OS, it is used by kvmd-tc358743.service and loaded into the video capture chip.

+

If you replace the EDID in this file, the EDID can be applied manually without rebooting +using the command kvmd-edidconf --apply.

+

If you just want to change the monitor's identification, we don't recommend that you change the entire EDID. +Just use kvmd-edidconf and its built-in EDID changing options.

+
+

Note

+

Windows caches drivers and registry settings so changing the monitor name is not enough, +you will also need to change the product ID and/or the serial number along with the monitor name:

+
[root@pikvm ~]# kvmd-edidconf --set-monitor-name=TOSHIBA --set-mfc-id=TTP --set-product-id=34953 --set-serial=2290649089 --apply
+
+
+
+

Quick IDs changing on PiKVM V4 Plus

+

PiKVM V4 Plus has a simple way read and adopt display identifiers like model and serial number +from your physical display. See here for details.

+
+

Run kvmd-edidconf on PiKVM:

+
[root@pikvm ~]# kvmd-edidconf
+Manufacturer ID: LNX
+Product ID:      0x7773 (30579)
+Serial number:   0x01010101 (16843009)
+Monitor name:    PiKVM V4 Plus
+Monitor serial:  CAFEBABE
+Audio:           yes
+
+

The fields have obvious names and purposes. Note the two similar fields Serial number and Monitor serial. +The first has a numeric value, and the second is ASCII. If you are using a custom EDID from some real display, some fields may be missing.

+

To change the values of the EDID fields, use the kvmd-edidconf with options, a complete list is available in kvmd-edidconfi --help.

+

Here the small example of changing all available fields from the previous listing:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# kvmd-edidconf --set-mfc-id=TTP --set-product-id=0x5B81 --set-serial=0x8DE11B79 --set-monitor-name=TOSHIBA --set-monitor-serial=ABCD1234 --apply
+Manufacturer ID: TTP
+Product ID:      0x5B81 (23425)
+Serial number:   0x8DE11B79 (2380340089)
+Monitor name:    TOSHIBA
+Monitor serial:  ABCD1234
+Audio:           yes
+...
+[root@pikvm ~]# ro
+
+

The full list of manufacturer IDs is available here.

+

Typical examples of working with EDID and the full cycle of using custom EDID will be shown below.

+
+

Adopt real display indentifiers on V4 Plus

+

PiKVM V4 Plus has a simple way read and adopt display identifiers like model and serial number +from the physical monitor connected to OUT2 port (it's also used for HDMI passthrough). +This way, the target host will recognize PiKVM as your display.

+

To adopt display identifiers, connect the display to OUT2 port and run these commands:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# kvmd-edidconf --import-display-ids --apply
+[root@pikvm ~]# ro
+
+

Now the display can be unplugged. PiKVM will remember the new settings.

+
+

Restore default EDID

+

If you need to restore the default EDID you can easily do this with kvmd-edidconf, for example:

+

[root@pikvm ~]# rw
+[root@pikvm ~]# kvmd-edidconf --import-preset=v4plus --apply
+[root@pikvm ~]# ro
+
+Available options: v0, v1, v2, v3, v4mini and v4plus. +

Also defaults edid can be found locally on your PiKVM: /usr/share/kvmd/configs.default/kvmd/edid, +or in the kvmd repo.

+
+

Force 1080p by default on PiKVM V0-V3

+

PiKVM V3 (or DIY V0-V2) has a hardware limit of 50Hz for 1080p mode, and this is a less common frequency than 60Hz. +Therefore, on V3, the default mode is 720p. Some OS (like Proxmox) may not work well with 720p, +so you can force 1080p resolution by default:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# kvmd-edidconf --import-preset=v3.1080p-by-default --apply  # Or, for example, v1.1080p-by-default
+[root@pikvm ~]# ro
+
+
+

Disable 1920x1200 on PiKVM V4

+

PiKVM V4 supports the advanced capture mode with 1920x1200. If it bothers you +(for example, if you use a physical monitor 1920x1080 with video passthrough), +you can easily disable it and use only 1920x1080:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# kvmd-edidconf --import-preset=v4plus.no-1920x1200 --apply  # Or v4mini.no-1920x1200
+[root@pikvm ~]# ro
+
+
+

Applying a custom EDID

+

PiKVM is able to emulate a physical display with a specific EDID. +You can find EDID examples in the community database +and then use it on PiKVM.

+

At the same time, you should pay attention to the hardware capabilities of PiKVM +and the EDID capabilities that you use. For example, if EDID reports 8K support, +then this obviously won't work: your host will try to send an 8K signal, +while PiKVM can process no more than 1080p.

+
    +
  • PiKVM V1-V3: The maximum resolution is 1920x1080 at 50Hz.
  • +
  • PiKVM V4: The maximum is 1920x1200 at 60Hz.
  • +
+

In the case of the PiKVM V4, almost any EDID for 1080p monitors will work. +All EDIDs that are suitable for PiKVM V3 will work too.

+

Example EDIDs for V4

+
+Acer B246WL, 1920x1200, with audio +

Taken here, as described above. +

00FFFFFFFFFFFF00047265058A3F6101
+101E0104A53420783FC125A8554EA026
+0D5054BFEF80714F8140818081C08100
+8B009500B300283C80A070B023403020
+360006442100001A000000FD00304C57
+5716010A202020202020000000FC0042
+323436574C0A202020202020000000FF
+0054384E4545303033383532320A01F8
+02031CF14F9002030405060701111213
+1415161F2309070783010000011D8018
+711C1620582C250006442100009E011D
+007251D01E206E28550006442100001E
+8C0AD08A20E02D10103E960006442100
+0018C344806E70B028401720A8040644
+2100001E000000000000000000000000
+00000000000000000000000000000096
+
+
+
+ASUS PA248QV, 1920x1200, with audio +

Taken here, as described above. +

00FFFFFFFFFFFF0006B3872401010101
+021F010380342078EA6DB5A7564EA025
+0D5054BF6F00714F8180814081C0A940
+9500B300D1C0283C80A070B023403020
+360006442100001A000000FD00314B1E
+5F19000A202020202020000000FC0050
+4132343851560A2020202020000000FF
+004D314C4D51533035323135370A014D
+02032AF14B900504030201111213141F
+230907078301000065030C001000681A
+00000101314BE6E2006A023A80187138
+2D40582C450006442100001ECD5F80B0
+72B0374088D0360006442100001C011D
+007251D01E206E28550006442100001E
+8C0AD08A20E02D10103E960006442100
+001800000000000000000000000000DC
+
+
+
+DELL D2721H to avoid black screen on some HDMI splitters, 1920x1080, no audio +

Taken here, as described above. +

00FFFFFFFFFFFF0010AC132045393639
+201E0103803C22782ACD25A3574B9F27
+0D5054A54B00714F8180A9C0D1C00101
+010101010101023A801871382D40582C
+450056502100001E000000FF00335335
+475132330A2020202020000000FC0044
+454C4C204432373231480A20000000FD
+00384C1E5311000A2020202020200181
+02031AB14F9005040302071601061112
+1513141F65030C001000023A80187138
+2D40582C450056502100001E011D8018
+711C1620582C250056502100009E011D
+007251D01E206E28550056502100001E
+8C0AD08A20E02D10103E960056502100
+00180000000000000000000000000000
+0000000000000000000000000000004F
+
+
+

Example EDIDs for V1-V3

+
+1280x1024 as preferred. Useful for Gigabyte GA-H77-DS3H +
00FFFFFFFFFFFF005262888800888888
+1C150103800000780AEE91A3544C9926
+0F505425400001000100010001000100
+010001010101D51B0050500019400820
+B80080001000001EEC2C80A070381A40
+3020350040442100001E000000FC0050
+492D4B564D20566964656F0A000000FD
+00323D0F2E0F0000000000000000014D
+02030400DE0D20A03058122030203400
+F0B400000018E01500A0400016303020
+3400000000000018B41400A050D01120
+3020350080D810000018AB22A0A05084
+1A3030203600B00E1100001800000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000045
+
+
+
+1920x1080 as preferred. Useful for motherboards such as ASRock H670 PG Riptide, Gigabyte GA-H77-DS3H, MSI series such as B550M, B660M, Z690-A and X570. Also the Intel NUC. +
00FFFFFFFFFFFF005262888800888888
+1C150103800000780AEE91A3544C9926
+0F505425400001000100010001000100
+010001010101D32C80A070381A403020
+350040442100001E7E1D00A050001940
+3020370080001000001E000000FC0050
+492D4B564D20566964656F0A000000FD
+00323D0F2E0F000000000000000001C4
+02030400DE0D20A03058122030203400
+F0B400000018E01500A0400016303020
+3400000000000018B41400A050D01120
+3020350080D810000018AB22A0A05084
+1A3030203600B00E1100001800000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000045
+
+
+
+1280x1024 as preferred, disabled 1080p at all. This may be necessary in extremely rare cases if the BIOS is completely buggy. In the future, we will provide a way to dynamically switch EDID +
00FFFFFFFFFFFF005262888800888888
+1C150103800000780AEE91A3544C9926
+0F50542FCF0001000100010001000100
+0100010101018C2300A050001E403020
+370080001000001E000000FC0050492D
+4B564D20566964656F0A000000FD0032
+3D0F2E0F000000000000000000000010
+0000000000000000000000000000016B
+02030400DE0D20A03058122030203400
+F0B400000018E01500A0400016303020
+3400000000000018B41400A050D01120
+3020350080D810000018AB22A0A05084
+1A3030203600B00E1100001800000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000045
+
+
+

Applying a choosen custom EDID

+

To apply the selected EDID, follow these steps:

+
    +
  1. +

    Switch filesystem to RW-mode:

    +
    [root@pikvm ~]# rw
    +
    +
  2. +
  3. +

    Open the file /etc/kvmd/tc358743-edid.hex with any text editor, for example, with Nano:

    +
    [root@pikvm ~]# nano /etc/kvmd/tc358743-edid.hex
    +
    +
  4. +
  5. +

    Replace the HEX data with the new, save and close the editor.

    +
  6. +
  7. +

    Apply the EDID:

    +
    [root@pikvm ~]# kvmd-edidconf --apply
    +
    +
  8. +
  9. +

    Sometimes it may be necessary to reboot the target host. Check the OS on the host, UEFI/BIOS. + If everything works, then your goal has been achieved and proceed to the last step. + If something went wrong, you can always undo these changes and restore the default EDID.

    +
  10. +
  11. +

    Don't forget to switch filesystem to the RO-mode:

    +
    [root@pikvm ~]# ro
    +
    +
  12. +
+
+

Editing EDID

+

To edit the EDID, it is best to use third-party utilities, such as the recommended advanced +AW EDID Editor for Windows (it's working great in wine) +or wxEDID. Both editors work with the binary EDID format, but you can easily import and export it +to PiKVM using the kvmd-edidconf utility.

+

So, to tune EDID on PiKVM, use the following steps:

+
    +
  1. +

    Switch filesystem to RW-mode:

    +
    [root@pikvm ~]# rw
    +
    +
  2. +
  3. +

    Export the system EDID to the binary file myedid.bin:

    +
    # kvmd-edidconf --export-bin=/root/myedid.bin
    +
    +
  4. +
  5. +

    Copy this file to your PC using SCP, Putty or something like that. + Open this binary file in the EDID editor and change the necessary parameters. + Save your changes and copy the binary file back to PiKVM.

    +
  6. +
  7. +

    Convert the binary file to the HEX and test it:

    +
    [root@pikvm ~]# kvmd-edidconf --import=/root/myedid.bin --apply
    +
    +
  8. +
  9. +

    Sometimes it may be necessary to reboot the target host. Check the OS on the host, UEFI/BIOS. + If everything works, then your goal has been achieved and proceed to the last step. + If something went wrong, you can always undo these changes and restore the default EDID.

    +
  10. +
  11. +

    Don't forget to switch filesystem to the RO-mode:

    +
    [root@pikvm ~]# ro
    +
    +
  12. +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ezcoo/ezcoo1.docx b/ezcoo/ezcoo1.docx new file mode 100644 index 00000000..a2e4c900 Binary files /dev/null and b/ezcoo/ezcoo1.docx differ diff --git a/ezcoo/index.html b/ezcoo/index.html new file mode 100644 index 00000000..73ec29c7 --- /dev/null +++ b/ezcoo/index.html @@ -0,0 +1,2870 @@ + + + + + + + + + + + + + + + + + + + + + + ezCoo managed multiport KVM switch - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

ezCoo managed multiport KVM switch

+ +
+

Warning

+

While we provide this document for your convenience, this is a third-party hardware device in the same path as a PiKVM. Therefore, you may need to experiment (trial and error) to get it to work how you like. In the case of the U3P (hot key version), it may or may not work as expected.

+
+
+

PiKVM + Multiport Switches compatibility

+

Please note that this switch requires a USB port for control. The following devices can provide this:

+
    +
  • PiKVM V3 & V4 Plus.
  • +
  • DIY devices based on Raspberry Pi 2, 3 and 4.
  • +
+

The following devices are not compatible:

+
    +
  • PiKVM V4 Mini - it doesn't have a USB host port and cannot control switches, it's a single-host device.
  • +
  • DIY based on Raspberry Pi Zero 2 W - it doesn't have USB host port too.
  • +
+
+

The ezCoo managed switch can be controlled by PiKVM to allow it to connect to multiple hosts. A typical scenario is a single PiKVM device which can control and switch between multiple hosts or servers using the ezCoo switch. UI elements can be added to the GPIO dropdown to allow switching between hosts from the PiKVM webpage.

+

The instructions here were tested with the ezCoo SW41HA HDMI 4x1 switch ezCoo EZ-SW41HA-KVMU3L 4x1 switch OR ezCoo EZ-SW41HA-KVMU3P 4x1 switch.

+

Both older USB2.0 and newer USB3.0 variants are supported. The following was testing on a Raspberry Pi 4 but should also work on the Pi 2 and 3.

+

This document was created using the contributions from multiple users in our Discord and the author appreciates their efforts.

+
+

Info

+

While most images of the switch do not show the sides, there is a Micro USB port on the side of the ezCoo switch. This is the management port, which is controlled via COM port on the ezCoo KVM. When plugged into the Raspberry Pi, it appears as /dev/ttyUSB0.

+
+
+

Info

+

Audio was not tested, it is assumed to be non-functional.

+
+
+

Tip

+

ezCoo EZ-SW41HA-KVMU3L - includes 4x1m USB 3.0 A Male to A Male. +You will need 1 extra USB A Male to USB Micro B to connect from the PiKVM to the ezcoo "F/W CTL - Management" port

+
+

Connections

+
+

EZCOO Wiring example can be found here Scroll down to bottom of page for picture

+
+

Please review the item description and manual before deploying.

+

From a high level, the ezCoo switch uses standard connections to the host machines (USB-A to USB-B and HDMI for USB2 version, USB-A to USB-A for the USB3 version). The Raspberry Pi OTG connector (the one coming from the USB-C port on a Pi 4 via the custom splitter cable or device) should be connected to the USB 3 port on the ezCoo switch. There is an additional USB cable connected to the managed port on the switch.

+
    +
  1. +

    Connect the USB-C cable from the Raspberry Pi OTG port to ezCoo switch USB 3 port on the front or USB 1 port on the back of the switch. Note: If this cable is connected to the keyboard port (USB 2) of the ezCoo switch, the mouse will not be present.

    +
  2. +
  3. +

    Connect the HDMI out from the ezCoo switch to the Raspberry Pi CSI-2 to HDMI input. Other users have reported HDMI encoder USB dongles as working.

    +
  4. +
  5. +

    Connect a USB-A to Micro USB cable from the Raspberry Pi to the management port on the side of the ezCoo switch.

    +
  6. +
  7. +

    Connect host USB and HDMI cables from the ezCoo switch to the machines to be managed per the switch instructions.

    +
  8. +
  9. +

    At this point the KVM switch should be present as a device on the PiKVM. SSH into PiKVM and ensure a device like /dev/ttyUSB0 is present. The following instructions assume this is the KVM switch.

    +
  10. +
+
+

Info

+

There is a limitation in the underlying PiKVM software related to plugging video cables from a host which is already powered and connected to a monitor to a Raspberry Pi CSI2-HDMI encoder. These limitations apply equally when using the ezCoo KVM switch. If video is not present in PiKVM, try keeping all host machines off and connecting them directly to the ezCoo switch before powering the hosts on.

+
+

Adding UI elements to control the KVM switch

+

The UI can be updated to add buttons to switch between KVM inputs and indicators for which input is currently selected. The instructions below will make these available in the PiKVM UI after clicking the "GPIO" menu button in the KVM view.

+
    +
  1. +

    Enable read-write mode on the SD card via rw

    +
  2. +
  3. +

    Edit the file: nano /etc/kvmd/override.yaml and include the following. Note the assumption that the KVM switch is present on /dev/ttyUSB0:

    +
    kvmd:
    +    gpio:
    +        drivers:
    +            ez:
    +                type: ezcoo
    +                protocol: 2
    +                device: /dev/ttyUSB0
    +        scheme:
    +            ch0_led:
    +                driver: ez
    +                pin: 0
    +                mode: input
    +            ch1_led:
    +                driver: ez
    +                pin: 1
    +                mode: input
    +            ch2_led:
    +                driver: ez
    +                pin: 2
    +                mode: input
    +            ch3_led:
    +                driver: ez
    +                pin: 3
    +                mode: input
    +            ch0_button:
    +                driver: ez
    +                pin: 0
    +                mode: output
    +                switch: false
    +            ch1_button:
    +                driver: ez
    +                pin: 1
    +                mode: output
    +                switch: false
    +            ch2_button:
    +                driver: ez
    +                pin: 2
    +                mode: output
    +                switch: false
    +            ch3_button:
    +                driver: ez
    +                pin: 3
    +                mode: output
    +                switch: false
    +        view:
    +            table:
    +                - ["#Input 1", ch0_led, ch0_button]
    +                - ["#Input 2", ch1_led, ch1_button]
    +                - ["#Input 3", ch2_led, ch2_button]
    +                - ["#Input 4", ch3_led, ch3_button]
    +
    +
    +Editing '#Input X' to '#Something else' will change the table name in the GUI drop down, if you want a different name, name it something else and restart kvmd. +
    +
    +

    This now only applies to older images, newer images do not have this issue. Make sure to notate the spaces for each line, needs to be a total of 4 spaces added per line (NOT tabs):

    +
    +
    For example:
    +    parent: 0 spaces (kvmd:)
    +    child: 4 spaces (gpio:)
    +    sub-child: 8 spaces (drivers:)
    +    sub-sub-child: 12 spaces (ez:)
    +
    +
  4. +
  5. +

    Return to read-only mode for the sd card via ro.

    +
  6. +
  7. +

    Restart the kvmd service: systemctl restart kvmd.

    +
  8. +
  9. +

    If you are still not getting KB output, issue a ls -la /dev/tty* | grep USB , if no output change cables (Alot of cables are power only)

    +
  10. +
+

Switching between hosts in the UI

+

To switch between hosts, enter the KVM UI and click the "GPIO" menu. You should see 4 inputs, one of which will have a green circle indicating it is currently selected. Click the other inputs to change the selected host.

+

Additional step for the USB 2.0 version (Old EOL version)

+

Please remove protocol: 2 to the override.yaml under the type: ezcoo at the same level:

+
kvmd:
+    gpio:
+        drivers:
+            ez:
+                type: ezcoo
+                device: /dev/ttyUSB0
+
+

Developer info

+
    +
  • The official protocol version 1 reference
  • +
  • +
    +Differences between protocols 1 and 2 +
    ===============================================================================================================================
    +=********************************************************Systems HELP*********************************************************=
    +=-----------------------------------------------------------------------------------------------------------------------------=
    +=                        System Address = 00           F/W Version : 1.20                                                     =
    +=   Azz                           :  All Commands start by Prefix System Address zz, if [01-99]                               =
    +=-----------------------------------------------------------------------------------------------------------------------------=
    +=   EZH                           : Help                                                                                      =
    +=   EZSTA                         : Show Global System Status                                                                 =
    +=   EZS RST                       : Reset to Factory Defaults                                                                 =
    +=   EZS ADDR xx                   : Set System Address to xx {xx=[00~99](00=Single)}                                          =
    +=   EZS CAS EN/DIS                : Set Cascade Mode Enable/Disable                                                           =
    +=   EZS OUTx VS INy               : Set Output x To Input y{x=[0~2](0=ALL), y=[1~4]}                                          =
    +=   EZS IR SYS xx.yy              : Set IR Custom Code{xx=[00-FFH],yy=[00-FFH]}                                               =
    +=   EZS IR OUTx INy CODE zz       : Set IR Data Code{x=[1~2],y=[1~4],zz=[00-FFH]}                                             =
    +=   EZG ADDR                      : Get System Address                                                                        =
    +=   EZG STA                       : Get System System Status                                                                  =
    +=   EZG CAS                       : Get Cascade Mode Status                                                                   =
    +=   EZG OUTx VS                   : Get Output x Video Route{x=[0~2](0=ALL)}                                                  =
    +=   EZG IR SYS                    : Get IR Custom Code                                                                        =
    +=   EZG IR OUTx INy CODE          : Get IR Data Code{x=[1~2],y=[1~4]}                                                         =
    +=   EZS OUTx VIDEOy               : Set Output VIDEO Mode                                                                     =
    +=                                   {x=[1~2], y=[1~2](1=BYPASS,2=4K->2K)}                                                     =
    +=-----------------------------------------------------------------------------------------------------------------------------=
    +=Input Setup Commands:(Note:input number(x)=HDMI(x),x=1)                                                                      =
    +=   EZS INx EDID y                : Set Input x EDID{x=[0~4](0=ALL), y=[0~15]}                                                =
    +=                                   0:EDID_BYPASS         1:1080P_2CH_HDR          2:1080P_6CH_HDR        3:1080P_8CH_HDR     =
    +=                                   4:1080P_3D_2CH_HDR    5:1080P_3D_6CH_HDR   6:1080P_3D_8CH_HDR                             =
    +=                                   7:4K30HZ_3D_2CH_HDR  8:4K30HZ_3D_6CH_HDR  9:4K30HZ_3D_8CH_HDR                             =
    +=                                   10:4K60HzY420_3D_2CH_HDR  11:4K60HzY420_3D_6CH_HDR  12:4K60HzY420_3D_8CH_HDR              =
    +=                                   13:4K60HZ_3D_2CH_HDR  14:4K60HZ_3D_6CH_HDR  15:4K60HZ_3D_8CH_HDR                          =
    +=                                   16:H4K_DOLBY_VISION_ATMOS                                                                 =
    +=   EZG INx EDID                  : Get Input x EDID  Index{x=[0~4](0=ALL)}                                                   =
    +=-----------------------------------------------------------------------------------------------------------------------------=
    +=*****************************************************************************************************************************=
    +===============================================================================================================================
    +
    +
  • +
+

Simple troubleshooting steps to perform

+
    Video Issues:
+        Hook a monitor to the output and test
+        Reseat the cables
+        Change out the cables
+
+    Switching issues:
+        SSH or open a web terminal to your PiKVM
+        `ls -la /dev/ttyUSB*` - This should give you an output. If not, try a different cable till an output is displayed.
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/faq/bios_glitch.png b/faq/bios_glitch.png new file mode 100644 index 00000000..74bef2d5 Binary files /dev/null and b/faq/bios_glitch.png differ diff --git a/faq/chrome.png b/faq/chrome.png new file mode 100644 index 00000000..5591c6fd Binary files /dev/null and b/faq/chrome.png differ diff --git a/faq/index.html b/faq/index.html new file mode 100644 index 00000000..5759ef71 --- /dev/null +++ b/faq/index.html @@ -0,0 +1,3291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + FAQ & Troubleshooting - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

FAQ & Troubleshooting

+ +

As a first step, we recommend carefully reading our documentation on GitHub or the updated documentation. Most steps to successfully set up your PiKVM are already described there.

+

If you run into any issues you can check this page which will list common errors. If that still doesn't help you you're welcome to raise an issue ticket or contact our Suppor for further help.

+

Common questions

+
+Where can I get a memory card image for PiKVM? +

See here: https://pikvm.org/download

+
+
+Can PiKVM work on Raspberry Pi 5? +
    +
  • Not now, but it will. Pi5 does not support hardware video encoding so there is no any reason to use it for PiKVM.
  • +
  • RPi5 is not compatible with PiKVM V3 HAT due to the difference in form factor with RPi4.
  • +
+
+
+Can I connect multiple servers to a single PiKVM? +

Yes, but it requires additional work to set up. See this page.

+
+
+How can I get the access to PiKVM in my local network over Internet? +

You can use port forwarding for port 443 on your router if it has an external IP address. In all other cases, you can use the excellent free VPN service Tailscale, which can be configured on PiKVM with a few simple commands.

+
+
+Can I assign a static IP to a PiKVM +

Yes, we highly suggest using this document first for those that are not Linux savvy.

+

[ONLY FOR ADVANCED LINUX USERS]

+

Edit file /etc/systemd/network/eth0.network for Ethernet or wlan0.network for Wi-Fi and edit the [Network] section:

+
[Network]
+Address=192.168.x.x/24
+Gateway=192.168.x.x
+DNS=192.168.x.x
+DNS=192.168.x.x
+
+

Don't forget the /24 suffix (CIDR), otherwise it will not work and your PiKVM will become unreachable.

+
+
+How can I disable IPv6 on PiKVM? +

To do this, you need at least KVMD 3.301 installed on your device. If this is not the case, update the OS.

+

Next, append the ipv6.disable=1 parameter to /boot/cmdline.txt and perform reboot.

+
+
+How do I recover my PiKVM, it cannot be reached now +
    +
  1. Take the USB-C end cable you have for your target and move to the PiKVM IOIO port or CON port
  2. +
  3. Take the USB-A end cable and put this on the HOST(The controlling PC)
  4. +
  5. Turn on or reboot your PiKVM, you should now see a COMx port on your HOST PC
  6. +
  7. Connect using something like Putty, use 115200 as your baud rate
  8. +
  9. Edit the file using nano or whatever text editor you are comfortable with, save the file
  10. +
  11. Reboot your PiKVM, check for functionality
  12. +
  13. If still unreachable, edit the same file to fix it
  14. +
  15. ONLY Disconnect the IOIO port once you have fully recovered your PiKVM and place this back onto the Target system
  16. +
+
+
+Can I use PiKVM for gaming? +

No, because:

+
    +
  • For HDMI-CSI bridge, bus bandwidth is not enough to transmit more than 1080p50.
  • +
  • For HDMI-USB dongle, high latency and low video quality.
  • +
  • General hardware video capture differs from software streaming and introduces additional latency.
  • +
+
+
+Can PiKVM do 4K video? +
    +
  • For HDMI-CSI bridge, no. There is not enough bandwidth in the CSI bus for that much data. 1080p50 will max out the bandwidth.
  • +
  • For the USB capture devices: technically yes, they will down sample to something smaller to meet the USB 2.0 bandwidth limitations, so the source may be 4k, but the stream will not.
  • +
  • The 4K real-time video will not fit through the network anyway.
  • +
+
+
+Where does the cursor/video latency come from? +

Here is the chain of transferring an image to your browser or VNC client.

+

Capture device -> Compression -> Network -> Decompression -> Rendering

+

100-200ms is very, very fast for this. But we are working to speed things up even more.

+
+
+I am expecting to see 60fps and I am not, why? +

PiKVM receives the entire signal, but then the encoding is the bottleneck. For 1080p, this is no more than 30 fps. V4 throws out every second frame of 60 hz/fps, and 30 fps is encoded. V3 and DIY can't process 60 hz and is only able to capture 50 hz, and in the same way they take every second frame, all you get out is 25 fps. The reason why V3 and DIY does not encode 30 out of 50 is that the picture will be jerky, but smooth at 25.

+
+
+Does PiKVM support sound? +

Yes but the only officially supported version is the PiKVM V3+ devices, V2 we will attempt best effort but ultimately we do not support CSI modules or USB.

+
+
+Can I power the Pi via PoE? +

Yes!

+

For a POE HAT

+

You still need a splitter to ensure you isolate the 5v connection between the Raspberry Pi and host PC to prevent back power issues that can cause instability or damage to either the host PC or the Pi. Power/Data cable + USB power blocker would work.

+

For a POE Splitter

+

No, there is no need for anything additional, you can power your RPi and or the PiKVM Mini with the USB-C variant.

+
+
+Do I need a power splitter? Why do I need one? +
    +
  • Yes for RPi4 - Please see the main v2 document for splitter types listed under V2 hardware
  • +
  • Yes for Zero W and Zero W 2, if using dedicated power you still need to split the power from the data towards the target. If using the target for power, this is not needed.
  • +
  • This is not needed if you have a PiKVM V3 and V4, as they splits power and signal on the board.
  • +
+
+
+Can I use PiKVM with non-Raspberry Pi boards (Orange, Nano, etc)? +

Yes, but you will have to prepare the operating system yourself. For the PiKVM software, you will need to replace some config files (such as UDEV rules). If you are a developer or an experienced system administrator, you will not have any problems with this. In addition, we are open to patches. If you need help with this, please contact us via Discord (#unofficial_ports channel).

+
+
+Is PiKVM OS its own custom distro? +

No. PiKVM OS is an Arch Linux ARM with our own repository for KVM-related packages. We distribute OS images (that is, our Arch Linux ARM build) to simplify installation, since PiKVM requires some tuning of the OS and special partitioning of the memory card.

+
+
+Why is PiKVM OS based on Arch Linux ARM and not Raspbian / Raspberry Pi OS? +

There are several reasons:

+
    +
  • Several years ago, when PiKVM was just starting out, Raspbian didn't have a minimalistic image and the transition to systemd was in full swing, which is why the distribution was not too stable.
  • +
  • Raspbian did not have all the necessary packages in the repositories to satisfy most software dependencies.
  • +
  • PiKVM was born as a pet project, and the founder likes Arch the most.
  • +
+

However, we plan to provide an alternative OS image based on Raspberry Pi OS in the future - now it is quite stable.

+
+
+Can I use an iPad on PiKVM? +
    +
  • Yes, with the correct hardware you can control an iPad.
  • +
  • In the opposite sense - yes, use VNC and use JUMP app (fully-featured but more expensive), or bVNC (cheap). RealVNC does NOT work.
  • +
+
+
+How do I add my own SSL cert? +

If you have a certificate (making a cert falls outside the scope of PiKVM - please reference OpenSSL documentation or use Let's Encrypt), replace keys in /etc/kvmd/nginx/ssl, edit /etc/kvmd/nginx/ssl.conf if necessary and restart kvmd-nginx service.

+
+
+How do I emulate various USB devices on the target machine? +

For a detailed description, see here.

+

Use the following USB database to get the desired devices: https://the-sz.com/products/usbid or https://devicehunt.com.

+
+
+Can I run a desktop on PiKVM? +

Yes, but it's strongly not recommended OR supported as this OS should be used in read-only mode and it will need read-write enabled all of the time, however if you insist on running one, instructions are here.

+
+
+How do I blank the oled screen? +

Please run the following: +

# systemctl disable --now kvmd-oled kvmd-oled-reboot kvmd-oled-shutdown
+# kvmd-oled --height=32 --interval=0 --clear-on-exit --text=x
+
+To re-enable the display: +
# systemctl enable --now kvmd-oled kvmd-oled-reboot kvmd-oled-shutdown
+
+
+
+How do I rotate the OLED display? +

Please run the following: +

1. mkdir -p /etc/systemd/system/kvmd-oled.service.d
+2. Create file /etc/systemd/system/kvmd-oled.service.d/override.conf:
+[Service]
+ExecStart=
+ExecStart=/usr/bin/kvmd-oled --height=32 --clear-on-exit --rotate=2
+
+
+
+I am getting a 500/503 error when I try and access the main KVM page! +

This maybe due to a few of the following:

+
    +
  • Missing /etc/kvmd/override.yaml file, to resolve it run rw; touch /etc/kvmd/override.yaml; ro
  • +
  • Bad YAML syntax, edit your /etc/kvmd/override.yaml file and undo what you did and restart PiKVM.
  • +
+
+
+How can I use the serial console to gain access to other devices +

You need to stop the service which listens on the /dev/ttyAMA0:

+
rw
+systemctl stop serial-getty@ttyAMA0.service
+
+

If you want this change permanent (not starting again after reboot), you can disable this service, ('enable' to reverse this decision):

+
systemctl disable serial-getty@ttyAMA0.service
+
+
+

Note

+
    +
  • Only USB OR the RJ-45 serial connector will work, you can't use them together!
  • +
  • If you disable the service permanently, you can't recover your device via serial console if you need this.
  • +
  • There are some reports, that you need to remove ttyAMA0 from /boot/cmdline.txt, but this is not needed on new installations.
  • +
+
+
+
+Can I run PiKVM in a docker? +

No, technically it might be possible but the OS requires many specific settings that cannot be performed inside the container.

+
+
+How can I change the HTTP/HTTPS ports? +

To do this, you need at least KVMD 3.301 installed on your device. If this is not the case, update the OS.

+

Add some of these lines to /etc/kvmd/override.yaml:

+
nginx:
+    https:
+        port: 4430
+    http:
+        port: 8080
+
+

After that, restart the server: systemctl restart kvmd-nginx.

+
+
+Can I control IR devices using PiKVM? +

This goes far beyond the usual use of PiKVM, so there is no official way to do this, but there are some ways from the community that you can try if you know how to handle a soldering iron.

+
+

First steps

+
+I can't find the PiKVM IP address in my network +

Follow the device guide of your PiKVM here.

+
+
+What is the default password? How do I change it? +

See here.

+
+
+How do I add another user? +

See here.

+
+
+How do I get root access in the web terminal? +

See here.

+
+
+Where is the PiKVM configuration located? +

Almost all KVMD (the main daemon controlling PiKVM) configuration files are located in /etc/kvmd. You can also find nginx configs and SSL certificates there. KVMD configs use YAML syntax. The specific platform parameters can be found in the file /etc/kvmd/main.yaml and you should never edit it. Use /etc/kvmd/override.yaml to redefine the system parameters.

+

Files that are not recommended for editing have read-only permissions. If you edit any of these files, you will need to manually make changes to them when you upgrade your system. You can view the current configuration and all available KVMD parameters using the command kvmd -m.

+
+
+I can't edit any file on PiKVM. Why is the system in read-only mode? +

The PiKVM file system is always mounted in read-only mode. This measure prevents it from being damaged by a sudden power outage. To change the configuration you must first switch the filesystem to write mode using the command rw from root. After the changes, be sure to run the command ro to switch it back to read-only. If you get a message that the file system is busy, then the easiest way is to perform a reboot.

+
+
+I want to get read-write filesystem all of the time +
+

DON'T DO THIS

+
+
+

DON'T DO THIS

+
+
+

DON'T DO THIS

+
+

Seriously, DON'T. Read-only mode increases the life of the memory card and protects the filesystem from power loss failures. See the question above ^ ^ ^

+

You can turn it off, but don't say you weren't warned.

+
+DON'T OPEN THIS SPOILER AND DON'T DO THIS +

Okay, fine.

+
    +
  • Edit /boot/cmdline.txt and change option ro to rw.
  • +
  • Do the same in /etc/fstab for the /boot partition.
  • +
  • Comment tmpfs lines in /etc/fstab for /var/lib and /var/log.
  • +
+
+

But again: DON'T DO THIS

+
+
+

If you do plan on doing this, no assistance will be provided beyond this point other than the existing documentation.

+
+
+
+
+How to set the date, time and timezone from command line? +
    +
  • Become root with the command su - or sudo -s.
  • +
  • Enable read/write with the command rw.
  • +
  • Find your timezone string e.g. timedatectl list-timezones or timedatectl list-timezones | grep -i australia.
  • +
  • Set the timezone with timedatectl set-timezone <YourTimeZoneHere> e.g. timedatectl set-timezone Australia/Victoria.
  • +
  • Stop the time syncing service with systemctl stop systemd-timesyncd as this will prevent the next step if running.
  • +
  • Set the time and date with timedatectl set-time 'YYYY-MM-DD HH:MM:SS' e.g. timedatectl set-time '2023-02-26 14:50:10'.
  • +
  • If you have hardware clock e.g. V3+, update it with hwclock --systohc , then check it with hwclock --show.
  • +
  • Switch filesystem to RO-mode with the command ro.
  • +
+
+
+How do I update PiKVM with the latest software? +
+Updating PiKVM OS +

To update, run following commands under the root user:

+
[root@pikvm ~]# pikvm-update
+
+

If you encounter an error like:

+
[root@pikvm ~]# pikvm-update
+bash: pikvm-update: command not found
+
+

It's most likely you have an old OS release. You can update the OS as follows:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# pacman -Syy
+[root@pikvm ~]# pacman -S pikvm-os-updater
+[root@pikvm ~]# pikvm-update
+
+

Next time you will be able to use the usual method with pikvm-update.

+
+
+
+How do I install or remove packages in PiKVM OS? +

PiKVM OS is based on Arch Linux ARM and uses the pacman package manager.

+
    +
  • Ensure the date is correct: date. Otherwise you may get the error SSL certificate problem: certificate is not yet valid
  • +
  • It is recommended to update the OS before installing new packages (see the tip upper ^^^).
  • +
  • Switch filesystem to RW-mode: rw.
  • +
  • Find some packages (emacs for example): pacman -Ss emacs.
  • +
  • Install it: pacman -Syy to update local packages list and pacman -Su emacs to install.
  • +
  • Remove it: pacman -R emacs.
  • +
  • Switch filesystem to RO-mode: ro.
  • +
+
+
+I don't need ATX functions. How do I disable this in the Web UI? +

If you don't need ATX power control you can disable the relevant Web UI menu in /etc/kvmd/override.yaml:

+
kvmd:
+    atx:
+        type: disabled
+
+

... then restart kvmd:

+
# systemctl restart kvmd
+
+
+
+How do I disable the web terminal? +
# rw
+# systemctl disable --now kvmd-webterm
+# ro
+
+
+
+How do I completely disable authorization in PiKVM? +

See here.

+
+
+Can I have different hostnames for each of my PiKVMs? +

Yes! And it's easy to do! Using a SSH session or the web terminal: +* Make sure you are root, run rw then run hostnamectl set-hostname yournewhostname.domain. +* Optional: edit /etc/kvmd/meta.yaml to alter the displayed hostname in the web UI. +* Run ro and reboot.

+
+
+Why not add software support for another codec? +

Encoding is a heavy process and will add significant latency, its best to have hardware support to avoid additional latency.

+
+

Video problems

+
+I can see the video but I can't see the WebRTC / video mode switch +

WebRTC and Direct H.264 modes are only available on V2+ platforms with HDMI-CSI capture device, +including PiKVM V3 or V4 Plus/Mini. See the modes guide to solve any problems.

+
+
+PiKVM does not show the video from the computer at all +
    +
  • Double-check that the video capture device is connected correctly.
  • +
  • Some laptops do not output any signal until you switch the output (usually via the FN + and an F5 key on the keyboard).
  • +
  • Your computer may have turned on sleep mode for the monitor. Move the mouse to turn it off.
  • +
  • For windows you might need to check for the active signal resolution. To change the active signal resolution you have to go to Settings>System>Display>Advanced display settings>Display adapter properties then, click "List All Models" and choose the one you want. Keep trying different Hz settings.
  • +
+
+
+The video works in the booted OS, but not in the BIOS/UEFI +

This problem appears on Intel NUC, GA-H77-DS3H, and some other devices when using a CSI bridge. All you need to do is change the EDID data. This is the information about supported resolutions that the CSI bridge reports to your computer.

+
+
+Glitchy or wrong BIOS/UEFI resolution +

On some motherboards, the BIOS may be displayed at a lower resolution, or with some rendering issues/glitches, specially on newer ASUS ones. Like this:

+

ASUS BIOS glitch

+

This can be solved by enabling the Compatibility Support Module (CSM) in your BIOS, usually under the Boot options.

+

If you can't or don't want to enable the CSM, you can try connecting a DisplayPort (DP) monitor, or a dummy plug. If you remove the DP cable/adapter the bug will reappear.

+

If none of this works, try connecting the DP cable first, boot into the BIOS, disable the CSM and shutdown (do not restart) your PC. Then, boot into the BIOS and enable the CSM before shutting down your PC. Then connect the HDMI and turn your PC on again.

+
+
+There is no video in GRUB2, but there is before and after +

Sometimes this can be caused by the specifics of the BIOS/UEFI and how GRUB2 works with video.

+

This can be solved by enabling the Compatibility Support Module (CSM) in your BIOS, usually under the Boot options. The video mode will be located in the same section. Switch the Video mode from UEFI to Legacy.

+
+
+Why does the CSI bridge does not work with official Raspberry Pi PoE HAT? +

Details here. The reason is that the official HAT has a built-in fan controller that conflicts with the TC358743 chip of the bridge. The solution is to disable the fan control and connect the fan to the power line so that it works continuously. To turn off the controller you need to add the line disable_poe_fan=1 to /boot/config.txt.

+
+
+The video freezes a few seconds after the start, restarting the Web UI or VNC does not help +

The story is here. Very very rarely, Raspberry Pi boards can have a hardware defect that causes some of the chip blocks to be unstable under normal power. The solution is to slightly increase the power supply, as you would when overclocking. Add over_voltage=1 (or over_voltage=2 if previous doesn't help) to /boot/config.txt and perform reboot.

+

To make sure that you are facing this particular problem, first perform a diagnostic:

+
    +
  • Boot the PiKVM without the specified options.
  • +
  • Open Web-UI and wait for freezing.
  • +
  • Click System -> Reset Stream.
  • +
  • Click System -> Open log and make sure that the log contains messages like H264: Can't wait for the VCOS semaphore.
  • +
  • Make sure that the last message from ustreamer was H264: Configuring MMAL encoder (not counting messages about connecting and disconnecting stream clients).
  • +
+
+
+No image from computer with Linux + Awesome WM +

Sometimes Awesome WM on Linux can't recognize a video output change on a cable. That is, if the cable was first inserted into the monitor, and then you reconnected it to PiKVM - it may happen that you will not see the image. It seems that the problem is Awesome WM, since for example with KDE, it is not reproducible. If you turn on your workstation with PiKVM already connected, everything will work fine.

+
+
+Windows shows limited Available Resolutions +

This is due to a driver issue. A possible resolution can be found here.

+
+
+Firefox ESR from the Debian repo shows the black screen in H.264 mode +

Make sure the OpenH264 Plugin both exists and is enabled (known issue on Debian GNU/Linux). Press Ctrl+Shift+A to open the Add-ons Manager, then press Plugins. You should see OpenH264 Video Codec provided by Cisco Systems, Inc.. Make sure it is enabled by pressing the "more options" button (3 horizontal dots), then pressing Always Activate.

+
+
+Apple TB/USB-C HDMI video doesn't work +

A possible solution can be found here.

+
+
+I am seeing a NO SIGNAL, what can I do? +

If you are using PiKVM V2 or a V3, you need to ensure that your target is using the maximum resolution 1920x1080@50Hz, 60Hz will not work.

+

If you are using the PiKVM V4, ensure that you are getting a signal out from the target by using a physical monitor using the same exact cable/dongle, ensure that you are using the maximum resolution 1920x1200@60hz, 2K/4K resolutions will not work.

+
+

USB problems (keyboard, mouse, mass storage, etc)

+
+My computer does not recognize USB of PiKVM V2+ at all +
    +
  • Make sure that you have used the correct USB cable with DATA lines to connect the OTG port for the Raspberry to the computer. You may have decided to use a USB hub instead of a Y-cable and it won't work. Use good cables and follow the instructions :)
  • +
  • In rare cases, some very buggy BIOS's do not like HID and Mass Storage in one USB device. You can either disable Mass Storage, or use the Pico HID to physically separate them.
  • +
+
+
+BIOS/UEFI does not recognize USB of V2+, but computer does +

If you are using a USB hub or USB PCI controller, this may not be handled by your BIOS. Try to use another USB port. Some ports may have a built-in hub on the motherboard and a buggy BIOS that can't handle it.

+
+
+My keyboard works in BIOS/UEFI, but my mouse does not +

The BIOS does not support absolute mouse mode, which is preferred by PiKVM. In this case, you can enable relative or dual positioning mode.

+
+
+My mass storage drive works (I can boot an image from PiKVM V2+), but my keyboard/mouse does not +

In rare cases, some very buggy BIOS's does not like HID and Mass Storage in one USB device. You can either disable Mass Storage, or use the Pico HID to physically separate them.

+
+
+Buggy absolute mouse on Windows 98 as managed server +

How to fix:

+ +
+
+The mouse does not work with NVR/DVR CCTV +

Often these devices have a buggy USB driver that does not understand an absolute mouse and/or a mouse with horizontal scrolling. In this case, the following configuration for /etc/kvmd/override.yaml will help you:

+
kvmd:
+    hid:
+        mouse:
+            absolute: false
+            horizontal_wheel: false
+        mouse_alt:
+            device: ""
+
+

It will make the relative mouse without horizontal scrolling the only mice.

+
+
+There's big mouse latency on another Raspberry Pi as managed server +

Unusual case: RPi4 is used as a PiKVM to control RPi3. In this case, the mouse delay may be several seconds. To fix it, append usbhid.mousepoll=0 to the boot line in /boot/cmdline.txt on the managed server (i.e. RPI3 in our case) and reboot it. Source.

+
+
+What speed is the USB OTG port? +

Per the official RPI documentation, this is a limitation of the SoC. The OTG port is only USB2.0, so is limited to 455 Mbit/s.

+
+
+On MacOSX, my mouse/keyboard does not work! +

There are a few fixes the community has suggested:

+

If using a USB-C to USB-C cable, you need to use the included USB-C to USB-A cable then use a USB-A to USB-C adapter

+

You may need to allow new accessories to connect. Source

+
+

Web UI problems

+
+Chrome reports a Certificate Issue when I try to access the PiKVM web interface +

The latest versions of Chrome do not allow access to the page with a self signed certificate, so if you see the following screen when loading the PiKVM website:

+

Chrome Blocking

+

You can proceed by typing thisisunsafe and Chrome will then load the page. Also see Let's Encrypt page.

+
+
+Pressing ESC in full screen mode causes the PiKVM page to close +

Your browser does not support keyboard lock. Right now (January 2022), only Chromium implements this, so it works on Chrome, Edge, and Opera.

+
+
+The Web UI doesn't work properly in Firefox while it works fine in Chrome +

This might be related to your specific hardware combination or browser hardware acceleration. Try disabling hardware acceleration in Firefox or updating your GPU and chipset drivers.

+
+
+Unexpected interruption while loading the image for Mass storage drive +

If problems occur when uploading even a small disk image it may be due to unstable network operation or antivirus software. It is well known that Kaspersky antivirus cuts off PiKVM connections during uploading, so you should add the PiKVM website to Kaspersky's list of exceptions or not filter web requests with the antivirus. Antivirus programs can also affect the performance of certain interface elements, for example the quality slider. For Kaspersky, the steps to add the network address of PiKVM's website to the exclusion list is: Protection -> Private browsing -> Categories and exclusions -> Exclusions.

+
+
+I can't click on anything when using the WebGUI on my phone +

At this time, iOS has the buttons on the bottom if you have the correct resolution, sometimes you cannot see them due to the resolution. +At this time, android is not supported, our suggestion is to use a VNC client.

+
+
+I changed the Display Resolution to 720p but Windows still shows 1080p and the display looks blurry +

This is mostly seen on Windows, open Display Settings -> Advanced display settings -> Display adapter setting for Display 1 -> List all modes -> (Toggle between 720p30hz back to 50hz), this may need to be done if you need to change it back for 1080p.

+
+

Hardware problems (Wi-Fi, ATX, etc)

+
+I can't connect to Wi-Fi on a Raspberry Pi Zero W +
    +
  • Some Zeros contain a defective Wi-Fi chip. You can either return the device to the store, or try the software workaround.
  • +
+
+
+I can't connect to Wi-Fi at all! +
    +
  • +

    If your device is unable to connect to the Wi-Fi network that you have set up, check the 2.4 GHz Wi-Fi channel used by your Wi-Fi access point.

    +
  • +
  • +

    If channels 12 to 14 are used (some countries have banned these channels) try to use a channel between 1 and 11.

    +
  • +
+
+
+LEDs/Switches do not work in ATX control +

Double check your wiring. Make sure you placed the relays (G3VM-61A1) in the correct orientation. The relays for switches (Power, Reset) have a different orientation than the ones for LEDs.

+
+
+My PiKVM keeps disconnecting from the Wi-Fi network +

Try to edit /etc/conf.d/wireless-regdom and look for your region and uncomment it. For example: WIRELESS_REGDOM="US".

+
+
+PiKVM complains about low power warnings +
    +
  • Are you using a "proper" power supply? Not one you hacked together?
  • +
  • Some USB power bricks advertise 5V 2.1A or higher, but can't deliver consistent 5V. Best to use Raspberry Pi Foundation recommended power supplies.
  • +
+
+
+PiKVM complains about a RTC low voltage detected, date/time is not reliable +
    +
  • This is mearly a warning that can be ignored however, the following resolves the issue:
  • +
  • Leave plugged in for 24+ hours and or
  • +
  • Connect to the internet using the eth cable, the internal NTP service will set the time accordlingly
  • +
  • Force a time sync: rw && hwclock --systohc" or "rw && hwclock -w"
  • +
  • Set date and time manually can be found here.
  • +
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/first_steps/index.html b/first_steps/index.html new file mode 100644 index 00000000..1051f6a6 --- /dev/null +++ b/first_steps/index.html @@ -0,0 +1,14 @@ + + + + + + Redirecting... + + + + + +You're being redirected to a new destination. + + diff --git a/flashing_hid/index.html b/flashing_hid/index.html new file mode 100644 index 00000000..cacfe79c --- /dev/null +++ b/flashing_hid/index.html @@ -0,0 +1,2735 @@ + + + + + + + + + + + + + + + + + + + + + + Flashing hid - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +
+

Legacy warning

+

This page describes the legacy keyboard and mouse emulator used in old DIY builds. +There is no point using it today because there is a more modern and better replacement for the new Pico HID. +This one can also serve as an in-place compatible replacement for the Arduino HID in the old build.

+
+

Flashing the Arduino HID

+

Note for the recent images

+

Current image no longer ships with necessary tools for flashing Arduino HID, therefore please install platformio-core and avrdude and continue:

+
pacman -Syu
+pacman -S platformio-core avrdude
+
+

Serial Firmware (the default option)

+

This operation can be done using your RPi (except Pi Zero W). Here the common steps:

+
    +
  1. +

    Disconnect the RESET wire from the Arduino board.

    +
  2. +
  3. +

    Connect the Arduino and RPi with a suitable USB cable.

    +
  4. +
  5. +

    Log in to the Raspberry Pi console using SSH or Web Terminal.

    +
  6. +
  7. +

    Upload the firmware (USB keyboard & mouse is used by default, on this step you can choose PS/2 keyboard):

    +
    # rw
    +# systemctl stop kvmd
    +# cp -r /usr/share/kvmd/hid/arduino ~
    +# cd ~/arduino
    +# make
    +# make install
    +# reboot
    +
    +
  8. +
  9. +

    Connect the RESET wire, disconnect the USB cable, and reboot the RPi.

    +
  10. +
+

With a Pi Zero W, you may consider building the firmware on a faster system and programming using USB or booting from another SD card and following the build steps using a clone of the KVMD repo.

+

SPI Firmware

+

This operation can be done using your Raspberry Pi without disconnecting any wires:

+
    +
  1. +

    Connect the Arduino and RPi with a suitable USB cable.

    +
  2. +
  3. +

    Log in to the Raspberry Pi console using SSH or Web Terminal.

    +
  4. +
  5. +

    Execute rw, add line dtoverlay=spi0-1cs to /boot/config.txt and perform reboot.

    +
  6. +
  7. +

    Build and upload the firmware (USB keyboard & mouse is used by default)

    +
    # rw
    +# systemctl stop kvmd
    +# cp -r /usr/share/kvmd/hid/arduino ~
    +# cd ~/arduino
    +# make spi
    +# make install
    +# reboot
    +
    +
  8. +
+

Common Errors

+

Circuit Issues

+

Common - Reset Wire

+

Different pins are used for the reset wire but serve a similar function. For programming the TTL firmware over USB, the reset wire should be disconnected. When programming using SPI, the reset wire needs to be connected through a transistor circuit and connected to GPIO25 (pin 22 on the GPIO header)

+

SPI-specific Wiring

+

The 3v3, ground, Reset (GPIO25), MISO, MOSI, SCLK, and CS1 need to be connected appropriately. SPIO_CS0 and SPIO_CS1 can both be used but the default configuration uses SPIO_CS1 for the Arduino Microcontroller (CS0 is used for another device on the V3). These generally follow a block as follows:

+
Pin  0        2         4
+      2        0         0
+      .........GR.C.......
+Row # 12345678901234567890
+      ........3MMS........
+Pin   0       1          3
+       1       7          9
+
+

The most common error is an "off-by-one" error where pins are shifted by a row. Some cases have non-standard GPIO layouts so please be careful when following these instructions using a case that has a modified pinout.

+ + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/flashing_os/RPi-imager1.jpg b/flashing_os/RPi-imager1.jpg new file mode 100644 index 00000000..4dee3a98 Binary files /dev/null and b/flashing_os/RPi-imager1.jpg differ diff --git a/flashing_os/RPi-imager2.jpg b/flashing_os/RPi-imager2.jpg new file mode 100644 index 00000000..5527c62f Binary files /dev/null and b/flashing_os/RPi-imager2.jpg differ diff --git a/flashing_os/RPi-imager3.jpg b/flashing_os/RPi-imager3.jpg new file mode 100644 index 00000000..0a077567 Binary files /dev/null and b/flashing_os/RPi-imager3.jpg differ diff --git a/flashing_os/RPi-imager4.jpg b/flashing_os/RPi-imager4.jpg new file mode 100644 index 00000000..ee62fac6 Binary files /dev/null and b/flashing_os/RPi-imager4.jpg differ diff --git a/flashing_os/RPi-imager5.jpg b/flashing_os/RPi-imager5.jpg new file mode 100644 index 00000000..8cbcea94 Binary files /dev/null and b/flashing_os/RPi-imager5.jpg differ diff --git a/flashing_os/RPi-imager6.jpg b/flashing_os/RPi-imager6.jpg new file mode 100644 index 00000000..2ce1456f Binary files /dev/null and b/flashing_os/RPi-imager6.jpg differ diff --git a/flashing_os/RPi-imager7.jpg b/flashing_os/RPi-imager7.jpg new file mode 100644 index 00000000..7da31658 Binary files /dev/null and b/flashing_os/RPi-imager7.jpg differ diff --git a/flashing_os/index.html b/flashing_os/index.html new file mode 100644 index 00000000..1907f32d --- /dev/null +++ b/flashing_os/index.html @@ -0,0 +1,2884 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Flashing PiKVM OS image - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Flashing OS

+ +
+

Micro-SD Card Requirements

+

Minimum 32 Gb, Class 10 recommended.

+
+
+

Download the image

+

Download the appropriate SD card image. Select it based on the board, platform, and the video capture device you are using.

+
+

Official PiKVM Devices

+

These images are not suitable for DIY and are intended only for our branded devices.

+ +
+
+

DIY PiKVM V2 Platform

+ +
+
+

DIY PiKVM V1 Platform

+ +
+
+

Any other combinations for advanced users

+

Please check the file archives for ready-made image or build the image yourself.

+
+
+

Flashing the image

+
+

Tip

+

After inserting the memory card into your computer, ignore request to format. This is not nessessary.

+
+

Using Linux CLI (ADVANCED USERS)

+

Decompress (if nessessary) and flash the image. Be careful when choosing the device path, it may be different on your machine:

+
[user@localhost]$ xz --decompress v2-hdmi-rpi4-latest.img.xz
+[user@localhost]$ sudo dd if=v2-hdmi-rpi4-latest.img of=/dev/mmcblkX
+
+

You can also use dd_rescue or ddrescue.

+

Using RPi Imager (Linux, MacOS and Windows)

+
    +
  1. +

    Download and install the latest version of RPi Imager.

    +
  2. +
  3. +

    Run RPi Imager:

    +

    +
  4. +
  5. +

    Press NO FILTERING then CHOOSE OS and select Use custom image at bottom of the list:

    +

    +
  6. +
  7. +

    After clicking on this item, select the image file (*.img or *.img.xz), then click CHOOSE STORAGE:

    +
    +

    Warning

    +

    This should already be set to blank though the flashing process from step 7 but its best to double check the advanced settings (CTRL+SHIFT+X), make sure they are blank or the flash will fail.

    +
    +

    +
  8. +
  9. +

    Insert the memory card into the card reader. Choose the card reader from this list. Be careful and choose the right device:

    +

    +
  10. +
  11. +

    After choosing the memory card, press the WRITE button. Confirm the operation when you are asked about it:

    +

    +
  12. +
  13. +

    Refuse customization options.

    +
    +

    Warning

    +

    The customization is designed for Raspberry OS and will not work in PiKVM OS. +If you apply any custom settings, this will cause the image to malfunction.

    +

    PiKVM OS has its own settings mechanism, please use it after the flashing +if you need to configure Wi-Fi or something similar.

    +
    +

    +
  14. +
  15. +

    Wait for the process to finish. Get yourself a coffee or do some stretching :) + The process may hang at 99% for a long time, this is okay, just wait for it to complete.

    +

    +
  16. +
  17. +

    Remove the memory card after successful completion. If an error occurs during flashing or booting PiKVM, repeat the process. + If the error persists, use a different memory card.

    +
  18. +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gpio/gpio_menu.png b/gpio/gpio_menu.png new file mode 100644 index 00000000..f160c503 Binary files /dev/null and b/gpio/gpio_menu.png differ diff --git a/gpio/index.html b/gpio/index.html new file mode 100644 index 00000000..d34d980e --- /dev/null +++ b/gpio/index.html @@ -0,0 +1,3652 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + GPIO - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

GPIO (pins, relays, lamps, etc)

+ +

GPIO (general-purpose input/output) is a series of digital interfaces that can be used to connect relays, LEDs, sensors, and other components.

+
+

Warning

+
    +
  • Before using GPIO on PiKVM v3 HAT, carefully study the purpose of its ports.
  • +
  • Using GPIO on a PiKVM was designed as a feature for advanced users, so please familiarize yourself with the topic to make sure you understand how to use use it before setting it up.
  • +
  • Careless usage of GPIO can damage your Raspberry Pi or components.
  • +
+
+

When talking about PiKVM and GPIO it refers not solely to the physical interface of the Raspberry Pi, but also to various plugins (for example, for USB relays) that can also be used transparently by emulating an abstract GPIO API.

+
+

Basics

+

Setting up GPIO is considerably complex. The interface is divided into several layers for flexibility. Any configuration is performed using a file /etc/kvmd/override.yaml which uses the YAML syntax. We will look at each part of the configuration individually with an example for each. Sections should be combined under shared keys.

+
    +
  • +

    Wrong:

    +
    kvmd:
    +    gpio:
    +        drivers: ...
    +kvmd:
    +    gpio:
    +        scheme: ...
    +
    +
  • +
  • +

    Correct:

    +
    kvmd:
    +    gpio:
    +        drivers: ...
    +        scheme: ...
    +
    +
  • +
+
+

Drivers

+

The first part of the configuration refers to the hardware layer, which defines which IO channels are used (standard GPIO pins of the Raspberry Pi, an USB relay, and so on). If you just want to use GPIO with the default settings you can skip to the next section Scheme.

+

Each hardware input/output requires a individual driver configuration entry. Each driver has a type (which refers to the plugin that handles the communication between PiKVM and the hardware) and a unique name. This allows you to either can add multiple drivers of the same type with different settings or connect multiple USB HID relays.

+
+

Note

+

Each driver requires a unique name. Names surrounded by double underscore are system reserved and should not be used.

+
+

The only exception to this is the default GPIO driver with the name __gpio__, representing the physical GPIO interface of the Raspberry Pi. The configuration section for __gpio__ is only required in your /etc/kvmd/override.yaml if you want to change the default settings. It can be omitted if you are fine with the defaults.

+
kvmd:
+    gpio:
+        drivers:
+            # This example shows how the default __gpio__ driver settings can be changed. It can be omitted if you are fine with the defaults.
+            __gpio__:  # Names surrounded by double underscore are system reserved
+                type: gpio  # Refers to the plugin name handling the communication
+
+            # You can define another gpio driver for some reason
+            my_gpio: 
+                type: gpio
+
+            # Example for a USB HID relay connected to PiKVM
+            relay:
+                type: hidrelay
+                device: /dev/hidraw0  # The path to the linux device
+
+
+

Scheme

+

The second part defines how the various driver channels are configured. Each channel has a unique name, a mode (input or output), a pin number, and a reference to the driver configured in the previous part.

+
+

Note

+

Names that starts and ends with two underscores (like __magic__) are reserved.

+
+

Two interaction modes are available for outputs: pulse and switch. In pulse mode, the output quickly switches its state to logical 1 and back (just like pressing a button). In switch mode, it saves (toggles) the state that the user set. When PiKVM is started/rebooted (any time the KVMD daemon is started or stopped) all output channels are reset to 0. This can be changed using the initial parameter. For example, initial=true for logic 1 on startup.

+

If you don't specify a driver for the channel in the scheme the default driver, __gpio__ will be used.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeAllowed valuesDefaultDescription
led1, button1, relay1, etc.stringa-Z, numbers, _, -A section for the named channel
driverstringa-Z, numbers, _, -Optional, Name of the section defined above in Drivers if not GPIO
pinintegerX >= 0Refers to a GPIO pin or driver's pin/port
modeenuminput or outputDefines if a channel is used for input or output, may be limited by driver plugin
Input only
debouncefloatx >= 00.1Debounce time in seconds. 0 for disable debounce
Output only
switchbooltrue or falsetrueEnables or disables the switch mode on the channel (enabled by default).
initialnullable booltrue, false or nullfalseDefines the initial state of the switch upon boot, null for don't make changes (the last one does not supported by generic GPIO)
invertedbooltrue or falsefalseInverts the active logical level
pulseA section header to define switch pulse configuration
delayfloatX >= 00.1Defines the pulse time in seconds, 0 for disable pulsing
min_delayfloatX >= 0.10.1
max_delayfloatX >= 0.10.1
+
kvmd:
+    gpio:
+        scheme:
+            # A certain device sends signals to the RPi and we want the PiKVM to display this as an led
+            led1:
+                pin: 19 # GPIO pin number on the RPi
+                mode: input 
+            led2:
+                pin: 16
+                mode: input 
+
+            # Two outputs of RPi's GPIO
+            button1:
+                pin: 26 # GPIO pin number on the RPi
+                mode: output
+                switch: false  # Disable switching, only pulse available
+            button2:
+                pin: 20
+                mode: output
+                switch: false
+
+            relay1:  # Channel 1 of the relay /dev/hidraw0
+                driver: relay  # Not GPIO, so add name from the above Drivers section
+                pin: 0  # Numerating starts from 0
+                mode: output  # Relays can't be inputs
+                initial: null  # Don't reset the state to 0 when initializing and terminating KVMD
+            relay2:  # Channel 2
+                driver: relay
+                pin: 1
+                mode: output
+                initial: null
+                pulse:
+                    delay: 2  # Default pulse value
+                    max_delay: 2  # The pulse interval can be between min_delay=0.1 (by default) and max_delay=2
+
+
+

View

+

This is the last part of the required configuration. It defines how the previous driver and channel configuration is rendered on the Web interface. Here's an example for the example configuration above:

+
kvmd:
+    gpio:
+        view:
+            header:
+                title: Switches  # The menu title
+            table:  # The menu items are rendered in the form of a table of text labels and controls
+                - ["#Generic GPIO leds"]  # Text starting with the sharp symbol will be a label
+                - []  # creates a horizontal separator and starts a new table
+                - ["#Test 1:", led1, button1]  # Text label, one input, one button with text "Click"
+                - ["#Test 2:", led2, button2]
+                - []
+                - ["#HID Relays /dev/hidraw0"]
+                - []
+                - ["#Relay #1:", "relay1|Boop 0.1"]  # Text label and button with alternative text
+                - ["#Relay #2:", "relay2|Boop 2.0"]
+
+

This will be rendered as:

+

drawing

+

Some rules and customization options:

+
    +
  • Text starting with the # symbol will be a label.
  • +
  • To place a channel in a cell, use the name you defined in the scheme.
  • +
  • Inputs are displayed as round LEDs.
  • +
  • Outputs are displayed as a switch AND a button.
  • +
  • If the switch mode is disabled, only a button will be displayed. If pulse is disabled, only a switch will be shown.
  • +
  • To change the LED's color specify it after the channel name like "led1|red". Available: green, yellow, red, blue, cyan, magenta, pink and white.
  • +
  • To change title of the button, write some its name like "relay1|My cool relay".
  • +
  • Buttons and switches can request confirmation on acting. To do this write its name like "relay1|confirm|My cool relay". The third argument with a title is required in this case.
  • +
  • The button can automatically close the menu when clicked. Use something like "relay1|hide|My button". It can be used with confirmation option: "relay1|confirm,hide|My button".
  • +
+

Also you can place some leds in the menu title using the similar syntax:

+
kvmd
+    gpio:
+        view:
+            header:
+                title: ["#Test1:", led1, "Test2:", led2]
+
+
+

Hardware modules and pseudo-drivers

+

Raspberry's GPIO

+
+Click to view +

The driver gpio provides access to regular GPIO pins with input and output modes. It uses /dev/gpiochip0 and the libgpiod library to communicate with the hardware. Does not support saving state between KVMD restarts (meaning initial=null).

+

You can use the interactive scheme when selecting the pins to use. Please note that when selecting a pin for a channel, you need to use a logical number instead of a physical number. That is, if you want to use a physical pin with the number 40, the channel must have the number 21 corresponding to the logical GPIO21.

+

Channels should not use duplicate pins. You can also not use already used pins. To see which pins are currently used, run the command gpioinfo.

+
+

USB HID Relay

+
+Click to view +

The driver hidrelay provides access to cheap managed USB HID relays that can be found on AliExpress. This driver does not support input mode, only output. To use it, you need to specify the path to the device file (like /dev/hidraw0) using the device parameter.

+

Additionally, we recommend to configure access rights and static device name using UDEV rules. For example, create /etc/udev/rules.d/99-kvmd-extra.rules:

+
KERNEL=="hidraw[0-9]*", SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05df", GROUP="kvmd"
+
+

Channels should not use duplicate physical numbers. The driver supports saving state between KVMD restarts (meaning initial=null).

+
+

ezCoo KVM switch

+
+Click to view +

You can use GPIO to control KVM port switching. This usually requires the use of relays and buttons, but for the ezCoo switch there is a special ezcoo driver that simulates GPIO by sending commands to the switch via serial port. So you can make a menu in PiKVM to control the multiport switch.

+
+

IPMI

+
+Click to view +

The driver ipmi provides the ability to send IPMI commands (on, off, reset) and show the power status of the remote host. In fact, this is not a hardware driver, but something like a pseudo-GPIO. Each "pin" is actually responsible for a specific IPMI operation of ipmitool:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PinTypeCommand
0inputipmitool ... power status, can be used to draw the LED in the menu
1outputipmitool ... power on, sends the on command (and only this), so like all other outputs it should be a button
2outputipmitool ... power off
3outputipmitool ... power cycle
4outputipmitool ... power reset
5outputipmitool ... power diag
6outputipmitool ... power soft
+

You are supposed to define one driver per host:

+
kvmd:
+    gpio:
+        drivers:
+            my_server:
+                type: ipmi
+                host: myserver.local
+                user: admin
+                passwd: admin
+        scheme:
+            my_server_status:
+                driver: my_server
+                pin: 0
+                mode: input
+            my_server_on:
+                driver: my_server
+                pin: 1
+                mode: output
+                switch: false
+            my_server_off:
+                driver: my_server
+                pin: 2
+                mode: output
+                switch: false
+        view:
+            table:
+                - [my_server_status, "my_server_on|On", "my_server_off|Off"]
+
+
+

Wake-on-LAN

+
+Click to view +

The driver wol provides a simple generator of Wake-on-LAN packages. One driver and one output are generated for one host if a simplified configuration method is used. However, you can define multiple drivers if you want to manage different hosts. One driver controls one host, and can only be used as an output. Pin numbers are ignored.

+
kvmd:
+    gpio:
+        drivers:
+            wol_server1:
+                type: wol
+                mac: ff:ff:ff:ff:ff:f1
+            wol_server2:
+                type: wol
+                mac: ff:ff:ff:ff:ff:f2
+                ip: 192.168.0.100
+                port: 9
+        scheme:
+            wol_server1:
+                driver: wol_server1
+                pin: 0
+                mode: output
+                switch: false
+            wol_server2:
+                driver: wol_server2
+                pin: 0
+                mode: output
+                switch: false
+        view:
+            table:
+                - ["#Server 1", "wol_server1|Send Wake-on-LAN"]
+                - ["#Server 2", "wol_server2|Send Wake-on-LAN"]
+
+
+

CMD

+
+Click to view +

The cmd driver allows you to run custom command on PiKVM OS.

+
+

Note

+

This driver does not support bash operators, that is, it is a direct call to commands with arguments. For more complex cases, write your own shell scripts.

+
+

Commands are executed from the user kvmd. If you want to run the command as root, then you need to configure sudo. Example of the /etc/sudoers.d/custom_commands:

+

Granular example

+
kvmd ALL=(ALL) NOPASSWD: /usr/bin/reboot
+
+

NON Granular example (Captures ALL commands)

+
kvmd ALL=(ALL) NOPASSWD: ALL
+
+

Example of the /etc/kvmd/override.yaml:

+
kvmd:
+    gpio:
+        drivers:
+            reboot:
+                type: cmd
+                cmd: [/usr/bin/sudo, reboot]
+        scheme:
+            reboot_button:
+                driver: reboot
+                pin: 0
+                mode: output
+                switch: false
+        view:
+            table:
+                - ["reboot_button|confirm|Reboot PiKVM"]
+
+

An example to help you get started:

+
    +
  • cmd: [/usr/bin/sudo, kvmd-otgconf, --disable-function, mass_storage.usb0]
  • +
  • cmd: [(absolute path to sudo, command, flag, flag, absolute path to file]
  • +
+

Then run the following:

+
systemctl restart kvmd
+
+
+

PWM

+
+Click to view +

The pwm driver allows you to use some GPIO pins on the Raspberry Pi for PWM.

+
+

Note

+

Due to hardware limitations, this module conflicts with the kvmd-fan (the fan controller) on PiKVM V3 and V4 Plus. +To use it, you have to use hardware PWM for kvmfan. To do this, add the following lines to /etc/kvmd/fan.ini:

+
[main]
+pwm_soft = 80
+
+

Not needed for V4 Mini because it does not have a fan.

+
+

Here the small example with servo control:

+
    +
  1. +

    Add some params to /boot/config.txt:

    +
      +
    • +

      For PiKVM V3 or DIY device to enable PWM0_0 on RPi GPIO18:

      +
      dtoverlay=pwm
      +
      +
    • +
    • +

      For PiKVM V4 to enable PWM0_0 on CM4 GPIO12 (CN5 NeoPixel Pin) and set the PWM function to 4 (ALT0):

      +
      dtoverlay=pwm,pin=12,func=4
      +
      +
    • +
    +
  2. +
  3. +

    Create /etc/udev/rules.d/99-kvmd-pwm.rules:

    +
    SUBSYSTEM=="pwm*", ACTION=="add", RUN+="/bin/chgrp -R kvmd /sys%p", RUN+="/bin/chmod -R g=u /sys%p"
    +SUBSYSTEM=="pwm*", ACTION=="change", ENV{TRIGGER}!="none", RUN+="/bin/chgrp -R kvmd /sys%p", RUN+="/bin/chmod -R g=u /sys%p"
    +
    +
  4. +
  5. +

    Connect Servo motor like SG90 PWM connection to RPi GPIO18 or CM4 GPIO12, +5V and GND to a 5V and GND pin on header:

    +
  6. +
  7. +

    Add to /etc/kvmd/override.yaml

    +
    kvmd:
    +    gpio:
    +        drivers:
    +            servo1:
    +                type: pwm
    +                chip: 0                      # PWM Chip Number
    +                period: 20000000             # Servo Motor SG90 Period in nano-seconds
    +                duty_cycle_push: 1500000     # Servo Motor SG90 duty_cycle for pushing button
    +                duty_cycle_release: 1000000  # Servo Motor SG90 duty_cycle for releasing button
    +        scheme:
    +            __v4_locator__:  # v4-mini only
    +                pin: 25      # v4-mini only
    +            short_press:
    +                driver: servo1
    +                pin: 0  # Pin number is the PWM channel number on the PWM Chip
    +                mode: output
    +                switch: false
    +                pulse:
    +                    delay: 0.5
    +                    max_delay: 2
    +            long_press:
    +                driver: servo1
    +                pin: 0
    +                mode: output
    +                switch: false
    +                pulse:
    +                    delay: 2
    +                    max_delay: 2
    +            extra_long_press:
    +                driver: servo1
    +                pin: 0
    +                mode: output
    +                switch: false
    +                pulse:
    +                    delay: 10
    +                    max_delay: 20
    +        view:
    +            header:
    +                title: Controls
    +            table:
    +                - ["#Servo - Short Press", "short_press|Press"]
    +                - ["#Servo - Long Press", "long_press|Press"]
    +                - ["#Servo - Extra Long Press", "extra_long_press|Press"]
    +
    +
  8. +
+
+

Servo

+
+Click to view +

The servo module is built on top of the pwm module and allows user to define angles instead of duty_cyles to control a PWM enabled servo motor like SG90. When the button is pressed the servo motor moves to an angle defined by angle_push and when button is released it moves back to angle_release. In the example configuration for a cheap 5V SG90 Servo, the motor moves to an angle of 45 degrees when button is pressed and moves back to 20 degress when released.

+
+

Note

+

Due to hardware limitations, this module conflicts with the kvmd-fan (the fan controller) on PiKVM V3 and V4 Plus. +To use it, you have to use hardware PWM for kvmfan. To do this, add the following lines to /etc/kvmd/fan.ini:

+
[main]
+pwm_soft = 80
+
+

Not needed for v4-mini because it does not have a fan.

+
+

To use Servo motors in PiKVM you need to follow steps 1-3 for PWM Module and then use the following configuration.

+

Add to /etc/kvmd/override.yaml:

+
kvmd:
+    gpio:
+        drivers:
+            servo1:
+                type: servo
+                chip: 0                  # PWM Chip Number
+                period: 20000000         # Servo Motor SG90 Period in nano-seconds
+                duty_cycle_min: 350000   # Servo Motor SG90 duty_cycle for -90 degrees
+                duty_cycle_max: 2350000  # Servo Motor SG90 duty_cycle for +90 degrees
+                angle_max: 90            # Servo Motor SG90 angle at duty_cycle_max
+                angle_min: -90           # Servo Motor SG90 angle at duty_cycle_min
+                angle_push: 45           # Servo Motor SG90 angle to push button
+                angle_release: 20        # Servo Motor SG90 angle to release button
+        scheme:
+            __v4_locator__:  # v4-mini only
+                pin: 25      # v4-mini only
+            short_press:
+                driver: servo1
+                pin: 0  # Pin number is the PWM channel number on the PWM Chip
+                mode: output
+                switch: false
+                pulse:
+                    delay: 0.5
+                    max_delay: 2
+            long_press:
+                driver: servo1
+                pin: 0
+                mode: output
+                switch: false
+                pulse:
+                    delay: 2
+                    max_delay: 2
+            extra_long_press:
+                driver: servo1
+                pin: 0
+                mode: output
+                switch: false
+                pulse:
+                    delay: 10
+                    max_delay: 20
+        view:
+            header:
+                title: Controls
+            table:
+                - ["#Servo - Short Press", "short_press|Press"]
+                - ["#Servo - Long Press", "long_press|Press"]
+                - ["#Servo - Extra Long Press", "extra_long_press|Press"]
+
+
+

Philips Hue

+
+Click to view +

The hue module can control smartplugs and lamps over Philips Hue Bridge API. In general the plugin can switch any device on/off which is connected to the bridge. To use it you will need API token aka username:

+
    +
  1. Open http://bridge/debug/clip.html.
  2. +
  3. In the URL: Field type /api/.
  4. +
  5. In the Message Body: Field type: {"devicetype": "pikvm"}.
  6. +
  7. Hit the Get Button.
  8. +
  9. As the Response you become the Username: {"success": {"username": "apiusername"}.
  10. +
+

Example:

+
kvmd:
+    gpio:
+        drivers:
+            hue:
+               type: hue
+               url: http://bridge
+               token: YG-xxxxxxxxxxxx
+        scheme:
+            plug_button:
+                driver: hue
+                pin: 32
+                mode: output
+                initial: null
+                switch: true
+                pulse:
+                    delay: 0
+            plug_led:
+                driver: hue
+                pin: 32
+                mode: input
+        view:
+            table:
+                - ["plug_led", "plug_button"]
+
+
+

ANEL NET-PwrCtrl

+
+Click to view +

The anelpwr plugin allows you to use ANEL NET-PwrCrtl IP-PDUs (switchabel sockets) as gpios. There are up to 8 Ports per PDU. Input pulls the the current state from the PDU, Output switches the Socket.

+
kvmd:
+    gpio:
+        drivers:
+            anel_pdu_0:
+                type: anelpwr
+                url: http://IP:port
+                user: admin
+                passwd: anel
+        scheme:
+            pdu0_0_pwr:
+                pin: 0
+                driver: anel_pdu_0
+                mode: output
+                pulse:
+                    delay: 0
+            pdu0_0_led:
+                pin: 0
+                driver: anel_pdu_0
+                mode: input
+        view:
+            header:
+               title: "PDUs"
+            table:
+                - ["#PDU0"]
+                - []
+                - ["#PDU0_Port0:", pdu0_0_led, "pdu0_0_pwr|confirm|test"] 
+
+
+

Extron SW Series Switchers

+
+Click to view +

The extron plugin allows you to control Extron SW series switchers (ex. SW4 USB, SW4 VGA, etc.). There are up to 4 Ports per switcher. Input pulls the the current state from the switcher, Output switches the active port.

+
kvmd:
+    gpio:
+        drivers:
+            extron_vga:
+                type: extron
+                device: /dev/ttyUSB0  # The path to the RS-232 serial adapter
+        scheme:
+            vga_port1_led:
+                pin: 0
+                driver: extron_vga
+                mode: input
+            vga_port2_led:
+                pin: 1
+                driver: extron_vga
+                mode: input
+            vga_port3_led:
+                pin: 2
+                driver: extron_vga
+                mode: input
+            vga_port4_led:
+                pin: 3
+                driver: extron_vga
+                mode: input
+            vga_port1_button:
+                pin: 0
+                driver: extron_vga
+                mode: output
+            vga_port2_button:
+                pin: 1
+                driver: extron_vga
+                mode: output
+            vga_port3_button:
+                pin: 2
+                driver: extron_vga
+                mode: output
+            vga_port4_button:
+                pin: 3
+                driver: extron_vga
+                mode: output
+        view:
+            header:
+               title: "Extron SW4 VGA"
+            table:
+                - ["vga_port1_led|red", "vga_port1_button||Port 1"]
+                - ["vga_port2_led|red", "vga_port2_button||Port 2"]
+                - ["vga_port3_led|red", "vga_port3_button||Port 3"]
+                - ["vga_port4_led|red", "vga_port4_button||Port 4"]
+
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gsm/index.html b/gsm/index.html new file mode 100644 index 00000000..db411a9a --- /dev/null +++ b/gsm/index.html @@ -0,0 +1,14 @@ + + + + + + Redirecting... + + + + + +You're being redirected to a new destination. + + diff --git a/id/index.html b/id/index.html new file mode 100644 index 00000000..43769d8d --- /dev/null +++ b/id/index.html @@ -0,0 +1,2932 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Identifying PiKVM on the target host - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

PiKVM identification

+ +

This page explains how PiKVM is presented to the target host's operating +system, and how this can be changed. This is useful for developers, +testers and system administrators who need PiKVM to emulate a specific +USB device or monitor.

+
+

Info

+

Before exploring this page, we recommend to read the PiKVM configuration guide +so that you understand the terminology and how exactly the parameters described below change.

+
+
+

Basics

+

PiKVM is a combined emulator of several devices for user interaction. +Simply put, your host sees the connected PiKVM not just as a single device, but as a set of multiple devices.

+

In the most default case out of the box, these are the following:

+
    +
  • HDMI video display;
  • +
  • USB keyboard;
  • +
  • USB mouse (two mice for PiKVM V4);
  • +
  • USB mass storage drive (ejectable);
  • +
+

Thus, PiKVM emulates two types of devices: HDMI and USB. Each of them has a specific set of identifiers. +For example, if you go to monitor settings on the host, you will see something like PiKVM V4 Plus. +It works in a similar way with USB.

+
+

HDMI Identifiers

+
+

Info

+

This applies to PiKVM V3, V4 and DIY based on CSI bridge. +It is impossible to change the EDID for the HDMI-USB dongle.

+
+

The EDID (Extended Display Identification Data) is responsible for presenting the display. +It also provides the host with information about the resolutions that PiKVM supports. +More information about this is written on this page, and here we will provide brief information.

+
+

Quick IDs changing on PiKVM V4 Plus

+

PiKVM V4 Plus has a simple way read and adopt display identifiers like model and serial number +from your physical display. See here for details.

+
+

Run kvmd-edidconf on PiKVM:

+
[root@pikvm ~]# kvmd-edidconf
+Manufacturer ID: LNX
+Product ID:      0x7773 (30579)
+Serial number:   0x01010101 (16843009)
+Monitor name:    PiKVM V4 Plus
+Monitor serial:  CAFEBABE
+Audio:           yes
+
+

The fields have obvious names and purposes. Note the two similar fields Serial number and Monitor serial. +The first has a numeric value, and the second is ASCII. If you are using a custom EDID from some real display, some fields may be missing.

+

To change the values of the EDID fields, use the kvmd-edidconf with options, a complete list is available in kvmd-edidconfi --help.

+

Here the small example of changing all available fields from the previous listing:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# kvmd-edidconf --set-mfc-id=TTP --set-product-id=0x5B81 --set-serial=0x8DE11B79 --set-monitor-name=TOSHIBA --set-monitor-serial=ABCD1234 --apply
+Manufacturer ID: TTP
+Product ID:      0x5B81 (23425)
+Serial number:   0x8DE11B79 (2380340089)
+Monitor name:    TOSHIBA
+Monitor serial:  ABCD1234
+Audio:           yes
+...
+[root@pikvm ~]# ro
+
+

The full list of manufacturer IDs is available here.

+

For a detailed guide on customizing EDID, please visit this page. There you can also find out how to set the EDID from a real monitor, or quickly adopt your real monitor IDs with PiKVM V4 Plus.

+
+

USB Identifiers

+
+

Info

+

This applies to PiKVM V2+. Identifiers on V1 and/or the Pico HID can't be changed +without recompilation and reflashing of the firmware.

+
+

USB is a much more complex subsystem and another part of PiKVM is responsible for it. +Be careful when changing the settings here, it may cause the USB to fail.

+

For information on how to control emulated devices see here. +The identification is described below.

+

As you may have found out from the PiKVM configuration guide (if you haven't read it yet, now is the time), +you can get the list of all configuration parameters using the kvmd -m command.

+

Below is a listing of all the parameters, from which the unrelated and those USB parameters +that should not be changed have been removed. In the context of identifiers, we are interested in the following:

+
[root@pikvm ~]# kvmd -m
+otg:
+    vendor_id: 7531
+    product_id: 260
+    manufacturer: PiKVM
+    product: PiKVM Composite Device
+    serial: CAFEBABE
+    device_version: -1
+    max_power: 250
+
+    devices:
+        drives:
+            default:
+                inquiry_string:
+                    cdrom:
+                        vendor: PiKVM
+                        product: Optical Drive
+                        revision: '1.00'
+
+                    flash:
+                        vendor: PiKVM
+                        product: Flash Drive
+                        revision: '1.00'
+
+        msd:
+            default:
+                inquiry_string:
+                    cdrom:
+                        vendor: PiKVM
+                        product: Optical Drive
+                        revision: '1.00'
+
+                    flash:
+                        vendor: PiKVM
+                        product: Flash Drive
+                        revision: '1.00'
+
+

Pay attention to the nesting levels. The parameters are always located in certain sections. +All numeric values are displayed in decimal form, but in the config you can use a hex form. +The generally accepted names from the USB specifications are shown too.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterUSB SpecDescription
vendor_ididVendorUnique vendor ID assigned by USB.org.
product_ididProductJust an ID for the product assigned by this vendor.
manufactureriManufacturer to 0x409ASCII name of the vendor.
productiProduct to 0x409ASCII name of the product.
serialiSerialNumber to 0x409ASCII serial number of the product.
device_versionbcdDeviceKinda the revision of the device. Assigned automatically. It can be changed to 256, 257, 258 or something like this
+

These IDs are also used for the microphone on PiKVM V4.

+

The strings under otg/drives and otg/msd sections deserve a special description. +They relate to virtual media emulation and are separate parts of the SCSI inquiry string, the drive identifier used by the OS driver. +All three parameters vendor, product, and revision are short ASCII strings responsible for CD/DVD or Flash representation.

+

The msd refers to a virtual drive accessible from the Web UI, +and the drives describes all additional drives if you have configured them (disabled by default). +Note that mass storage drive can be completely disabled.

+

To change the parameters, use the /etc/kvmd/override.yaml, for example, like this:

+
otg:
+    vendor_id: 0x6940
+    product_id: 0x6973
+    manufacturer: Corsair
+    product: Gaming RGB
+    serial: 1000
+
+    devices:
+        msd:
+            default:
+                inquiry_string:
+                    cdrom:
+                        vendor: Corsair
+                        product: DVD
+                        revision: '1.00'
+
+                    flash:
+                        vendor: Corsair
+                        product: STICK
+                        revision: '1.00'
+
+

After changing validate the config using kvmd -m. You will see the full config list with changed and default values, +or a message about configuration error.

+

If everything is fine, perform the soft reboot.

+

Replicating setups

+

You can use kvmd-edidconf and kvmd-otgconf to replicate an entire host configuration for testing or other purposes. What you can do will vary depending on the PiKVM device you have:

+
    +
  • V4 Plus: you can import both EDID and USB IDs.
  • +
  • V4 Mini: you must manually edit override.yaml, as there is neither a second HDMI Out or additional USB ports on your PiKVM.
  • +
  • V3: you can import USB IDs only, as there is no second HDMI output on your PiKVM.
  • +
+

Assuming you have PiKVM V4 Plus, follow these steps:

+
    +
  1. Connect the host's display to one of the two HDMI Out ports on the rear panel of your PiKVM.
  2. +
  3. Connect the host's USB keyboard and mouse to USB ports on the front and the rear panel of you PiKVM.
  4. +
  5. Run rw to switch to read-write mode.
  6. +
  7. Run kvmd-edidconf --import-display-ids --apply as root on the PiKVM. This will fetch EDID information from the connected physical display and place it into the /etc/kvmd/override.yaml configuration file.
  8. +
  9. Run kvmd-otgconf --import-usb-ids as root on the PiKVM. This will fetch IDs of the connected physical USB devices and place them into the /etc/kvmd/override.yaml configuration file.
  10. +
  11. Run ro to switch to read-only mode.
  12. +
  13. Run reboot to reboot your PiKVM and apply newly the added customization.
  14. +
  15. Reconnect the host's display and keyboard/mouse back to the host.
  16. +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..d09fe41d --- /dev/null +++ b/index.html @@ -0,0 +1,2661 @@ + + + + + + + + + + + + + + + + + + + + + + PiKVM Handbook - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

PiKVM Handbook

+ +

Welcome to the PiKVM Handbook—a complete +documentation of the Open-Source KVM-over-IP on Raspberry Pi!

+

Here you will find comprehensive information about all aspects of the +operation of PiKVM, get answers to your most difficult questions and be +able to solve the problems that have arisen.

+

Where to start?

+ + +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ipmi/index.html b/ipmi/index.html new file mode 100644 index 00000000..d59f62e0 --- /dev/null +++ b/ipmi/index.html @@ -0,0 +1,2779 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + IPMI & Redfish - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

IPMI & Redfish integration

+ +
+

Info

+

This page is about the server-side IPMI emulation if you want to manage PiKVM using ipmitool or something similar. +If you want to use the PiKVM Web UI to manage the server using IPMI (that is, as an IPMI client), +see GPIO functions with IPMI plugin.

+
+
+

Warning

+

Although PiKVM supports the IPMI protocol, we strongly recommend that you DO NOT USE IT outside of trusted networks +due to the protocol's insecurity.

+

Please consider to using the Redfish or KVMD API instead of it.

+
+
+

IPMI BMC

+

IPMI is a legacy protocol for remote server management. +It can be useful for managing a large number of machines with PiKVM. Its advantage is that it is supported by many enterprise systems.

+
+Step by step: Enabling IPMI server on PiKVM +
    +
  1. +

    Switch the filesystem to the RW-mode:

    +
    [root@pikvm ~]# rw
    +
    +
  2. +
  3. +

    Set up IPMI account in file /etc/kvmd/ipmipasswd (see the comment inside it).

    +
  4. +
  5. +

    Enable the kvmd-ipmi daemon:

    +
    [root@pikvm ~]# systemctl enable --now kvmd-ipmi
    +
    +
  6. +
  7. +

    Switch the filesystem back to the RO:

    +
    [root@pikvm ~]# ro
    +
    +
  8. +
  9. +

    Try some commands on the client PC:

    +
    $ ipmitool -I lanplus -U admin -P admin -H pikvm power status
    +$ ipmitool -I lanplus -U admin -P admin -H pikvm power on
    +
    +
  10. +
+
+
+

IPMI SoL

+

IPMI supports the ability to get console access to the server using Serial-over-LAN. +With this feature PiKVM will act as a proxy for your server's COM port.

+

To use this feature, you will need a USB-COM adapter that you need to connect to the PiKVM. +The COM port of the adapter need to be connected to the server.

+
+Step by step: Enabling IPMI SoL for USB-COM adapter +

As with IPMI BMC, you need to configure kvmd-ipmi server (see the previous chapter about IPMI BMC) +and add the following configuration to /etc/kvmd/override.yaml:

+
ipmi:
+    sol:
+        device: /dev/ttyUSB0  # Path of your USB-COM adapter
+        speed: 115200
+
+

Then restart the kvmd-ipmi server: systemctl restart kvmd-ipmi.

+

All requests that it receives over the network regarding the COM port will be forwarded to your server. For example:

+
[root@pikvm ~]$ ipmitool -I lanplus -U admin -P admin -H pikvm sol activate
+
+
+
+

Redfish

+

Redfish is a more modern server management protocol designed to replace IPMI. +It is based on HTTP and fixes many security issues. If possible, we recommend using it instead of IPMI, or using the KVMD API.

+

PiKVM supports the Redfish natively and provides a power management handles with it.

+

To access the Redfish API, use HTTP Basic Auth methods. Also you can use the redfishtool:

+
[root@pikvm ~]$ redfishtool -S Never -r pikvm root
+[root@pikvm ~]$ redfishtool -S Never -u admin -p admin -r pikvm Systems
+[root@pikvm ~]$ redfishtool -S Never -u admin -p admin -r pikvm Systems reset ForceOff
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/letsencrypt/index.html b/letsencrypt/index.html new file mode 100644 index 00000000..49ba59fa --- /dev/null +++ b/letsencrypt/index.html @@ -0,0 +1,3155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Let's Encrypt certificates - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Let's Encrypt certificates

+ +

PiKVM uses self-signed SSL certificates out of the box. If you have a +domain name, you can use Let's Encrypt certificates.

+

Usually Let's Encrypt certificates are issued and updated automatically +using Certbot, however, since PiKVM uses a read-only file system, +special tools around Certbot are required to work with certificates. +KVMD 3.117 provides them.

+
+

Note

+

This feature is available on images as old as 2022.06.19 since it requires PST storage partition on SD card. +Ports 80+443 need to be opened if you are port forwarding for this to work properly.

+
+
+

Basic setup

+
    +
  1. +

    Update the OS and make sure that you are using a new image with PST storage.

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
    # kvmd-pstrun -- true
    +
    +

    If the storage is not available, you need to reflash the OS image to the latest one from our official website.

    +
  2. +
  3. +

    Switch filesystem to RW and obtain the certificate (for example, pikvm.example.com. The method depends on the network configuration. In the simplest case, if PiKVM is open for access from the Internet, it is recommended to use the webroot. Another examples will be described below.

    +
    # rw
    +# kvmd-certbot certonly_webroot --agree-tos -n --email user@example.com -d pikvm.example.com
    +
    +
  4. +
  5. +

    Install the certificate for KVMD-Nginx and (optionally) KVMD-VNC. Running services will be restarted/reloaded automatically. Switch filesystem to RO.

    +
    # kvmd-certbot install_nginx pikvm.example.com
    +# kvmd-certbot install_vnc pikvm.example.com
    +# ro
    +
    +
  6. +
  7. +

    Check the renewal immediately, just for testing:

    +
    # kvmd-certbot renew --force-renewal
    +
    +
  8. +
  9. +

    Enable automatic certificate renewal:

    +
    # rw
    +# systemctl enable --now kvmd-certbot.timer
    +# ro
    +
    +
  10. +
+
+

Cloudflare DNS

+

This example shows that PiKVM may not be accessible from the internet, but you can still get a certificate if you use Cloudflare DNS.

+
    +
  1. +

    Switch filesystem to RW and install the Cloudflare DNS plugin:

    +
    # rw
    +# pacman -S certbot-dns-cloudflare
    +
    +
  2. +
  3. +

    Prepare the environment for the DNS plugin (place the auth data):

    +

    # kvmd-pstrun -- mkdir -p /var/lib/kvmd/pst/data/certbot/runroot
    +# kvmd-pstrun -- nano /var/lib/kvmd/pst/data/certbot/runroot/.cloudflare.auth
    +# kvmd-pstrun -- chmod 600 /var/lib/kvmd/pst/data/certbot/runroot/.cloudflare.auth
    +# kvmd-pstrun -- chown kvmd-certbot: /var/lib/kvmd/pst/data/certbot/runroot/.cloudflare.auth
    +
    + See certbot-dns-cloudflare's doc here about the content of .cloudflare.auth. +
  4. +
  5. +

    Obtain the certificate:

    +
    # kvmd-certbot certonly \
    +   --dns-cloudflare \
    +   --dns-cloudflare-propagation-seconds 60 \
    +   --dns-cloudflare-credentials /var/lib/kvmd/pst/data/certbot/runroot/.cloudflare.auth \
    +   --agree-tos \
    +   -n \
    +   --email user@example.com \
    +   -d pikvm.example.com
    +
    +
  6. +
  7. +

    Next follow the basic guide starts at step 3.

    +
  8. +
+
+

Route53 DNS

+

This example shows that PiKVM may not be accessible from the internet, but you can still get a certificate if you use AWS Route53 DNS. Make sure you are running an image newer than 2022.06.20 and kvmd version 3.119-1 or greater.

+
    +
  1. +

    Switch filesystem to RW and install the Route53 DNS plugin:

    +
    # rw
    +# pacman -S certbot-dns-route53
    +
    +
  2. +
  3. +

    Configure Your AWS User + For the certbot_dns_route53 plugin to work it needs to be able to connect to AWS using an access key with the correct permissions.

    +

    To do this securely you’ll want to create a new AWS user that only has the necessary permissions it needs to work.

    +

    You can find instructions for creating a user here. The basics of it is you’ll want a user with Programmatic access (not console), add it to a group (I created a new one just for this user and any future certbot users I might need).

    +

    The user will need specific permissions that are required to allow the certbot plugin to create the necessary CNAME records. These can be added by manually selecting them from a very long list or you can use the json view to give it the following permissions.

    +
    {
    +"Version": "2012-10-17",
    +"Statement": [
    +   {
    +      "Effect": "Allow",
    +      "Action": ["route53:ListHostedZones", "route53:GetChange"],
    +      "Resource": ["*"]
    +   },
    +   {
    +      "Effect": "Allow",
    +      "Action": ["route53:ChangeResourceRecordSets"],
    +      "Resource": ["arn:aws:route53:::hostedzone/YOURHOSTEDZONEID"]
    +   }
    +]
    +}
    +
    +

    Make sure you replace YOURHOSTEDZONEID with the instance ID of your hosted zone.

    +

    Once the user is created don’t forget to download and save your access key and secret access key (somewhere secure, these are as sensitive as your passwords).

    +
  4. +
  5. +

    Setup credentials:

    +

    We now need to put the AWS credentials on the PiKVM so the certbot can use them.

    +
    # kvmd-pstrun -- mkdir -p /var/lib/kvmd/pst/data/certbot/runroot
    +
    +

    Copy and paste your AWS credentials into the nano editor and save the file.

    +
    # kvmd-pstrun -- nano /var/lib/kvmd/pst/data/certbot/runroot/.route53.auth
    +
    +

    Here is an example .route53.auth file. Replace the placeholders with the access key and secret access key that you just saved from AWS and fill them in.

    +
    [default]
    +aws_access_key_id=XXXXXX
    +aws_secret_access_key=XXXX/XXXXX
    +
    +

    Update permissions:

    +
    # kvmd-pstrun -- chmod 600 /var/lib/kvmd/pst/data/certbot/runroot/.route53.auth
    +# kvmd-pstrun -- chown kvmd-certbot: /var/lib/kvmd/pst/data/certbot/runroot/.route53.auth
    +
    +
  6. +
  7. +

    Obtain the certificate:

    +
    # export AWS_SHARED_CREDENTIALS_FILE="/var/lib/kvmd/pst/data/certbot/runroot/.route53.auth"
    +# kvmd-certbot certonly \
    +   --dns-route53 \
    +   --agree-tos \
    +   -n \
    +   --email user@example.com \
    +   -d pikvm.example.com
    +
    +
  8. +
  9. +

    Enable automatic certificate renewal:

    +

    Create the file: /etc/conf.d/kvmd-certbot with the following contents so the renewall service can find the authentication file containing the AWS credentials:

    +
    AWS_SHARED_CREDENTIALS_FILE="/var/lib/kvmd/pst/data/certbot/runroot/.route53.auth"
    +
    +

    Now enable the renewal service:

    +
    # systemctl enable --now kvmd-certbot.timer
    +
    +
  10. +
+
+

ACME DNS

+

ACME DNS is a "Limited DNS server with RESTful HTTP API to handle ACME DNS challenges easily and securely." The acme-dns-client works, in conjunction, with Certbot (kvmd-certbot) to enable DNS-01 challenge support via ACME DNS.

+

These instructions are for how to install and use the acme-dns-client with ACME DNS for PiKVM.

+

Assumptions

+
    +
  • ACME DNS is already set up and functioning in the environment
  • +
  • ACME DNS Server is auth.example.org
  • +
  • PiKVM Fully Qualified Domain Name (FQDN) is pikvm.example.org
  • +
  • PiKVM is running on a supported Raspberry Pi using the PiKVM OS (which is 32-bit as of the writing of this documentation)
  • +
  • All configuration examples below are as user root via a terminal session to PiKVM
  • +
+

Not in Scope

+
    +
  • Installation and Setup of ACME DNS Server
  • +
+

Instructions

+
    +
  1. Ensure that Step 1 from Basic Setup has been completed
  2. +
  3. Visit the Releases page to get the download URL for the latest acme-dns-client release (PiKVM OS is 32-bit, which is linux_armv6)
  4. +
  5. +

    Install acme-dns-client

    +

    The acme-dns-client is not distributed by pacman and is a manual installation. The steps below are for:

    +
      +
    • Creating a folder for acme-dns-client
    • +
    • Downloading and extracting the acme-dns-client TAR from Github
    • +
    • Moving the acme-dns-client binary to the created folder
    • +
    • Cleaning up files from the download
    • +
    • Creating the necessary persistent symbolic link to allow acme-dns-client to be ran
    • +
    • Initialize acme-dns-client
    • +
    +
    +

    Note

    +

    Make sure to replace the URL below with the one gathered from Step 1.
    +As of the writing of this documentation:
    +- The latest (and demonstrated) version is v0.3
    +- (Demonstrated) Platform is linux-armv6

    +
    +
    # mkdir /etc/acmedns
    +# curl -LO https://github.com/acme-dns/acme-dns-client/releases/download/v0.3/acme-dns-client_0.3_linux_armv6.tar.gz
    +# tar -zxvf acme-dns-client_0.3_linux_armv6.tar.gz
    +# mv acme-dns-client /etc/acmedns/acme-dns-client
    +# ln -sf /etc/acmedns/acme-dns-client /usr/local/bin/acme-dns-client
    +# rm LICENSE README.md acme-dns-client_0.3_linux_armv6.tar.gz
    +# acme-dns-client
    +
    +
  6. +
  7. +

    Register acme-dns-client with ACME DNS

    +
    +

    Note

    +

    This is interactive, follow instructions for creating and verifying the appropriate CNAME record.

    +
    +
    # acme-dns-client register -d pikvm.example.org -s http://auth.example.org
    +
    +

    Once registration is complete ownership of clientstorage.json must be changed to kvmd-certbot.

    +
    # chown kvmd-certbot:kvmd-certbot /etc/acmedns/clientstorage.json
    +
    +
    +

    Note

    +

    If using acme-dns-client on an internal/private domain with an ACME compatible Certificate Authority do not forget to add -ns <dns-server-ip>:<dns-server-port> to acme-dns-client register

    +
    +
  8. +
  9. +

    Register Certbot

    +
    # kvmd-certbot register
    +
    +
  10. +
  11. +

    Request Certificate via Certbot

    +
    # kvmd-certbot certonly --manual --preferred-challenges dns --manual-auth-hook 'acme-dns-client' -d pikvm.example.org
    +
    +
    +

    Note

    +

    If using an ACME compatible Certificate Authority (other than Let's Encrypt) do not forget to add --server https://ca.example.org/acme/acme/directory to kvmd-certbot

    +
    +
  12. +
  13. +

    Follow steps 3 through 5 under Basic Setup to complete setup and renewal of certificates

    +
  14. +
+

Wireguard proxy

+

If you don't have public IP, and you don't want to put your API keys in PiKVM, +you can forward HTTP traffic over wireguard. To Let's Encrypt you'll appear to +serve ACME challenges from a host they can reach from the Internet (e.g. VPS), +to which you'll connect over wireguard.

+

Assumptions

+
    +
  • FQDN of your pikvm is pikvm1.int.example;
  • +
  • FQDN of the proxy VPS is acme-proxy.example;
  • +
  • public IP addresses of VPS are 198.51.100.1 and 2001:db8::1;
  • +
  • internal (wireguard) IPv4 address of the PiKVM is 10.11.12.13.
  • +
+

Instructions

+
    +
  1. +

    Setup wireguard and ensure it's working.

    +
  2. +
  3. +

    Setup public DNS zone to point the domain address at the public VPS:

    +
    acme-proxy.example. IN A      198.51.100.1
    +acme-proxy.example. IN AAAA   2001:db8::1
    +pikvm1.int.example. IN CNAME  acme-proxy.example.
    +
    +
  4. +
  5. +

    On the public VPS, configure HTTP proxy to forward + /.well-known/acme-challenge to PiKVM. For example in nginx:

    +
    server {
    +   listen 80;
    +   listen [::]:80;
    +
    +   server_name pikvm1.int.example;
    +
    +   location ^~ /.well-known/acme-challenge {
    +      proxy_pass http://10.11.12.13:80;
    +      proxy_set_header Host $host;
    +   }
    +
    +   location / {
    +      return 404;
    +   }
    +}
    +
    +
  6. +
  7. +

    Now you can use kvmd-certbot certonly_webroot as in basic scenario above.

    +
  8. +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lte/index.html b/lte/index.html new file mode 100644 index 00000000..db411a9a --- /dev/null +++ b/lte/index.html @@ -0,0 +1,14 @@ + + + + + + Redirecting... + + + + + +You're being redirected to a new destination. + + diff --git a/modem/index.html b/modem/index.html new file mode 100644 index 00000000..91089511 --- /dev/null +++ b/modem/index.html @@ -0,0 +1,2881 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Setting up 3G/4G/LTE modem - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Setting up 3G/4G/LTE modem

+ +

With PiKVM, you can create a portable device to work in a distant +environment without a permanent wired internet connection. A cellular +modem in combination with any VPN like Tailscale is also +an excellent backup for emergency access to the host.

+
+

Choosing a modem

+

PiKVM supports a huge number of USB modems. If the modem works with a desktop Linux, it will work with PiKVM as well.

+

Mini-PCI on PiKVM V4 Plus

+

PiKVM V4 Plus has an internal Mini-PCI and built-in SIM card slot for installing a modem. +Please note that only modems with USB data lines are supported.

+

Here is a list of good modems that you can start with:

+ +

An antenna and an SMA pigtail are also required to use the modem.

+

When choosing an antenna, check the supported frequency list of your cellular ISP and the antenna itself.

+
+

Setting up the connection

+

Change default passwords if you haven't done so earlier. It's very important for the security.

+

Cellular networks can open your device to the big world. PiKVM is safe if you use a strong password, so...

+
+Changing PiKVM Passwords +

PiKVM comes with the following default passwords:

+
    +
  • +

    Linux OS-level admin (SSH, console...):

    +
      +
    • Username: root
    • +
    • Password: root
    • +
    +
  • +
  • +

    KVM user (Web Interface, API, VNC...):

    +
      +
    • Username: admin
    • +
    • Password: admin
    • +
    • No 2FA code
    • +
    +
  • +
+

They are two separate accounts with independent passwords.

+

To change passwords, you will need to use the console access via SSH or the Web Terminal. +If you are using the Web Terminal, enter the su - command to get the root access (enter the root user password).

+
[root@pikvm ~]# rw
+[root@pikvm ~]# passwd root
+[root@pikvm ~]# kvmd-htpasswd set admin
+[root@pikvm ~]# ro
+
+

If you require additional user for the Web UI access, use the following:

+
[root@pikvm ~]# kvmd-htpasswd add <user> # Add a new user with password
+[root@pikvm ~]# kvmd-htpasswd del <user> # Remove/delete a user
+
+

Optionally you can enable the two-factor authentication for more security.

+

Changing the VNCAuth key and IPMI password at the first start of PiKVM is not required, +since these services are disabled by default. But it is here just so that you remember their existence.

+
+
    +
  1. +

    Update the OS and reboot.

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
  2. +
  3. +

    Make filesystem writable using rw command.

    +
  4. +
  5. +

    Install NetworkManager and ModemManager:

    +
    [root@pikvm ~]# pacman -S modemmanager networkmanager
    +
    +
  6. +
  7. +

    Create file /etc/NetworkManager/conf.d/pikvm-unmanaged.conf with following content:

    +
    [keyfile]
    +unmanaged-devices=*,except:type:gsm
    +
    +
  8. +
  9. +

    Run the services:

    +
    [root@pikvm ~]# systemctl enable --now NetworkManager ModemManager
    +
    +
  10. +
  11. +

    Make sure that ModemManager detects your modem. You will see something similar after mmcli, modem 0 is detected here:

    +
    [root@pikvm ~]# mmcli --list-modems
    +    /org/freedesktop/ModemManager1/Modem/0 [QUALCOMM INCORPORATED] SIMCOM_SIM7600G-H
    +
    +
  12. +
  13. +

    View the modem 0 information:

    +
    [root@pikvm ~]# mmcli -m 0
    +  -----------------------------------
    +  General  |                    path: /org/freedesktop/ModemManager1/Modem/0
    +           |               device id: ...
    +  -----------------------------------
    +  Hardware |            manufacturer: QUALCOMM INCORPORATED
    +           |                   model: SIMCOM_SIM7600G-H
    +           |       firmware revision: LE20B04SIM7600G22
    +           |          carrier config: ROW_Gen_VoLTE
    +           | carrier config revision: ...
    +           |            h/w revision: 10000
    +           |               supported: gsm-umts, lte
    +           |                 current: gsm-umts, lte
    +           |            equipment id: ...
    +  ...
    +  -----------------------------------
    +  Status   |                    lock: sim-pin
    +           |          unlock retries: sim-pin (3), sim-puk (10), sim-pin2 (3), sim-puk2 (10)
    +           |                   state: locked
    +           |             power state: on
    +  ...
    +
    +
  14. +
  15. +

    Set up the connection. You will need the APN value (from the mobile ISP) and PIN-code for the SIM:

    +
    [root@pikvm ~]# nmcli c add type gsm ifname '*' con-name pikvm-lte gsm.apn cytamobile gsm.pin 1234
    +
    +
      +
    • pikvm-lte is just a meaning name of the connection, use any you like.
    • +
    • gsm.apn cytamobile sets APN value to cytamobile (will be different for other ISP).
    • +
    • gsm.pin 1234 sets PIN for unlocking the SIM card. If the SIM is not locked, omit these words.
    • +
    +

    Depending on the ISP, you may need to specify a password and/or +some other parameters.

    +
  16. +
  17. +

    Make the connection automatically connected:

    +
    [root@pikvm ~]# nmcli connection modify pikvm-lte autoconnect yes
    +
    +
  18. +
  19. +

    The connection will already be working:

    +
    [root@pikvm ~]# nmcli
    +cdc-wdm0: connected to pikvm-lte
    +        "cdc-wdm0"
    +        gsm (option, qmi_wwan), hw, iface wwan0, mtu 1500
    +        ip4 default
    +        inet4 XXX.XXX.XXX.XXX/XX
    +        route4 XXX.XXX.XXX.XXX/XX metric 700
    +        route4 default via XXX.XXX.XXX.XXX/XX metric 700
    +...
    +
    +
  20. +
  21. +

    Perform reboot.

    +
  22. +
+

To set up a Tailscale VPN, refer to this page.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mouse/index.html b/mouse/index.html new file mode 100644 index 00000000..67e61e9c --- /dev/null +++ b/mouse/index.html @@ -0,0 +1,2855 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Mouse - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

Mouse modes

+ +

There are two modes of pointer device: absolute and relative.

+

In absolute mode, the input device transmits the exact coordinates (X,Y) where the cursor should be moved. This is how touchscreens or drawing tablets work.

+

In relative mode, only the relative offset (dX,dY) to the current position is transmitted, which is unknown to the input device itself. This is a regular mouse.

+

By default, PiKVM uses absolute positioning mode as the most convenient for the user and software. +However, this is not always supported by the BIOS/UEFI. +For such cases, support is provided for the relative mode of operation, which can be enabled in the config.

+

When using relative mode, the browser will exclusively capture your mouse when you click on the stream window in PiKVM once. +When you press Esc, the browser releases the mouse.

+
+

Important notes

+

The relative mouse generates a huge number of events that can be poorly transmitted over the network or very slowly perceived by the BIOS/UEFI driver. To solve this problem, mouse events are optimized using a vector sum. This mode is enabled by activating the below first and is available in the web menu System -> Squash mouse moves. You can try disabling this if you have problems with mouse acceleration. This is the best and most reasonable compromise right now.

+

Also currently the relative mouse mode is not supported by PiKVM VNC server yet. The reason is that none of the recommended clients support the QEMU Pointer Motion Change extension. +We expect to implement this in TigerVNC. The relative mode is also not supported by mobile browsers.

+
+

Relative mouse on V2+ platform (OTG HID)

+
+

Info

+

On PiKVM V4 dual mode is enabled by default. To disable it and enable single mode, set kvmd/hid/mouse_alt/device (see below) to empty string:

+
kvmd:
+    hid:
+        mouse_alt:
+            device: ""
+
+
+

Dual mode

+

Using dual mouse mode you can switch between the absolute and relative mouse in the System menu without reloading. +This is more convenient, but for compatibility reasons it is disabled by default. To enable it, do the following:

+
    +
  1. +

    Switch filesystem to RW-mode using command rw.

    +
  2. +
  3. +

    Edit /etc/kvmd/override.yaml and add these lines:

    +
    kvmd:
    +    hid:
    +        mouse_alt:
    +            device: /dev/kvmd-hid-mouse-alt
    +
    +
  4. +
  5. +

    Perform reboot. After that reboot your PC.

    +
  6. +
+

Single relative mode

+
    +
  1. +

    Switch filesystem to RW-mode using command rw.

    +
  2. +
  3. +

    Edit /etc/kvmd/override.yaml and add these lines:

    +
    kvmd:
    +    hid:
    +        mouse:
    +            absolute: false
    +
    +
  4. +
  5. +

    Perform reboot. After that reboot your PC.

    +
  6. +
  7. +

    If the mouse is still not detected by the BIOS/UEFI, try disabling horizontal scrolling to achieve the maximum compatibility:

    +
    kvmd:
    +    hid:
    +        mouse:
    +            absolute: false
    +            horizontal_wheel: false
    +
    +
  8. +
  9. +

    Don't forget to perform reboot.

    +
  10. +
+

Fixing the absolute mouse on Windows 98

+

Due to an ancient buggy driver, the absolute mouse on Windows 98 moves only within the upper-left quarter of the screen. To fix this, you need to activate some magic workaround. Due to the specifics of the implementation, you will have to turn on the relative mouse too. Write it in /etc/kvmd/override.yaml:

+
kvmd:
+    hid:
+        mouse:
+            absolute_win98_fix: true
+        mouse_alt:
+            device: /dev/kvmd-hid-mouse-alt
+
+

... and run systemctl restart kvmd. After that, you will get 3 new buttons with mouse modes in the System menu in Web UI. Switch it to Abs-Win98.

+
+

Relative mouse on V0-V1 platform (Pico/Arduino HID)

+

Mode switching for the Pico HID or legacy Arduino HID can be performed on-the-fly starting with KVMD 2.6 and the corresponding firmware. No additional actions are required.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mouse_jiggler/index.html b/mouse_jiggler/index.html new file mode 100644 index 00000000..8ee73d7d --- /dev/null +++ b/mouse_jiggler/index.html @@ -0,0 +1,2768 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Mouse Jiggler - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Mouse jiggler

+ +

The mouse jiggler is a feature used to simulate the movement of a computer mouse. +It prevents sleep mode, standby mode or the screensaver from activating. +It is very useful when some lengthy process is going on on the target host +(for example, installing software), and the user needs to monitor it with his side vision, +without having to move the mouse manually to avoid the screensaver.

+
+

Using the Jiggler

+

With a latest PiKVM OS, the jiggler is available in the Web UI:

+

+

If you don't see this switch, please update OS first:

+
+Updating PiKVM OS +

To update, run following commands under the root user:

+
[root@pikvm ~]# pikvm-update
+
+

If you encounter an error like:

+
[root@pikvm ~]# pikvm-update
+bash: pikvm-update: command not found
+
+

It's most likely you have an old OS release. You can update the OS as follows:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# pacman -Syy
+[root@pikvm ~]# pacman -S pikvm-os-updater
+[root@pikvm ~]# pikvm-update
+
+

Next time you will be able to use the usual method with pikvm-update.

+
+
+

Jiggler settings

+

This is not required usually, but it is possible to change some of the parameters of the jiggler or disable it completely.

+

Here are some examples to place it to /etc/kvmd/override.yaml.

+
    +
  1. +

    Make the jiggler unavailable in the menu:

    +
    kvmd:
    +    hid:
    +        jiggler:
    +            enabled: false
    +
    +
  2. +
  3. +

    Activate it by default after PiKVM reboot:

    +
    kvmd:
    +    hid:
    +        jiggler:
    +            active: true
    +
    +
  4. +
+
+

Description of the algorithm

+

When the Jiggler is active, PiKVM counts down the time that has elapsed since the last user input: +that is, any action with the keyboard or mouse. If there have been no actions for more than 15 seconds, +the Jiggler performs a mouse movement and waits another 15 seconds until the next iteration.

+

The Jiggler supports both mouse modes: absolute and relative.

+

Movement patterns looks like these:

+
    +
  • Absolute: (+100, +100), wait, (-100, -100), wait...
    The coordinates are converted depending on the screen resolution.
  • +
  • Relative: (+10, +10), wait, (-10, -10), wait...
  • +
+

The Jiggler works on the PiKVM device side, even if the Web UI was closed.

+

An important feature of the Jiggler is that it does not interfere with normal user work. +If the user is actively interacting with the keyboard and mouse, Jiggler will not introduce its interference +until it notices that the period of inactivity has exceeded the threshold of 15 seconds.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mouse_jiggler/mouse_jiggler_menu.png b/mouse_jiggler/mouse_jiggler_menu.png new file mode 100644 index 00000000..b9d6bf0c Binary files /dev/null and b/mouse_jiggler/mouse_jiggler_menu.png differ diff --git a/msd/drive_menu.png b/msd/drive_menu.png new file mode 100644 index 00000000..37dbe92e Binary files /dev/null and b/msd/drive_menu.png differ diff --git a/msd/index.html b/msd/index.html new file mode 100644 index 00000000..947d14f2 --- /dev/null +++ b/msd/index.html @@ -0,0 +1,3305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Mass Storage Drive - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

Mass Storage Drive

+ +

This powerful feature that is available on all PiKVM V2+ devices. +It allows PiKVM to emulate a virtual CD/DVD or Flash Drive for the target host +which will be available even in BIOS/UEFI when you need live disk to revive the OS +or even reinstall it.

+
+

Warning

+

This document is relevant for KVMD >= 4.49.

+

Also since this version, PiKVM supports DVD emulation!

+

If you are using an older version, please update the PiKVM OS:

+
+Updating PiKVM OS +

To update, run following commands under the root user:

+
[root@pikvm ~]# pikvm-update
+
+

If you encounter an error like:

+
[root@pikvm ~]# pikvm-update
+bash: pikvm-update: command not found
+
+

It's most likely you have an old OS release. You can update the OS as follows:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# pacman -Syy
+[root@pikvm ~]# pacman -S pikvm-os-updater
+[root@pikvm ~]# pikvm-update
+
+

Next time you will be able to use the usual method with pikvm-update.

+
+
+ + + + + + + + + + + +
Take a look at the Drive menu in the Web UI
+

The following actions are available here:

+
    +
  • Uploading an image to the internal storage of PiKVM.
  • +
  • Selecting an image to connect to the target host.
  • +
  • Changing the media type and write availability mode.
  • +
  • Downloading an image from the PiKVM storage.
  • +
  • Drive connection management and much more.
  • +
+
+

Warning

+

Never turn off the power of the PiKVM while the image is being uploaded +or while the image is connected to the target host in write mode. +This may cause file corruption.

+

The rest of the time, power off is safe because the PiKVM filesystem +will be in read-only mode.

+
+
+

Changing the media type between CD/DVD and Flash is possible only when the device is reconnected

+

On PiKVM V3 and V4, this can be done using the System -> Connect main USB switch in the Web UI.

+

In this case, the media type is determined at the time of connecting the image, and not by clicking on the switch. +The switch affects the settings of the future connection. For non-V3/V4 devices, +you need to either reboot your target host or otherwise reinitialize the drive.

+
+
+

Manual images uploading

+

PiKVM stores images in a special memory card partition mounted in /var/lib/kvmd/msd.

+

Most of the time, the partition is read-only, and is remounted for writing automatically +if the appropriate drive emulation mode is enabled, or to upload a new image. +This protects the data from damage in the event of a sudden loss of power.

+
+Step by step: Manual image uploading using SCP or rsync +
    +
  1. +

    Remount internal storage to read-write mode manually:

    +
    [root@pikvm ~]# kvmd-helper-otgmsd-remount rw
    +
    +
  2. +
  3. +

    Upload the image(s) to /var/lib/kvmd/msd using scp or some other tool.

    +
  4. +
  5. +

    Remount internal storage back to safe read-only mode:

    +
    [root@pikvm ~]# kvmd-helper-otgmsd-remount ro
    +
    +
  6. +
+
+
+

Tip

+

An HTTP API for Mass Storage management is also available for advanced use.

+
+
+

Writable Flash Drive

+

When emulating Flash Drive on PiKVM, you can allow the target host to write files to the image. +After stopping the drive, this image can be downloaded and opened on the local host. +This is useful if you need to get some files from the target host.

+

The file system image for the virtual Flash Drive must be prepared in advance. +This can be done either on the local host or in the PiKVM console.

+

Here some options:

+
+Step by step: Creating simple FAT32 image on PiKVM +
    +
  1. +

    Remount internal storage to read-write mode manually:

    +
    [root@pikvm ~]# kvmd-helper-otgmsd-remount rw
    +
    +
  2. +
  3. +

    Create an empty image file in /var/lib/kvmd/msd (this is the internal storage of PiKVM images) + of desired size (512MB in this example) and format it to FAT32:

    +
    [root@pikvm ~]# fallocate -l 512M /var/lib/kvmd/msd/flash.img
    +[root@pikvm ~]# loop=$(losetup -f)
    +[root@pikvm ~]# echo -e 'o\nn\np\n1\n\n\nt\nc\nw\n' | fdisk /var/lib/kvmd/msd/flash.img
    +[root@pikvm ~]# losetup -P $loop /var/lib/kvmd/msd/flash.img
    +[root@pikvm ~]# mkfs.vfat ${loop}p1
    +[root@pikvm ~]# losetup -d $loop
    +[root@pikvm ~]# chmod 666 /var/lib/kvmd/msd/flash.img
    +
    +
  4. +
  5. +

    Remount internal storage back to safe read-only mode:

    +
    [root@pikvm ~]# kvmd-helper-otgmsd-remount ro
    +
    +
  6. +
+
+
+

Note

+
    +
  • For PiKVM V3+ you'll need to toggle the USB connection using the Web UI: Switch System -> Connect Main USB to off, then on.
  • +
  • For V2 you'l need to reboot the target host.
  • +
+
+
+Step by step: Creating an image on a local macOS +
    +
  1. +

    Open Disk Utility.

    +
  2. +
  3. +

    Click menu File -> New Image -> Blank Image.

    +
  4. +
  5. +

    Set some options:

    + + + + + + + + + + + +
    Format and Partitions are very important
    +
  6. +
  7. +

    Click Save. The drive will automatically be mounted.

    +
  8. +
  9. +

    Copy files (such as BIOS updates) onto the new image (via terminal or drag and drop in Finder).

    +
  10. +
  11. +

    Eject image.

    +
  12. +
  13. +

    Rename the image file from .dmg to .img.

    +
  14. +
  15. +

    Upload the image to PiKVM.

    +
  16. +
+
+

The image flash.img now should be available in the Drive menu in Web UI. +Change drive mode to the Flash position and enable Writable switch. +Connect the image, do whatever is necessary, with files, and disconnect it. +The modified image containing your files can be downloaded to a local host +by selecting it from the menu and clicking the floppy disk icon.

+
+

NFS storage

+

It is possible to create a shared image storage for an entire fleet of PiKVMs using NFS.

+

If you have some shares, you can easily connect them to PiKVM by creating mount points and adding relevant records to /etc/fstab. +At the same time, you will be able to upload images via PiKVM Web UI to NFS, and still use local storage.

+
+Step by step: Connecting NFS storage +
    +
  1. +

    Update OS:

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
  2. +
  3. +

    Make some preparations:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -S nfs-utils
    +[root@pikvm ~]# kvmd-helper-otgmsd-remount rw
    +[root@pikvm ~]# mkdir -p /var/lib/kvmd/msd/NFS_Primary
    +[root@pikvm ~]# mkdir -p /var/lib/kvmd/msd/NFS_Secondary
    +[root@pikvm ~]# kvmd-helper-otgmsd-remount ro
    +
    +
  4. +
  5. +

    Add NFS shares to /etc/fstab:

    +
    server:/srv/nfs/NFS_Primary    /var/lib/kvmd/msd/NFS_Primary    nfs vers=3,timeo=1,retrans=1,soft,nolock  0 0
    +server:/srv/nfs/NFS_Secondary  /var/lib/kvmd/msd/NFS_Secondary  nfs vers=3,timeo=1,retrans=1,soft,nolock  0 0
    +
    +
  6. +
  7. +

    Perform reboot to apply all changes.

    +
  8. +
+
+

Make sure that the kvmd user has the read access from these directories. You can also give the write access if needed. +For the best performance, it is required to ensure reliable connectivity with NFS server and use minimum timeo and retrans values. +Using the soft option is mandatory, nolock is recommended.

+

Note if an image is added to the NFS storage from the outside, PiKVM will not be able to track this event, so it is required to use +Drive -> Reset in the Web UI to update the list of images.

+

Configuring an NFS server is beyond the scope of this guide.

+
+

Samba/CIFS storage

+

If you already have a local samba server e.g. Unraid or another NAS you can use the isos from there.

+

To refresh the list of available isos on the share it is currently necessary to reboot.

+
+Step by step: Connecting Samba/CIFS storage +
    +
  1. +

    Update OS:

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
  2. +
  3. +

    Make some preparations:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -S cifs-utils
    +[root@pikvm ~]# kvmd-helper-otgmsd-remount rw
    +[root@pikvm ~]# mkdir -p /var/lib/kvmd/msd/isos
    +[root@pikvm ~]# kvmd-helper-otgmsd-remount ro
    +
    +
  4. +
  5. +

    Add Samba/CIFS shares to /etc/fstab:

    +
    //192.168.0.1/isos   /var/lib/kvmd/msd/isos   cifs  guest,_netdev,nofail 0 0
    +
    +
  6. +
  7. +

    Perform reboot to apply all changes.

    +
  8. +
+
+
+

exFAT filesystem warning

+

Using the existing USB ports you can reduce writes to the internal SSD card by storing +images on a USB thumb drive. This is mounted as would NFS or Samba, above. As recent +drives are starting to come formatted with exfat instead of fat or NTFS, the +linux kernel will default to 'root' ownership of the mountpoint. This means the +volume will be visible in the 'Media' menu, but will be marked as [read-only], without +any obvious reason.

+

The correct /etc/fstab entry for a USB drive that presents as /dev/sda1 with an +exfat filesystem is:

+
    ```fstab
+    /dev/sda1   /var/lib/kvmd/msd/usb   exfat  auto,nofail,rw,umask=0000  0 0
+    ```
+
+ +

This says to mount it automatically, do not fail if it's missing, mount it read/write by +default, and allow all users and groups access to it.

+

Don't forget to create /var/lib/kvmd/msd/usb directory:

+
[root@pikvm ~]# kvmd-helper-otgmsd-remount
+[root@pikvm ~]# mkdir -p /var/lib/kvmd/msd/usb
+[root@pikvm ~]# kvmd-helper-otgmsd-remount ro
+
+
+

Multiple drives

+

By default, PiKVM creates one virtual drive for Mass Storage emulation. +However, if necessary, you can create additional ones and manage them using console utility. +This is useful if there is a need to boot the target host from the first drive, +and then connect the second to exchange files.

+
+

Note

+

The first virtual drive is available for management both in the Web UI (the Drive menu) +and using the kvmd-otgmsd console utility (see below). +Extra drives are controlled only from console.

+
+

The issue of additional drives concerns compatibility. +There is an assumption that multiple drives on the same USB may confuse some BIOS/UEFI. +So for paranoid reasons, this feature requires manual activation. +It is recommended setting up the drives in advance, making sure that booting from ISO CD or Flash is still working +with your specific target host, and then using the drives as planned.

+

Also additional drives consumes extra endpoints, read more under the spoiler:

+
+

USB limitations

+

Each emulated USB device consumes a limited hardware resource called endpoints.

+

Short info: by default, you can add only one additional USB device.

+

To get more information about the endpoints, add more devices, and flexibly manage the configuration on the fly, see here.

+
+

So, to add a second virtual drive, follow this:

+
+Step by step: Enabling an additional drive +
    +
  1. +

    Switch the filesystem to read-write mode:

    +
    [root@pikvm ~]# rw
    +
    +
  2. +
  3. +

    Edit /etc/kvmd/override.yaml and add the extra drive config section:

    +
    otg:
    +    devices:
    +        drives:
    +            enabled: true  # Set it to true to enable
    +            count: 1  # +1 drive, default value
    +            default:  # Default configuration for the all extra drives
    +                cdrom: false  # Default value (false for the generic flash drive, true for CD/DVD)
    +                rw: false # Read-only by default
    +
    +

    The count parameter determines the number of additional drives (remember the limit on endpoints). +Each of the drives will be created with the same initial parameters described in the default section.

    +
  4. +
  5. +

    Perform reboot:

    +
    [root@pikvm ~]# reboot
    +
    +
  6. +
+
+
+

Manual drives management

+

The kvmd-otgmsd console utility is used to manage additional (and the first main one) drives. +The full list of options can be found by running kvmd-otgmsd --help.

+
+Step by step: Creating the flash drive image to get some files from the target host +
    +
  1. +

    Switch the filesystem to read-write mode:

    +
    [root@pikvm ~]# rw
    +
    +
  2. +
  3. +

    Create an empty image file with desired size (1GB in this example):

    +
    [root@pikvm ~]# fallocate -l 1000M /root/flash.img
    +
    +
  4. +
  5. +

    Connect it to the drive 1 (the creation process is described in the previous section):

    +
    [root@pikvm ~]# kvmd-otgmsd -i 1 --set-rw=1 --set-cdrom=0 --set-image=/root/flash.img
    +
    +
    +

    Note

    +
      +
    • +

      Index 0 represents the main drive that is controlled via the Web UI and API.

      +
    • +
    • +

      If --set-cdrom=1, the drive will work as CD-ROM for small images, and as DVD-ROM for big. + Please note that CD/DVD can't be writable (you should use --set-rw=0 in this case).

      +
    • +
    +
    +
  6. +
  7. +

    On this step, you will be able to access the flash drive from the target host + and format the it in the usual way.

    +
  8. +
  9. +

    View the drive state:

    +
    [root@pikvm ~]# kvmd-otgmsd -i 1
    +Image file:  /root/flash.img
    +CD/DVD flag: no
    +RW flag:     yes
    +
    +
  10. +
  11. +

    To disable the flash drive and view the files on it from the PiKVM, run:

    +
    [root@pikvm ~]# kvmd-otgmsd -i 1 --unlock --eject
    +
    +
  12. +
  13. +

    Don't forget to remount the root filesystem to read-only mode:

    +
    [root@pikvm ~]# ro
    +
    +
  14. +
  15. +

    You can download the resulting image via SCP or mount it as a loop device on the PiKVM:

    +
    [root@pikvm ~]# mount -o loop /root/flash.img /mnt
    +[root@pikvm ~]# ls /mnt
    +[root@pikvm ~]# umount /mnt
    +
    +
  16. +
+
+
+

Tip

+

The main drive can also be switched to read-write mode, this can be done from the Web UI.

+

In this case, the image will have to be prepared outside of PiKVM, and upload it to use, +then download it back to your local host for files extraction.

+
+
+

Disabling Mass Storage

+

In rare cases, it may be necessary to disable Mass Storage emulation if the BIOS/UEFI +does not recognize it correctly and even refuses to work with USB keyboard and mouse.

+
+Step by step: Permanent disabling Mass Storage +
    +
  1. +

    Switch the filesystem to read-write mode:

    +
    [root@pikvm ~]# rw
    +
    +
  2. +
  3. +

    Edit /etc/kvmd/override.yaml and add the extra drive config section:

    +
    kvmd:
    +    msd:
    +        type: disabled
    +
    +
  4. +
  5. +

    Perform reboot:

    +
    [root@pikvm ~]# reboot
    +
    +
  6. +
+
+
+

Tip

+

As an alternative method may be to use the dynamic USB configuration, +which allows you to temporarily disable any of the emulated devices, including Mass Storage Drive.

+
+
+

Big DVD images on old PiKVM

+

Since KVMD 4.49, PiKVM is able to emulate DVD images.

+

Before that, users had to use Ventoy and other utilities to pre-convert large DVD images +such as the official Windows ISO to Flash.

+

We strongly recommend updating the PiKVM OS to simplify your Mass Storage experience when using DVDs:

+
+Updating PiKVM OS +

To update, run following commands under the root user:

+
[root@pikvm ~]# pikvm-update
+
+

If you encounter an error like:

+
[root@pikvm ~]# pikvm-update
+bash: pikvm-update: command not found
+
+

It's most likely you have an old OS release. You can update the OS as follows:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# pacman -Syy
+[root@pikvm ~]# pacman -S pikvm-os-updater
+[root@pikvm ~]# pikvm-update
+
+

Next time you will be able to use the usual method with pikvm-update.

+
+

Anyway, you can still view all these legacy recipes.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msd/macos_flash_dmg.png b/msd/macos_flash_dmg.png new file mode 100644 index 00000000..82d8630e Binary files /dev/null and b/msd/macos_flash_dmg.png differ diff --git a/msd_legacy/index.html b/msd_legacy/index.html new file mode 100644 index 00000000..f047a35c --- /dev/null +++ b/msd_legacy/index.html @@ -0,0 +1,2886 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Big DVD images on old PiKVM - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

Big DVD images on old PiKVM

+ +

Since KVMD 4.49, PiKVM is able to emulate DVD images.

+

Before that, users had to use Vento and other utilities to pre-convert large DVD images +such as the official Windows ISO to Flash.

+

We strongly recommend updating the PiKVM OS to simplify your Mass Storage experience when using DVDs:

+
+Updating PiKVM OS +

To update, run following commands under the root user:

+
[root@pikvm ~]# pikvm-update
+
+

If you encounter an error like:

+
[root@pikvm ~]# pikvm-update
+bash: pikvm-update: command not found
+
+

It's most likely you have an old OS release. You can update the OS as follows:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# pacman -Syy
+[root@pikvm ~]# pacman -S pikvm-os-updater
+[root@pikvm ~]# pikvm-update
+
+

Next time you will be able to use the usual method with pikvm-update.

+
+
+

Making Windows Boot Flash Image

+

An alternative version of this can be found below that does not require a physical usb flash

+

This procedure will create a disk image of a USB stick. +This is mostly required for Windows based images since they are larger than the CDROM based limit of 2.2GB. +You can create a bootable USB stick with the normal Microsoft tools, e.g. Media Creation Tool. +Creating a bootable USB stick can also be made from an ISO file with other tools like Rufus.

+

Without resizing, the full size of the USB stick will be used, so keep the stick as small as possible (e.g. 4GB or 8GB) +but still large enough for all Windows files. The Media Creation tool will tell you what the minimum size is.

+

Before creating the image file, you can use a tool like +EaseUS Partition Master Free or GParted +to resize the main FAT32 partition on the USB stick. This will save space on PiKVM.

+

You can also perform these steps on a separate UNIX machine and transfer the image over to PiKVM. +Or, on Windows you could use a program like PassMark ImageUSB (only for full USB size images) +or dd for Windows to create the image.

+

Once you have the desired USB stick perform the following on the RPi to create the image directly to the PiKVM image storage folder.

+
    +
  1. +

    Insert Windows based USB stick into Pi4, generated with Microsoft USB creation tool. SSH to PiKVM as root.

    +
    # dmesg
    +[ 3025.025401] usb-storage 2-1:1.0: USB Mass Storage device detected
    +[ 3025.038911] scsi host0: usb-storage 2-1:1.0
    +[ 3026.132248] scsi 0:0:0:0: Direct-Access     Kingston DataTraveler 3.0 PMAP PQ: 0 ANSI: 6
    +[ 3026.771425] sd 0:0:0:0: [sda] 15360000 512-byte logical blocks: (7.86 GB/7.32 GiB)
    +[ 3026.790276] sd 0:0:0:0: [sda] Write Protect is off
    +[ 3026.802530] sd 0:0:0:0: [sda] Mode Sense: 23 00 00 00
    +[ 3026.804450] sd 0:0:0:0: [sda] No Caching mode page found
    +[ 3026.814082] sd 0:0:0:0: [sda] Assuming drive cache: write through
    +[ 3026.908712]  sda: sda1
    +[ 3026.922794] sd 0:0:0:0: [sda] Attached SCSI removable disk
    +[root@pikvm ~]#
    +
    +

    USB devices shows as sda. We will use sda1 as the Windows partition.

    +
  2. +
  3. +

    mount msd folder as read/write

    +
    # kvmd-helper-otgmsd-remount rw
    +
    +
  4. +
  5. +

    Create image of USB data PARTITION to an image file, this will take some time, in this case about 12 minutes (RPi4).

    +
    # dd if=/dev/sda1 of=/var/lib/kvmd/msd/windows10-2004.bin bs=8M status=progress
    +4458545152 bytes (4.5 GB, 4.2 GiB) copied, 736 s, 6.1 MB/s
    +531+1 records in
    +531+1 records out
    +4458545152 bytes (4.5 GB, 4.2 GiB) copied, 736.213 s, 6.1 MB/s
    +
    +
  6. +
  7. +

    Correct ownership of new image and make sure the website reports the file as complete.

    +
    # chown kvmd:kvmd /var/lib/kvmd/msd/windows10-2004.bin
    +
    +
  8. +
  9. +

    Remount msd folder as read only

    +
    # kvmd-helper-otgmsd-remount ro
    +
    +
  10. +
  11. +

    On PiKVM webpage, under Storage select the new image and connect it in Drive Mode: Flash to the server.

    +
  12. +
+

Boot the server and select boot device like you normally would. +E.g. in a AMI BIOS the boot device is called "Linux File-CD Gadget 0504".

+
+

An alternative to making a Windows boot image that does not require a physical usb flash drive

+
    +
  • Physical USB is not needed but external system is mandatory.
  • +
  • Create Ventoy image (on Ubuntu x86 machine) (Unaware of a windows version).
  • +
  • There is an assumption that you know basic linux to understand that not all dev devices are named exactly like the below
  • +
+
# dd if=/dev/zero of=ventoy.img bs=1M count=4700 status=progress
+
+
    +
  • This makes a ventoy.img file, I would name this what it is EG: ventoy_win10.img
  • +
  • +

    At the same time, download Media Creation Tool and select iso

    +
  • +
  • +

    On the Ubuntu machine

    +
  • +
  • At the time of this, it was 1.0.51, change to latest version
  • +
+
# wget https://github.com/ventoy/Ventoy/releases/download/v1.0.51/ventoy-1.0.51-linux.tar.gz
+# tar zxvf ventoy-1.0.51-linux.tar.gz
+# sudo losetup -f ventoy.img
+# sudo losetup -l | grep ventoy (To locate which loop device was used)
+# sudo sh ~/ventoy-1.0.51/Ventoy2Disk.sh -i /dev/loopXX (This will make a loopXXp1 and a loopXXp2 and will format both partitions
+# cd /media/XXX (Usually your login)
+# mkdir ventoy
+# sudo mount /dev/loopXXp1 /media/XXX/ventoy
+
+
    +
  • Either cp/scp over the .iso you downloaded from the Media tool or use a NFS mount
  • +
+
sudo cp windows.iso /media/XXX/ventoy
+sudo umount /dev/loopXX 
+# This is going to be different for everyone, please choose the same one you mounted earlier
+sudo losetup -d /dev/loopXX 
+# This may or may not work for everyone, if it doesnt work, skip and move forward#
+
+

ssh into the Ubuntu system (Or whatever OS you are using)

+
    +
  • On PiKVM
  • +
+
# cd /var/lib/kvmd/msd
+# mount -o remount,rw .
+
+
    +
  • On Ubuntu
  • +
+
# scp ventoy.img root@pikvm:/var/lib/kvmd/msd
+
+
    +
  • Mount ventoy.img as normal flash and select the PiKVM boot device, it should popup with the VenToy logo with the window.iso as a selection
  • +
+
+

An alternative to making a Windows boot image that does not require a physical usb flash drive on a single windows machine

+
    +
  • Physical USB is not needed
  • +
  • +

    Requires Administrator rights on the windows machine

    +
  • +
  • +

    Testing was done on a Windows 11 machine with a Windows 11 23H2 ISO

    +
  • +
  • +

    Requires a windows ISO (can be downloaded from the microsoft website), Rufus (To write the ISO to the VHD) and VirtualBox (Uses VBoxManage to convert VHD to IMG)

    +
  • +
  • +

    Create a VHD in Windows, This can be done in two ways that i know of.

    +

    Method 1: +Open up the windows settings, go to storage, press advanced storage settings and press Disks & Volumes +Press the Create VHD button, Give the disk a name, set a storage location and set the Virtual hard disk size (for 23H2 i used 6300MB). Set the Virtual hard disk format to VHD and set it to Fixed Size. +Press Create and then you will get a menu to initialize the disk, press cancel

    +

    Method 2: +Open up the windows partition manager, make sure you don't have any partitions or disks selected by pressing on empty space, Go to Action and select Create VHD. +Select a location for the VHD file, set the VHD size (for 23H2 i used 6300MB), Set the Virtual hard disk format to VHD and set it to Fixed Size. +Press OK

    +
  • +
+

2. + Download the Windows ISO and Rufus (i use the portable version), open rufus select the NO_LABEL disk that should roughly match size selected when creating the VHD (MiB vs MB). + Select the ISO you downloaded and press start + Once it is done close rufus (optionally delete rufus)

+
    +
  1. Unmount the VHD by either opening up windows explorer, right clicking on the windows installer drive and pressing eject or opening up the windows partition manager, right clicking on the virtual disk and detaching the VHD
  2. +
+

4. + Download and install Virtualbox + Open up a command prompt in the location where you stored the VHD +

VBoxManage clonehd input.vhd output.img --format raw
+
+ Or if virtualbox didn't get added to the system environment variables +
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" clonehd input.vhd output.img --format raw
+
+ This will convert the VHD to the IMG ready to be uploaded to the pikvm +
    +
  • using vboxmanage does have a slight quirk where it writes every conversion to .VirtualBox\VirtualBox.xml so if you make changes to the vhd and try to convert it again it throws and error that the uuid doesn't match the stored value in VirtualBox.xml and you need to either throw away VirtualBox.xml or edit it and delete the line that matches the error
  • +
  • this method has also been tested using the windows installer for ventoy (needs enabling show all devices in the windows installer)
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/multiport/index.html b/multiport/index.html new file mode 100644 index 00000000..f0ba43bf --- /dev/null +++ b/multiport/index.html @@ -0,0 +1,2771 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Multiport KVM-over-IP - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Multiport KVM-over-IP

+ +
+Note +

V4 MINI can ONLY be used with the TESmart or other KVMs with LAN control, the TESmart has a convenience driver for easier setup

+
+

+

If you need to connect multiple hosts to a single PiKVM, then the best way to do this is to use our PiKVM Switch. It is designed specifically for PiKVM and has many advantages and features compared to regular desktop multiport switches.

+
    +
  • ATX control on each port.
  • +
  • Per-port EDID configuration.
  • +
  • HDMI dummy plug functionality.
  • +
  • True Plug-n-Play with no need for override.yaml setups and complete control via Web UI.
  • +
  • Multifunctional RGB LEDs with beacon mode and customizable color schemes.
  • +
  • Firmware update directly from PiKVM and ready for future hardware extensions.
  • +
  • Compatible with V4 Plus, V3 and DIY devices based on Pi2-Pi4 except Zero and V4 Mini.
  • +
+

And now the best part: the switches can be chained! Need four ports? Get a PiKVM Switch. +As your server fleet expands to eight, simply add another switch and link it to the first one. +Need even more? No worries — connect up to five switches and enjoy 20 fully functional ports on your PiKVM.

+

Just take a look!.

+

You can order PiKVM Switch Multiport Extender from our international store.

+

Canadian customers can place an order at PiShop.ca.

+
+

List of tested third-party KVMs

+

There are many ways to do this with third-party switches. For example you can choose a switch with USB control connection like ezCoo KVM switch.

+

Also, PiKVM can be connected to a multi-port HDMI/USB switch and the switch's buttons can be connected via optocouplers to the Pi's GPIO to switch channels.

+

If your KVM switches channels using keyboard shortcuts, there is a chance that it will not be able to work with OTG (v2+ platform, see below), since it does not fully implement the USB stack. In this case, you will have to use the Pico HID to emulate the keyboard & mouse (PiKVM supports this configuration).

+
+

Warning

+

If you choose AIMOS, be aware that it has a back powering issue that you need to use work arounds for. Limitations are are listed below. Also please be aware that Pico's will not work with the AIMOS KVM's.

+
+

Here the status is:

+
    +
  • ✔ - Everything is working as expected. There may be some subtleties.
  • +
  • ☹ - Not everything works. Additional work is needed for some functions to work, like MSD.
  • +
  • ✘ - The keyboard or mouse does not work at all, the switch loses the image, etc.
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ModelStatusNotes
ezCoo EZ-SW41HA-KVMU3L 4x1 switch ezCoo SW41HA HDMI 4x1 switch (legacy)Using with PiKVM - 4 Port is the ONLY supported KVM, 2 Port does not work the same and is not supported, the same can be said about any of the HDMI splitters 1-in-2 Out
eccoo EZ-SW41HA-KVMU3P 4x1 switchUsing with PiKVM. Make sure you buy the with hotkey version as that has the control port
ezcoo EZ-SW41H21-KVMU3P 8K 4x1 switchDoes NOT have a control port. MSD Works. Can be managed through key combo (ctrl+ctrl+#)
Level1Techs KVM switchesJust working pretty good
TESmart 8 or 16 PORT - HDMI KVM SWITCHUse OTG with USB 2.0 Hub only, limited hotkey support on certain models, but MSD only works through Hub ports. Switching available with serial (DIY/v4Plus) or IP-to-serial interface using fixed IP (v4mini et al) (/31 peer-to-peer addressing supported). Can be managed via WebUI or CLI tool
XH-HK4401 4-port HDMI USB KVM SwitchUsing with PiKVM - USB MSD works, requires the HDMI backpower solutions found below
AIMOS 8-port HDMI USB-C KVM SwitchSimilar to Ali's noname model, available in 4/8port editions, has same HDMI bridge boot problem/solution using a Marmitek 312 UHD HDMI splitter. ONLY supports HotKey switching. Limitations are are listed below
Aten CS1758 8-port PS/2 / USB VGA KVM switchOlder Aten switches can be had for cheap and can be a viable alternative. Devices are connected via PS/2 so USB media support does not work. The setup relies on a VGA-> HDMI adapter to make the video signal work and there can be issues with unsupported VGA resolutions with some adapters. KVM hotkeys and switching all work and so does mouse and keyboard.
+

Limitations:

+
    +
  • HDMI backpower solutions:
      +
    • See here
    • +
    • See here - Advanced soldering required
    • +
    • This loop capture device
    • +
    • v3 HAT v3.3 (Kickstarter model and later) also takes care of the back power issue
    • +
    +
  • +
  • Mass Storage Device (MSD) workaround (will not work OOB)
      +
    • RPi4 OTG needs to be in the KB port for mouse and KB funtionality, ZeroW is required and needs to be connected to the HUB port for MSD functionality - ✔KNOWN WORKING
    • +
    • AIMOS 4/8-port: See here - Advanced soldering required - allows use of GPIO menu to change input by cycling
    • +
    • AIMOS 8-port: See here - Advanced soldering required - allows use of GPIO menu to change input directly
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ocr/index.html b/ocr/index.html new file mode 100644 index 00000000..463e18d3 --- /dev/null +++ b/ocr/index.html @@ -0,0 +1,2647 @@ + + + + + + + + + + + + + + + + + + + + + + OCR - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

OCR

+ +

This feature allows you to select a screen region, recognize it as text +and copy this text to the clipboard. Recognition works locally on your +PiKVM and does not use any cloud services. It uses the Tesseract OCR +library. Tesseract does not +see your image until you explicitly give the recognition command. The +evil AI is not watching your screen.

+

Language support

+

For any language, you will have to install its support. It is very easy to do this (English language for example): +

# rw
+# pacman --assume-installed tessdata -S tesseract-data-eng
+# ro
+
+

List all available languages in the repository: +

# pacman -Ss tesseract-data
+
+

Disabling OCR

+

If you want to get rid of this feature completely, you need to delete Tesseract and all its data:

+
# rw
+# pacman -R tesseract
+# reboot
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/on_boot_config/index.html b/on_boot_config/index.html new file mode 100644 index 00000000..ac3942ab --- /dev/null +++ b/on_boot_config/index.html @@ -0,0 +1,2847 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + On-boot configuration & production deployment - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

On-boot configuration

+ +

At the first boot, PiKVM generates encryption keys and performs other +actions necessary to configure the device.

+

Some parameters, such as connecting to Wi-Fi, or configuring a static +interface for wired Ethernet, can be easily changed by the user if there +is physical access to the memory card. This is convenient for quick +customization of your device before the first use.

+

All settings are made using a file pikvm.txt on the first section of +the memory card. After applying the settings, the file is automatically +deleted.

+
+

Setting up Wi-Fi

+
+

Note

+

Devices based on Raspberry Pi Zero 2 W does not support 5GHz Wi-Fi.

+
+
    +
  1. +

    Remove the PiKVM memory card. The device must be turned off.

    +
  2. +
  3. +

    Insert the memory card into the computer and mount the first FAT32 partition.

    +
  4. +
  5. +

    Among the system files you will see the file pikvm.txt.

    +
      +
    • +

      If you haven't powered up PiKVM yet, this file will contain a single line FIRST_BOOT=1. Do not remove it, just add following lines from the next step.

      +
    • +
    • +

      If the file does not exist, create an empty file (don't add FIRST_BOOT option).

      +
    • +
    +
  6. +
  7. +

    To connect to Wi-Fi with DHCP, you will need an ESSID (network name) and a password. Add this to pikvm.txt. + If the file doesn't exists, just create it. Like following:

    +
    WIFI_ESSID='mynet'
    +WIFI_PASSWD='p@s$$w0rd'
    +
    +

    Note that backslash in the password should be escaped: \ should be written as \\.

    +

    If there was a string FIRST_BOOT=1 in the file, do not remove it. +This is the trigger needed to initialize the OS at the first boot. +On the contrary, if the file pikvm.txt does not exist, you should not add this line.

    +
  8. +
  9. +

    Unmount partition and return the memory card to PiKVM.

    +
  10. +
  11. +

    A few things to keep in mind:

    +
      +
    • Note that after applying the settings, the pikvm.txt file will be deleted.
    • +
    • WPA3 is not supported. Enable WPA2 on your router, while AES is supported, some aspects of it is not and you may need to disable AES for it to connect.
    • +
    • There is a possibility that, in countries that support channel 13, the device will not connect. + You will need to configure your router to disable channels 12-14 or disable Auto scan mode.
    • +
    +
  12. +
+
+

Other available options

+

A number of other parameters can be applied in the same way as with Wi-Fi.

+
+

Note

+

The parameters must be specified strictly each on a separate line.

+
+
    +
  • +

    FIRST_BOOT=1
    + Triggers initialization of the first OS startup. The following actions are performed:

    +
      +
    • Generates unique /etc/machine-id for internal systemd machinery.
    • +
    • Generates unique SSH host keys.
    • +
    • Generates unique SSL certificates for HTTPS and VNC.
    • +
    • Generates Avahi ZeroConf service /etc/avahi/services/pikvm.service with Pi's serial number. But keeps Avahi disabled by default.
    • +
    • Mass Storage image partition is reformatted to fill the available space at the end of SD card (only for V2+).
    • +
    • Different minor things are performed like fc-cache update.
    • +
    +

    Note that this option does not reset the OS to factory defaults. +There is no way to do this other than reflashing.

    +
  • +
  • +

    ENABLE_AVAHI=1
    + Triggers Avahi service generation (if needed) and enables avahi-daemon. It's disabled by default.

    +
  • +
  • +

    ENABLE_OTG_SERIAL=1
    + Only for V2+. Enables a virtual serial port on a USB emulator, that can be used to log in + to PiKVM from the target host side. Disabled for security reasons.

    +
  • +
  • +

    SSH_PORT=1234
    + Changes SSH server port to 1234 instead of 22.

    +
  • +
  • +

    ETH_DHCP=1
    + Configures Ethernet port for DHCP. This is a default for PiKVM OS.

    +
  • +
  • +

    ETH_ADDR=192.168.0.100/24
    ETH_DNS=8.8.8.8
    ETH_GW=192.168.0.1
    + Configures a static IP on the Ethernet port. Only IPv4 is available here. For IPv6 you'll need to change + systemd configuration files on the live OS. + All three options must be set simultaneously to avoid incorrect configuration.

    +
  • +
  • +

    WIFI_ESSID=foo
    WIFI_PASSWD=bar
    + Configures Wi-Fi with DHCP, described in more detail in previous paragrpah. + Both options must be set simultaneously to avoid incorrect configuration. + Can be followed by several options:

    +
      +
    • +

      WIFI_WPA23=1
      + Allows to connect to mixed WPA2/WPA3 network. Available only on new images >= 2025.03.03.

      +
    • +
    • +

      WIFI_HIDDEN=1
      + Allows to connect to hidden Wi-Fi network. Available only on new images >= 2024.03.12.

      +
    • +
    • +

      WIFI_ADDR=192.168.0.100/24
      WIFI_DNS=8.8.8.8
      WIFI_GW=192.168.0.1
      + Configures a static IP on the Wifi. Only IPv4 is available here. For IPv6 you'll need to change + systemd configuration files on the live OS. + All three options must be set simultaneously with WIFI_ESSID and WIFI_PASSWD to avoid incorrect configuration.

      +
    • +
    +
  • +
  • +

    WIFI_REGDOM=US
    + Changes Wi-Fi regulatory domain to the US. Other domains available by + ISO 3166-1 alpha-2 country codes.

    +
  • +
+
+

Advanced production deployment

+

For a production environment, it may be important to integrate PiKVM into an existing infrastructure automatically. +Usually, such actions are performed by special scripts written by the administrator.

+

To run such scripts, PiKVM OS suggests placing them in pikvm-scripts.d directory (/boot/pikvm-scripts.d on the system itself) +on the same partition next to pikvm.txt file.

+

If pikvm.txt exists, all the parameters described there will be applied, and the contents inside pikvm-scripts.d +will be checked if this directory exists. Scripts in this directory are run in alphabetical order, +the failure will be ignored, it is assumed that the script author should handle this situation.

+

If the script needs to reboot the OS, it should create an empty file /boot/pikvm-reboot.txt. +The reboot is performed once after all scripts.

+

In order not to copy scripts manually on each memory card on each PiKVM, it may make sense to build +a custom OS image containing everything you need.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/override/index.html b/override/index.html new file mode 100644 index 00000000..2e78d582 --- /dev/null +++ b/override/index.html @@ -0,0 +1,14 @@ + + + + + + Redirecting... + + + + + +You're being redirected to a new destination. + + diff --git a/pass/index.html b/pass/index.html new file mode 100644 index 00000000..2e6ca00b --- /dev/null +++ b/pass/index.html @@ -0,0 +1,2811 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + HDMI Video Passthrough - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

HDMI Video Passthrough

+

This feature allows directing the video stream from the host to a display attached directly to the HDMI output of PiKVM V4 Plus. This simplifies accessing the host locally while retaining the remote access to the host via the Web UI or VNC. This feature is limited to PiKVM V4 Plus because it’s the only PiKVM version with an HDMI Out port. It also works best with USB passthrough enabled.

+
+

Info

+
    +
  • The passthrough feature supports a screen resolution up to 1920x1200 pixels.
  • +
+
+

This is shown more clearly below:

+

+
+

Setting up the passthrough

+

Connect the display to OUT2 port on the back side of PiKVM V4 Plus. +This feature should be enabled by default on new images.

+

If not, follow two simple steps:

+
    +
  1. +

    Update OS and reboot:

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
  2. +
  3. +

    After rebooting, you will see an image on the physical display.

    +
  4. +
+
+

My monitor does not support the 1920x1200 mode

+

PiKVM V4 supports the advanced capture mode of 1920x1200. +If your physical monitor is limited to 1920x1080, then part of the image from the bottom will be cropped.

+

To avoid this, you can change the resolution of the host OS, or if the OS does not support this, +disable the 1920x1200 mode on PiKVM itself:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# kvmd-edidconf --import-preset=v4plus.no-1920x1200
+[root@pikvm ~]# reboot
+
+
+

Current limitations

+

Please note the feature is pretty new and will be improved.

+
    +
  • +

    Display resolution must be greater than or equal to that used by PiKVM capture. + If the maximum display resolution is 720p and the signal has a 1080p resolution, you will not see the image. + PiKVM does not perform any downscaling.

    +
  • +
  • +

    At the same time, PiKVM will try to show at least something than nothing. + If the input signal has a resolution of 1920x1200, and the display supports only 1920x1080, + the image will be shown but cropped from the bottom so that you at least have the opportunity + to adjust the image parameters of the host.

    +
  • +
  • +

    Audio is not supported at the moment.

    +
  • +
+
+

Disabling the passthrough

+
    +
  1. +

    Add few lines to /etc/kvmd/override.yaml:

    +
    kvmd:
    +    streamer:
    +        forever: false
    +        cmd_remove:
    +            - "--v4p"
    +
    +
  2. +
  3. +

    Perform reboot.

    +
  4. +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pass/pass.png b/pass/pass.png new file mode 100644 index 00000000..7a3cebf0 Binary files /dev/null and b/pass/pass.png differ diff --git a/pico_hid/basic_breadboard.png b/pico_hid/basic_breadboard.png new file mode 100644 index 00000000..384798b6 Binary files /dev/null and b/pico_hid/basic_breadboard.png differ diff --git a/pico_hid/basic_scheme.png b/pico_hid/basic_scheme.png new file mode 100644 index 00000000..1cf2503f Binary files /dev/null and b/pico_hid/basic_scheme.png differ diff --git a/pico_hid/index.html b/pico_hid/index.html new file mode 100644 index 00000000..df51c961 --- /dev/null +++ b/pico_hid/index.html @@ -0,0 +1,3066 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + The Pico HID - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+ +
+ + + +
+
+ + + + + +

Pico HID (USB, PS/2)

+ +
+

A fast way to get PS/2 on PiKVM V2+

+

If you need PS/2 keyboard & mouse on PiKVM V2, V3 and V4 Plus +(but not V4 Mini or DIY based on Zero 2 W boards), +you can use a faster and easier way: The Pico HID Bridge.

+
+
+

Pico requirements

+

Raspberri Pi Pico +(the first model) based on RP2040 microcontroller is required. +Pico 2 is not supported right now.

+
+

The Pico HID is a part of DIY PiKVM V1 platform that performs +keyboard and mouse emulation. It has excellent compatibility, and +emulates USB by default, including two mouse modes: absolute and +relative.

+

Full list of features:

+ + + + + + + + + + + + + + + + + + + + + +
FeatureEnabled by default
USB Keyboard, absolute & relative mouseYes
USB Absolute Mouse for Windows 95No
PS/2 Keyboard & mouseNo
+

The scope of the Pico HID is not limited to V1 platform, it can also be used with V2 and V3, +if you need to emulate a PS/2 keyboard and mouse or use a legacy multiport KVM switch +which does not fully support USB standards.

+

This page explains how to build, connect and use all the features of the Pico HID.

+
+

Software requirements

+

KVMD >= 3.241 is required for the Pico HID. +For new builds, this will be the case, but if you want to use the Pico HID on the old PiKVM, you will need to update OS.

+
+
+

Making the Pico HID

+

If you are building PiKVM V1, then the hardware should already be assembled. Skip this step unless you need PS/2 support.

+

But if you are making the Pico HID for V2 or V3, then follow this guide:

+
+The Pico HID from scratch +

Parts list:

+
    +
  • +

    x1 Raspberry Pi Pico board with soldered pins. Pico 2 is not supported right now.

    +
  • +
  • +

    x1 USB-A to Micro-USB cable.

    +
  • +
  • +

    x10 dupont wires female-female.

    +
  • +
  • +

    x1 1N5819 diode. It's optional but strongly recommended. Any similar one will do.

    +
    +

    Warning

    +

    The diode is needed to provide power to the Pico HID regardless of the target host state, +which prevents the backpowering problem. It will allow you to keep the keyboard buttons pressed +during the target host power cycle, which is, for example, important for MacOS to get into the boot menu.

    +

    Do not connect the red wire (the VSYS (Pico) -> 5V (Pi) line) without a diode. +If you can't find a diode, don't connect this wire at all.

    +
    +
  • +
+

Connect all the parts according to this scheme:

+
+Simple wiring diagram +

+
+
+Electrical schematic diagram for advanced users +

+
+
+

PS/2 Keyboard & Mouse

+
+Additional steps for PS/2 support +

If you need PS/2 keyboard and mouse support, you will need a few additional components. +Soldering skills will also come in handy.

+
    +
  • x1 3.3V/5V bi-directional logic level shifter like this.
  • +
  • x2 PS/2 cable with male connector (can be salvaged from the an keyboard or mouse).
  • +
+

Make sure that the level shifter pinout matches the scheme, and connect everything according to the Pico pinout.

+
                                   >>> To the PC <<<
+                 _________________
+                |                 |
+Pico GP11 ______| LV1         HV1 |______ PS/2 keyboard data
+Pico GP12 ______| LV2         HV2 |______ PS/2 keyboard clock
+Pico GP13 ______| LV          HV  |______ PS/2 5V
+Pico  GND ______| GND         GND |______ PS/2 GND
+Pico GP14 ______| LV3         HV3 |______ PS/2 mouse data
+Pico GP15 ______| LV4         HV4 |______ PS/2 mouse clock
+                |_________________|
+
+

You can take the 5V power line from one of the PS/2, for example from the keyboard, +or from both at once, but use a multimeter to make sure that both PS/2 female +connectors have the same line.

+

+

PS/2 female socket pinout on the motherboard is the same for the keyboard and the mouse. +A purple socket usually corresponds to the keyboard, and a green one to the mouse. +If your motherboard only has one port, it's probably universal and can be used for both +the keyboard and the mouse. Most likely, it will be painted both colors.

+

Use a multimeter to determine the purpose of the wires in your PS/2 cables.

+

A good idea is to mount the level shifter on top of the Pico, as in this photo:

+

+
+

Note

+

Don't forget to enable PS/2 mode support as described in the next paragraph

+
+
+Optional: PS/2 passthrough +

This optional addon allows to use a real PS/2 keyboard and mouse together with emulated by PiKVM.

+

These two ports work as PS/2 inputs and are passed through to the PS/2 output ports.

+
                                   >>> To the REAL keyboard and mouse <<<
+                 _________________
+                |                 |
+Pico GP26 ______| LV1         HV1 |______ PS/2 keyboard data
+Pico GP27 ______| LV2         HV2 |______ PS/2 keyboard clock
+Pico GP13  _____| LV          HV  |______ PS/2 5V
+Pico  GND ______| GND         GND |______ PS/2 GND
+Pico GP16 ______| LV3         HV3 |______ PS/2 mouse data
+Pico GP17 ______| LV4         HV4 |______ PS/2 mouse clock
+                |_________________|
+
+
+
+
+

Configuring the HID modes

+

By default, Pico HID emulates a USB keyboard and an absolute or relative mouse +(read here about the difference between mouse modes). +For most cases, nothing needs to be changed here. However, if you need something special +(like Windows 98 support), you can do it without reflashing the current firmware.

+

To achieve this, the Pico HID uses a runtime configuration, which is set by connecting +some GPIOs with Ground (GND) lines.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Pin name on the Pico boardDescription
GP2Enable PS/2 keyboard & mouse support (see below).
GP3Prefer the PS/2 keyboard over USB when turning on the HID (if PS/2 is enabled).
GP4Prefer the PS/2 mouse over USB (if PS/2 is enabled)
GP6Disable USB keyboard & mouse support. This is useful if you only want to use PS/2.
GP7Enable the special USB absolute mouse for Windows 98.
GP8Prefer the relative USB mouse over the absolute one.
GP9Prefer the Windows 98 USB absolute mouse over the regular absolute one (if enabled).
+
+

Example

+

To enable Windows 98 absolute mouse, just connect pin GP9 to any GND on the Pico.

+
+
+

Flashing the firmware

+

To upload the firmware to Pico HID, you can use any computer with a USB port.

+
    +
  1. Download the latest release of the firmware. The file is called pico-hid.uf2.
  2. +
  3. Press and hold the white button on the Pico board.
  4. +
  5. While still holding the button, plug it in the computer using a USB cable.
  6. +
  7. Release the button.
  8. +
  9. The Pico board appears as a flash drive on your computer.
  10. +
  11. Copy the pico-hid.uf2 file to this flash drive.
  12. +
  13. Safely eject the USB device.
  14. +
+

If you want to compile the firmware yourself, you can find the source code here.

+
+

The final steps

+

Connect the Pico HID to the target host using the USB cable.

+

If you are building PiKVM V1, no further action with the Pico HID is required.

+

If you are making the Pico HID for V2 or V3, add the following lines to the PiKVM configuration and reboot it:

+
    +
  • +

    /boot/config.txt +

    dtoverlay=spi0-1cs
    +
    +
  • +
  • +

    /etc/kvmd/override.yaml: +

    kvmd:
    +    hid:
    +        type: spi
    +        chip: 0
    +        bus: 0
    +        sw_cs_pin: 7
    +        sw_cs_per_byte: true
    +        reset_pin: 25
    +        reset_inverted: true
    +        reset_self: true
    +        power_detect_pin: 16
    +        power_detect_pull_down: true
    +
    +
  • +
+
+

Replacing the Arduino HID

+
+

Warning

+

This section is intended for advanced users of the legacy Arduino HID.

+

It may seem tempting, but don't to use the Arduino HID for new PiKVM builds +just because you have it at your fingertips. Connecting and flashing Arduino +is much more time consuming than Pico. In addition, different Arduino board work +with different voltages, they may or may not have SPI (for the Pico, we use SPI to +free up the UART on Raspberry Pi for the console and other useful things), etc.

+

Using the Pico HID is the recommended fast and standard way in the PiKVM world.

+
+

The Pico HID can be used to replace the legacy Arduino HID. +It can use both Serial (UART) port and the SPI. The connection scheme is also much simpler, +getting rid of the transistor for the Reset line and the level shifter for RX/TX (MOSI/MISO).

+
+For the Arduino HID over SPI +

Throw away the Reset transistor and level shifter, and follow this guide +from the very beginning, as if you were connecting Pico HID to PiKVM V2 or V3.

+
+
+For the classic Serial (UART) HID +

Get rid of the transistor and level shifter, and follow this guide +from the very beginning, but the schemes and configs will be slightly different.

+
    +
  • +

    The GP22 on the Pico is connected directly to the GND. This enables UART mode instead of the default SPI.

    +
  • +
  • +

    In the good old PiKVM V0, GPIO4 on the Raspberry Pi was used for the Reset line. + Now we recommend to use GPIO25 for consistency reasons. + However, you can use GPIO4 by changing the reset_pin value in the config example below. + On the scheme, this is a yellow wire, the RUN (Pico) -> GPIO25 (Pi) line.

    +
  • +
+
+Simple wiring diagram +

+
+
+Electrical schematic diagram +

+
+
+Configs +
    +
  • +

    Don't add line dtoverlay=spi0-1cs to the /boot/config.txt file. It's only needed for SPI.

    +
  • +
  • +

    /etc/kvmd/override.yaml: +

    kvmd:
    +    hid:
    +        type: serial
    +        device: /dev/kvmd-hid
    +        reset_pin: 25
    +        reset_inverted: true
    +        reset_self: true
    +        power_detect_pin: 16
    +        power_detect_pull_down: true
    +
    +
  • +
+
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pico_hid/ps2_level_shifter_soldering.png b/pico_hid/ps2_level_shifter_soldering.png new file mode 100644 index 00000000..1e6d051e Binary files /dev/null and b/pico_hid/ps2_level_shifter_soldering.png differ diff --git a/pico_hid/ps2_pinout.png b/pico_hid/ps2_pinout.png new file mode 100644 index 00000000..1ac19da3 Binary files /dev/null and b/pico_hid/ps2_pinout.png differ diff --git a/pico_hid/serial_breadboard.png b/pico_hid/serial_breadboard.png new file mode 100644 index 00000000..6551bf6f Binary files /dev/null and b/pico_hid/serial_breadboard.png differ diff --git a/pico_hid/serial_scheme.png b/pico_hid/serial_scheme.png new file mode 100644 index 00000000..90289b1e Binary files /dev/null and b/pico_hid/serial_scheme.png differ diff --git a/pico_hid_bridge/index.html b/pico_hid_bridge/index.html new file mode 100644 index 00000000..8dd37ca3 --- /dev/null +++ b/pico_hid_bridge/index.html @@ -0,0 +1,2739 @@ + + + + + + + + + + + + + + + + + + + + + + The Pico HID - PS/2 Bridge - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

The Pico HID - PS/2 Bridge

+ +
+

Pico requirements

+

Raspberri Pi Pico +(the first model) based on RP2040 microcontroller is required. +Pico 2 is not supported right now.

+
+

The Pico HID Bridge is a special version of the generic Pico HID. +It is a PS/2 keyboard and mouse emulator that connects to PiKVM via USB-A. +Unlike generic Pico HID and legacy Arduino HID, +it doesn't require SPI wiring with GPIO.

+

It is suitable for all devices except V4 Mini and DIY based on Zero 2 W board.

+

At one end it connects to USB-A on PiKVM, on the other side it has two PS/2 connectors for keyboard and mouse:

+

+

In addition, on PiKVM V2+, the use of Pico the HID Bridge does not exclude the use of a regular USB OTG port with Mass Storage emulation. +Thus, on V2+ you will be able to use PS/2 and USB Mass Storage at the same time, and even switch between OTG HID and Pico HID.

+
+

Making the Bridge

+
    +
  • x1 Raspberry Pi Pico board with soldered pins.
  • +
  • x1 USB-A to Micro-USB cable.
  • +
  • x1 3.3V/5V bi-directional logic level shifter like this.
  • +
  • x2 PS/2 cable with male connector.
  • +
  • x2 Small dip jumpers.
  • +
+

Make sure that the level shifter pinout matches the scheme, and connect everything according to the Pico pinout.

+
                                   >>> To the PC <<<
+                 _________________
+                |                 |
+Pico GP11 ______| LV1         HV1 |______ PS/2 keyboard data
+Pico GP12 ______| LV2         HV2 |______ PS/2 keyboard clock
+Pico GP13 ______| LV          HV  |______ PS/2 5V
+Pico  GND ______| GND         GND |______ PS/2 GND
+Pico GP14 ______| LV3         HV3 |______ PS/2 mouse data
+Pico GP15 ______| LV4         HV4 |______ PS/2 mouse clock
+                |_________________|
+
+

You can take the 5V power line from one of the PS/2, for example from the keyboard, +or from both at once, but use a multimeter to make sure that both PS/2 female +connectors have the same line.

+

+

PS/2 female socket pinout on the motherboard is the same for the keyboard and the mouse. +A purple socket usually corresponds to the keyboard, and a green one to the mouse. +If your motherboard only has one port, it's probably universal and can be used for both +the keyboard and the mouse. Most likely, it will be painted both colors.

+

Use a multimeter to determine the purpose of the wires in your PS/2 cables.

+

A good idea is to mount the level shifter on top of the Pico, as in this photo:

+

+

Finally, install DIP jumpers to soldered pins of the Pico to enable PS/2 and Bridge modes:

+
    +
  • GP2 <-> GND
  • +
  • GP5 <-> GND
  • +
+

Like this:

+

+
+

PS/2 passthrough

+

This optional addon allows to use a real PS/2 keyboard and mouse together with emulated by PiKVM.

+

These two ports work as PS/2 inputs and are passed through to the PS/2 output ports.

+
                                   >>> To the REAL keyboard and mouse <<<
+                 _________________
+                |                 |
+Pico GP26 ______| LV1         HV1 |______ PS/2 keyboard data
+Pico GP27 ______| LV2         HV2 |______ PS/2 keyboard clock
+Pico GP13  _____| LV          HV  |______ PS/2 5V
+Pico  GND ______| GND         GND |______ PS/2 GND
+Pico GP16 ______| LV3         HV3 |______ PS/2 mouse data
+Pico GP17 ______| LV4         HV4 |______ PS/2 mouse clock
+                |_________________|
+
+
+

Flashing the firmware

+

To upload the firmware to Pico HID, you can use any computer with a USB port.

+
    +
  1. Download the latest release of the firmware. The file is called pico-hid.uf2.
  2. +
  3. Press and hold the white button on the Pico board.
  4. +
  5. While still holding the button, plug it in the computer using a USB cable.
  6. +
  7. Release the button.
  8. +
  9. The Pico board appears as a flash drive on your computer.
  10. +
  11. Copy the pico-hid.uf2 file to this flash drive.
  12. +
  13. Safely eject the USB device.
  14. +
+

If you want to compile the firmware yourself, you can find the source code here.

+
+

The final steps

+

Connect the Pico HID to the target host using PS/2 cable and USB to USB-A port on PiKVM.

+

Add following lines to the PiKVM configuration and reboot it:

+
    +
  • /etc/kvmd/override.yaml: +
    kvmd:
    +    hid:
    +        type: serial
    +        device: /dev/kvmd-hid-bridge
    +        reset_pin: -1
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pico_hid_bridge/pico_hid_bridge_ps2.jpg b/pico_hid_bridge/pico_hid_bridge_ps2.jpg new file mode 100644 index 00000000..9a5c8218 Binary files /dev/null and b/pico_hid_bridge/pico_hid_bridge_ps2.jpg differ diff --git a/pico_hid_bridge/pico_hid_bridge_ps2_jumpers.jpg b/pico_hid_bridge/pico_hid_bridge_ps2_jumpers.jpg new file mode 100644 index 00000000..c9c633fb Binary files /dev/null and b/pico_hid_bridge/pico_hid_bridge_ps2_jumpers.jpg differ diff --git a/port_forwarding/index.html b/port_forwarding/index.html new file mode 100644 index 00000000..15885c77 --- /dev/null +++ b/port_forwarding/index.html @@ -0,0 +1,2635 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Port forwarding - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Port forwarding

+ +

If you need to make PiKVM accessible from Internet, the easiest way to +achieve this is by forwarding a port on the router. In this case, an +external (global) IP address must be assigned to the router. This +service is provided by the ISP.

+
+

Tip

+

If using an external IP address is not possible, it is recommended to try +the Tailscale VPN.

+
+
    +
  • To configure port forwarding, refer to the documentation of the router.
  • +
  • The Web UI listening ports are 80 (HTTP) and 443 (HTTPS).
  • +
  • By default, port 80 performs permanent forwarding to 443 for security reasons.
  • +
  • Forwarding the port 443 is sufficient in most cases.
  • +
  • If enabled, the VNC server runs on port 5900 (disabled by default).
  • +
+
+

Warning

+
    +
  • Set strong passwords and enable two-factor authorization + before opening access to PiKVM from the Internet!
  • +
  • It is strongly recommended to obtain a valid HTTPS certificate, for example via Let's Encrypt.
  • +
  • A good practice is using a custom port number instead of 443 from the Internet side, for example 14438, to avoid common port scanners.
  • +
  • If you still decide to use the 443 port number, you may want to forward port 80 to get a convenient redirect.
  • +
+
+

Port forwarding is a powerful and convenient tool, but remember that security depends entirely on your configuration. +In most cases, a VPN is a more secure, but less convenient option (since it requires a VPN client on all devices that access PiKVM).

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/prometheus/index.html b/prometheus/index.html new file mode 100644 index 00000000..f6a9744e --- /dev/null +++ b/prometheus/index.html @@ -0,0 +1,2780 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Prometheus metrics - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Prometheus monitoring

+ +

Prometheus is one of the popular monitoring +systems. It pulls service's endpoint to get metrics in a simple text +format. +PiKVM has the ability to export some information to this system such as +the server's ATX state, Pi's temperature, GPIO state and some +other things.

+

Configure Prometheus

+

To enable Prometheus getting metrics from pikvm following config could be used:

+
scrape_configs:
+  - job_name: "pikvm"
+    metrics_path: "/api/export/prometheus/metrics"
+    basic_auth:
+      username: admin
+      password: admin
+    scheme: https
+    static_configs:
+    - targets: ["pikvm"]
+    tls_config:
+      insecure_skip_verify: true # For self-signed certificate
+
+

Output example

+

This example includes the GPIO from the PiKVM's test config.

+
$ curl -k -HX-KVMD-User:admin -HX-KVMD-Passwd:admin https://pikvm/api/export/prometheus/metrics
+
+# TYPE pikvm_atx_enabled gauge
+pikvm_atx_enabled 1
+
+# TYPE pikvm_atx_power gauge
+pikvm_atx_power 0
+
+# TYPE pikvm_gpio_input_online_led1 gauge
+pikvm_gpio_input_online_led1 0
+
+# TYPE pikvm_gpio_input_state_led1 gauge
+pikvm_gpio_input_state_led1 0
+
+# TYPE pikvm_gpio_input_online_led2 gauge
+pikvm_gpio_input_online_led2 0
+
+# TYPE pikvm_gpio_input_state_led2 gauge
+pikvm_gpio_input_state_led2 0
+
+# TYPE pikvm_gpio_output_online_button1 gauge
+pikvm_gpio_output_online_button1 0
+
+# TYPE pikvm_gpio_output_state_button1 gauge
+pikvm_gpio_output_state_button1 0
+
+# TYPE pikvm_gpio_output_online_button2 gauge
+pikvm_gpio_output_online_button2 0
+
+# TYPE pikvm_gpio_output_state_button2 gauge
+pikvm_gpio_output_state_button2 0
+
+# TYPE pikvm_gpio_output_online_relay1 gauge
+pikvm_gpio_output_online_relay1 0
+
+# TYPE pikvm_gpio_output_state_relay1 gauge
+pikvm_gpio_output_state_relay1 0
+
+# TYPE pikvm_gpio_output_online_relay2 gauge
+pikvm_gpio_output_online_relay2 0
+
+# TYPE pikvm_gpio_output_state_relay2 gauge
+pikvm_gpio_output_state_relay2 0
+
+# TYPE pikvm_hw_temp_cpu gauge
+pikvm_hw_temp_cpu 36.511
+
+# TYPE pikvm_hw_temp_gpu gauge
+pikvm_hw_temp_gpu 35.0
+
+# TYPE pikvm_hw_throttling_freq_capped_now gauge
+pikvm_hw_throttling_freq_capped_now 0
+
+# TYPE pikvm_hw_throttling_freq_capped_past gauge
+pikvm_hw_throttling_freq_capped_past 0
+
+# TYPE pikvm_hw_throttling_throttled_now gauge
+pikvm_hw_throttling_throttled_now 0
+
+# TYPE pikvm_hw_throttling_throttled_past gauge
+pikvm_hw_throttling_throttled_past 0
+
+# TYPE pikvm_hw_throttling_undervoltage_now gauge
+pikvm_hw_throttling_undervoltage_now 0
+
+# TYPE pikvm_hw_throttling_undervoltage_past gauge
+pikvm_hw_throttling_undervoltage_past 0
+
+# TYPE pikvm_hw_throttling_raw_flags gauge
+pikvm_hw_throttling_raw_flags 0
+* Connection #0 to host localhost left intact
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pst/index.html b/pst/index.html new file mode 100644 index 00000000..fefd9593 --- /dev/null +++ b/pst/index.html @@ -0,0 +1,2717 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Persistent storage - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Persistent storage

+ +
+

Note

+

This feature is available on images newer than 2022.06.20

+
+

Sometimes advanced use of PiKVM requires storing some data on disk like +API keys, config files, or something like that. For example, you want to +have a script that will update SSL certificates once a week. However, +the root file system is in a read-only state and does not involve +remounting automatically by user scripts.

+

To solve this problem, new versions of PiKVM have a small 256MiB storage +partition that can be used to store that data. A special kvmd-pst +daemon makes sure that this partition is mounted in read-only all the +time, and remounts it to RW only when some user script requires it. This +also solves the problems of simultaneous access, so the RW mode will be +kept as long as at least one client is working with the storage.

+

Usage

+

Below is an example of a script /root/test.sh that wants to save a certain file in PST:

+
#!/bin/bash
+echo `date` + $@ > $KVMD_PST_DATA/foo
+cat $KVMD_PST_DATA/foo
+
+

To run it use: +

# kvmd-pstrun -- /root/test.sh --some --script --args
+--    INFO -- Opening PST session ...
+--    INFO -- PST write is allowed: /var/lib/kvmd/pst/data
+--    INFO -- Running the process ...
+Mon Jun 20 04:23:14 MSK 2022 + --some --script --args
+--    INFO -- Process finished: returncode=0
+
+

So, what's going on here:

+
    +
  1. +

    kvmd-pstrun connects to the kvmd-pst daemon, which manages the mounting of the storage.

    +
  2. +
  3. +

    If everything is fine, the daemon will remount the storage to RW mode and report the data root to kvmd-pstrun.

    +
  4. +
  5. +

    kvmd-pstrun runs the script and pass the data root path using the environment variable KVMD_PST_DATA (/var/lib/kvmd/pst/data).

    +
  6. +
  7. +

    If the kvmd-pst daemon stops or any other daemon error occurs, the script will be killed.

    +
  8. +
  9. +

    After the script is finished, the daemon will remount the storage to RO mode.

    +
  10. +
+

To be able to write to the storage, the user must be a member of kvmd-pst group, or have to be root.

+

The return code will be equal to the script code if it was run, or 1 if a remount error occurred.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/reverse_proxy/index.html b/reverse_proxy/index.html new file mode 100644 index 00000000..cb2bf092 --- /dev/null +++ b/reverse_proxy/index.html @@ -0,0 +1,2852 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Reverse proxy - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Reverse proxy

+ +

A reverse proxy allows you to pass requests through your web server to +another site or program. The reverse proxy will make it look like PiKVM +Web UI is a page within your existing site.

+

This is especially useful if:

+
    +
  • +

    You need to access the WebUI on port 80 or 443 but you already host a website on the same device.

    +
  • +
  • +

    You want to share SSL certificates with an existing site.

    +
  • +
  • +

    You want to share authentication with an existing setup.

    +
  • +
+
+

PiKVM Configuration

+

PiKVM supports reverse proxying since KVMD 4.51. For older version, please update OS first:

+
+Updating PiKVM OS +

To update, run following commands under the root user:

+
[root@pikvm ~]# pikvm-update
+
+

If you encounter an error like:

+
[root@pikvm ~]# pikvm-update
+bash: pikvm-update: command not found
+
+

It's most likely you have an old OS release. You can update the OS as follows:

+
[root@pikvm ~]# rw
+[root@pikvm ~]# pacman -Syy
+[root@pikvm ~]# pacman -S pikvm-os-updater
+[root@pikvm ~]# pikvm-update
+
+

Next time you will be able to use the usual method with pikvm-update.

+
+

By default, PiKVM redirects all requests from HTTP port 80 to HTTPS port 443 with self-signed +certificate. For the simplest configuration, you can leave it as it is, and terminate +SSL traffic from PiKVM on your web server.

+

Alternatively, you can change the HTTP and HTTPS ports on PiKVM or disable HTTPS at all +to deliver HTTP-only traffic to your server.

+

In both cases you should take care of your own SSL certificate for your web server because +when using HTTP-only access to your website, you will lose the ability to use some features +such as Direct H.264 streaming, because browser security policies will require +HTTPS for them.

+
+Various examples with changing HTTP/HTTPS settings +

PiKVM uses Nginx internally, so don't be confused by its own configuration, +it has nothing to do with your reverse proxy if you're using Nginx too.

+
    +
  • +

    Changing HTTP and HTTPS ports. Place this config to /etc/kvmd/override.yaml on PiKVM:

    +
    nginx:
    +    https:
    +        port: 4430
    +    http:
    +        port: 8080
    +
    +
  • +
  • +

    Disabling HTTPS. All requests will be handled via HTTP port 80.

    +
    nginx:
    +    https:
    +        enabled: false
    +
    +
  • +
+

Don't forget to run systemctl restart kvmd-nginx to apply your changes.

+
+
+

Server Configuration

+

If you have access to your web server’s configuration use the following examples +to pass the location /pikvm on the server to PiKVM Web UI hosted on https://pikvm.local +on HTTPS port 443.

+

Nginx

+

Nginx does not validate certificates by default and PiKVM's self-signed certificate is fine for it.

+
location /pikvm {
+    rewrite ^/pikvm$ / break;
+    rewrite ^/pikvm\?(.*)$ ?$1 break;
+    rewrite ^/pikvm/(.*)$ /$1 break;
+    proxy_redirect ~^(/.*)$ /pikvm$1;
+    proxy_pass https://pikvm.local;
+
+    proxy_set_header Host $host;
+    proxy_set_header X-Real-IP $remote_addr;
+    proxy_set_header X-Scheme $scheme;
+    proxy_set_header X-Forwarded-Proto $scheme;
+    proxy_set_header X-Forwarded-Port $server_port;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+
+    # For some handles (like MJPEG) buffering should be disabled
+    postpone_output 0;
+    proxy_buffering off;
+    proxy_ignore_headers X-Accel-Buffering;
+
+    # Some handles (ends with /ws) are WebSockets
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "upgrade";
+    proxy_connect_timeout 7d;
+    proxy_send_timeout 7d;
+    proxy_read_timeout 7d;
+
+    # Some other handles requires big POST payload
+    client_max_body_size 0;
+    proxy_request_buffering off;
+}
+
+

Caddy

+

Caddy doesn't like self-signed certificates, so we'll have to convince it that it's okay.

+
handle_path /pikvm/* {
+    reverse_proxy https://pikvm.local {
+        transport http {
+            tls_insecure_skip_verify  # Same behaviour as Nginx
+        }
+        header_up Host {upstream_hostport}
+        header_down Location "^(/.*)$" "/pikvm$1"
+    }
+}
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 00000000..2a5fc118 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"PiKVM Handbook","text":"

Welcome to the PiKVM Handbook\u2014a complete documentation of the Open-Source KVM-over-IP on Raspberry Pi!

Here you will find comprehensive information about all aspects of the operation of PiKVM, get answers to your most difficult questions and be able to solve the problems that have arisen.

"},{"location":"#where-to-start","title":"Where to start?","text":"
  • Check out the device instructions:

    PiKVM V4 Mini & Plus

    PiKVM V3

    DIY PiKVM V2

    DIY PiKVM V1

  • Learn about the basics of working with PiKVM.

  • Explore the features of PiKVM using the site's table of contents.

  • If you encounter a problem, take a look at the FAQ, but if nothing helped, feel free to contact our Support - many of experienced users and the PiKVM team will definitely help you.

"},{"location":"#links","title":"Links","text":"
  • Website: https://pikvm.org
  • GitHub: https://github.com/pikvm
  • Discord:
  • Reddit:
  • Forum
"},{"location":"3d_printing/","title":"Cases for 3D printing","text":""},{"location":"3d_printing/#pikvm-v3-hat-cases","title":"PiKVM V3 HAT cases","text":"
  • v3.3 model (Kickstarter, Store)
  • Unofficial but great v3.3 case mod for Noctua fan
  • v3.2 model (Pre-release)
"},{"location":"3d_printing/#diy-cases","title":"DIY cases","text":"Model Notes https://www.thingiverse.com/thing:4799094 Case for the USB-C/PWR Splitter without Barrel jack https://www.thingiverse.com/thing:4931970 Raspberry Pi 4 Pi-KVM Case https://www.thingiverse.com/thing:4862304 Case for PiKVM (LCD + ATX) https://www.thingiverse.com/thing:4868258 R4C3R - Low Profile PCIe bracket for PiKVM based on Raspberry Pi Zero + Lusya + ATX controls https://www.thingiverse.com/thing:4866005 R4C3R - Full Profile PCIe bracket for PiKVM based on Raspberry Pi Zero + Lusya + ATX controls https://www.thingiverse.com/thing:4832248 Case for the USB-C/PWR Splitter without Barrel jack and HDMI-CSI bridge https://www.thingiverse.com/thing:4916230 A very compact case without internal power splitter https://www.thingiverse.com/thing:4915627 ZeroW + CSI case https://www.thingiverse.com/thing:4950281 PiKVM RETRO Case for CSI-2 C779 Bridge w/ OLED Display Screen https://www.thingiverse.com/thing:4950280 USB Power Blocker Case https://www.thingiverse.com/thing:4642116 Conix's PI-KVM case for v2 https://www.thingiverse.com/thing:7148243 Wall mount for PiKVM v3"},{"location":"api/","title":"HTTP API reference","text":"

This document describes the PiKVM API. Since the system consists of microservices, here is a common API with a common entry point provided by Nginx. The below examples use curl and websocat with the -k option disables SSL certificate verification, since the self-signed certificateis are used in the default installation.

There is a third-party library for using the PiKVM API. Please note that this is an unofficial library, so use it carefully.

"},{"location":"api/#authentication","title":"Authentication","text":"

All APIs are restricted to authentication. To make requests, you either need to auth each request individually, or get a token and pass it as a cookie with each request.

With enabled 2FA, you will need to add the one-time code to the password without spaces. That is, if the password is foobar and the code is 123456, then you need to use foobar123456 as the password.

The code can be generated using any TOTP library, for example in Python:

import requests\nimport pyotp\n\nuser = \"admin\"\npasswd = \"admin\"\nsecret = \"3OBBOGSJRYRBZH35PGXURM4CMWTH3WSU\"  # Can be found in /etc/kvmd/totp.secret\n\nprint(requests.get(\n    url=\"https://pikvm/api/info\",\n    verify=False,  # For self-signed SSL certificate\n    headers={\n        \"X-KVMD-User\": user,\n        \"X-KVMD-Passwd\": passwd + pyotp.TOTP(secret).now(),\n    },\n).text)\n

Since in the borderline case of the 2FA code lifetime, the code may be invalid, it makes sense to either handle error 403 by repeating the request in seconds.

A more correct way is to combine this method and check the remaining lifetime and postpone the request if there is a second or so left. You can find out how much time is left in this way:

totp = pyotp.TOTP(secret)\nnow = int(time.time())\nremaining = now - (now % totp.interval)\n
"},{"location":"api/#single-request-authentication","title":"Single-request authentication","text":"

There are two options here:

  • Using X-headers. Just pass X-KVMD-User and X-KVMD-Passwd with the request:

    $ curl -k -H X-KVMD-User:admin -H X-KVMD-Passwd:admin https://<pikvm-ip>/api/auth/check\n
  • Using HTTP Basic Auth. Please note: contrary to the standard, this method DOES NOT use the WWW-Authenticate header. HTTP Basic Auth in this implementation is intended only for compatibility with other systems, such as Prometheus.

    $ curl -k -u admin:admin https://<pikvm-ip>/api/auth/check\n
"},{"location":"api/#session-based-cookie-auth","title":"Session-based cookie auth","text":"
  1. Get the access token for the user using POST /api/auth/login:

    $ curl -k -v -X POST --data user=admin --data passwd=admin https://pikvm/api/auth/login\n...\n< Set-Cookie: auth_token=796cb83b11de4fcb749bc1bad14a91fb06dede84672b2f847fef1e988e6900de; Path=/\n...\n

    On success the cookie auth_token will be received with 200 OK. On invalid user or password you will get 403 Forbidden.

  2. The handle GET /api/auth/check can be used for check the auth status. Return of 200 OK will signal that user is authenticated. If the token or any of the single-request auth methods are missing, 401 Unauthorized will be returned. In case of incorrect credentials or token, 403 Forbidden will be returned.

  3. The handle POST /api/auth/logout can be used to invalidate session token. The response codes will be similar to the previous handle.

"},{"location":"api/#session-based-login-using-html-form","title":"Session-based login using HTML form","text":"

You can submit PiKVM credentials from another site and go directly to the KVM page by passing the redirect parameter as follows:

<html>\n<body>\n    <form method=\"POST\" action=\"https://pikvm/api/auth/login\">\n        <input name=\"user\" value=\"admin\">\n        <input name=\"passwd\" value=\"admin\">\n        <input name=\"expire\" value=\"0\">\n        <input name=\"redirect\" value=\"/kvm/\"> <!-- Available since KVMD 4.108 -->\n        <button type=\"submit\">Open PiKVM</button>\n    </form>\n</body>\n<html>\n
"},{"location":"api/#websocket-events","title":"WebSocket events","text":"

Most of the data during the user's work with PiKVM is transmitted over WebSocket. This includes mouse events, keyboard input, and changing the state of the various subsystems (such as ATX and Mass Storage Drive). Each event type will be described in the corresponding paragraph for its component. When connecting via WebSocket, the client receives current states as separate events. Then, as the states change, it will receive new events.

In a normal situation, opening a socket session triggers the video streamer to start. The streamer works as long as there is at least one client connected via WebSocket. After the last connection is closed and the client timeout expires, the streamer will also be terminated.

It is possible create a session that will not start the streamer and will not be counted when counting clients to stop the streamer. To do this, use the URL parameter stream=0:

$ websocat -k wss://<pikvm-ip>/api/ws?stream=0 -H X-KVMD-User:admin -H X-KVMD-Passwd:admin\n
Output with initial events
{\"event_type\": \"gpio_model_state\", \"event\": {\"scheme\": {\"inputs\": {\"led1\": {\"hw\": {\"driver\": \"__gpio__\", \"pin\": 19}}, \"led2\": {\"hw\": {\"driver\": \"__gpio__\", \"pin\": 16}}}, \"outputs\": {\"button1\": {\"switch\": false, \"pulse\": {\"delay\": 0.1, \"min_delay\": 0.1, \"max_delay\": 0.1}, \"hw\": {\"driver\": \"__gpio__\", \"pin\": 26}}, \"button2\": {\"switch\": false, \"pulse\": {\"delay\": 0.1, \"min_delay\": 0.1, \"max_delay\": 0.1}, \"hw\": {\"driver\": \"__gpio__\", \"pin\": 20}}, \"relay1\": {\"switch\": true, \"pulse\": {\"delay\": 0.1, \"min_delay\": 0.1, \"max_delay\": 0.1}, \"hw\": {\"driver\": \"relay\", \"pin\": 0}}, \"relay2\": {\"switch\": true, \"pulse\": {\"delay\": 2.0, \"min_delay\": 0.1, \"max_delay\": 5.0}, \"hw\": {\"driver\": \"relay\", \"pin\": 1}}}}, \"view\": {\"header\": {\"title\": \"Switches\"}, \"table\": [[{\"type\": \"label\", \"text\": \"Generic GPIO leds\"}], null, [{\"type\": \"label\", \"text\": \"Test 1:\"}, {\"type\": \"input\", \"channel\": \"led1\", \"color\": \"green\"}, {\"type\": \"output\", \"channel\": \"button1\", \"text\": \"Click\"}], [{\"type\": \"label\", \"text\": \"Test 2:\"}, {\"type\": \"input\", \"channel\": \"led2\", \"color\": \"green\"}, {\"type\": \"output\", \"channel\": \"button2\", \"text\": \"Click\"}], null, [{\"type\": \"label\", \"text\": \"HID Relays /dev/hidraw0\"}], null, [{\"type\": \"label\", \"text\": \"Relay #1:\"}, {\"type\": \"output\", \"channel\": \"relay1\", \"text\": \"Boop 0.1\"}], [{\"type\": \"label\", \"text\": \"Relay #2:\"}, {\"type\": \"output\", \"channel\": \"relay2\", \"text\": \"Boop 2.0\"}]]}}}\n{\"event_type\": \"info_extras_state\", \"event\": {\"vnc\": {\"name\": \"VNC\", \"description\": \"Show VNC information\", \"icon\": \"share/svg/vnc.svg\", \"path\": \"vnc\", \"keyboard_cap\": false, \"daemon\": \"kvmd-vnc\", \"port\": 5900, \"place\": 20, \"enabled\": true}, \"ipmi\": {\"name\": \"IPMI\", \"description\": \"Show IPMI information\", \"icon\": \"share/svg/ipmi.svg\", \"path\": \"ipmi\", \"keyboard_cap\": false, \"daemon\": \"kvmd-ipmi\", \"port\": 623, \"place\": 21, \"enabled\": true}}}\n{\"event_type\": \"info_hw_state\", \"event\": {\"platform\": {\"type\": \"rpi\", \"base\": \"Virtual Raspberry Pi\"}, \"health\": {\"temp\": {\"cpu\": 36.511, \"gpu\": 35.0}, \"throttling\": {\"raw_flags\": 0, \"parsed_flags\": {\"undervoltage\": {\"now\": false, \"past\": false}, \"freq_capped\": {\"now\": false, \"past\": false}, \"throttled\": {\"now\": false, \"past\": false}}}}}}\n{\"event_type\": \"info_meta_state\", \"event\": {\"server\": {\"host\": \"localhost.localdomain\"}, \"kvm\": {}}}\n{\"event_type\": \"info_system_state\", \"event\": {\"kvmd\": {\"version\": \"1.102\"}, \"streamer\": {\"app\": \"ustreamer\", \"version\": \"1.25\", \"features\": {\"WITH_OMX\": false, \"WITH_GPIO\": false, \"WITH_PTHREAD_NP\": true, \"WITH_SETPROCTITLE\": true, \"HAS_PDEATHSIG\": true}}, \"kernel\": {\"system\": \"Linux\", \"release\": \"5.8.10-arch1-1\", \"version\": \"#1 SMP PREEMPT Thu, 17 Sep 2020 18:01:06 +0000\", \"machine\": \"x86_64\"}}}\n{\"event_type\": \"wol_state\", \"event\": {\"enabled\": false, \"target\": {\"ip\": \"255.255.255.255\", \"port\": 9, \"mac\": \"\"}}}\n{\"event_type\": \"gpio_state\", \"event\": {\"inputs\": {\"led1\": {\"online\": true, \"state\": false}, \"led2\": {\"online\": true, \"state\": false}}, \"outputs\": {\"button1\": {\"online\": true, \"state\": false, \"busy\": false}, \"button2\": {\"online\": true, \"state\": false, \"busy\": false}, \"relay1\": {\"online\": false, \"state\": false, \"busy\": false}, \"relay2\": {\"online\": false, \"state\": false, \"busy\": false}}}}\n{\"event_type\": \"hid_state\", \"event\": {\"online\": true, \"keyboard\": {\"online\": true, \"leds\": {\"caps\": false, \"scroll\": false, \"num\": false}}, \"mouse\": {\"online\": true}}}\n{\"event_type\": \"atx_state\", \"event\": {\"enabled\": true, \"busy\": false, \"leds\": {\"power\": false, \"hdd\": false}}}\n{\"event_type\": \"msd_state\", \"event\": {\"enabled\": true, \"online\": true, \"busy\": false, \"storage\": {\"size\": 234950152192, \"free\": 23514271744, \"images\": {}, \"uploading\": false}, \"drive\": {\"image\": null, \"connected\": false, \"cdrom\": true}, \"features\": {\"multi\": true, \"cdrom\": true}}}\n{\"event_type\": \"streamer_state\", \"event\": {\"limits\": {\"max_fps\": 40}, \"params\": {\"desired_fps\": 30, \"quality\": 80}, \"snapshot\": {\"saved\": null}, \"streamer\": null, \"features\": {\"quality\": true, \"resolution\": false}}}\n{\"event_type\": \"loop\", \"event\": {}}\n

After connecting the client receives a bundle of states of all KVMD subsystems. After the batch is completed, it sends a loop event, which means that the websocket has entered event loop mode. Now it will send new states and respond to client's requests.

Another type of event is ping, which can be sent by the client: {\"event_type\": \"ping\", \"event\": {}}. If the server is running, it will respond with pong: {\"event_type\": \"pong\", \"event\": {}}.

Sending key events using Python

For keypresses, set event_type to key and fill in the event structure with key and state, where key is the key from mapping and state is boolean that determines if the key is pressed or released:

# python, install websocket-client\nimport websocket\nimport ssl, time\nuri = \"wss://10.0.0.7/api/ws?stream=0\"\nheaders = {\"X-KVMD-User\": \"admin\", \"X-KVMD-Passwd\": \"admin\"}\nws = websocket.WebSocket(sslopt={\"cert_reqs\": ssl.CERT_NONE})\nws.connect(uri, header=headers)\n# Key codes: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values\nws.send('{\"event_type\": \"key\", \"event\": {\"key\": \"Enter\", \"state\": true}}')\ntime.sleep(0.05)\nws.send('{\"event_type\": \"key\", \"event\": {\"key\": \"Enter\", \"state\": false}}')\nws.close()\n
"},{"location":"api/#system-functions","title":"System functions","text":""},{"location":"api/#get-system-info","title":"Get system info","text":"

Method: GET

Route: /api/info

Description: Returns the general information about the PiKVM device.

Query parameters:

Parameter Type Optionality Description Acceptable values fields string optional Return only specified categories auth, extras, fan, hw, meta, system

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/info?fields=hw\n
Example output
{\n    \"ok\": true,\n    \"result\": {\n        \"hw\": {\n            \"health\": {\n                \"cpu\": {\n                    \"percent\": 2\n                },\n                \"mem\": {\n                    \"available\": 1568993280,\n                    \"percent\": 14.6,\n                    \"total\": 1836331008\n                },\n                \"temp\": {\n                    \"cpu\": 45.277\n                },\n                \"throttling\": {\n                    \"ignore_past\": false,\n                    \"parsed_flags\": {\n                        \"freq_capped\": {\n                            \"now\": false,\n                            \"past\": false\n                        },\n                        \"throttled\": {\n                            \"now\": false,\n                            \"past\": false\n                        },\n                        \"undervoltage\": {\n                            \"now\": false,\n                            \"past\": false\n                        }\n                    },\n                    \"raw_flags\": 0\n                }\n            },\n            \"platform\": {\n                \"base\": \"Raspberry Pi 4 Model B Rev 1.5\",\n                \"board\": \"rpi4\",\n                \"model\": \"v3\",\n                \"serial\": \"10000000C8DA432D\",\n                \"type\": \"rpi\",\n                \"video\": \"hdmi\"\n            }\n        }\n    }\n}\u23ce  \n

Each category is represented by its own event in the websocket (info_hw_state, info_system_state, etc). The event content has the same format as the category content in the API.

"},{"location":"api/#get-system-log","title":"Get system log","text":"

Method: GET

Route: /api/log

Description: Displays logs from all KVMD services as plain text.

Parameter Type Optionality Description Acceptable values follow boolean optional Turns the request into long-polling mode and follow log messages in real time Enable: 1, true, or yes. Disable: 0, false, or no seek integer optional Runs the log for the specified time in seconds \u22650

Example of use: the following query returns commit messages for the last 1 hour and enables the long-polling mode:

$ curl -k -u admin:admin 'https://<pikvm-ip>/api/log?follow=1&seek=3600'\n
Example output
[2025-06-10 22:38:07 kvmd.service] --- kvmd.apps.kvmd.auth               INFO --- Authorized user 'admin' via auth service 'htpasswd'\n[2025-06-10 22:38:15 kvmd.service] --- kvmd.apps.kvmd.auth               INFO --- Authorized user 'admin' via auth service 'htpasswd'\n
"},{"location":"api/#hid","title":"HID","text":"

The PiKVM HID (Human Interface Device) API provides remote control capabilities for keyboard and mouse input devices. It allows users to perform the following operations:

  • Get the device state and set/reset parameters.
  • Send keyboard shortcuts and text to be typed in the host system.
  • Send various mouse events: move to absolute coordinates and relatively, click virtual mouse buttons, and scroll the virtual mouse wheel.
"},{"location":"api/#get-devices-state","title":"Get devices state","text":"

Method: GET

Route: /api/hid

Description: Gets the current HID devices state.

Query parameters: none.

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/hid\n
Example output
{\n    \"ok\": true,\n    \"result\": {\n        \"busy\": false,\n        \"connected\": null,\n        \"enabled\": true,\n        \"jiggler\": {\n            \"active\": false,\n            \"enabled\": true,\n            \"interval\": 60\n        },\n        \"keyboard\": {\n            \"leds\": {\n                \"caps\": false,\n                \"num\": false,\n                \"scroll\": false\n            },\n            \"online\": false,\n            \"outputs\": {\n                \"active\": \"\",\n                \"available\": []\n            }\n        },\n        \"mouse\": {\n            \"absolute\": true,\n            \"online\": false,\n            \"outputs\": {\n                \"active\": \"usb\",\n                \"available\": [\n                    \"usb\",\n                    \"usb_rel\"\n                ]\n            }\n        },\n        \"online\": true\n    }\n}\u23ce\n
"},{"location":"api/#set-parameters","title":"Set parameters","text":"

Method: POST

Route: /api/hid/set_params

Description: Configures HID device parameters, such as the type of emulated keyboard and mouse.

Query parameters:

Parameter Type Optionality Description Acceptable values keyboard_output string optional Sets the type of the emulated keyboard usb, ps2, disabled mouse_output string optional Sets the type of the emulated mouse usb, usb_win98, usb_rel, ps2, disabled jiggler boolean optional Enable/disable mouse jiggler functionality true

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/hid/set_params?jiggler=0\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce \n
"},{"location":"api/#set-the-connected-state","title":"Set the connected state","text":"

Method: POST

Route: /api/hid/set_connected

Description: Sets the HID devices connection state.

Query parameters:

Parameter Type Optionality Description Acceptable values connected boolean required Sets the connection state Enable: 1, true, or yes. Disable: 0, false, or no

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/hid/set_connected?connected=0\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce \n
"},{"location":"api/#reset-devices-state","title":"Reset devices' state","text":"

Method: POST

Route: /api/hid/reset

Description: Resets HID devices to their initial state.

Query parameters: none

Example of use:

$ curl -k -X POST -u admin:admin https://<pikvm-ip>/api/hid/reset\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce   \n
"},{"location":"api/#get-keyboard-layouts","title":"Get keyboard layouts","text":"

Method: GET

Route: /api/hid/keymaps

Description: Gets available keyboard layouts and the current defaults for use with POST /api/hid/print.

Query parameters: none

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/hid/keymaps\n
Example output
{\n    \"ok\": true,\n    \"result\": {\n        \"keymaps\": {\n            \"available\": [\n                \"ar\",\n                \"bepo\",\n                \"cz\",\n                \"da\",\n                \"de\",\n                \"de-ch\",\n                \"en-gb\",\n                \"en-us\",\n                \"en-us-altgr-intl\",\n                \"en-us-colemak\",\n                \"es\",\n                \"et\",\n                \"fi\",\n                \"fo\",\n                \"fr\",\n                \"fr-be\",\n                \"fr-ca\",\n                \"fr-ch\",\n                \"hr\",\n                \"hu\",\n                \"is\",\n                \"it\",\n                \"ja\",\n                \"lt\",\n                \"lv\",\n                \"mk\",\n                \"nl\",\n                \"no\",\n                \"pl\",\n                \"pt\",\n                \"pt-br\",\n                \"ru\",\n                \"sl\",\n                \"sv\",\n                \"th\",\n                \"tr\"\n            ],\n            \"default\": \"de\"\n        }\n    }\n}\u23ce \n
"},{"location":"api/#type-text-remotely","title":"Type text remotely","text":"

Method: POST

Route: /api/hid/print

Description: Transmits user-defined text to emulate typing it on the PiKVM by sequencing key presses.

Query parameters:

Parameter Type Optionality Description Acceptable values limit integer optional Maximum characters to process 0 = no limit. No maximum value. Default: 1024 keymap string optional Keymap to use (defaults to system default) Any keymap listed in the output of GET /hid/keymaps slow boolean optional Enables slow typing mode (regular large intervals between key presses), false by default Enable: 1, true, or yes. Disable: 0, false, or no delay float optional How many seconds to delay the transmission of keys by in the slow mode. Defaults to 0.02 when slow is enabled, otherwise defaults to 0 0..5.0

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    -d \"Einige Worte\" \\\n    https://<pikvm-ip>/api/hid/print?keymap=de\n
Example output
{\n\"ok\": true,\n\"result\": {}\n}\u23ce \n
"},{"location":"api/#send-a-keyboard-shortcut","title":"Send a keyboard shortcut","text":"

Method: POST

Route: /api/hid/events/send_shortcut

Description: Sends a keyboard shortcut, or key combination, to be typed on the PiKVM.

Query parameters:

Parameter Type Optionality Description Acceptable values keys string required Comma-separated list of key names For a full list of supported values, please see here. Use values from the web_name column

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/hid/events/send_shortcut?keys=ControlLeft,KeyL\n
Example output
{\n\"ok\": true,\n\"result\": {}\n}\u23ce\n
"},{"location":"api/#send-a-single-key-event","title":"Send a single key event","text":"

Method: POST

Route: /api/hid/events/send_key

Description: Transmits a command to emulate a single key press on the PiKVM.

Query parameters:

Parameter Type Optionality Description Acceptable values key string required Key identifier to send For a full list of supported values, please see here state boolean optional Key state: true for press, false for release Enable: 1, true, or yes. Disable: 0, false, or no finish boolean optional Releases non-modifier keys right after pressing them so that they don't get stuck when the connection is not stable. Defaults to false Enable: 1, true, or yes. Disable: 0, false, or no

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/hid/events/send_key?key=Delete\n
Example output
{\n\"ok\": true,\n\"result\": {}\n}\u23ce\n
"},{"location":"api/#send-mouse-button-events","title":"Send mouse button events","text":"

Method: POST

Route: /api/hid/events/send_mouse_button

Description: Sends mouse button press/release events.

Query parameters:

Parameter Type Optionality Description Acceptable values button string required Mouse button identifier left, middle, right, up, down state boolean optional Mouse button state: true for press, false for release Enable: 1, true, or yes. Disable: 0, false, or no

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/hid/events/send_mouse_button?button=left\n
Example output
{\n\"ok\": true,\n\"result\": {}\n}\u23ce\n
"},{"location":"api/#move-the-mouse-pointer","title":"Move the mouse pointer","text":"

Method: POST

Route: /api/hid/events/send_mouse_move

Description: Sends a command to move the mouse pointer to user-defined coordinates where 0,0 is the center of the screen. Only works if the mouse mode is set to absolute in the configuration.

Query parameters:

Parameter Type Optionality Description Acceptable values to_x integer required Target X coordinate Any negative or positive integer value to_y integer required Target Y coordinate Any negative or positive integer value

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/hid/send_mouse_move?to_x=0&to_y=50'\n
Example output
{\n\"ok\": true,\n\"result\": {}\n}\u23ce  \n
"},{"location":"api/#move-the-mouse-ppinter-relatively","title":"Move the mouse ppinter relatively","text":"

Method: POST

Route: /api/hid/events/send_mouse_relative

Description: Sends a command to move the mouse pointer by a relative offset in pixels. Only works if the mouse mode is set to absolute in the configuration.

Query parameters:

Parameter Type Optionality Description Acceptable values delta_x integer required Horizontal movement delta Any negative or positive integer value delta_y integer required Vertical movement delta Any negative or positive integer value

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/hid/send_mouse_relative?delta_x=20&delta_y=200'\n
Example output
{\n\"ok\": true,\n\"result\": {}\n}\u23ce  \n
"},{"location":"api/#send-mouse-wheel-scroll-events","title":"Send mouse wheel scroll events","text":"

Method: POST

Route: /api/hid/events/send_mouse_wheel

Description: Sends mouse wheel scroll events to be emulated on the host by PiKVM.

Query parameters:

Parameter Type Optionality Description Acceptable values delta_x integer required Horizontal scroll delta Any negative or positive integer value delta_y integer required Vertical scroll delta Any negative or positive integer value

Example of use: Sends mouse wheel scroll events.

$ curl -k -X POST \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/hid/send_mouse_wheel?delta_x=0&delta_y=200'\n
Example output
{\n\"ok\": true,\n\"result\": {}\n}\u23ce  \n
"},{"location":"api/#atx-power-management","title":"ATX power management","text":"

The PiKVM ATX API provides control over ATX (Advanced Technology eXtended) power management functions. It allows users perform the following operations:

  • Get the current ATX state.
  • Change the ATX state.
  • Send an ATX button press event.
"},{"location":"api/#get-atx-state","title":"Get ATX state","text":"

Method: GET

Route: /api/atx

Description: Shows the current ATX state

Query parameters: None.

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/atx\n
Example output
{\n    \"ok\": true,\n    \"result\": {\n        \"busy\": false, // True if ATX is busy performing an operation and does not accept commands\n        \"enabled\": true,\n        \"leds\": {\n            \"hdd\": false,\n            \"power\": false\n        }\n    }\n}\n
"},{"location":"api/#set-atx-power","title":"Set ATX power","text":"

Method: POST

Route: /api/atx/power

Description: Changes the ATX power state to desired.

Query parameters:

Parameter Type Optionality Description Acceptable values action string optional Specifies desired state on - Turn on (do nothing in case PSU is already on). off - Turn off (aka soft-off), emulates click on the power button. off_hard - Perform long press on the power button (5+ seconds). reset_hard - Emulate pressing reset button (hardware hot reset) wait boolean optional Says if call should return immediately or just after finishing operation. Enable: 1, true, or yes. Disable: 0, false, or no

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/atx/power?action=on\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce\n
"},{"location":"api/#click-atx-button","title":"Click ATX button","text":"

Method: POST

Route: /api/atx/click

Description: Sends the ATX button press event.

Query parameters:

Parameter Type Optionality Description Acceptable values button string optional Specifies the desired PC case button power - Short click on the power button. power_long - Long press on the power button (5+ seconds). reset - Short click on the reset button. wait boolean optional Says if call should return immediately or just after finishing operation. Enable: 1, true, or yes. Disable: 0, false, or no

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/atx/click?button=power\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce   \n
"},{"location":"api/#mass-storage-drive","title":"Mass Storage Drive","text":"

The PiKVM Mass Storage Drive API provides controls for remote management of disk images that can be mounted as virtual storage devices. It allows users perform the following operations:

  • Get current MSD status and configuration
  • Upload, download, and delete disk images
  • Fetch disk images directly from URLs with progress streaming
  • Connect/disconnect virtual storages, enable CD-ROM and read-write modes
  • Set image names, access modes, and device type settings
"},{"location":"api/#get-msd-state","title":"Get MSD state","text":"

Method: GET

Route: /api/msd

Description: Retrieves the current state of the Mass Storage Device.

Query parameters: None.

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/msd\n
Example output
{\n    \"ok\": true,\n    \"result\": {\n        \"busy\": false,\n        \"drive\": {\n            \"cdrom\": true,\n            \"connected\": false,\n            \"image\": null,\n            \"rw\": false\n        },\n        \"enabled\": true,\n        \"online\": true,\n        \"storage\": {\n            \"downloading\": null,\n            \"images\": {},\n            \"parts\": {\n                \"\": {\n                    \"free\": 24358789120,\n                    \"size\": 24375590912,\n                    \"writable\": true\n                }\n            },\n            \"uploading\": null\n        }\n    }\n}\u23ce\n
"},{"location":"api/#upload-msd-image","title":"Upload MSD image","text":"

Method: POST

Route: /api/msd/write

Description: uploads an ISO to the Mass Storage Device.

Query parameters:

Parameter Type Optionality Description Acceptable values image string required Specifies the name of the image. Binary data should be passed to the POST body filename.iso

Example of use:

$ # create a test image\n$ dd if=/dev/zero of=test.iso bs=1M count=1\n\n$ # upload it to pikvm\n$ curl -v -X POST --data-binary @test.iso -k \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/msd/write?image=test.iso\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce   \n
"},{"location":"api/#upload-msd-image-by-url","title":"Upload MSD image by URL","text":"

Method: POST

Route: /api/msd/write_remote

Description: Downloads an image from HTTP(S) URL to the MSD.

Note

This is a long-polling request. Do not interrupt the request until the download is complete, otherwise the download will stop.

Query parameters:

Parameter Type Optionality Description Acceptable values url string required Image URL Any URL using HTTP(S) image string optional Image name Any alphanumeric name like image321.iso timeout integer optional Remote request timeout, 10 seconds by default \u22650

Example of use:

$ # create test image\n$ dd if=/dev/zero of=test.iso bs=1M count=1\n\n$ # upload it to pikvm\n$ curl -v -X POST -k \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/msd/write_remote?url=http://example.com/test.iso\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce   \n
"},{"location":"api/#set-msd-parameters","title":"Set MSD parameters","text":"

Method: POST

Route: /api/msd/set_params

Description: Changes the current image and/or set drive parameters.

Query parameters:

Parameter Type Optionality Description Acceptable values image string optional Change the current image filename.iso cdrom boolean optional Change the media type to the CD-ROM or Flash. 1 (CD-ROM) or 0 (Flash) rw boolean optional Sets read-write or read-only mode. Ignored (always read-only) when cdrom=1 1 (read-write) or 0 (read-only)

Example of use:

$ curl -X POST -k \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/msd/set_params?image=test.iso&cdrom=1'\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce   \n
"},{"location":"api/#control-msd","title":"Control MSD","text":"

Method: POST

Route: /api/msd/set_connected

Description: Connects or disconnects the MSD to/from the host.

Query parameters:

Parameter Type Optionality Description Acceptable values connected boolean required Changes the state 1 connects the MSD, 0 disconnects it

Example of use:

$ curl -X POST -k \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/msd/set_connected?connected=1\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce   \n
"},{"location":"api/#remove-msd-image","title":"Remove MSD image","text":"

Method: POST

Route: /api/msd/remove

Description: Removes the specified image.

Query parameters:

Parameter Type Optionality Description Acceptable values image string required Name of the image to remove filename.iso

Example of use:

$ curl -X POST -k \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/msd/remove?image=test.iso\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce   \n
"},{"location":"api/#reset-msd","title":"Reset MSD","text":"

Method: POST

Route: /api/msd/reset

Description: Drops all the custom parameters you set before and resets the Mass Storage Device to its default state.

Query parameters: None.

Example of use:

$ curl -X POST -k \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/msd/reset\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce   \n
"},{"location":"api/#gpio","title":"GPIO","text":"

This is a PiKVP API for controlling User GPIO (General Purpose Input/Output) pins. It allows users perform the following operations:

  • Read GPIO states.
  • Switch pins on/off.
  • Send pulses to GPIO channels.
"},{"location":"api/#get-gpio-state","title":"Get GPIO state","text":"

Method: GET

Route: /api/gpio

Description: Retrieves the current state of all GPIO channels.

Query parameters: None.

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/gpio\n
Example output
{\n    \"ok\": true,\n    \"result\": {\n        \"model\": {\n            \"scheme\": {\n                \"inputs\": {},\n                \"outputs\": {\n                    \"__v3_usb_breaker__\": {\n                        \"hw\": {\n                            \"driver\": \"__gpio__\",\n                            \"pin\": \"5\"\n                        },\n                        \"pulse\": {\n                            \"delay\": 0.0,\n                            \"max_delay\": 0.0,\n                            \"min_delay\": 0.0\n                        },\n                        \"switch\": true\n                    }\n                }\n            },\n            \"view\": {\n                \"header\": {\n                    \"title\": [\n                        {\n                            \"text\": \"GPIO\",\n                            \"type\": \"label\"\n                        }\n                    ]\n                },\n                \"table\": []\n            }\n        },\n        \"state\": {\n            \"inputs\": {},\n            \"outputs\": {\n                \"__v3_usb_breaker__\": {\n                    \"busy\": false,\n                    \"online\": true,\n                    \"state\": true\n                }\n            }\n        }\n    }\n}\u23ce \n
"},{"location":"api/#switch-gpio-channel","title":"Switch GPIO channel","text":"

Method: POST

Route: /gpio/switch

Description: Sets a GPIO channel to a specific state (on/off).

Query parameters:

Parameter Type Optionality Description Acceptable values channel string required The GPIO driver channel Alphanumeric channel name, e.g., __v3_usb_breaker__ state boolean required The new switch state 1 to switch on, 0 to switch off wait boolean optional Defines when a call should return 1 return immediately, 0 return after finishing operation

Example of use:

# Switch GPIO channel led1 to OFF state without waiting\n$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/gpio/switch?channel=led1&state=0&wait=0\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce\n
"},{"location":"api/#pulse-gpio-channel","title":"Pulse GPIO channel","text":"

Method: POST

Route: /api/gpio/pulse

Description: Sends a pulse signal to a GPIO channel (briefly activates then deactivates). Only works for channels that support the pulse mode.

Query parameters:

Parameter Type Optionality Description Acceptable values channel string required The GPIO driver channel Alphanumeric channel name, e.g., led1 delay float optional The pulse time in seconds Any float number, 0 for default delay wait boolean optional Defines when a call should return 1 return immediately, 0 return after finishing operation

Example of use:

# Send a pulse to GPIO channel led1 with 2 sec delay without waiting\n$ curl -k -X POST \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/gpio/pulse?channel=led1&delay=2.0&wait=0'\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce\n
"},{"location":"api/#streamer","title":"Streamer","text":"

The PiKVM Streamer API provides remote access to video stream capture and management functionality of PiKVM devices. It allows users perform the following operations:

  • Capture screenshots.
  • Perform optical character recognition (OCR) on captured images.
  • Monitor the streamer's operational status.
"},{"location":"api/#get-streamer-state","title":"Get streamer state","text":"

Method: GET

Route: /api/streamer

Description: Retrieves the current state of the streamer.

Query parameters: None

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/streamer\n
Example output
{\n    \"ok\": true,\n    \"result\": {\n        \"features\": {\n            \"h264\": true,\n            \"quality\": true,\n            \"resolution\": false\n        },\n        \"limits\": {\n            \"desired_fps\": {\n                \"max\": 70,\n                \"min\": 0\n            },\n            \"h264_bitrate\": {\n                \"max\": 20000,\n                \"min\": 25\n            },\n            \"h264_gop\": {\n                \"max\": 60,\n                \"min\": 0\n            }\n        },\n        \"params\": {\n            \"desired_fps\": 40,\n            \"h264_bitrate\": 5000,\n            \"h264_gop\": 30,\n            \"quality\": 80\n        },\n        \"snapshot\": {\n            \"saved\": null\n        },\n        \"streamer\": {\n            \"encoder\": {\n                \"quality\": 80,\n                \"type\": \"M2M-IMAGE\"\n            },\n            \"h264\": {\n                \"bitrate\": 5000,\n                \"fps\": 60,\n                \"gop\": 30,\n                \"online\": true\n            },\n            \"instance_id\": \"\",\n            \"sinks\": {\n                \"h264\": {\n                    \"has_clients\": true\n                },\n                \"jpeg\": {\n                    \"has_clients\": false\n                }\n            },\n            \"source\": {\n                \"captured_fps\": 59,\n                \"desired_fps\": 40,\n                \"online\": true,\n                \"resolution\": {\n                    \"height\": 720,\n                    \"width\": 1280\n                }\n            },\n            \"stream\": {\n                \"clients\": 0,\n                \"clients_stat\": {},\n                \"queued_fps\": 0\n            }\n        }\n    }\n}\u23ce  \n
"},{"location":"api/#take-snapshot","title":"Take snapshot","text":"

Method: GET

Route: /api/streamer/snapshot

Description: Captures a snapshot from the video stream. Can optionally perform OCR text recognition or generate a preview image. For optical character recognition, the coordinates origin starts at top left.

Query parameters:

Parameter Type Optionality Description Acceptable values save boolean optional Whether to save the snapshot, default: false Enable: 1, true, or yes. Disable: 0, false, or no load boolean optional Whether to load an existing snapshot, default: false Enable: 1, true, or yes. Disable: 0, false, or no allow_offline boolean optional Whether to allow taking snapshots when offline, default: false Enable: 1, true, or yes. Disable: 0, false, or no ocr boolean optional Whether to perform OCR text recognition on the snapshot, default: false Enable: 1, true, or yes. Disable: 0, false, or no ocr_langs string optional Comma-separated list of language codes for OCR recognition Typically, a 3-letter code, such as eng for English or deu for German. Run pacman -Ss tesseract-data on PiKVM to get the full list ocr_left integer optional X coordinate of the top left corner of the OCR region, default: -1 \u22650 ocr_top integer optional Y coordinate of the top left corner of the OCR region, default: -1 \u22650 ocr_right integer optional Width of the OCR region, default: -1 \u22650 ocr_bottom integer optional Height of the OCR region, default: -1 \u22650 preview boolean optional Whether to generate a preview image, default: false Enable: 1, true, or yes. Disable: 0, false, or no preview_max_width integer optional Maximum width for preview image, default: 0 Any positive integer value preview_max_height integer optional Maximum height for preview image, default: 0 Any positive integer value preview_quality integer optional JPEG quality for preview (valid stream quality value), default: 80 Any integer value in the 0..100 range

Example of use: the following command will capture a snapshot of the current video stream and save it to a JPEG file.

$ curl -k \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/streamer/snapshot?save=1&preview_quality=95' \\\n    --output=file.jpg\n
Example output
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n                                 Dload  Upload   Total   Spent    Left  Speed\n100  107k  100  107k    0     0   619k      0 --:--:-- --:--:-- --:--:--  619k\n

Example of use: the following command will capture a region of the current video stream (left corner starts at the top left, extends 1000px to the right and 150px to the bottom), run it through Tesseract for optical character recognition (language defined as English), and output the recognized text into the console.

$ curl -k \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/streamer/snapshot?ocr=true&ocr_left=0&ocr_top=0&ocr_right=1000&ocr_bottom=150&ocr_langs=eng'\n

Responses:

  • When ocr=true:
    • Content-Type: text/plain
    • Body: Recognized text from the image
  • When preview=true or default:
    • Content-Type: image/jpeg
    • Body: JPEG image data (either preview or full snapshot)
  • When snapshot unavailable:
    • Status: 503 Service Unavailable
    • Error: UnavailableError
"},{"location":"api/#remove-snapshot","title":"Remove snapshot","text":"

Method: DELETE

Route: /api/streamer/snapshot

Description: Removes/deletes the current snapshot from memory.

Query parameters: None

Example of use:

$ curl -k -X DELETE \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/streamer/snapshot\n
Example output
{\n    \"ok\": true,\n    \"result\": {}\n}\u23ce \n
"},{"location":"api/#get-ocr-state","title":"Get OCR state","text":"

Method: GET

Route: /api/streamer/ocr

Description: Retrieves the current state and configuration of the optical character recognition (OCR) service.

Query parameters: None

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/streamer/ocr\n
Example output
{\n    \"ok\": true,\n    \"result\": {\n        \"ocr\": {\n            \"enabled\": true,\n            \"langs\": {\n                \"available\": [\n                    \"eng\",\n                    \"osd\"\n                ],\n                \"default\": [\n                    \"eng\"\n                ]\n            }\n        }\n    }\n}\u23ce\n
"},{"location":"api/#switch","title":"Switch","text":"

The PiKVM Switch API provides handles to control the PiKVM Switch: get information, set active ports, and control beacons.

The API heavily relies on specifying ports on the PiKVM Switch. There are two ways to do that: with continuous numbering or with float numbers. Both options are equally valid and supported.

  1. With continuous numbering, ports enumeration starts at 0 and ends at 19, because you can create up to 20 ports by adding more PiKVM Switch devices to the first Switch's downlink.
  2. If you use a float value, the integer part specifies the number of the unit in the downlink, while the fractional part specifies the number of the port on that unit.
"},{"location":"api/#get-switch-state","title":"Get Switch state","text":"

Method: GET

Route: /api/switch

Description: Returns the information about the PiKVM Switch state.

Query parameters: None.

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/switch\n
Example output
FIXME\n
"},{"location":"api/#set-active-port-previous","title":"Set active port (previous)","text":"

Method: POST

Route: /api/switch/set_active_prev

Description: Switches to the previous active port.

Query parameters: None.

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/switch/set_active_prev\n
Example output
FIXME\n
"},{"location":"api/#set-active-port-next","title":"Set active port (next)","text":"

Method: POST

Route: /api/switch/set_active_next

Description: Switches to the next active port.

Query parameters: None.

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/switch/set_active_next\n
Example output
FIXME\n
"},{"location":"api/#set-active-port-specific","title":"Set active port (specific)","text":"

Method: POST

Route: /api/switch/set_active

Description: Switches to a specific port.

Query parameters:

Parameter Type Optionality Description Acceptable values port float required Specifies the port number Integer in the 0..19 range or float (0,0 through 4,3)

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/switch/set_active?port=2,2\n
Example output
FIXME\n
"},{"location":"api/#set-beacon","title":"Set beacon","text":"

Method: POST

Route: /api/switch/set_beacon

Description: Controls beacon lights on ports or uplink/downlink units.

Query parameters:

Parameter Type Optionality Description Acceptable values state boolean required Turn beacon on/off Enable: 1, true, or yes. Disable: 0, false, or no port float optional Specify the port beacon Integer in the 0..19 range or float (0,0 through 4,3) uplink integer optional Number of the uplink beacon, same as the port Integer in the 0..19 range or float (0,0 through 4,3) downlink integer optional Number of the downlink beacon, same as the port Integer in the 0..19 range or float (0,0 through 4,3)

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/switch/set_beacon\n
Example output
FIXME\n
"},{"location":"api/#set-port-parameters","title":"Set port parameters","text":"

Method: POST

Route: /api/switch/set_port_params

Description: Configures parameters for a specific port.

Query parameters:

Parameter Type Optionality Description Acceptable values port float required Specifies the port number 0..19 edid_id string optional EDID identifier (allows default value) Alphanumeric string like ca3d7114-79ca-47fc-80b4-b80ac63fc329 dummy boolean optional When enabled, the switch will pretend the host has a display attached Enable: 1, true, or yes. Disable: 0, false, or no name string optional String port name, none set by default Any combination of ASCII letters and numbers atx_click_power_delay float optional ATX power click delay value 0..10 atx_click_power_long_delay float optional ATX long power click delay value 0..10 atx_click_reset_delay float optional ATX reset click delay value 0..10

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/switch/set_port_params?port=2&name=PORT3'\n
Example output
FIXME\n
"},{"location":"api/#set-beacon-color","title":"Set beacon color","text":"

Method: POST

Route: /api/switch/set_colors

Description: Sets the beacon color for the PiKVM Switch and all switches in the downlink (where applicable).

Query parameters:

Parameter Type Optionality Description Acceptable values beacon hex required Sets color, brightness, and blink interval (ms) A valid hex value (see example below)

Example of use: Let's set the beacon to be orange at 75% of full brightness, blinking with an interval of 40ms.

$ curl -k -X POST \\\n    -u admin:admin \\\n    -d \"FFA500:BF:0028\" \\\n    https://<pikvm-ip>/api/switch/set_colors\n
Example output
FIXME\n
"},{"location":"api/#reboot-the-device","title":"Reboot the device","text":"

Method: POST

Route: /api/switch/reset

Description: Reboots the PiKVM Switch with an option to enter the reflashing mode after the reboot.

Query parameters:

Parameter Type Optionality Description Acceptable values unit integer required Specifies the unit number 0..4 bootloader boolean optional Whether to enter the reflashing mode after rebooting, defaults to false Enable: 1, true, or yes. Disable: 0, false, or no

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/switch/reset?unit=0&bootloader=1'\n
Example output
FIXME\n
"},{"location":"api/#create-a-new-edid-configuration","title":"Create a new EDID configuration","text":"

Method: POST

Route: /api/switch/edids/create

Description: Creates a new EDID configuration from user-specified EDID name and data.

Query parameters:

Parameter Type Optionality Description Acceptable values name string required EDID name Alphanumeric name (see example below) data string required EDID data Hexadecimal string (see example below)

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/switch/edids/create?name=Gigabyte-GA-H77-DS3H&data=00FFFFFFFFFFFF0052628888008888881C150103800000780AEE91A3544C99260F505425400001000100010001000100010001010101D51B0050500019400820B80080001000001EEC2C80A070381A403020350040442100001E000000FC0050492D4B564D20566964656F0A000000FD00323D0F2E0F0000000000000000014D02030400DE0D20A03058122030203400F0B400000018E01500A04000163030203400000000000018B41400A050D011203020350080D810000018AB22A0A050841A3030203600B00E1100001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045'\n
Example output
FIXME\n
"},{"location":"api/#change-edid-configuration","title":"Change EDID configuration","text":"

Method: POST

Route: /api/switch/edids/change

Description: Modifies an existing EDID configuration.

Query parameters:

Parameter Type Optionality Description Acceptable values id string required EDID identifier Alphanumeric id (see example below) name string optional New EDID name Alphanumeric name (see example below) data string optional New EDID data Hexadecimal string (see example below)

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/switch/edids/change?id=ca3d7114-79ca-47fc-80b4-b80ac63fc329&name=Gigabyte-GA-H77-DS3H&data=00FFFFFFFFFFFF0052628888008888881C150103800000780AEE91A3544C99260F505425400001000100010001000100010001010101D51B0050500019400820B80080001000001EEC2C80A070381A403020350040442100001E000000FC0050492D4B564D20566964656F0A000000FD00323D0F2E0F0000000000000000014D02030400DE0D20A03058122030203400F0B400000018E01500A04000163030203400000000000018B41400A050D011203020350080D810000018AB22A0A050841A3030203600B00E1100001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045'\n
Example output
FIXME\n
"},{"location":"api/#remove-edid-configuration","title":"Remove EDID configuration","text":"

Method: POST

Route: /api/switch/edids/remove

Description: Deletes an EDID configuration.

Query parameters:

Parameter Type Optionality Description Acceptable values id string required EDID identifier Alphanumeric id (see example below)

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    https://<pikvm-ip>/api/switch/edids/remove?id=ca3d7114-79ca-47fc-80b4-b80ac63fc329\n
Example output
FIXME\n
"},{"location":"api/#atx-power-control","title":"ATX Power Control","text":"

Method: POST

Route: /api/switch/atx/power

Description: Controls ATX power states for a specific port.

Query parameters:

Parameter Type Optionality Description Acceptable values port float required Specifies the port number 0..19 action string required Power action on - Power on, off - Power off, off_hard - Hard power off, reset_hard - Hard reset

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/switch/atx/power?port=0&action=reset_hard'\n
Example output
FIXME\n
"},{"location":"api/#atx-button-click","title":"ATX Button Click","text":"

Method: POST

Route: /api/switch/atx/click

Description: Simulates ATX button clicks for a specific port.

Query parameters:

Parameter Type Optionality Description Acceptable values port float required Specifies the port number 0..19 button string required Power action power - Power button click, power_long - Long power button press, reset - Reset button click

Example of use:

$ curl -k -X POST \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/switch/atx/click?port=0&button=power_long'\n
Example output
FIXME\n
"},{"location":"api/#redfish","title":"Redfish","text":"

The PiKVM Redfish API implements the industry-standard DMTF Redfish specification for remote server control. It allows you to monitor and control the power of the target system.

Most endpoints require authentication using your PiKVM credentials. You can interact with the API using standard HTTP clients, curl, or the specialized Redfish tools.

"},{"location":"api/#root-service-discovery","title":"Root service discovery","text":"

Method: GET

Route: /api/redfish/v1

Description: Returns the basic Redfish service information and links to available resources. Doesn't require authentication.

Query parameters: None.

Example of use:

$ curl -k https://<pikvm-ip>/api/redfish/v1\n
Example output
{\n    \"@odata.id\": \"/redfish/v1\",\n    \"@odata.type\": \"#ServiceRoot.v1_6_0.ServiceRoot\",\n    \"Id\": \"RootService\",\n    \"Name\": \"Root Service\",\n    \"RedfishVersion\": \"1.6.0\",\n    \"Systems\": {\n        \"@odata.id\": \"/redfish/v1/Systems\"\n    }\n}\u23ce\n
"},{"location":"api/#systems-collection","title":"Systems collection","text":"

Method: GET

Route: /api/redfish/v1/Systems

Description: Returns collection of available computer systems.

Query parameters: None.

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/redfish/v1/Systems\n
Example output
{\n    \"@odata.id\": \"/redfish/v1/Systems\",\n    \"@odata.type\": \"#ComputerSystemCollection.ComputerSystemCollection\",\n    \"Members\": [\n        {\n            \"@odata.id\": \"/redfish/v1/Systems/0\"\n        }\n    ],\n    \"Members@odata.count\": 1,\n    \"Name\": \"Computer System Collection\"\n}\u23ce\n
"},{"location":"api/#individual-system-information","title":"Individual system information","text":"

Method: GET

Route: /api/redfish/v1/Systems/0

Description: Returns detailed information about the specific system, including power state, hostname, and available actions.

Query parameters: None.

Example of use:

$ curl -k -u admin:admin https://<pikvm-ip>/api/redfish/v1/Systems/0\n
Example output
{\n    \"@odata.id\": \"/redfish/v1/Systems/0\",\n    \"@odata.type\": \"#ComputerSystem.v1_10_0.ComputerSystem\",\n    \"Actions\": {\n        \"#ComputerSystem.Reset\": {\n            \"ResetType@Redfish.AllowableValues\": [\n                \"On\",\n                \"ForceOff\",\n                \"GracefulShutdown\",\n                \"ForceRestart\",\n                \"ForceOn\",\n                \"PushPowerButton\"\n            ],\n            \"target\": \"/redfish/v1/Systems/0/Actions/ComputerSystem.Reset\"\n        },\n        \"#ComputerSystem.SetDefaultBootOrder\": {\n            \"target\": \"/redfish/v1/Systems/0/Actions/ComputerSystem.SetDefaultBootOrder\"\n        }\n    },\n    \"Boot\": {\n        \"BootSourceOverrideEnabled\": \"Disabled\",\n        \"BootSourceOverrideTarget\": null\n    },\n    \"HostName\": \"pikvm\",\n    \"Id\": \"0\",\n    \"PowerState\": \"Off\"\n}\u23ce\n
"},{"location":"api/#system-configuration-update","title":"System configuration update","text":"

Method: PATCH

Route: /api/redfish/v1/Systems/0

Description: This handle was added to aid in scenarios where installing OKD (Kubernetes) using installer-provisioned infrastructure involves expecting two fields to be returned and the patch request to return a 204. Hence, this handle is currently a no-op that just returns success.

Query parameters: None

Example of use:

$ curl -k -X PATCH -u admin:admin https://<pikvm-ip>/api/redfish/v1/Systems/0\n

There will be zero output for this command by design.

Responses:

Code Description 204 Returns success"},{"location":"api/#system-power-control","title":"System power control","text":"

Method: POST

Route: /api/redfish/v1/Systems/0/Actions/ComputerSystem.Reset

Description: Performs power control actions on the system.

Query parameters: This handles expects JSON with ResetType in the request body and one of the following values:

  • On - Power on
  • ForceOff - Hard power off
  • GracefulShutdown - Graceful power off
  • ForceRestart - Hard reset
  • ForceOn - Force power on
  • PushPowerButton - Simulate power button press

Example of use:

$ curl -k -X POST \\\n    -H \"Content-Type: application/json\" \\\n    -u admin:admin \\\n    -d '{\"ResetType\": \"ForceRestart\"}' \\\n    https://<pikvm-ip>/api/redfish/v1/Systems/0/Actions/ComputerSystem.Reset\n

There will be zero output for this command by design.

Responses:

Code Description 204 Success 400 Invalid or missing ResetType"},{"location":"api/#misc","title":"Misc","text":""},{"location":"api/#get-prometheus-metrics","title":"Get Prometheus metrics","text":"

The GET /api/export/prometheus/metrics handle returns the Prometheus metrics. Also see here for details.

$ curl -k -u admin:admin https://<pikvm-ip>/api/export/prometheus/metrics\n
"},{"location":"api/#video","title":"Video","text":"

PiKVM has 3 different ways to receive video and audio, depending on the device. This is also reflected in the web interface.

| Mode |

"},{"location":"api/#get-raw-h264-video-stream","title":"Get raw H.264 video stream","text":""},{"location":"arduino_hid/","title":"Arduino HID","text":"

Legacy warning

This page describes the legacy keyboard and mouse emulator used in old DIY builds. There is no point using it today because there is a more modern and better replacement for the new Pico HID. This one can also serve as an in-place compatible replacement for the Arduino HID in the old build.

"},{"location":"arduino_hid/#serial-hid","title":"Serial HID","text":"

PiKVM V3 note

Use the SPI HID for V3. Otherwise, you won't be able to use the Serial console.

"},{"location":"arduino_hid/#usb-keyboard-and-mouse","title":"USB keyboard and mouse","text":"
  1. Get some parts
    • Arduino Pro Micro (based on an ATMega32u4).
    • Logic level shifter.
    • 1x NPN transistor (almost any NPN transistor: 2n2222 or similar).
    • 1x 390 Ohm resistor.
    • A breadboard and wires.
  2. Build the Arduino HID according to the scheme
  3. Power up PiKVM and switch it to RW-mode using command rw.

  4. Add these lines to /etc/kvmd/override.yaml:

    kvmd:\n    hid:\n        type: serial\n        reset_pin: 4\n        device: /dev/kvmd-hid\n
  5. Create file /etc/udev/rules.d/99-kvmd-extra.rules:

    KERNEL==\"ttyAMA0\", SYMLINK+=\"kvmd-hid\"\n
  6. Run systemctl disable getty@ttyAMA0.service.

  7. Remove console=ttyAMA0,115200or console=serial0,115200 and kgdboc=ttyAMA0,115200 or kgdboc=serial0,115200 from /boot/cmdline.txt.

  8. Flash the Arduino HID.

  9. Perform reboot.

"},{"location":"arduino_hid/#ps2-keyboard","title":"PS/2 keyboard","text":"

Using the PS/2 firmware currently have some limitations:

  • The possibility of using the switchable USB HID is excluded.
  • PS/2 mouse is not supported right now (but it will).

Both of these problems will be solved in the nearest future and the two different firmware versions will be combined into one universal one.

To select the PS/2 firmware, follow the instructions for the USB, but with one exception:

Before make you will need to edit file platformio-avr.ini

Open the file and find these lines:

[_common]\nbuild_flags =\n    -DHID_PS2_KBD_CLOCK_PIN=7\n    -DHID_PS2_KBD_DATA_PIN=5\n    -DHID_USB_CHECK_ENDPOINT\n# ----- The default config with dynamic switching -----\n    -DHID_DYNAMIC\n    -DHID_WITH_USB\n    -DHID_SET_USB_KBD\n    -DHID_SET_USB_MOUSE_ABS\n# ----- PS2 keyboard only -----\n#   -DHID_WITH_PS2\n#   -DHID_SET_PS2_KBD\n# ----- PS2 keyboard + USB absolute mouse -----\n#   -DHID_WITH_USB\n#   -DHID_WITH_PS2\n#   -DHID_SET_PS2_KBD\n#   -DHID_SET_USB_MOUSE_ABS\n# ----- PS2 keyboard + USB relative mouse -----\n#   -DHID_WITH_USB\n#   -DHID_WITH_PS2\n#   -DHID_SET_PS2_KBD\n#   -DHID_SET_USB_MOUSE_REL\n

By default, the firmware works with USB HID and supports dynamic mode switching. You can choose one of the other modes by commenting some lines and uncommenting others. This example to use a USB mouse and PS/2 keyboard:

...\n# ----- The default config with dynamic switching -----\n#   -DHID_DYNAMIC\n#   -DHID_WITH_USB\n#   -DHID_SET_USB_KBD\n#   -DHID_SET_USB_MOUSE_ABS\n# ----- PS2 keyboard only -----\n...\n# ----- PS2 keyboard + USB absolute mouse -----\n    -DHID_WITH_USB\n    -DHID_WITH_PS2\n    -DHID_SET_PS2_KBD\n    -DHID_SET_USB_MOUSE_ABS\n# ----- PS2 keyboard + USB relative mouse -----\n...\n

Next, connect Arduino pins to the female PS/2 port of your motherboard. Choose the purple port. If your motherboard only have one port, it's probably universal and can be used either for the keyboard or for the mouse. Most likely, it is painted in two colors: green and purple. You can use it either.

Follow the diagram Female PS/2 port (front view) Pinout Arduino pin 7 <-> PS/2 CLOCKArduino pin 5 <-> PS/2 DATAArduino GND pin <-> PS/2 GND

Warning

Connect VIN pin of Arduino to any Raspberry's 5v pin for PS/2 only device. But you don't need to connect the Arduino VIN pin if you connected USB (Arduino will get power through it).

"},{"location":"arduino_hid/#spi-hid","title":"SPI HID","text":"

Using an SPI connection, an Arduino Micro (not Pro) or compatible can be flashed from the Pi and used as an HID keyboard and mouse. Unlike UART, SPI does not share pins with Bluetooth on the Raspberry Pi so the Bluetooth radio does not need to be disabled.

Before powering either device, double-check the connections. The following should be wired from the Pi to either the level shifter or the Arduino. While the Arduino tolerates 3.3V logic input, 5V outputs from the Arduino can damage or destroy the Raspberry Pi and must not be connected directly to 3.3V GPIO pins directly.

"},{"location":"arduino_hid/#parts-list","title":"Parts list","text":"

There are very few parts needed besides the Raspberry Pi to build the solution. Some parts may be purchased with or without headers, if headers are not pre-soldered, it may be necessary to order some breakaway header strips and solder them to the boards prior to assembly unless the wires will be soldered directly to the boards.

  • Raspberry Pi Zero W or Pi 4 are the most popular boards for this solution, pre-soldered headers recommended
  • Arduino Micro (or compatible) microcontroller board with pre-soldered headers recommended
  • Logic Level Converter. This may be RX/TX, Bidirectional, or Single Supply
  • 1x PNP transistor (2n2907 or equivalent). Note this is different from the one suggested in the Serial HID docs above, that is an NPN while this is a PNP.
  • 1x 390 ohm resistor
  • Dupont wires (female to male pin) recommended for breadboard or other suitable means of making the connections
  • Optional: Breakaway headers for the logic level converter
  • Optional: Breadboard large enough to accommodate the parts
  • Optional: Header pins for connection to a breadboard

Note

A smaller \"Pro Micro\" board is available in a 3.3V model but the SS connection (RX_LED) is not available as a separate pin or solderable hole. If using this board, a jumper wire can be soldered to the resistor for the RX_LED but there is risk of burning the resistor, the LED, the board, or other components in the process. Advantages of this board include not requiring a logic level converter and reduced breadboard or board space for building the solution.

"},{"location":"arduino_hid/#list-of-connections-to-be-made","title":"List of connections to be made","text":"

For the primary functionality, most connections are made using a 4-channel bidirectional level shifter

  • Pi 3v3 to LV on the level shifter
  • Pi Ground to LV GND
  • Arduino GND to HV GND
  • GPIO10 (MOSI) via the level shifter to MOSI on the Arduino
  • GPIO9 (MISO) via the level shifter to MISO on the Arduino
  • GPIO11 (SPIO_SCLK) via the level shifter to SCK on the Arduino
  • GPIO7 (SPIO_CE1_N) via the level shifter to SS (or RX_LED) on the Arduino

An additional circuit is used with a transistor to reset the HID for mode changes and for SPI programming as follows:

  • GPIO25 to PNP base on transistor
  • PNP emitter to ground
  • PNP collector to RST on the Arduino

Pictures of this setup are also available in full resolution for download to assist for both the Raspberry Pi and the Arduino board. A smaller version of the images has been included on this page and can be downloaded.

Raspberry Pi Closeup Breadboard with Arduino

Programming assumes the Arduino is powered via USB, either from the connected host or the Pi itself. If the USB is not connected, 5 V may be provided by the Raspberry Pi GPIO but should be disconnected prior to connecting USB to the Arduino's USB port. The Raspberry Pi does not have backcurrent protection, a circuit using one or more Schottky diodes can be built to OR power from multiple sources but it's easier and more cost effective to avoid conflict and voltage differences between power supplies by leaving the 5 V wire disconnected.

"},{"location":"arduino_hid/#preparing-the-installation-for-spi-devices-and-programming","title":"Preparing the installation for SPI devices and programming","text":"

As of the latest package release, the kvmd service supports SPI. It should be sufficient to ensure the packages are up-to-date with the latest release, the programmer is installed, and the SPI device overlay is loaded at boot.

  • Switch the filesystem to read-write mode with rw
  • Add dtoverlay=spi0-1cs to /boot/config.txt
  • Perform reboot.
"},{"location":"arduino_hid/#flashing-the-arduino","title":"Flashing the Arduino","text":"

Instructions on flashing the Arduino can be found on the page Flash the Arduino HID.

If programming fails, ensure the Arduino is powered and check the wiring again. If there is a misconfiguration, power off the Pi and the Arduino, correct the wiring, and try again. Note it is not recommended or required to supply 5V power from the Raspberry Pi if the Arduino is USB powered, if the issue appears to be power related it may be removed from the solution and replaced with a powered USB connection if it will aid in troubleshooting but check all other wires first to ensure there are no shorts.

After you have double and triple-checked your wiring (in particular make sure the pins you are using on the Pi are correct, the documentation uses the GPIO pin labels, NOT the sequential pin numbers from 1-40. A good pinout reference is @Gadgetoid's version, you might try flashing the Arduino by holding down the RESET button on the chip while running make install. If this works, then at least you know your SPI wiring is correct.

Wiring problems are a common issue but there could be other reasons for programming not to complete. While it is not possible to list every possible problem and solution here, there is an active user community with others familiar with the solution and willing to help.

"},{"location":"arduino_hid/#enable-the-spi-configuration-and-restart-kvmd","title":"Enable the SPI configuration and restart kvmd","text":"

Once the installation has completed, all that should remain is to add the following configuration to /etc/kvmd/override.yaml and restart the kvmd service. If the first line exists due to existing overrides, omit that line and either add or update the hid section as appropriate.

kvmd:\n    hid:\n        type: spi\n        chip: 0\n        bus: 0\n        sw_cs_pin: 7\n        reset_pin: 25\n        reset_inverted: true\n

After saving the changes to /etc/kvmd/override.yaml, restart kvmd and clear your browser cache. The command to restart kvmd is

# systemctl restart kvmd\n

If your device is still in read-write mode, ro will put the SD back in read-only mode.

"},{"location":"arduino_hid/#fixing-the-usb-absolute-mouse-on-windows-98","title":"Fixing the USB absolute mouse on Windows 98","text":"

Due to an ancient buggy driver, the USB absolute mouse on Windows 98 moves only within the upper-left quarter of the screen. To fix this, just recompile the firmware with uncommented flag -DHID_WITH_USB_WIN98 in platformio-avr.ini.

"},{"location":"atx_board/","title":"ATX control board","text":"

To manage the power of your computer, you will need to install an ATX adapter board inside the case and connect it to the motherboard. There is a female to female ribbon cable that goes from the motherboard to the ATX adapter board and a male to female ribbon cable that goes from the adapter board to the front panel ribbon cable. There are two rows of pins on the ATX adapter board, it does not matter which ribbon cable is attached to which row. The columns must line up from the front panel through the ATX adapter to the motherboard.

Apple's Mac computers are not ATX compatible as they lack the needed ATX headers, this is ONLY compatible with PC servers and desktops.

"},{"location":"atx_board/#detailed-instructions","title":"Detailed instructions","text":"
  1. Connect the rainbow wires to the board, one row to the front panel, one row to the motherboard. You can use either row for either cable. To secure the ATX board in the case you can optionally print the mounting plate for the PCI slot on a 3D-printer. Assemble everything like the pictures below. Secure wires in any convenient way (we used soft ties).

    Example

  2. Find the pins on the motherboard responsible for connecting the buttons and LEDs of the front panel of the case. Usually wires and connectors on the motherboard have designations. If you're not sure, check the documentation on your motherboard.

    Example

  3. Place the ATX board nearby and, focusing on the labels and polarity (+ or -), connect the male pins to the female pin of the front panel wires. Be sure to align the labels and polarity (the polarity is indicated on the ATX board).

    Example

  4. Repeat the procedure with the female pin of the ATX board by connecting them to the motherboard connector. Check the documentation on your motherboard to find out which pin on the motherboard goes to which pin on the ATX adapter. Sometimes it is printed on the motherboard.

    Example

  5. Install the ATX board into the PCI slot of the case and fix it with a screw, or use a different mounting method at your discretion.

    Example

  6. Arrange the wires in a way that is convenient for you and fix them if necessary. Ensure the cables do not come into contact with any fans in your case.

    Example

  7. Connect the ATX board to PiKVM using a straight Ethernet cable with 8 wires.

    Example

"},{"location":"atx_board/#pinout","title":"Pinout","text":"ATX RJ-45 pinout

The pinout of the RJ-45 connector is the same on the AT and ATX adapter.

ATX LED wiring example

"},{"location":"audio/","title":"PiKVM V3+ two-way audio","text":"

Official PiKVM V3 and PiKVM V4 Mini/Plus devices have an exclusive audio transmission feature, including two-way communication with microphone directly in the browser.

The incoming stream is captured from the target host via HDMI, the outgoing stream is transmitted to an emulated USB microphone. This brings the user experience of working with voice applications on the remote host even closer to the local one.

Note

  • Audio does not work with DIY devices, either CSI or USB video dongles.

  • VNC does not support audio, it only works in the Web UI in WebRTC mode.

"},{"location":"audio/#speakers-incoming-audio","title":"Speakers (incoming audio)","text":"
  • On PiKVM V4 Mini and Plus, this feature is enabled by default, unless you didn't disable it with custom EDID.

  • On PiKVM V3, this is disabled for historical reasons so as not to break old user's configurations that was created before audio support was introduced.

    Enabling audio on PiKVM V3
    1. Make sure that you have not removed the audio jumpers (4) on the V3 HAT board and have not deleted or commented the dtoverlay=tc358743-audio line in /boot/config.txt. Return everything as it was, if you changed it.

    2. Update OS and reboot:

      Updating PiKVM OS

      To update, run following commands under the root user:

      [root@pikvm ~]# pikvm-update\n

      If you encounter an error like:

      [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

      It's most likely you have an old OS release. You can update the OS as follows:

      [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

      Next time you will be able to use the usual method with pikvm-update.

    3. Enable the Basic Audio support in the EDID in the /etc/kvmd/tc358743-edid.hex and reboot the device again:

      [root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-edidconf --set-audio=yes\n[root@pikvm ~]# reboot\n

The target host determines whether it is possible to output audio via HDMI. Each OS does this in its own way. In general, make sure that the audio output is HDMI in the mixer. PiKVM supports stereo mode with any standard bits and frequencies like 32/44.1/48 kHz with 16/24 bit.

  • Mac OS usually understands the priority of HDMI for audio output on its own, but you can specify this explicitly in the settings.

  • Windows requires explicit specifying of the audio output device.

  • In Linux, everything depends on the distribution you use. In ancient times, the audio required performing a ritual dance under the full Moon. For now, a working Pipewire or Pulseaudio most likely be enough. Just specify HDMI as the audio sink in the mixer.

To receive audio in the PiKVM Web UI, go to the System menu and switch the video mode to WebRTC. If everything is in order, the volume slider will appear. Set the volume to a non-zero value. The video stream will restart and you should start hearing sounds from the target host.

If the volume slider is set to zero, then PiKVM does not accept the audio stream to save traffic, while the target host will still assume that the audio output to HDMI is available.

Besides, when the page is reloaded, the volume slider will be reset to zero. Saving this setting is not possible due to browser limitation that do not allow web pages to play audio immediately after opening without user activity to protect against annoying ads.

"},{"location":"audio/#microphone-outgoing-audio","title":"Microphone (outgoing audio)","text":"

PiKVM is able to emulate a USB microphone on the target host to transmit your speech from the browser to the host. This feature is disabled by default for backward compatibility reasons.

USB limitations

Each emulated USB device consumes a limited hardware resource called endpoints.

Short info: by default, you can add only one additional USB device.

To get more information about the endpoints, add more devices, and flexibly manage the configuration on the fly, see here.

Enabling USB Microphone
  1. Microphone requires speakers support so check the previous paragraph. Also perform OS updating and reboot if you didn't:

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  2. Switch filesystem to RW-mode:

    [root@pikvm ~]# rw\n
  3. Add a config to /etc/kvmd/override.yaml:

    otg:\n    devices:\n        audio:\n            enabled: true\n
  4. Perform reboot:

    [root@pikvm ~]# reboot\n

To receive and transmit audio in the PiKVM Web UI, go to the System menu and switch the video mode to WebRTC. If everything is in order, the volume slider will appear with additional Microphone switch. Set the volume to a non-zero value, next switch the mic switch. Your browser will ask for permission to use the microphone, allow it.

The switch state will be saved in the browser's local settings. The microphone signal will not be transmitted if the volume level is zero.

USB compatibility

This feature is very new, so we don't know how much it affects the ability to interact with the BIOS and UEFI.

Please try this and let us know if you have lost the ability to access the BIOS or boot OS from PiKVM Mass Storage after turning on the USB microphone.

But even if this happens, don't worry. You can use the dynamic USB device control to temporarily turn off the microphone emulation.

"},{"location":"audio/#troubleshooting","title":"Troubleshooting","text":"
  • If the browser does not play sound or does not show audio slider, try a different browser and/or incognito mode without extensions. Google Chrome works best.

  • Check the log: journalctl -u kvmd-janus.

  • If nothing helped, please report about the problem to our support

"},{"location":"auth/","title":"Authentication","text":"

Info

PiKVM supports additional authentication methods commonly used on enterprise networks. See here for detailed documentation.

PiKVM comes with the following default passwords

  • Linux OS-level admin (SSH, console...):

    • Username: root
    • Password: root
  • KVM user (Web Interface, API, VNC...):

    • Username: admin
    • Password: admin
    • No 2FA code

They are two separate accounts with independent passwords.

Don't forget to change BOTH passwords on the new device

This page describes how to do this and enable two-factor authentication.

The 2FA is also strongly recommended if you plan to expose PiKVM to the internet or use it in untrusted networks.

In addition to the KVM user and Linux root, there are some other auth entities:

  • The OS user kvmd-webterm This is a special user with non-privileged rights in PiKVM OS. It can't be used for login or remote access via SSH. Password access and sudo are also disabled. It is used only for the Web Terminal. These restrictions are set for security reasons.

  • VNCAuth key - disabled by default.

  • IPMI password - disabled by default.

"},{"location":"auth/#root-access-in-the-web-terminal","title":"Root access in the Web Terminal","text":"

As mentioned above, the Web Terminal runs under user kvmd-webterm with disabled sudo and password access. However, most PiKVM administration commands require the root access. To obtain it in the Web Terminal, type su - and then enter the root user password:

[kvmd-webterm@pikvm ~]$ su -\n...\n[root@pikvm kvmd-webterm]#\n
Step by step: Disabling the Web Terminal

Sometimes the actual owner of a PiKVM device and the user who is allowed to use it are different people. So you may want to disable console access from the Web UI. To do this, use the following:

[root@pikvm ~]# rw\n[root@pikvm ~]# systemctl disable --now kvmd-webterm\n[root@pikvm ~]# ro\n

For your own access to PiKVM OS, you still have SSH.

"},{"location":"auth/#changing-the-linux-password","title":"Changing the Linux password","text":"
[root@pikvm ~]# rw\n[root@pikvm ~]# passwd root\n[root@pikvm ~]# ro\n
"},{"location":"auth/#changing-the-kvm-password","title":"Changing the KVM password","text":"

This password is used, among the Web UI login, to access the API, VNC (if enabled) and other functions that do not concern the OS shell.

By default, an authentication method similar to Apache Server is configured: users and passwords are stored encrypted in the /etc/kvmd/htpasswd file. To manage them, there is a utility kvmd-htpasswd.

[root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-htpasswd set admin\n[root@pikvm ~]# ro\n

The admin is a name of a default user.

Step by step: Add KVM users

It is possible to create several different KVM users with different passwords to access the Web UI and VNC, but keep in mind that they all have the same rights:

[root@pikvm ~]# kvmd-htpasswd add <user> # Add a new user with password\n[root@pikvm ~]# kvmd-htpasswd list # Show the list of users\n[root@pikvm ~]# kvmd-htpasswd del <user> # Removes/deletes a user\n

At the moment there is no way to create any ACL for different KVM users.

"},{"location":"auth/#two-factor-authentication","title":"Two-factor authentication","text":"

Two-factor authentication (2FA) is a new method of strengthening the protection of PiKVM, available since KVM >= 3.196. It is strongly recommended to enable it if you expose the PiKVM in the big and scary Internet.

Warning

Please note that 2FA does not concern the Linux OS access for the root user, so take care of a strong password for it for SSH access (or setup the key access).

Step by step: Enabling 2FA on PiKVM
  1. Update OS and reboot:

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  2. Make sure that NTP is running otherwise you will not be able to access (timedatectl command). The timezone doesn't matter.

  3. Install the Google Authenticator app to your mobile device (iOS, Android). It will generate one-time access codes.

  4. Create a secret for one-time codes on PiKVM:

[root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-totp init\n[root@pikvm ~]# ro\n
  1. Run the Google Authenticator and scan the QR code.

  2. Now, on the PiKVM login page, you will need to add 6 digits to the 2FA code field.

All Web UI users will be required to enter a one-time password on login. In other words, the secret is the same for all users.

Note

With 2FA for API or VNC authentication (except VNCAuth mode), you will need to append the one-time code to the password without spaces. That is, if the password is foobar and the code is 123456, then you need to use foobar123456 as the password.

To view the current QR code of the secret use command kvmd-totp show.

To disable 2FA and remove the secret, use command kvmd-totp del.

"},{"location":"auth/#session-expiration","title":"Session expiration","text":"

Since KVMD 4.53, on the PiKVM Web UI login page, you can choose the maximum duration of the authentication session: 1 hour, 12 hours or infinite (until PiKVM is rebooted or the kvmd system service is restarted). The selected session duration is valid for this browser and this user. When the time is up, the auth cookie will be revoked. It will not affect other sessions for the same user in other browsers.

Note if you click the Logout button on the main page, it will log out all sessions of this user in all browsers.

Long-lived connections

PiKVM actively uses websockets and long-lived HTTP connections for video streaming.

If the session has expired, this will cause its authorization cookie to be revoked and new connections with this auth cookie will not be able to be established. However, long-lived connections will not be terminated until the user closes the browser tab. The session expiration feature is primarily intended to \"clean up\" when the user closes the browser but don't hit the Logout button.

In the future, we plan to add immediate termination of expired connections.

Step by step: Set a global session expiration limit

You can set the default expiration time to limit the user's ability to create endless sessions. This will be an invisible limit valid on KVM login for Web UI (but not for VNC, please note that VNC sessions are always endless).

  1. Switch filesystem to read-write mode:

    [root@pikvm ~]# rw\n
  2. Edit the file /etc/kvmd/override.yaml:

    kvmd:\n    auth:\n        expire: 21600  # 21600 seconds is 6 shours\n
  3. Restart the kvmd service and make sure that the limit is applied:

    [root@pikvm ~]# systemctl restart kvmd\n[root@pikvm ~]# journalctl -u kvmd -g 'Maximum user session'\n... INFO --- Maximum user session time is limited: 6:00:00\n
  4. Switch filesystem to read-only mode back:

    [root@pikvm ~]# ro\n
"},{"location":"auth/#disabling-authentication","title":"Disabling authentication","text":"

If necessary, you can disable authentication for KVM access (Web UI, VNC, etc. except SSH).

Warning

Don't do this in untrusted networks, because you can give a potential attacker access to your target machine.

If you really need this, please consider to disable the Web Terminal so as not to open the shell access to PiKVM console. You still can use SSH to access to the console.

Step by step: Disabling authentication
  1. Switch filesystem to read-write mode:

    [root@pikvm ~]# rw\n
  2. Edit the file /etc/kvmd/override.yaml:

    kvmd:\n    auth:\n        enabled: false\n
  3. Restart kvmd, optionally disable web terminal switch filesystem to read-only mode:

    [root@pikvm ~]# systemctl restart kvmd\n[root@pikvm ~]# systemctl disable --now kvmd-webterm  # Optional if you have SSH access\n[root@pikvm ~]# ro\n
"},{"location":"auth_advanced/","title":"Advanced authentication","text":""},{"location":"auth_advanced/#advanced-authentication-methods","title":"Advanced authentication methods","text":"

PiKVM provides flexible authentication options to integrate with your existing security infrastructure. By default, PiKVM uses a simple file-based authentication system (htpasswd), but it can be configured to authenticate users against external systems for enterprise environments.

This guide covers the configuration of PiKVM's authentication methods. All external authentication servers (LDAP, RADIUS, HTTP auth servers) are assumed to be already configured and accessible from your PiKVM device.

Warning

This is advanced material. Before you try setting this up, we recommend (re)familirizing yourself with the documentation on configuration and taking another look at the cheat sheet.

Whenever you customize authentication, restart kvmd:

$ systemctl restart kvmd\n
"},{"location":"auth_advanced/#overview","title":"Overview","text":"

PiKVM supports the following authentication methods through its pluggable authentication system:

  • HTTP Authentication: External HTTP-based authentication service integration. PiKVM forwards authentication requests to a custom HTTP API endpoint.
  • PAM (Pluggable Authentication Modules): Integration with Linux PAM system, allowing authentication against system users, LDAP, Active Directory, and other PAM-supported backends.
  • LDAP (Lightweight Directory Access Protocol): Direct LDAP authentication against directory servers like Active Directory, OpenLDAP, or other LDAP-compatible systems.
  • RADIUS (Remote Authentication Dial-In User Service): Authentication against RADIUS servers, commonly used in enterprise networks with support for multi-factor authentication.
  • Unix Socket Credentials: Process-based authentication using Unix domain sockets with credential passing for local system integration.
"},{"location":"auth_advanced/#authentication-methods-comparison","title":"Authentication methods comparison","text":"Method Best For Complexity External Dependencies HTTP Auth Custom authentication systems, microservices Low HTTP auth server PAM System integration, existing PAM setups Medium PAM modules LDAP Active Directory, directory services Medium LDAP server RADIUS Enterprise networks, centralized auth Medium RADIUS server Unix Socket Credentials Local process integration, containers Low Local processes

2FA/TOTP is always available works locally and is compatible with all the methods listed here.

"},{"location":"auth_advanced/#basic-configuration","title":"Basic configuration","text":"

You can customize authentication and authorization with /etc/kvmd/override.yaml. If you want to keep the configuration modular, create and edit /etc/kvmd/override.d/9999-auth.yaml instead. You can use any 4-digit number prepending the filename.

Here are the keys you need to know about.

"},{"location":"auth_advanced/#enabled","title":"enabled","text":"

This is a global authentication switch, enabled by default:

kvmd:\n    auth:\n        enabled: true\n

Setting it to false will disable all authentication, regardless of the methods you configured.

"},{"location":"auth_advanced/#expire","title":"expire","text":"

This key sets the cookie expiration time measured in seconds. Please see this part of the documentation for details.

In this example, the cookie will expire in 10 minutes:

kvmd:\n    auth:\n        expire: 600\n
"},{"location":"auth_advanced/#usc","title":"usc","text":"

This group of keys is in charge for basic configuration of Unix Socket Credentials:

  • users: this key is for listing valid usernames
  • groups: this key is for listing valid user groups

Here is a configuration example:

kvmd:\n    auth:\n        usc:\n            users: [cyril,jane,mike,sheryl]\n
"},{"location":"auth_advanced/#internal-and-external","title":"internal and external","text":"

internal is the authentication method that is applied first, external is used for external services. Note that there is no fallback from external to internal.

kvmd defaults to using htpasswd as the internal method and doesn't set the external one:

kvmd:\n    auth:\n        internal:\n            type: htpasswd\n            force_users: []\n            file: /etc/kvmd/htpasswd\n\n        external:\n            type: ''\n

The recommended configuration is either htpasswd or pam as the internal authentication method and any other method as the external one. In that case, do the following:

  1. Keep the default admin user.
  2. Change its password to a random 30 characters long one (e.g., use pwgen -y 30).
  3. Keep htpasswd as the internal method.
  4. Use ldap or any other method as the external one, depending on your use case.

Here is a configuration example:

kvmd:\n    auth:\n        internal:\n            #type: htpasswd\n            force_users: [admin]\n            #file: /etc/kvmd/htpasswd\n\n        external:\n            type: ldap\n            ...\n

Type and file are defaults in the above example.

However, if your LDAP server has a guaranteed high availability, you can use ldap as an internal authentication method and discard the external authentication method entirely.

"},{"location":"auth_advanced/#totp","title":"totp","text":"

You can pass the secret file along with the password. The secret file location defaults to /etc/kvmd/totp.secret. See here for more information on 2FA authenticaion on PiKVM.

"},{"location":"auth_advanced/#http-authentication","title":"HTTP authentication","text":"

The HTTP authentication plugin delegates credential validation to an external HTTP/HTTPS endpoint. This enables integration with custom authentication services and third-party identity providers.

The plugin sends authentication requests as JSON POST requests to a configurable URL and grants access when the endpoint returns HTTP 200 OK. This approach allows you to implement complex authentication logic without modifying PiKVM's core code.

For an example of using HTTP authentication, please see this GitHub repository.

"},{"location":"auth_advanced/#parameters","title":"Parameters","text":""},{"location":"auth_advanced/#url","title":"url","text":"

The URL of the external HTTP authentication endpoint. PiKVM will send POST requests to this URL to authenticate users.

  • Type: String (URL)
  • Default value: \"http://localhost/auth\"
  • Examples:
    • http://localhost:8080/api/auth - Local authentication service
    • https://auth.example.com/validate - Remote HTTPS endpoint
    • http://10.0.0.100/auth - Internal network service
  • Note: The endpoint must accept POST requests with JSON payload.
"},{"location":"auth_advanced/#verify","title":"verify","text":"

Controls SSL/TLS certificate verification when using HTTPS URLs.

  • Type: Boolean
  • Default value: true
  • Acceptable values: true and false
  • Behavior:
    • true: Verifies the server's SSL/TLS certificate (recommended for production)
    • false: Disables certificate verification (useful for self-signed certificates or testing)
  • Note: Only applies when using https:// URLs. When set to false, SSL is completely disabled.
"},{"location":"auth_advanced/#secret","title":"secret","text":"

An optional shared secret token sent in the authentication request JSON payload. This can be used by the authentication endpoint to verify that requests are coming from an authorized PiKVM instance.

  • Type: String
  • Default value: \"\" (empty string)
  • Use Case: Provides an additional layer of security to prevent unauthorized services from using your authentication endpoint.
  • Note: The secret is sent as part of the JSON body, not as a header.
"},{"location":"auth_advanced/#user","title":"user","text":"

Optional username for HTTP basic authentication to the authentication endpoint itself. Used when the authentication service requires its own authentication.

  • Type: String
  • Default value: \"\" (empty string)
  • Note: Works in combination with the passwd parameter. If user is empty, Basic Auth is not used.
"},{"location":"auth_advanced/#passwd","title":"passwd","text":"

Optional password for HTTP basic authentication to the authentication endpoint. Used in combination with the user parameter.

  • Type: String
  • Default value: \"\" (empty string)
  • Note: Only used when user is configured.
"},{"location":"auth_advanced/#timeout","title":"timeout","text":"

The total timeout for the HTTP authentication request. If the authentication endpoint doesn't respond within this time, the authentication attempt fails.

  • Type: Float (\u2265 0.1)
  • Default value: 5.0
  • Unit: Seconds
  • Considerations:
  • Network latency to the authentication endpoint
  • Processing time on the authentication server
  • Balance between security (shorter timeout) and reliability (longer timeout)
"},{"location":"auth_advanced/#authentication-flow","title":"Authentication flow","text":"
  1. Session Creation: Create or reuse an HTTP client session configured with:
  2. SSL verification settings (based on verify parameter)
  3. Basic Authentication credentials (if user is configured)

  4. Request Construction: Create a POST request to the configured url with:

    • Method: POST
    • Content-Type: application/json
    • Headers:
      • User-Agent: \"KVMD\" with version information
      • X-KVMD-User: The username being authenticated
    • JSON Body:
         {\n     \"user\": \"username\",\n     \"passwd\": \"password\",\n     \"secret\": \"shared_secret\"\n   }\n
  5. Request Transmission: Send the HTTP request to the authentication endpoint

  6. Response Processing: Wait for response (up to timeout period)

  7. Authorization Decision: Grant access if:

    • The response is received within the timeout
    • The HTTP status code is 200 (OK)
    • Any other status code (including 401, 403, 404, etc.) results in authentication failure
"},{"location":"auth_advanced/#authentication-endpoint-requirements","title":"Authentication endpoint requirements","text":"
  1. Accept POST requests with JSON payload

  2. Parse the JSON body containing:

    • user: The username attempting to authenticate
    • passwd: The password provided by the user
    • secret: The shared secret (if configured)
  3. Validate credentials according to your authentication logic

  4. Return appropriate HTTP status codes:

    • 200 OK: Authentication successful
    • 401 Unauthorized: Invalid credentials
    • 403 Forbidden: User not authorized
    • Any other status code: Authentication failure
"},{"location":"auth_advanced/#basic-configuration-example","title":"Basic configuration example","text":"
kvmd:\n    auth:\n        internal:\n            type: http\n            url: http://localhost:8080/api/auth\n            verify: true\n            secret: \"\"\n            user: \"\"\n            passwd: \"\"\n            timeout: 5.0\n
"},{"location":"auth_advanced/#pam-plugin-configuration","title":"PAM plugin configuration","text":"

The PAM authentication plugin leverages Linux's Pluggable Authentication Modules framework to authenticate users against the same mechanisms used by the underlying operating system.

This plugin supports any authentication backend configured through PAM, including local user accounts, SSSD for Active Directory, LDAP, Kerberos, or any other PAM-compatible service.

It also includes access control features such as username whitelists/blacklists and UID-based filtering to prevent system accounts from authenticating.

"},{"location":"auth_advanced/#parameters_1","title":"Parameters","text":""},{"location":"auth_advanced/#service","title":"service","text":"

Specifies the PAM service name to use for authentication. This corresponds to a configuration file in /etc/pam.d/ on the system. The default value login uses the standard PAM login service configuration.

  • Type: String
  • Default: \"login\"
"},{"location":"auth_advanced/#allow_users","title":"allow_users","text":"

A whitelist of usernames that are explicitly allowed to authenticate. If the list is empty, this check is bypassed, all users are allowed and are subject to other checks.

  • Type: List of strings
  • Default: [] (empty list)
  • Behavior: When a user attempts to authenticate:
    • If the list is not empty and the user is not in the list, authentication fails with an error message.
"},{"location":"auth_advanced/#deny_users","title":"deny_users","text":"

A blacklist of usernames that are explicitly denied authentication. Users in this list cannot authenticate regardless of their credentials.

  • Type: List of strings
  • Default: [] (empty list)
  • Behavior: When a user attempts to authenticate:
    • If the user is in the deny list, authentication fails with an error message.
"},{"location":"auth_advanced/#allow_uids_at","title":"allow_uids_at","text":"

Specifies a minimum UID (User ID) threshold for authentication. Only users with UIDs greater than or equal to this value are allowed to authenticate. A value of 0 disables this check.

  • Type: Integer (\u2265 0)
  • Default: 0
  • Behavior: When set to a value greater than 0:
    • The plugin retrieves the UID of the authenticating user from the system
    • If the user's UID is less than the configured threshold, authentication fails
    • This is useful for preventing system users (typically UIDs < 1000) from authenticating
  • Use case: Commonly used to restrict authentication to regular user accounts and prevent service accounts or system users from accessing the interface.
"},{"location":"auth_advanced/#authentication-flow_1","title":"Authentication flow","text":"

The authentication process follows the steps in the following order:

  1. Allow list check: If allow_users is configured, verify the user is in the list
  2. Deny list check: If deny_users is configured, verify the user is not in the list
  3. UID threshold check: If allow_uids_at > 0, verify the user's UID meets the minimum threshold
  4. PAM authentication: Finally, authenticate the user credentials against the specified PAM service

All checks must pass for authentication to succeed.

"},{"location":"auth_advanced/#basic-configuration-example_1","title":"Basic configuration example","text":"
kvmd:\n    auth:\n        internal:\n            type: pam\n            service: login\n            allow_users: [admin, operator, viewer]\n            deny_users: [guest, test]\n            allow_uids_at: 1000\n

This configuration would:

  • Use the standard \"login\" PAM service
  • Only allow users named admin, operator, or viewer
  • Explicitly deny users named guest or test
  • Only allow users with UID \u2265 1000 (excluding most system accounts)
"},{"location":"auth_advanced/#advanced-pam-configuration-examples","title":"Advanced PAM configuration examples","text":"
  • Multiple PAM modules (stacking)
  • Time-based restrictions (pam_time)
  • Access control lists (pam_access)
  • Account lockout policies
"},{"location":"auth_advanced/#ldap-plugin-configuration","title":"LDAP plugin configuration","text":"

The LDAP authentication plugin integrates with LDAP directories and Active Directory environments for centralized user management.

The plugin authenticates users through LDAP bind operations and validates group membership to enforce authorization policies, so that only users in specified security groups can access the KVM interface.

It supports both standard LDAP and secure LDAPS connections with configurable certificate verification, optional domain suffix auto-appending, and timeout settings.

"},{"location":"auth_advanced/#parameters_2","title":"Parameters","text":""},{"location":"auth_advanced/#url_1","title":"url","text":"

The LDAP server URL, should be in either ldap://hostname:port or the ldaps://hostname:port format.

  • Type: String (non-empty)
  • Default: \"\" (empty string, must be configured)
  • Required: Yes
  • Examples:
  • ldap://dc.example.com:389 - Standard LDAP
  • ldaps://dc.example.com:636 - LDAP over SSL/TLS
  • Note: When using ldaps://, the plugin automatically configures TLS options.
"},{"location":"auth_advanced/#verify_1","title":"verify","text":"

Controls SSL/TLS certificate verification when using LDAPS connections.

  • Type: Boolean
  • Default: True
  • Behavior:
  • true: Verifies the server's SSL/TLS certificate (recommended for production)
  • false: Disables certificate verification (useful for self-signed certificates or testing)
  • Note: Only applies when using ldaps:// URLs.
"},{"location":"auth_advanced/#base","title":"base","text":"

The LDAP base DN (Distinguished Name) where user searches will start. This defines the starting point in the directory tree for user lookups.

  • Type: String (non-empty)
  • Default: \"\" (empty string, must be configured)
  • Required: Yes
  • Example: DC=example,DC=com or OU=Users,DC=example,DC=com
"},{"location":"auth_advanced/#group","title":"group","text":"

The full DN of the LDAP/Active Directory group that users must be members of to authenticate successfully. Only users who are members of this group will be granted access.

  • Type: String (non-empty)
  • Default: \"\" (empty string, must be configured)
  • Required: Yes
  • Example: CN=PiKVM-Users,OU=Groups,DC=example,DC=com
  • Note: The plugin checks for exact group membership using the memberOf attribute.
"},{"location":"auth_advanced/#user_domain","title":"user_domain","text":"

An optional domain suffix to append to usernames during authentication. When configured, the username will be transformed to username@user_domain format (User Principal Name format).

  • Type: String
  • Default: \"\" (empty string)
  • Examples:
  • If set to example.com and user enters john, the plugin authenticates as john@example.com
  • If empty, the username is used as-is
  • Use Case: Simplifies login by allowing users to enter just their username instead of the full UPN.
"},{"location":"auth_advanced/#timeout_1","title":"timeout","text":"

Timeout value for LDAP operations (bind and search). If the LDAP server doesn't respond within this time, the operation fails.

  • Type: Integer (\u2265 1)
  • Default: 5
  • Unit: Seconds
  • Recommendation: Adjust based on network latency and LDAP server performance.
"},{"location":"auth_advanced/#authentication-flow_2","title":"Authentication flow","text":"

The authentication process works as follows:

  1. Username transformation: If user_domain is configured, append it to the username (e.g., user > user@example.com).

  2. Connection initialization: Connect to the LDAP server specified in url.

  3. TLS configuration: If using ldaps://, configure TLS settings based on the verify parameter.

  4. Bind attempt: Attempt to bind (authenticate) to the LDAP server using the username and password.

  5. Group membership search: Search for the user in the directory and verify they are a member of the specified group.

  6. Authorization decision: Grant access only if:

    • The bind (authentication) succeeds
    • The user is found in the directory under the specified base
    • The user is a member of the specified group
"},{"location":"auth_advanced/#basic-configuration-example_2","title":"Basic configuration example","text":"
kvmd:\n    auth:\n        internal:\n            type: ldap:\n                url: ldaps://dc.example.com:636\n                verify: true\n                base: DC=example,DC=com\n                group: CN=PiKVM-Admins,OU=Security Groups,DC=example,DC=com\n                user_domain: example.com\n                timeout: 5\n
"},{"location":"auth_advanced/#configuration-with-a-self-signed-certificate","title":"Configuration with a self-signed certificate","text":"
kvmd:\n    auth:\n        internal:\n            type: ldap:\n            url: ldaps://dc.internal.local:636\n            verify: false\n            base: OU=Users,DC=internal,DC=local\n            group: CN=KVM-Users,OU=Groups,DC=internal,DC=local\n            user_domain: internal.local\n            timeout: 10\n
"},{"location":"auth_advanced/#configuration-for-standard-ldap-non-ssl","title":"Configuration for standard LDAP (non-SSL)","text":"
kvmd:\n    auth:\n        internal:\n            type: ldap\n            url: ldap://ldap.example.com:389\n            verify: true\n            base: DC=example,DC=com\n            group: CN=RemoteAccess,DC=example,DC=com\n            user_domain: \"\"\n            timeout: 5\n
"},{"location":"auth_advanced/#radius-plugin-configuration","title":"RADIUS plugin configuration","text":"

This plugin enables authentication against RADIUS (Remote Authentication Dial-In User Service) servers. Supported features:

  • Standard RADIUS Access-Request/Access-Accept protocol over UDP.
  • Password encryption using the RADIUS shared secret mechanism.
  • Supports any RFC 2865-compliant server (FreeRADIUS, Microsoft NPS, Cisco ISE).
"},{"location":"auth_advanced/#parameters_3","title":"Parameters","text":""},{"location":"auth_advanced/#host","title":"host","text":"

The hostname or IP address of the RADIUS authentication server.

  • Type: String (IP address or hostname)
  • Default: \"localhost\"
  • Examples:
    • 192.168.1.100 - IP address
    • radius.example.com - Hostname
    • localhost - Local RADIUS server
"},{"location":"auth_advanced/#port","title":"port","text":"

The UDP port number on which the RADIUS server is listening for authentication requests.

  • Type: Integer (valid port number: 1-65535)
  • Default: 1812
  • Standard ports:
    • 1812 - Standard RADIUS authentication port (recommended, RFC 2865)
    • 1645 - Legacy RADIUS authentication port (deprecated but sometimes still used)
"},{"location":"auth_advanced/#secret_1","title":"secret","text":"

The shared secret (password) used to encrypt communication between the PiKVM client and the RADIUS server. This must match the shared secret configured on the RADIUS server for this client.

  • Type: String
  • Default: \"\" (empty string, must be configured)
  • Required: Yes
  • Security:
    • This value should be kept confidential and stored securely
    • Use a strong, random secret
    • The secret is used for encrypting user passwords in transit and authenticating packets
  • Note: The secret is encoded as ASCII before use.
"},{"location":"auth_advanced/#timeout_2","title":"timeout","text":"

The timeout value for RADIUS authentication requests. If the RADIUS server doesn't respond within this time, the authentication attempt fails.

  • Type: Integer (\u2265 1)
  • Default: 5
  • Unit: Seconds
  • Considerations:
    • Network latency between PiKVM and RADIUS server
    • RADIUS server load and response time
    • Consider increasing for servers on slow or distant networks
"},{"location":"auth_advanced/#authentication-flow_3","title":"Authentication flow","text":"

The authentication process works as follows:

  1. Dictionary loading: Load the RADIUS attribute dictionary (embedded FreeRADIUS dictionary format)

  2. Client creation: Create a RADIUS client configured with:

    • Server hostname/IP
    • Authentication port
    • Shared secret (encrypted)
    • Timeout value
  3. Packet creation: Create a RADIUS Access-Request packet containing:

    • Username (User-Name attribute)
    • Encrypted password (User-Password attribute, encrypted using the shared secret)
  4. Request transmission: Send the authentication packet to the RADIUS server via UDP

  5. Response processing: Wait for response (up to timeout period)

  6. Authorization decision: Grant access if:

    • A response is received within the timeout
    • The response code is AccessAccept (code 2)
"},{"location":"auth_advanced/#basic-configuration-example_3","title":"Basic Configuration Example","text":"
kvmd:\n    auth:\n        radius:\n            host: radius.example.com\n            port: 1812\n            secret: \"MySharedSecret123\"\n            timeout: 5\n
"},{"location":"auth_advanced/#unix-socket-credentials-configuration","title":"Unix Socket Credentials configuration","text":"

USC is a built-in mehanism that is primarily used for authorizing local PiKVM microservices, such as VNC \u0438 IPMI. You can use this method to execute scripts that use the local KVMD API.

For example, the following command will authenticate a script with a unix socket and return PiKVM status:

[root@pikvm ~]# sudo -u monitoring curl --unix-socket /run/kvmd/kvmd.sock http://localhost/info\n

Note that there is no api prefix used when accessing the API. The prefix is added by KVMD-Nginx when exposing the socket on ports 80 and 443.

For scheduling the execution, you can use either systemd-timers (available by default and recommended) or cron (not installed by default).

Here are some best practices:

  • Never add system users (start with kvmd-*) to any of the lists below, unless you are 100% sure you know what you are doing.
  • Adding the root user to the users list is a really bad idea. We srongly recommed against doing that.
  • kvmd-webterm is the only KVMD user we can recommend adding to the users list. Once you've done it, you can use /run/kvmd/kvmd.sock from the web terminal without authentication.
  • It's best to create a per-script user, add it to the users list, and then schedule the script execution.
"},{"location":"auth_advanced/#parameters_4","title":"Parameters","text":""},{"location":"auth_advanced/#users","title":"users","text":"

List of Unix usernames that are allowed to authenticate via Unix Socket Credentials. Any user in this list can connect to KVMD's Unix socket and be automatically authenticated.

  • Type: List of strings
  • Default: [] (empty list)
"},{"location":"auth_advanced/#groups","title":"groups","text":"

List of Unix group names whose members are allowed to authenticate via Unix Socket Credentials. Any user who is a member of one of these groups can connect to KVMD's Unix socket and be automatically authenticated.

  • Type: List of strings
  • Default: [] (empty list)
"},{"location":"auth_advanced/#kvmd_users-and-kvmd_groups","title":"kvmd_users and kvmd_groups","text":"

These two lists are reserved for system users and groups. They should never be customized.

"},{"location":"auth_advanced/#authentication-flow_4","title":"Authentication flow","text":"

When a client connects to KVMD through its Unix socket (/run/kvmd/kvmd.sock), the following authentication process occurs:

  1. Connection establishment. The client process opens a connection to the Unix socket: /run/kvmd/kvmd.sock

  2. Kernel credential passing. The Linux kernel automatically attaches the connecting process's credentials to the socket connection:

    • UID (User ID) - The numeric user ID of the process
    • GID (Group ID) - The primary group ID of the process
    • Supplementary groups - Additional groups the user belongs to

    This happens transparently at the kernel level using the SO_PEERCRED socket option.

  3. Credential retrieval.. KVMD receives the connection and extracts the peer credentials from the socket. It obtains:

    • The username (resolved from UID)
    • The primary group name (resolved from GID)
    • All supplementary group names the user is a member of .
  4. Authorization check. KVMD compares the credentials against the user whitelist and the group whitelist. If the connecting user is a member of ANY group in the groups list (primary or supplementary), authentication succeeds.

  5. Access decision.

    • Success: If either the user check or group check passes, the connection is authenticated and the client gains full API access.
    • Failure: If neither check passes, the connection is rejected and must use standard HTTP authentication instead.
"},{"location":"auth_advanced/#basic-configuration-example_4","title":"Basic configuration example","text":"

In the following example, processes run from users monitoring and backup-service are allowed to authenticate:

kvmd:\n    auth:\n        usc:\n            users: [\"monitoring\", \"backup-service\"]\n

Both users should exist prior to listing them in configuration. You can use useradd to create these users.

"},{"location":"auto_snapshots/","title":"Automatic snapshots","text":"

You can configure PiKVM to automatically take screenshots of the server screen and save them into the memory, so that you retrieve it with the HTTP API.

"},{"location":"auto_snapshots/#enabling-snapshots","title":"Enabling snapshots","text":"

Automatic snapshots are disabled by default, you need to enable and configure this feature. Switch to the read-write mode (rw), then open /etc/kvmd/override.yaml and add the following lines:

kvmd:\n    snapshot:\n        idle_interval: 3600\n        live_interval: 60\n        wakeup_key: ShiftLeft\n        wakeup_move: 1000\n

Here is what these parameters do:

  • idle_interval=3600 means that every hour the PiKVM must turn on the streamer, take a screenshot, and save it, if there are no users on the PiKVM.
  • live_interval=60 means that KVM must take a screenshot every minute as long as there are users working on the PiKVM.
  • wakeup_key=ShiftLeft means that if there are no users on KVM, before taking a screenshot, KVM must wake up the server so that it turns on the \"screen\" from power-saving mode. To do this, it clicks and releases the left shift, simulating the user's actions.
  • wakeup_move=1000 is another simulator of user actions. It moves the mouse to the position 0x0, and then to 1000x1000 (units, not pixels, but it doesn't matter, just write a large number), and then returns it back.

Although the last two options work, PiKVM may not know if you are using the server to bypass it with a monitor and keyboard, and PiKVM input may be mix with your own. So if the PiKVM is not the only way to work with the server, we recommend not using the wakeup options. INstead, disable the power saving mode for HDMI.

"},{"location":"auto_snapshots/#retrieving-snapshots","title":"Retrieving snapshots","text":"

As soon as you have snapshots, you can retrieve them from the PiKVM using Streamer API as follows:

$ curl -k \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/streamer/snapshot?load=1' \\\n    --output=file.jpg\n

You can also ask PiKVM to give you a small preview of the screenshot:

$ curl -k \\\n    -u admin:admin \\\n    'https://<pikvm-ip>/api/streamer/snapshot?load=1&preview=1' \\\n    --output=preview.jpg\n

Additional parameters can be used to configure the preview: preview_max_width=100, preview_max_height=100, preview_quality=75.

"},{"location":"bluetooth_hid/","title":"Bluetooth HID","text":"

PiKVM is able to emulate a Bluetooth keyboard & mouse. This is not the main case of using PiKVM since you still need it to pair with a remote host, but can be used for something like mobile KVM.

Warning

Using Bluetooth HID requires additional configuration of the operating system. For v2+, this means losing the UART port, since it will be used by Bluetooth. Also, Bluetooth operation was tested only on RPi4 and v2+ platform. Other boards may require different system service settings. Making the required changes for BT to work will also disable normal KB/MOUSE functionality therefor this will need to be disabled before normal operation can occur.

Note

Bluetooth mouse can work only in relative mode. The reason is that many Bluetooth host drivers do not correctly implement HID descriptors. Horizontal scrolling is not supported for the same reason.

"},{"location":"bluetooth_hid/#configuring-the-os","title":"Configuring the OS","text":"
  1. Switch filesystem to RW-mode and install some packages:

    # rw\n# pacman -Syy   \n# pacman -Su bluez bluez-utils raspberrypi-bluetooth\n
  2. Edit /boot/config.txt and comment these lines:

    #enable_uart=1\n#dtoverlay=disable-bt\n
  3. Create an empty directory /var/lib/bluetooth and add mountpoint to /etc/fstab:

    # mkdir /var/lib/bluetooth\n# echo 'tmpfs /var/lib/bluetooth tmpfs nodev,nosuid,mode=0755 0 0' >> /etc/fstab\n
  4. Override and enable the services:

    # mkdir /etc/systemd/system/bluetooth.service.d\n# cat << EOF > /etc/systemd/system/bluetooth.service.d/override.conf\n[Service]\nExecStart=\nExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=*\nEOF\n# systemctl enable bluetooth\n# systemctl enable raspberrypi-btuart\n
  5. Override kvmd service:

    # mkdir /etc/systemd/system/kvmd.service.d\n# cat << EOF > /etc/systemd/system/kvmd.service.d/override.conf\n[Service]\nAmbientCapabilities=CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SYS_ADMIN CAP_SETUID CAP_SETGID CAP_CHOWN\nCapabilityBoundingSet=CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SYS_ADMIN CAP_SETUID CAP_SETGID CAP_CHOWN\nEOF\n
  6. Add following lines to /etc/kvmd/override.yaml:

    kvmd:\n    hid:\n        type: bt\n
  7. Perform reboot.

  8. To reverse, uncomment lines from Step 2 and remove lines in Step 6, and reboot.

"},{"location":"bluetooth_hid/#using-bluetooth-hid","title":"Using Bluetooth HID","text":"
  • After a reboot, the PiKVM will be ready for detection and pairing with no auth. You will see the PiKVM HID device.

  • Once the server is connected, PiKVM will no longer be discoverable and pairable to other clients until you unpair the server.

  • If something went wrong, use the web menu System -> Reset keyboard & mouse. This will cause unpair the device and switch the PiKVM to public mode before the first client is connected.

"},{"location":"building_os/","title":"Building PiKVM OS","text":"

The assembly of PiKVM OS is carried out using a special build environment. Here the minimum required for its use, imposed on the build machine:

  • kernel >= 5.8
  • glibc >= 2.33
  • docker >= 19.03.13
  • git

Docker must work in privileged mode.

  1. When starting with a clean OS you need to install and configure Docker. An example for Ubuntu:

    [user@localhost ~]$ sudo apt-get install git make curl binutils -y\n[user@localhost ~]$ sudo apt-get install docker.io\n[user@localhost ~]$ sudo usermod -aG docker $USER\n

    Re-login to apply the changes.

  2. Checkout the build environment:

    [user@localhost ~]$ git clone --depth=1 https://github.com/pikvm/os\n[user@localhost ~]$ cd os\n
  3. Determine the target board and platform:

    • Choose the board:

      • BOARD=rpi4 for Raspberry Pi 4.
      • BOARD=zero2w
      • BOARD=rpi3
      • BOARD=rpi2
    • Choose the platform:

      • PLATFORM=v4mini-hdmi for PiKVM V4 Mini.
      • PLATFORM=v4plus-hdmi for PiKVM V4 Plus.
      • PLATFORM=v3-hdmi for RPi4 and PiKVM V3 HAT.
      • PLATFORM=v2-hdmi for RPi3a+/RPi4 or Zero2W with HDMI-CSI bridge.
      • PLATFORM=v2-hdmiusb for RPi4 with HDMI-USB dongle.
      • PLATFORM=v1-hdmi for RPi2 or 3b+ with HDMI-CSI bridge and the Pico HID.
      • PLATFORM=v1-hdmiusb for RPi2 or 3b+ with HDMI-USB dongle and the Pico HID.
  4. Create the build config file config.mk for the target system and and the BOARD and PLATFORM variables. You can also set some other parameters as you wish (see below). Please note: if your password contains the # character, you must escape it using a backslash like ROOT_PASSWD = pass\\#word.

    # Base board\nBOARD = rpi4\n\n# Hardware configuration\nPLATFORM = v2-hdmi\n\n# Target hostname\nHOSTNAME = pikvm\n\n# ru_RU, etc. UTF-8 only\nLOCALE = en_US\n\n# See /usr/share/zoneinfo\nTIMEZONE = Europe/Nicosia\n\n# For SSH root user\nROOT_PASSWD = rootpass\n\n# Web UI credentials: user=admin, password=adminpass\nWEBUI_ADMIN_PASSWD = adminpass\n\n# IPMI credentials: user=admin, password=adminpass\nIPMI_ADMIN_PASSWD = adminpass\n
  5. Build the OS. It may take about one hour depending on the Internet connection:

    [user@localhost os]$ make os\n

    Tip

    If you get an error about failing to retrieving a file, please edit the Makefile and remove de3. from the repo URL.

  6. Create an image. It will be stored in the images directory as a file with *.img extension:

    [user@localhost os]$ make image\n
  7. Flash the result image to SD card.

"},{"location":"cheatsheet/","title":"PiKVM Cheat Sheet","text":""},{"location":"cheatsheet/#pikvm-cheat-sheet","title":"PiKVM Cheat Sheet","text":"

Here are first steps guides for each PiKVM device:

PiKVM V4 Mini & Plus

PiKVM V3

DIY PiKVM V2

DIY PiKVM V1

"},{"location":"cheatsheet/#basics","title":"Basics","text":"Performing commands with root privileges

There are two ways to perform any command with root privileges.

  1. Gain root privileges, then perform any command.

    [kvmd-webterm@pikvm ~]$ su -

    After providing root account password, you will be able to run any commands as a root user as long as the session is running. Use it wisely. For example, if you need to reboot PiKVM, all you need to do is this:

    [root@pikvm ~]# reboot

    The use of su - applies to both SSH and web terminal sessions.

  2. Use su -c followed by the command wrapped in apostrophes. This will perform the command with root privileges a single time, you will not gain permanent root access. This will For example, to reboot PiKVM, do this:

    [kvmd-webterm@pikvm ~]$ su -c 'reboot'

    The use of su -c applies to both SSH and web terminal sessions.

Changing PiKVM Passwords

PiKVM comes with the following default passwords:

  • Linux OS-level admin (SSH, console...):

    • Username: root
    • Password: root
  • KVM user (Web Interface, API, VNC...):

    • Username: admin
    • Password: admin
    • No 2FA code

They are two separate accounts with independent passwords.

To change passwords, you will need to use the console access via SSH or the Web Terminal. If you are using the Web Terminal, enter the su - command to get the root access (enter the root user password).

[root@pikvm ~]# rw\n[root@pikvm ~]# passwd root\n[root@pikvm ~]# kvmd-htpasswd set admin\n[root@pikvm ~]# ro\n

If you require additional user for the Web UI access, use the following:

[root@pikvm ~]# kvmd-htpasswd add <user> # Add a new user with password\n[root@pikvm ~]# kvmd-htpasswd del <user> # Remove/delete a user\n

Optionally you can enable the two-factor authentication for more security.

Changing the VNCAuth key and IPMI password at the first start of PiKVM is not required, since these services are disabled by default. But it is here just so that you remember their existence.

Configuring PiKVM OS

Need more info? We have it!

The following is a brief guide to configuring PiKVM. For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), please refer to this page.

Most of the PiKVM configuration files are located in the /etc/kvmd directory.

The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. To redefine system parameters use the file /etc/kvmd/override.yaml. All other files that are also not recommended for editing have read-only permissions.

You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory to split your customization into logical parts. The override.yaml file definitions takes precedence over the override.d directory.

A complete list of all parameters can be viewed using the kvmd -m command.

Files with the *.yaml suffix uses the YAML syntax and describes a parameter tree with key-value pairs of different types. To define the parameters within one section, an indent of 4 spaces is used. Comments starts with the # symbol.

Only 4 spaces should be used for indentation

Be careful when editing YAML and follow this rule. Invalid indentation or tabs instead of spaces will cause an error when starting the services.

Sections under the same keys should be merged:

  • Wrong:

    kvmd:\n    gpio:\n        drivers: ...\nkvmd:\n    gpio:\n        scheme: ...\n
  • Correct:

    kvmd:\n    gpio:\n        drivers: ...\n        scheme: ...\n

In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

Updating PiKVM OS

To update, run following commands under the root user:

[root@pikvm ~]# pikvm-update\n

If you encounter an error like:

[root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

It's most likely you have an old OS release. You can update the OS as follows:

[root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

Next time you will be able to use the usual method with pikvm-update.

Connecting to PiKVM via SSH

SSH is the most common remote access method in the Linux world. Normally, it should be possible to simply run ssh root@pikvm in a terminal window to connect to your PiKVM. However, this can fail for various reasons. In that case, you will have to connect using PiKVM's IP address.

To connect to PiKVM via SSH, do this:

  1. Discover PiKVM's IP address in the local network. There are several ways to do that:

    • Open the web interface of your router and find the list of issued IP addresses there.
    • Linux-only: install and run arp-scan: sudo arp-scan --localnet.
    • Linux, MacOS, Windows: Download and run Angry IP Scanner.
    • Windows PowerShell: Use the arp -a command.

    In each case, look for the entry that says \"Raspberry Pi Trading Ltd\" and copy its IP address to the clipboard. Let's assume that the IP address is 192.168.0.100.

  2. Run the SSH client to connect to PiKVM:

    • Linux, MacOS: Open any terminal application and run: ssh root@192.168.0.100.
    • Windows: Use PuTTY for this.
  3. Submit your root user credentials. The default password is root. If you haven't changed it, you absolutely should do it.

  4. You should now be able to see and interact with the serial port. All the system tools in PiKVM will be available in the terminal window. Once you are done, type exit and press Enter, or simply press Ctrl+d to terminate the session.

Connecting to PiKVM via serial console

A serial console is a convenient and fast way to connect to PiKVM when there is no network, or get boot logs and a console if something goes wrong.

  1. Connect to the physical universal asynchronous receiver / transmitter (UART) console from your host computer:

    • On PiKVM V3 or V4, you have a built-in USB-UART adapter in your device. Just disconnect the OTG cable and place the USB-C end into the IOIOI port on V4 (or the CON port on V3). Place the USB-A end into the port you want serial to be accessed, typically done on the host. If you have a Windows host, you may need to install this driver, other operating systems may not need one.

    • On DIY PiKVM V1 or V2, you'll need to get the right TTY to USB cable, we recommend the RPi Debug Probe and follow existing RPi TTY serial setups.

  2. Install picocom on a Linux or a macOS host (available in Homebrew and MacPorts), or Putty on Windows.

  3. Identify the port that your operating system exposes for connecting to the PiKVM.

    • Windows: look this up in the Device Manager

    • Linux: open a terminal program, run sudo dmesg | grep ttyand look for a message like this:

    [14362.388405] usb 1-2: cp210x converter now attached to ttyUSB0\n

    This means you will need to use /dev/ttyUSB0.

    • macOS: open the terminal and list all USB serial devices with ls /dev/cu.usbserial-*. Look for a device that contains cu.usbserial, e.g. /dev/cu.usbserial-FT0RVWSW.
  4. Connect via the serial port:

    • Windows: select the COM port in Putty and use the 115200 baud rate, then connect.

    • Linux/macOS: open your terminal program and run sudo picocom -b 115200 $USB_SERIAL_DEVICE where $USB_SERIAL_DEVICE is the device you looked up, e.g. /dev/ttyUSB0 on Linux or /dev/cu.usbserial-FT0RVWSW on macOS.

    After running the command, press Enter to get to a login prompt.

  5. Submit your root user credentials.

  6. You should now be able to see and interact with the serial port. All the system tools in PiKVM will be available in the terminal window. Once you are done, press Ctrl+a and then immediately Ctrl+x to terminate the session.

Shutting down PiKVM

PiKVM defaults to using the system in read-only mode, so there is no need to explicitly shut it down. You can simply unplug the device from power.

If you absolutely need to use the shutdown command, please ensure the following requirements are met:

  • This is not one of the DIY (V1 or V2) devices. If you shut down a DIY PiKVM, it will not power on until you physically reconnect the power cord.
  • You are not currently running a system update. If you are, you will likely corrupt the system.
  • You are not currently uploading a mass storage drive image. If you are, you will likely corrupt the system.

If all these requirements are met, do this:

[kvmd-webterm@pikvm ~]$ su -\n[root@pikvm ~]# shutdown -h now\n

PiKVM V3 and V4 will automatically reboot after several minutes of being halted. DIY PiKVM will need a power cord reconnection to become available again.

"},{"location":"cheatsheet/#getting-user-support","title":"Getting User Support","text":"

If something doesn't work, check out our FAQ. Otherwise, head straight to our Support.

"},{"location":"cloudflared/","title":"Cloudflare tunnels","text":"

Warning

This is unofficial instructions proposed by the community. We don't officially support this and don't know what problems may arise when using cloudflared.

Cloudflare Tunnels can be used to access PiKVM over the internet securely using Cloudflare Zero Trust with Cloudflared. This is a convenient and free (for 50 users) tool for allowing access to web services running on your internal network without port forwarding or IPv4/IPv6 compatability issues. This document is provided as an example for accessing your PiKVM over the internet but you can also use Zerotier/Tailscale/Insert XYZ VPN service here. Basic support like whats shown below is provided as an example, any other setting or functionality needs to be redirected to the appropriate community.

If you get error 1033 / lookup localhost error

You might need to add 127.0.0.1 localhost into your /etc/hosts file

"},{"location":"cloudflared/#prequisites","title":"Prequisites","text":"
  1. A domain utilizing Cloudflare for DNS

  2. A Cloudflare tunnel configured with an application created and secured by an access policy

  3. Custom firewall rules configured in Cloudflare as needed

"},{"location":"cloudflared/#cloudflare-tunnel-steps","title":"Cloudflare Tunnel Steps","text":"
  1. Login to Cloudflare and provision a tunnel using the steps here. Save the tunnel token as we will need this later. In most cases the target will be https://localhost

  2. Create a self-hosted application with the URL matching one created in the previous step by following the steps here.

  3. You will need to check the http options to disable SSL certificate verification under Tunnels -> Configure -> Public Hostname -> yourapplication.yourdomain -> Edit -> TLS Settings -> No TLS Verify as the PiKVM uses self-signed certificates.

  4. Don't skip the access policies as this important to preventing randoms from the internet from gaining access to your PiKVM. Cloudflare offers a variety of login options with the simplest being One-time PINs that are emailed to you. NOTE: This external authentication will not replace the username/password for the PiKVM but instead supplement it acting as a first line of defense from the internet.

"},{"location":"cloudflared/#installation-on-the-pikvm","title":"Installation on the PiKVM","text":"
  1. Use these commands to install Cloudflared:

    # rw\n# curl -L -o /usr/local/bin/cloudflared \"$(curl -s \"https://api.github.com/repos/cloudflare/cloudflared/releases/latest\" | grep -e 'browser_download_url.*/cloudflared-linux-armhf\"' | sed -e 's/[\\ \\\":]//g' -e 's/browser_download_url//g' -e 's/\\/\\//:\\/\\//g')\"\n# chmod +x /usr/local/bin/cloudflared\n# cloudflared version\n
  2. Update /etc/systemd/resolved.conf and set cloudflare nameservers.

    # sudo vim /etc/systemd/resolved.conf\n# Uncomment DNS line and set 'DNS=1.1.1.1 1.0.0.1'\n# systemctl restart systemd-resolved\n
  3. Install the Cloudflare tunnel service to Cloudflared.

    # sudo cloudflared service install SERVICE_TOKEN_HERE\n
  4. Ensure cloudflared service is enabled so it starts on boot.

    # sudo systemctl enable cloudflared\n
  5. Open a web browser and attempt to connect to your tunnel.

  6. Drop back in to read only mode

    # ro\n
  7. Reboot pikvm and ensure your tunnel comes back up. This may take a few minutes.

"},{"location":"cloudflared/#updating-cloudflared","title":"Updating Cloudflared","text":"

Use these commands to update Cloudflared:

# rw\n# cloudflared update\n# ro\n
"},{"location":"compliance/","title":"Compliance","text":""},{"location":"compliance/#compliance-information","title":"Compliance Information","text":"
  • PiKVM CE/UKCA
"},{"location":"config/","title":"Overriding system settings","text":"

PiKVM OS has various low-level settings you can customize: timeout for the kvmd daemon, default keymap for the emulated keyboard, scroll rate for VNC sessions, logs formatting, etc. To do that, you need to override default settings.

"},{"location":"config/#how-overrides-work-in-pikvm-os","title":"How overrides work in PiKVM OS","text":"

Main default settings are stored in /usr/lib/kvmd/main.yaml. However, you should never edit that file. To override these and other defaults, you need to edit /etc/kvmd/override.yaml instead.

PiKVM OS applies settings from main.yaml first and then applies anything it finds in override.yaml. This approach helps keeping defaults and customizations safely separate from each other.

"},{"location":"config/#how-overrideyaml-is-structured","title":"How override.yaml is structured","text":"

The /etc/kvmd/override.yaml file has YAML syntax. All configurations are stored as key-value pairs.

Consider this example:

file: /etc/kvmd/ipmipasswd\n

Here, file is a key, or the name of a configuration entry, and /etc/kvmd/ipmipasswd is the value. Keys and values are separated by a semicolon.

YAML files can have nested key-value pairs:

ipmi:\n    auth:\n        file: /etc/kvmd/ipmipasswd\n

To nest key-value pairs correctly, use four spaces rather than tabulation for indentation.

There is no need to copy and paste an entire configuration tree of key-value pairs to change just one setting. For example, if you want to change just the kvmd timeout, you only need the timeout setting and its parent keys, kvmd and vnc:

vnc:\n    kvmd:\n        timeout: 7.0\n

An important rule is that sections under the same keys should be merged:

  • Wrong:

    kvmd:\n    gpio:\n        drivers: ...\nkvmd:\n    gpio:\n        scheme: ...\n
  • Correct:

    kvmd:\n    gpio:\n        drivers: ...\n        scheme: ...\n

Anything that starts with # is considered a comment. This is useful when you need to document your customizations, e.g., write down the rationale for changing a particular default.

You can start new lines with comments if you need to write a longer explanation.

# 2025-05-08: changed the default timeout to 7.0 after some troubleshooting.\nvnc:\n    kvmd:\n        timeout: 7.0\n

You can also write inline comments like this:

vnc:\n    kvmd:\n        timeout: 7.0 #this seems to work better\n

Let's practice changing a default setting by switching to a German keyboard map by default. This is just an example to explain how overrides work.

"},{"location":"config/#change-file-system-access-to-read-write","title":"Change file system access to read-write","text":"

For safety reasons, access to the file system of PiKVM OS is read-only by default. You need to temporarily change it to read-write to be able to save changes to the configuration file. To do it, use the rw command:

[root@pikvm ~]# rw\n
"},{"location":"config/#identify-the-configuration-entry","title":"Identify the configuration entry","text":"

Before you start editing, you need to find the setting you will need to override. Run kvmd -m to look up configuration entries you can redefine. This command will print the entire list. We need the keymap setting somewhere in the kvmd group:

So, the correct hierarchy is kvmd/hid/keymap, and the path to keymaps is /usr/share/kvmd/keymaps/.

List all keymaps in that directory:

[root@pikvm ~]# ls /usr/share/kvmd/keymaps/\nar    cz  de     en-gb  en-us-altgr-intl  es  fi  fr     fr-ca  hr  is  ja  lv  nl  pl  pt-br  sl  th\nbepo  da  de-ch  en-us  en-us-colemak     et  fo  fr-be  fr-ch  hu  it  lt  mk  no  pt  ru     sv  tr\n

You will need de, which is a two-letter code for German.

"},{"location":"config/#edit-overrideyaml","title":"Edit override.yaml","text":"

Now, let's open override.yaml for editing. PiKVM ships with both nano and vim. We generally recommend nano over vim for new users:

[root@pikvm ~]# nano /etc/kvmd/override.yaml\n

nano has a console user interface, so it displays the text file right in the terminal window:

Scroll down to the bottom of the file (use Ctrl+End, PageDown, or ArrowDown keys). Type this:

kvmd:\n    hid:\n        keymap: /usr/share/kvmd/keymaps/de\n

Don't forget to indent each child key with four spaces.

"},{"location":"config/#save-the-file","title":"Save the file","text":"

Now, you need to save the configuration file and exit. Nano displays hints on the most important keyboard shortcuts at the bottom of its window.

^ stands for Ctrl on Windows and Linux and for Cmd on macOS. M stands for Alt.

Press Ctrl+O to save the configuration file and then Ctrl+X to quit nano.

"},{"location":"config/#validate-the-configuration","title":"Validate the configuration","text":"

Before attempting to make your changes take effect, you should always validate override.yaml. To do that, run kvmd -m. If there are any syntax errors, kvmd will complain about them.

For example, if you accidentally used a semicolon instead of a colon between the key and the value like this:

keymap; /usr/share/kvmd/keymaps/de\n

kvmd -m will display this message instead of outputting all configuration entries:

ConfigError: The node 'vnc' must be a dictionary\n

If you see any errors in the output, fix them and run kvmd -m again to verify that the error is gone.

Note that kvmd -m does not validate configuration entries for correct key names. So if your changes don't work, that's #1 thing to check for when troubleshooting.

"},{"location":"config/#change-access-to-read-only","title":"Change access to read-only","text":"

Before you go to the next step, change the file system access mode to read-only. To do that, run the ro command:

[root@pikvm kvmd-webterm]# ro\n
"},{"location":"config/#reboot-your-pikvm","title":"Reboot your PiKVM","text":"

There are close to a dozen various system daemons that depend on configuration settings. The easiest way to apply your changes is to simply reboot your PiKVM:

[root@pikvm ~]# reboot\n

Once the device restarts, your changes take effect.

"},{"location":"config/#keeping-customizations-atomic","title":"Keeping customizations atomic","text":"

When you apply massive customizations, it may help separating changes into several files to keep them manageable.

To do that, create these YAML files inside the /etc/kvmd/override.d/ directory. KVMD will apply all configurations in the following order: main.yaml -> legacy auth.yaml -> override.d -> override.yaml. Inside the override.d directory, KVMD will apply YAML files in alphabetical order, so please pay attention to how you name them.

We recommend sticking with a particular file-naming scheme, e.g. 0000-vendor-otg-serial.yaml. We do reserve -vendor- and -pikvm- prefixes for our own future needs, though.

Once you completed the customization and validated newly created/edited files, reboot your PiKVM for the changes to take effect.

"},{"location":"config/#legacy-notes","title":"Legacy notes","text":"
  • Older installations may have used the outdated /etc/kvmd/auth.yaml for authorization settings. It existed even before the introduction of /etc/override* mechanism. It has never been recommended for use in this documentation and should contain only the string {}, meaning an empty configuration.

    However, if you have used it, you should move your configuration from /etc/kvmd/auth.yaml somewhere in /etc/kvmd/override.d or even /etc/kvmd/override.yaml, and then delete the source file /etc/kvmd/auth.yaml.

    For example, if the /etc/kvmd/auth.yaml contained the following text:

    enabled: false\n

    You can move it to /etc/kvmd/override.d/9999-auth.yaml and change the nesting of the parameters as follows:

    kvmd:\n    auth:\n        enabled: false\n
  • Early YAML configurations could contain the !include directive, which loaded the content of another file to the appropriate level. It still works, but has been deprecated and should not be used. Support will be removed in the future.

"},{"location":"edid/","title":"EDID","text":"

Info

This applies to PiKVM V3, V4 and DIY based on CSI bridge. It is impossible to change the EDID for the HDMI-USB dongle.

The EDID provides an information about the video modes supported by the video capture device. In the case of PiKVM, this is an HDMI CSI bridge. Usually, you don't need to change this, since the default configuration is quite flexible, but sometimes, for example for strange UEFIs/BIOSes, this may be necessary (a story).

"},{"location":"edid/#basics","title":"Basics","text":"

The EDID is stored on the PiKVM in the file /etc/kvmd/tc358743-edid.hex in HEX format. When booting PiKVM OS, it is used by kvmd-tc358743.service and loaded into the video capture chip.

If you replace the EDID in this file, the EDID can be applied manually without rebooting using the command kvmd-edidconf --apply.

If you just want to change the monitor's identification, we don't recommend that you change the entire EDID. Just use kvmd-edidconf and its built-in EDID changing options.

Note

Windows caches drivers and registry settings so changing the monitor name is not enough, you will also need to change the product ID and/or the serial number along with the monitor name:

[root@pikvm ~]# kvmd-edidconf --set-monitor-name=TOSHIBA --set-mfc-id=TTP --set-product-id=34953 --set-serial=2290649089 --apply\n

Quick IDs changing on PiKVM V4 Plus

PiKVM V4 Plus has a simple way read and adopt display identifiers like model and serial number from your physical display. See here for details.

Run kvmd-edidconf on PiKVM:

[root@pikvm ~]# kvmd-edidconf\nManufacturer ID: LNX\nProduct ID:      0x7773 (30579)\nSerial number:   0x01010101 (16843009)\nMonitor name:    PiKVM V4 Plus\nMonitor serial:  CAFEBABE\nAudio:           yes\n

The fields have obvious names and purposes. Note the two similar fields Serial number and Monitor serial. The first has a numeric value, and the second is ASCII. If you are using a custom EDID from some real display, some fields may be missing.

To change the values of the EDID fields, use the kvmd-edidconf with options, a complete list is available in kvmd-edidconfi --help.

Here the small example of changing all available fields from the previous listing:

[root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-edidconf --set-mfc-id=TTP --set-product-id=0x5B81 --set-serial=0x8DE11B79 --set-monitor-name=TOSHIBA --set-monitor-serial=ABCD1234 --apply\nManufacturer ID: TTP\nProduct ID:      0x5B81 (23425)\nSerial number:   0x8DE11B79 (2380340089)\nMonitor name:    TOSHIBA\nMonitor serial:  ABCD1234\nAudio:           yes\n...\n[root@pikvm ~]# ro\n

The full list of manufacturer IDs is available here.

Typical examples of working with EDID and the full cycle of using custom EDID will be shown below.

"},{"location":"edid/#adopt-real-display-indentifiers-on-v4-plus","title":"Adopt real display indentifiers on V4 Plus","text":"

PiKVM V4 Plus has a simple way read and adopt display identifiers like model and serial number from the physical monitor connected to OUT2 port (it's also used for HDMI passthrough). This way, the target host will recognize PiKVM as your display.

To adopt display identifiers, connect the display to OUT2 port and run these commands:

[root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-edidconf --import-display-ids --apply\n[root@pikvm ~]# ro\n

Now the display can be unplugged. PiKVM will remember the new settings.

"},{"location":"edid/#restore-default-edid","title":"Restore default EDID","text":"

If you need to restore the default EDID you can easily do this with kvmd-edidconf, for example:

[root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-edidconf --import-preset=v4plus --apply\n[root@pikvm ~]# ro\n
Available options: v0, v1, v2, v3, v4mini and v4plus.

Also defaults edid can be found locally on your PiKVM: /usr/share/kvmd/configs.default/kvmd/edid, or in the kvmd repo.

"},{"location":"edid/#force-1080p-by-default-on-pikvm-v0-v3","title":"Force 1080p by default on PiKVM V0-V3","text":"

PiKVM V3 (or DIY V0-V2) has a hardware limit of 50Hz for 1080p mode, and this is a less common frequency than 60Hz. Therefore, on V3, the default mode is 720p. Some OS (like Proxmox) may not work well with 720p, so you can force 1080p resolution by default:

[root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-edidconf --import-preset=v3.1080p-by-default --apply  # Or, for example, v1.1080p-by-default\n[root@pikvm ~]# ro\n
"},{"location":"edid/#disable-1920x1200-on-pikvm-v4","title":"Disable 1920x1200 on PiKVM V4","text":"

PiKVM V4 supports the advanced capture mode with 1920x1200. If it bothers you (for example, if you use a physical monitor 1920x1080 with video passthrough), you can easily disable it and use only 1920x1080:

[root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-edidconf --import-preset=v4plus.no-1920x1200 --apply  # Or v4mini.no-1920x1200\n[root@pikvm ~]# ro\n
"},{"location":"edid/#applying-a-custom-edid","title":"Applying a custom EDID","text":"

PiKVM is able to emulate a physical display with a specific EDID. You can find EDID examples in the community database and then use it on PiKVM.

At the same time, you should pay attention to the hardware capabilities of PiKVM and the EDID capabilities that you use. For example, if EDID reports 8K support, then this obviously won't work: your host will try to send an 8K signal, while PiKVM can process no more than 1080p.

  • PiKVM V1-V3: The maximum resolution is 1920x1080 at 50Hz.
  • PiKVM V4: The maximum is 1920x1200 at 60Hz.

In the case of the PiKVM V4, almost any EDID for 1080p monitors will work. All EDIDs that are suitable for PiKVM V3 will work too.

"},{"location":"edid/#example-edids-for-v4","title":"Example EDIDs for V4","text":"Acer B246WL, 1920x1200, with audio

Taken here, as described above.

00FFFFFFFFFFFF00047265058A3F6101\n101E0104A53420783FC125A8554EA026\n0D5054BFEF80714F8140818081C08100\n8B009500B300283C80A070B023403020\n360006442100001A000000FD00304C57\n5716010A202020202020000000FC0042\n323436574C0A202020202020000000FF\n0054384E4545303033383532320A01F8\n02031CF14F9002030405060701111213\n1415161F2309070783010000011D8018\n711C1620582C250006442100009E011D\n007251D01E206E28550006442100001E\n8C0AD08A20E02D10103E960006442100\n0018C344806E70B028401720A8040644\n2100001E000000000000000000000000\n00000000000000000000000000000096\n
ASUS PA248QV, 1920x1200, with audio

Taken here, as described above.

00FFFFFFFFFFFF0006B3872401010101\n021F010380342078EA6DB5A7564EA025\n0D5054BF6F00714F8180814081C0A940\n9500B300D1C0283C80A070B023403020\n360006442100001A000000FD00314B1E\n5F19000A202020202020000000FC0050\n4132343851560A2020202020000000FF\n004D314C4D51533035323135370A014D\n02032AF14B900504030201111213141F\n230907078301000065030C001000681A\n00000101314BE6E2006A023A80187138\n2D40582C450006442100001ECD5F80B0\n72B0374088D0360006442100001C011D\n007251D01E206E28550006442100001E\n8C0AD08A20E02D10103E960006442100\n001800000000000000000000000000DC\n
DELL D2721H to avoid black screen on some HDMI splitters, 1920x1080, no audio

Taken here, as described above.

00FFFFFFFFFFFF0010AC132045393639\n201E0103803C22782ACD25A3574B9F27\n0D5054A54B00714F8180A9C0D1C00101\n010101010101023A801871382D40582C\n450056502100001E000000FF00335335\n475132330A2020202020000000FC0044\n454C4C204432373231480A20000000FD\n00384C1E5311000A2020202020200181\n02031AB14F9005040302071601061112\n1513141F65030C001000023A80187138\n2D40582C450056502100001E011D8018\n711C1620582C250056502100009E011D\n007251D01E206E28550056502100001E\n8C0AD08A20E02D10103E960056502100\n00180000000000000000000000000000\n0000000000000000000000000000004F\n
"},{"location":"edid/#example-edids-for-v1-v3","title":"Example EDIDs for V1-V3","text":"1280x1024 as preferred. Useful for Gigabyte GA-H77-DS3H
00FFFFFFFFFFFF005262888800888888\n1C150103800000780AEE91A3544C9926\n0F505425400001000100010001000100\n010001010101D51B0050500019400820\nB80080001000001EEC2C80A070381A40\n3020350040442100001E000000FC0050\n492D4B564D20566964656F0A000000FD\n00323D0F2E0F0000000000000000014D\n02030400DE0D20A03058122030203400\nF0B400000018E01500A0400016303020\n3400000000000018B41400A050D01120\n3020350080D810000018AB22A0A05084\n1A3030203600B00E1100001800000000\n00000000000000000000000000000000\n00000000000000000000000000000000\n00000000000000000000000000000045\n
1920x1080 as preferred. Useful for motherboards such as ASRock H670 PG Riptide, Gigabyte GA-H77-DS3H, MSI series such as B550M, B660M, Z690-A and X570. Also the Intel NUC.
00FFFFFFFFFFFF005262888800888888\n1C150103800000780AEE91A3544C9926\n0F505425400001000100010001000100\n010001010101D32C80A070381A403020\n350040442100001E7E1D00A050001940\n3020370080001000001E000000FC0050\n492D4B564D20566964656F0A000000FD\n00323D0F2E0F000000000000000001C4\n02030400DE0D20A03058122030203400\nF0B400000018E01500A0400016303020\n3400000000000018B41400A050D01120\n3020350080D810000018AB22A0A05084\n1A3030203600B00E1100001800000000\n00000000000000000000000000000000\n00000000000000000000000000000000\n00000000000000000000000000000045\n
1280x1024 as preferred, disabled 1080p at all. This may be necessary in extremely rare cases if the BIOS is completely buggy. In the future, we will provide a way to dynamically switch EDID
00FFFFFFFFFFFF005262888800888888\n1C150103800000780AEE91A3544C9926\n0F50542FCF0001000100010001000100\n0100010101018C2300A050001E403020\n370080001000001E000000FC0050492D\n4B564D20566964656F0A000000FD0032\n3D0F2E0F000000000000000000000010\n0000000000000000000000000000016B\n02030400DE0D20A03058122030203400\nF0B400000018E01500A0400016303020\n3400000000000018B41400A050D01120\n3020350080D810000018AB22A0A05084\n1A3030203600B00E1100001800000000\n00000000000000000000000000000000\n00000000000000000000000000000000\n00000000000000000000000000000045\n
"},{"location":"edid/#applying-a-choosen-custom-edid","title":"Applying a choosen custom EDID","text":"

To apply the selected EDID, follow these steps:

  1. Switch filesystem to RW-mode:

    [root@pikvm ~]# rw\n
  2. Open the file /etc/kvmd/tc358743-edid.hex with any text editor, for example, with Nano:

    [root@pikvm ~]# nano /etc/kvmd/tc358743-edid.hex\n
  3. Replace the HEX data with the new, save and close the editor.

  4. Apply the EDID:

    [root@pikvm ~]# kvmd-edidconf --apply\n
  5. Sometimes it may be necessary to reboot the target host. Check the OS on the host, UEFI/BIOS. If everything works, then your goal has been achieved and proceed to the last step. If something went wrong, you can always undo these changes and restore the default EDID.

  6. Don't forget to switch filesystem to the RO-mode:

    [root@pikvm ~]# ro\n
"},{"location":"edid/#editing-edid","title":"Editing EDID","text":"

To edit the EDID, it is best to use third-party utilities, such as the recommended advanced AW EDID Editor for Windows (it's working great in wine) or wxEDID. Both editors work with the binary EDID format, but you can easily import and export it to PiKVM using the kvmd-edidconf utility.

So, to tune EDID on PiKVM, use the following steps:

  1. Switch filesystem to RW-mode:

    [root@pikvm ~]# rw\n
  2. Export the system EDID to the binary file myedid.bin:

    # kvmd-edidconf --export-bin=/root/myedid.bin\n
  3. Copy this file to your PC using SCP, Putty or something like that. Open this binary file in the EDID editor and change the necessary parameters. Save your changes and copy the binary file back to PiKVM.

  4. Convert the binary file to the HEX and test it:

    [root@pikvm ~]# kvmd-edidconf --import=/root/myedid.bin --apply\n
  5. Sometimes it may be necessary to reboot the target host. Check the OS on the host, UEFI/BIOS. If everything works, then your goal has been achieved and proceed to the last step. If something went wrong, you can always undo these changes and restore the default EDID.

  6. Don't forget to switch filesystem to the RO-mode:

    [root@pikvm ~]# ro\n
"},{"location":"ezcoo/","title":"ezCoo managed multiport KVM switch","text":"

Warning

While we provide this document for your convenience, this is a third-party hardware device in the same path as a PiKVM. Therefore, you may need to experiment (trial and error) to get it to work how you like. In the case of the U3P (hot key version), it may or may not work as expected.

PiKVM + Multiport Switches compatibility

Please note that this switch requires a USB port for control. The following devices can provide this:

  • PiKVM V3 & V4 Plus.
  • DIY devices based on Raspberry Pi 2, 3 and 4.

The following devices are not compatible:

  • PiKVM V4 Mini - it doesn't have a USB host port and cannot control switches, it's a single-host device.
  • DIY based on Raspberry Pi Zero 2 W - it doesn't have USB host port too.

The ezCoo managed switch can be controlled by PiKVM to allow it to connect to multiple hosts. A typical scenario is a single PiKVM device which can control and switch between multiple hosts or servers using the ezCoo switch. UI elements can be added to the GPIO dropdown to allow switching between hosts from the PiKVM webpage.

The instructions here were tested with the ezCoo SW41HA HDMI 4x1 switch ezCoo EZ-SW41HA-KVMU3L 4x1 switch OR ezCoo EZ-SW41HA-KVMU3P 4x1 switch.

Both older USB2.0 and newer USB3.0 variants are supported. The following was testing on a Raspberry Pi 4 but should also work on the Pi 2 and 3.

This document was created using the contributions from multiple users in our Discord and the author appreciates their efforts.

Info

While most images of the switch do not show the sides, there is a Micro USB port on the side of the ezCoo switch. This is the management port, which is controlled via COM port on the ezCoo KVM. When plugged into the Raspberry Pi, it appears as /dev/ttyUSB0.

Info

Audio was not tested, it is assumed to be non-functional.

Tip

ezCoo EZ-SW41HA-KVMU3L - includes 4x1m USB 3.0 A Male to A Male. You will need 1 extra USB A Male to USB Micro B to connect from the PiKVM to the ezcoo \"F/W CTL - Management\" port

"},{"location":"ezcoo/#connections","title":"Connections","text":"

EZCOO Wiring example can be found here Scroll down to bottom of page for picture

Please review the item description and manual before deploying.

From a high level, the ezCoo switch uses standard connections to the host machines (USB-A to USB-B and HDMI for USB2 version, USB-A to USB-A for the USB3 version). The Raspberry Pi OTG connector (the one coming from the USB-C port on a Pi 4 via the custom splitter cable or device) should be connected to the USB 3 port on the ezCoo switch. There is an additional USB cable connected to the managed port on the switch.

  1. Connect the USB-C cable from the Raspberry Pi OTG port to ezCoo switch USB 3 port on the front or USB 1 port on the back of the switch. Note: If this cable is connected to the keyboard port (USB 2) of the ezCoo switch, the mouse will not be present.

  2. Connect the HDMI out from the ezCoo switch to the Raspberry Pi CSI-2 to HDMI input. Other users have reported HDMI encoder USB dongles as working.

  3. Connect a USB-A to Micro USB cable from the Raspberry Pi to the management port on the side of the ezCoo switch.

  4. Connect host USB and HDMI cables from the ezCoo switch to the machines to be managed per the switch instructions.

  5. At this point the KVM switch should be present as a device on the PiKVM. SSH into PiKVM and ensure a device like /dev/ttyUSB0 is present. The following instructions assume this is the KVM switch.

Info

There is a limitation in the underlying PiKVM software related to plugging video cables from a host which is already powered and connected to a monitor to a Raspberry Pi CSI2-HDMI encoder. These limitations apply equally when using the ezCoo KVM switch. If video is not present in PiKVM, try keeping all host machines off and connecting them directly to the ezCoo switch before powering the hosts on.

"},{"location":"ezcoo/#adding-ui-elements-to-control-the-kvm-switch","title":"Adding UI elements to control the KVM switch","text":"

The UI can be updated to add buttons to switch between KVM inputs and indicators for which input is currently selected. The instructions below will make these available in the PiKVM UI after clicking the \"GPIO\" menu button in the KVM view.

  1. Enable read-write mode on the SD card via rw

  2. Edit the file: nano /etc/kvmd/override.yaml and include the following. Note the assumption that the KVM switch is present on /dev/ttyUSB0:

    kvmd:\n    gpio:\n        drivers:\n            ez:\n                type: ezcoo\n                protocol: 2\n                device: /dev/ttyUSB0\n        scheme:\n            ch0_led:\n                driver: ez\n                pin: 0\n                mode: input\n            ch1_led:\n                driver: ez\n                pin: 1\n                mode: input\n            ch2_led:\n                driver: ez\n                pin: 2\n                mode: input\n            ch3_led:\n                driver: ez\n                pin: 3\n                mode: input\n            ch0_button:\n                driver: ez\n                pin: 0\n                mode: output\n                switch: false\n            ch1_button:\n                driver: ez\n                pin: 1\n                mode: output\n                switch: false\n            ch2_button:\n                driver: ez\n                pin: 2\n                mode: output\n                switch: false\n            ch3_button:\n                driver: ez\n                pin: 3\n                mode: output\n                switch: false\n        view:\n            table:\n                - [\"#Input 1\", ch0_led, ch0_button]\n                - [\"#Input 2\", ch1_led, ch1_button]\n                - [\"#Input 3\", ch2_led, ch2_button]\n                - [\"#Input 4\", ch3_led, ch3_button]\n
    Editing '#Input X' to '#Something else' will change the table name in the GUI drop down, if you want a different name, name it something else and restart kvmd.

    This now only applies to older images, newer images do not have this issue. Make sure to notate the spaces for each line, needs to be a total of 4 spaces added per line (NOT tabs):

    For example:\n    parent: 0 spaces (kvmd:)\n    child: 4 spaces (gpio:)\n    sub-child: 8 spaces (drivers:)\n    sub-sub-child: 12 spaces (ez:)\n
  3. Return to read-only mode for the sd card via ro.

  4. Restart the kvmd service: systemctl restart kvmd.

  5. If you are still not getting KB output, issue a ls -la /dev/tty* | grep USB , if no output change cables (Alot of cables are power only)

"},{"location":"ezcoo/#switching-between-hosts-in-the-ui","title":"Switching between hosts in the UI","text":"

To switch between hosts, enter the KVM UI and click the \"GPIO\" menu. You should see 4 inputs, one of which will have a green circle indicating it is currently selected. Click the other inputs to change the selected host.

"},{"location":"ezcoo/#additional-step-for-the-usb-20-version-old-eol-version","title":"Additional step for the USB 2.0 version (Old EOL version)","text":"

Please remove protocol: 2 to the override.yaml under the type: ezcoo at the same level:

kvmd:\n    gpio:\n        drivers:\n            ez:\n                type: ezcoo\n                device: /dev/ttyUSB0\n
"},{"location":"ezcoo/#developer-info","title":"Developer info","text":"
  • The official protocol version 1 reference
  • Differences between protocols 1 and 2
    ===============================================================================================================================\n=********************************************************Systems HELP*********************************************************=\n=-----------------------------------------------------------------------------------------------------------------------------=\n=                        System Address = 00           F/W Version : 1.20                                                     =\n=   Azz                           :  All Commands start by Prefix System Address zz, if [01-99]                               =\n=-----------------------------------------------------------------------------------------------------------------------------=\n=   EZH                           : Help                                                                                      =\n=   EZSTA                         : Show Global System Status                                                                 =\n=   EZS RST                       : Reset to Factory Defaults                                                                 =\n=   EZS ADDR xx                   : Set System Address to xx {xx=[00~99](00=Single)}                                          =\n=   EZS CAS EN/DIS                : Set Cascade Mode Enable/Disable                                                           =\n=   EZS OUTx VS INy               : Set Output x To Input y{x=[0~2](0=ALL), y=[1~4]}                                          =\n=   EZS IR SYS xx.yy              : Set IR Custom Code{xx=[00-FFH],yy=[00-FFH]}                                               =\n=   EZS IR OUTx INy CODE zz       : Set IR Data Code{x=[1~2],y=[1~4],zz=[00-FFH]}                                             =\n=   EZG ADDR                      : Get System Address                                                                        =\n=   EZG STA                       : Get System System Status                                                                  =\n=   EZG CAS                       : Get Cascade Mode Status                                                                   =\n=   EZG OUTx VS                   : Get Output x Video Route{x=[0~2](0=ALL)}                                                  =\n=   EZG IR SYS                    : Get IR Custom Code                                                                        =\n=   EZG IR OUTx INy CODE          : Get IR Data Code{x=[1~2],y=[1~4]}                                                         =\n=   EZS OUTx VIDEOy               : Set Output VIDEO Mode                                                                     =\n=                                   {x=[1~2], y=[1~2](1=BYPASS,2=4K->2K)}                                                     =\n=-----------------------------------------------------------------------------------------------------------------------------=\n=Input Setup Commands:(Note:input number(x)=HDMI(x),x=1)                                                                      =\n=   EZS INx EDID y                : Set Input x EDID{x=[0~4](0=ALL), y=[0~15]}                                                =\n=                                   0:EDID_BYPASS         1:1080P_2CH_HDR          2:1080P_6CH_HDR        3:1080P_8CH_HDR     =\n=                                   4:1080P_3D_2CH_HDR    5:1080P_3D_6CH_HDR   6:1080P_3D_8CH_HDR                             =\n=                                   7:4K30HZ_3D_2CH_HDR  8:4K30HZ_3D_6CH_HDR  9:4K30HZ_3D_8CH_HDR                             =\n=                                   10:4K60HzY420_3D_2CH_HDR  11:4K60HzY420_3D_6CH_HDR  12:4K60HzY420_3D_8CH_HDR              =\n=                                   13:4K60HZ_3D_2CH_HDR  14:4K60HZ_3D_6CH_HDR  15:4K60HZ_3D_8CH_HDR                          =\n=                                   16:H4K_DOLBY_VISION_ATMOS                                                                 =\n=   EZG INx EDID                  : Get Input x EDID  Index{x=[0~4](0=ALL)}                                                   =\n=-----------------------------------------------------------------------------------------------------------------------------=\n=*****************************************************************************************************************************=\n===============================================================================================================================\n
"},{"location":"ezcoo/#simple-troubleshooting-steps-to-perform","title":"Simple troubleshooting steps to perform","text":"
    Video Issues:\n        Hook a monitor to the output and test\n        Reseat the cables\n        Change out the cables\n\n    Switching issues:\n        SSH or open a web terminal to your PiKVM\n        `ls -la /dev/ttyUSB*` - This should give you an output. If not, try a different cable till an output is displayed.\n
"},{"location":"faq/","title":"FAQ & Troubleshooting","text":"

As a first step, we recommend carefully reading our documentation on GitHub or the updated documentation. Most steps to successfully set up your PiKVM are already described there.

If you run into any issues you can check this page which will list common errors. If that still doesn't help you you're welcome to raise an issue ticket or contact our Suppor for further help.

"},{"location":"faq/#common-questions","title":"Common questions","text":"Where can I get a memory card image for PiKVM?

See here: https://pikvm.org/download

Can PiKVM work on Raspberry Pi 5?
  • Not now, but it will. Pi5 does not support hardware video encoding so there is no any reason to use it for PiKVM.
  • RPi5 is not compatible with PiKVM V3 HAT due to the difference in form factor with RPi4.
Can I connect multiple servers to a single PiKVM?

Yes, but it requires additional work to set up. See this page.

How can I get the access to PiKVM in my local network over Internet?

You can use port forwarding for port 443 on your router if it has an external IP address. In all other cases, you can use the excellent free VPN service Tailscale, which can be configured on PiKVM with a few simple commands.

Can I assign a static IP to a PiKVM

Yes, we highly suggest using this document first for those that are not Linux savvy.

[ONLY FOR ADVANCED LINUX USERS]

Edit file /etc/systemd/network/eth0.network for Ethernet or wlan0.network for Wi-Fi and edit the [Network] section:

[Network]\nAddress=192.168.x.x/24\nGateway=192.168.x.x\nDNS=192.168.x.x\nDNS=192.168.x.x\n

Don't forget the /24 suffix (CIDR), otherwise it will not work and your PiKVM will become unreachable.

How can I disable IPv6 on PiKVM?

To do this, you need at least KVMD 3.301 installed on your device. If this is not the case, update the OS.

Next, append the ipv6.disable=1 parameter to /boot/cmdline.txt and perform reboot.

How do I recover my PiKVM, it cannot be reached now
  1. Take the USB-C end cable you have for your target and move to the PiKVM IOIO port or CON port
  2. Take the USB-A end cable and put this on the HOST(The controlling PC)
  3. Turn on or reboot your PiKVM, you should now see a COMx port on your HOST PC
  4. Connect using something like Putty, use 115200 as your baud rate
  5. Edit the file using nano or whatever text editor you are comfortable with, save the file
  6. Reboot your PiKVM, check for functionality
  7. If still unreachable, edit the same file to fix it
  8. ONLY Disconnect the IOIO port once you have fully recovered your PiKVM and place this back onto the Target system
Can I use PiKVM for gaming?

No, because:

  • For HDMI-CSI bridge, bus bandwidth is not enough to transmit more than 1080p50.
  • For HDMI-USB dongle, high latency and low video quality.
  • General hardware video capture differs from software streaming and introduces additional latency.
Can PiKVM do 4K video?
  • For HDMI-CSI bridge, no. There is not enough bandwidth in the CSI bus for that much data. 1080p50 will max out the bandwidth.
  • For the USB capture devices: technically yes, they will down sample to something smaller to meet the USB 2.0 bandwidth limitations, so the source may be 4k, but the stream will not.
  • The 4K real-time video will not fit through the network anyway.
Where does the cursor/video latency come from?

Here is the chain of transferring an image to your browser or VNC client.

Capture device -> Compression -> Network -> Decompression -> Rendering

100-200ms is very, very fast for this. But we are working to speed things up even more.

I am expecting to see 60fps and I am not, why?

PiKVM receives the entire signal, but then the encoding is the bottleneck. For 1080p, this is no more than 30 fps. V4 throws out every second frame of 60 hz/fps, and 30 fps is encoded. V3 and DIY can't process 60 hz and is only able to capture 50 hz, and in the same way they take every second frame, all you get out is 25 fps. The reason why V3 and DIY does not encode 30 out of 50 is that the picture will be jerky, but smooth at 25.

Does PiKVM support sound?

Yes but the only officially supported version is the PiKVM V3+ devices, V2 we will attempt best effort but ultimately we do not support CSI modules or USB.

Can I power the Pi via PoE?

Yes!

For a POE HAT

You still need a splitter to ensure you isolate the 5v connection between the Raspberry Pi and host PC to prevent back power issues that can cause instability or damage to either the host PC or the Pi. Power/Data cable + USB power blocker would work.

For a POE Splitter

No, there is no need for anything additional, you can power your RPi and or the PiKVM Mini with the USB-C variant.

Do I need a power splitter? Why do I need one?
  • Yes for RPi4 - Please see the main v2 document for splitter types listed under V2 hardware
  • Yes for Zero W and Zero W 2, if using dedicated power you still need to split the power from the data towards the target. If using the target for power, this is not needed.
  • This is not needed if you have a PiKVM V3 and V4, as they splits power and signal on the board.
Can I use PiKVM with non-Raspberry Pi boards (Orange, Nano, etc)?

Yes, but you will have to prepare the operating system yourself. For the PiKVM software, you will need to replace some config files (such as UDEV rules). If you are a developer or an experienced system administrator, you will not have any problems with this. In addition, we are open to patches. If you need help with this, please contact us via Discord (#unofficial_ports channel).

Is PiKVM OS its own custom distro?

No. PiKVM OS is an Arch Linux ARM with our own repository for KVM-related packages. We distribute OS images (that is, our Arch Linux ARM build) to simplify installation, since PiKVM requires some tuning of the OS and special partitioning of the memory card.

Why is PiKVM OS based on Arch Linux ARM and not Raspbian / Raspberry Pi OS?

There are several reasons:

  • Several years ago, when PiKVM was just starting out, Raspbian didn't have a minimalistic image and the transition to systemd was in full swing, which is why the distribution was not too stable.
  • Raspbian did not have all the necessary packages in the repositories to satisfy most software dependencies.
  • PiKVM was born as a pet project, and the founder likes Arch the most.

However, we plan to provide an alternative OS image based on Raspberry Pi OS in the future - now it is quite stable.

Can I use an iPad on PiKVM?
  • Yes, with the correct hardware you can control an iPad.
  • In the opposite sense - yes, use VNC and use JUMP app (fully-featured but more expensive), or bVNC (cheap). RealVNC does NOT work.
How do I add my own SSL cert?

If you have a certificate (making a cert falls outside the scope of PiKVM - please reference OpenSSL documentation or use Let's Encrypt), replace keys in /etc/kvmd/nginx/ssl, edit /etc/kvmd/nginx/ssl.conf if necessary and restart kvmd-nginx service.

How do I emulate various USB devices on the target machine?

For a detailed description, see here.

Use the following USB database to get the desired devices: https://the-sz.com/products/usbid or https://devicehunt.com.

Can I run a desktop on PiKVM?

Yes, but it's strongly not recommended OR supported as this OS should be used in read-only mode and it will need read-write enabled all of the time, however if you insist on running one, instructions are here.

How do I blank the oled screen?

Please run the following:

# systemctl disable --now kvmd-oled kvmd-oled-reboot kvmd-oled-shutdown\n# kvmd-oled --height=32 --interval=0 --clear-on-exit --text=x\n
To re-enable the display:
# systemctl enable --now kvmd-oled kvmd-oled-reboot kvmd-oled-shutdown\n
How do I rotate the OLED display?

Please run the following:

1. mkdir -p /etc/systemd/system/kvmd-oled.service.d\n2. Create file /etc/systemd/system/kvmd-oled.service.d/override.conf:\n[Service]\nExecStart=\nExecStart=/usr/bin/kvmd-oled --height=32 --clear-on-exit --rotate=2\n
I am getting a 500/503 error when I try and access the main KVM page!

This maybe due to a few of the following:

  • Missing /etc/kvmd/override.yaml file, to resolve it run rw; touch /etc/kvmd/override.yaml; ro
  • Bad YAML syntax, edit your /etc/kvmd/override.yaml file and undo what you did and restart PiKVM.
How can I use the serial console to gain access to other devices

You need to stop the service which listens on the /dev/ttyAMA0:

rw\nsystemctl stop serial-getty@ttyAMA0.service\n

If you want this change permanent (not starting again after reboot), you can disable this service, ('enable' to reverse this decision):

systemctl disable serial-getty@ttyAMA0.service\n

Note

  • Only USB OR the RJ-45 serial connector will work, you can't use them together!
  • If you disable the service permanently, you can't recover your device via serial console if you need this.
  • There are some reports, that you need to remove ttyAMA0 from /boot/cmdline.txt, but this is not needed on new installations.
Can I run PiKVM in a docker?

No, technically it might be possible but the OS requires many specific settings that cannot be performed inside the container.

How can I change the HTTP/HTTPS ports?

To do this, you need at least KVMD 3.301 installed on your device. If this is not the case, update the OS.

Add some of these lines to /etc/kvmd/override.yaml:

nginx:\n    https:\n        port: 4430\n    http:\n        port: 8080\n

After that, restart the server: systemctl restart kvmd-nginx.

Can I control IR devices using PiKVM?

This goes far beyond the usual use of PiKVM, so there is no official way to do this, but there are some ways from the community that you can try if you know how to handle a soldering iron.

"},{"location":"faq/#first-steps","title":"First steps","text":"I can't find the PiKVM IP address in my network

Follow the device guide of your PiKVM here.

What is the default password? How do I change it?

See here.

How do I add another user?

See here.

How do I get root access in the web terminal?

See here.

Where is the PiKVM configuration located?

Almost all KVMD (the main daemon controlling PiKVM) configuration files are located in /etc/kvmd. You can also find nginx configs and SSL certificates there. KVMD configs use YAML syntax. The specific platform parameters can be found in the file /etc/kvmd/main.yaml and you should never edit it. Use /etc/kvmd/override.yaml to redefine the system parameters.

Files that are not recommended for editing have read-only permissions. If you edit any of these files, you will need to manually make changes to them when you upgrade your system. You can view the current configuration and all available KVMD parameters using the command kvmd -m.

I can't edit any file on PiKVM. Why is the system in read-only mode?

The PiKVM file system is always mounted in read-only mode. This measure prevents it from being damaged by a sudden power outage. To change the configuration you must first switch the filesystem to write mode using the command rw from root. After the changes, be sure to run the command ro to switch it back to read-only. If you get a message that the file system is busy, then the easiest way is to perform a reboot.

I want to get read-write filesystem all of the time

DON'T DO THIS

DON'T DO THIS

DON'T DO THIS

Seriously, DON'T. Read-only mode increases the life of the memory card and protects the filesystem from power loss failures. See the question above ^ ^ ^

You can turn it off, but don't say you weren't warned.

DON'T OPEN THIS SPOILER AND DON'T DO THIS

Okay, fine.

  • Edit /boot/cmdline.txt and change option ro to rw.
  • Do the same in /etc/fstab for the /boot partition.
  • Comment tmpfs lines in /etc/fstab for /var/lib and /var/log.

But again: DON'T DO THIS

If you do plan on doing this, no assistance will be provided beyond this point other than the existing documentation.

How to set the date, time and timezone from command line?
  • Become root with the command su - or sudo -s.
  • Enable read/write with the command rw.
  • Find your timezone string e.g. timedatectl list-timezones or timedatectl list-timezones | grep -i australia.
  • Set the timezone with timedatectl set-timezone <YourTimeZoneHere> e.g. timedatectl set-timezone Australia/Victoria.
  • Stop the time syncing service with systemctl stop systemd-timesyncd as this will prevent the next step if running.
  • Set the time and date with timedatectl set-time 'YYYY-MM-DD HH:MM:SS' e.g. timedatectl set-time '2023-02-26 14:50:10'.
  • If you have hardware clock e.g. V3+, update it with hwclock --systohc , then check it with hwclock --show.
  • Switch filesystem to RO-mode with the command ro.
How do I update PiKVM with the latest software? Updating PiKVM OS

To update, run following commands under the root user:

[root@pikvm ~]# pikvm-update\n

If you encounter an error like:

[root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

It's most likely you have an old OS release. You can update the OS as follows:

[root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

Next time you will be able to use the usual method with pikvm-update.

How do I install or remove packages in PiKVM OS?

PiKVM OS is based on Arch Linux ARM and uses the pacman package manager.

  • Ensure the date is correct: date. Otherwise you may get the error SSL certificate problem: certificate is not yet valid
  • It is recommended to update the OS before installing new packages (see the tip upper ^^^).
  • Switch filesystem to RW-mode: rw.
  • Find some packages (emacs for example): pacman -Ss emacs.
  • Install it: pacman -Syy to update local packages list and pacman -Su emacs to install.
  • Remove it: pacman -R emacs.
  • Switch filesystem to RO-mode: ro.
I don't need ATX functions. How do I disable this in the Web UI?

If you don't need ATX power control you can disable the relevant Web UI menu in /etc/kvmd/override.yaml:

kvmd:\n    atx:\n        type: disabled\n

... then restart kvmd:

# systemctl restart kvmd\n
How do I disable the web terminal?
# rw\n# systemctl disable --now kvmd-webterm\n# ro\n
How do I completely disable authorization in PiKVM?

See here.

Can I have different hostnames for each of my PiKVMs?

Yes! And it's easy to do! Using a SSH session or the web terminal: * Make sure you are root, run rw then run hostnamectl set-hostname yournewhostname.domain. * Optional: edit /etc/kvmd/meta.yaml to alter the displayed hostname in the web UI. * Run ro and reboot.

Why not add software support for another codec?

Encoding is a heavy process and will add significant latency, its best to have hardware support to avoid additional latency.

"},{"location":"faq/#video-problems","title":"Video problems","text":"I can see the video but I can't see the WebRTC / video mode switch

WebRTC and Direct H.264 modes are only available on V2+ platforms with HDMI-CSI capture device, including PiKVM V3 or V4 Plus/Mini. See the modes guide to solve any problems.

PiKVM does not show the video from the computer at all
  • Double-check that the video capture device is connected correctly.
  • Some laptops do not output any signal until you switch the output (usually via the FN + and an F5 key on the keyboard).
  • Your computer may have turned on sleep mode for the monitor. Move the mouse to turn it off.
  • For windows you might need to check for the active signal resolution. To change the active signal resolution you have to go to Settings>System>Display>Advanced display settings>Display adapter properties then, click \"List All Models\" and choose the one you want. Keep trying different Hz settings.
The video works in the booted OS, but not in the BIOS/UEFI

This problem appears on Intel NUC, GA-H77-DS3H, and some other devices when using a CSI bridge. All you need to do is change the EDID data. This is the information about supported resolutions that the CSI bridge reports to your computer.

Glitchy or wrong BIOS/UEFI resolution

On some motherboards, the BIOS may be displayed at a lower resolution, or with some rendering issues/glitches, specially on newer ASUS ones. Like this:

This can be solved by enabling the Compatibility Support Module (CSM) in your BIOS, usually under the Boot options.

If you can't or don't want to enable the CSM, you can try connecting a DisplayPort (DP) monitor, or a dummy plug. If you remove the DP cable/adapter the bug will reappear.

If none of this works, try connecting the DP cable first, boot into the BIOS, disable the CSM and shutdown (do not restart) your PC. Then, boot into the BIOS and enable the CSM before shutting down your PC. Then connect the HDMI and turn your PC on again.

There is no video in GRUB2, but there is before and after

Sometimes this can be caused by the specifics of the BIOS/UEFI and how GRUB2 works with video.

This can be solved by enabling the Compatibility Support Module (CSM) in your BIOS, usually under the Boot options. The video mode will be located in the same section. Switch the Video mode from UEFI to Legacy.

Why does the CSI bridge does not work with official Raspberry Pi PoE HAT?

Details here. The reason is that the official HAT has a built-in fan controller that conflicts with the TC358743 chip of the bridge. The solution is to disable the fan control and connect the fan to the power line so that it works continuously. To turn off the controller you need to add the line disable_poe_fan=1 to /boot/config.txt.

The video freezes a few seconds after the start, restarting the Web UI or VNC does not help

The story is here. Very very rarely, Raspberry Pi boards can have a hardware defect that causes some of the chip blocks to be unstable under normal power. The solution is to slightly increase the power supply, as you would when overclocking. Add over_voltage=1 (or over_voltage=2 if previous doesn't help) to /boot/config.txt and perform reboot.

To make sure that you are facing this particular problem, first perform a diagnostic:

  • Boot the PiKVM without the specified options.
  • Open Web-UI and wait for freezing.
  • Click System -> Reset Stream.
  • Click System -> Open log and make sure that the log contains messages like H264: Can't wait for the VCOS semaphore.
  • Make sure that the last message from ustreamer was H264: Configuring MMAL encoder (not counting messages about connecting and disconnecting stream clients).
No image from computer with Linux + Awesome WM

Sometimes Awesome WM on Linux can't recognize a video output change on a cable. That is, if the cable was first inserted into the monitor, and then you reconnected it to PiKVM - it may happen that you will not see the image. It seems that the problem is Awesome WM, since for example with KDE, it is not reproducible. If you turn on your workstation with PiKVM already connected, everything will work fine.

Windows shows limited Available Resolutions

This is due to a driver issue. A possible resolution can be found here.

Firefox ESR from the Debian repo shows the black screen in H.264 mode

Make sure the OpenH264 Plugin both exists and is enabled (known issue on Debian GNU/Linux). Press Ctrl+Shift+A to open the Add-ons Manager, then press Plugins. You should see OpenH264 Video Codec provided by Cisco Systems, Inc.. Make sure it is enabled by pressing the \"more options\" button (3 horizontal dots), then pressing Always Activate.

Apple TB/USB-C HDMI video doesn't work

A possible solution can be found here.

I am seeing a NO SIGNAL, what can I do?

If you are using PiKVM V2 or a V3, you need to ensure that your target is using the maximum resolution 1920x1080@50Hz, 60Hz will not work.

If you are using the PiKVM V4, ensure that you are getting a signal out from the target by using a physical monitor using the same exact cable/dongle, ensure that you are using the maximum resolution 1920x1200@60hz, 2K/4K resolutions will not work.

"},{"location":"faq/#usb-problems-keyboard-mouse-mass-storage-etc","title":"USB problems (keyboard, mouse, mass storage, etc)","text":"My computer does not recognize USB of PiKVM V2+ at all
  • Make sure that you have used the correct USB cable with DATA lines to connect the OTG port for the Raspberry to the computer. You may have decided to use a USB hub instead of a Y-cable and it won't work. Use good cables and follow the instructions :)
  • In rare cases, some very buggy BIOS's do not like HID and Mass Storage in one USB device. You can either disable Mass Storage, or use the Pico HID to physically separate them.
BIOS/UEFI does not recognize USB of V2+, but computer does

If you are using a USB hub or USB PCI controller, this may not be handled by your BIOS. Try to use another USB port. Some ports may have a built-in hub on the motherboard and a buggy BIOS that can't handle it.

My keyboard works in BIOS/UEFI, but my mouse does not

The BIOS does not support absolute mouse mode, which is preferred by PiKVM. In this case, you can enable relative or dual positioning mode.

My mass storage drive works (I can boot an image from PiKVM V2+), but my keyboard/mouse does not

In rare cases, some very buggy BIOS's does not like HID and Mass Storage in one USB device. You can either disable Mass Storage, or use the Pico HID to physically separate them.

Buggy absolute mouse on Windows 98 as managed server

How to fix:

  • V2+.
  • Pico HID.
The mouse does not work with NVR/DVR CCTV

Often these devices have a buggy USB driver that does not understand an absolute mouse and/or a mouse with horizontal scrolling. In this case, the following configuration for /etc/kvmd/override.yaml will help you:

kvmd:\n    hid:\n        mouse:\n            absolute: false\n            horizontal_wheel: false\n        mouse_alt:\n            device: \"\"\n

It will make the relative mouse without horizontal scrolling the only mice.

There's big mouse latency on another Raspberry Pi as managed server

Unusual case: RPi4 is used as a PiKVM to control RPi3. In this case, the mouse delay may be several seconds. To fix it, append usbhid.mousepoll=0 to the boot line in /boot/cmdline.txt on the managed server (i.e. RPI3 in our case) and reboot it. Source.

What speed is the USB OTG port?

Per the official RPI documentation, this is a limitation of the SoC. The OTG port is only USB2.0, so is limited to 455 Mbit/s.

On MacOSX, my mouse/keyboard does not work!

There are a few fixes the community has suggested:

If using a USB-C to USB-C cable, you need to use the included USB-C to USB-A cable then use a USB-A to USB-C adapter

You may need to allow new accessories to connect. Source

"},{"location":"faq/#web-ui-problems","title":"Web UI problems","text":"Chrome reports a Certificate Issue when I try to access the PiKVM web interface

The latest versions of Chrome do not allow access to the page with a self signed certificate, so if you see the following screen when loading the PiKVM website:

You can proceed by typing thisisunsafe and Chrome will then load the page. Also see Let's Encrypt page.

Pressing ESC in full screen mode causes the PiKVM page to close

Your browser does not support keyboard lock. Right now (January 2022), only Chromium implements this, so it works on Chrome, Edge, and Opera.

The Web UI doesn't work properly in Firefox while it works fine in Chrome

This might be related to your specific hardware combination or browser hardware acceleration. Try disabling hardware acceleration in Firefox or updating your GPU and chipset drivers.

Unexpected interruption while loading the image for Mass storage drive

If problems occur when uploading even a small disk image it may be due to unstable network operation or antivirus software. It is well known that Kaspersky antivirus cuts off PiKVM connections during uploading, so you should add the PiKVM website to Kaspersky's list of exceptions or not filter web requests with the antivirus. Antivirus programs can also affect the performance of certain interface elements, for example the quality slider. For Kaspersky, the steps to add the network address of PiKVM's website to the exclusion list is: Protection -> Private browsing -> Categories and exclusions -> Exclusions.

I can't click on anything when using the WebGUI on my phone

At this time, iOS has the buttons on the bottom if you have the correct resolution, sometimes you cannot see them due to the resolution. At this time, android is not supported, our suggestion is to use a VNC client.

I changed the Display Resolution to 720p but Windows still shows 1080p and the display looks blurry

This is mostly seen on Windows, open Display Settings -> Advanced display settings -> Display adapter setting for Display 1 -> List all modes -> (Toggle between 720p30hz back to 50hz), this may need to be done if you need to change it back for 1080p.

"},{"location":"faq/#hardware-problems-wi-fi-atx-etc","title":"Hardware problems (Wi-Fi, ATX, etc)","text":"I can't connect to Wi-Fi on a Raspberry Pi Zero W
  • Some Zeros contain a defective Wi-Fi chip. You can either return the device to the store, or try the software workaround.
I can't connect to Wi-Fi at all!
  • If your device is unable to connect to the Wi-Fi network that you have set up, check the 2.4 GHz Wi-Fi channel used by your Wi-Fi access point.

  • If channels 12 to 14 are used (some countries have banned these channels) try to use a channel between 1 and 11.

LEDs/Switches do not work in ATX control

Double check your wiring. Make sure you placed the relays (G3VM-61A1) in the correct orientation. The relays for switches (Power, Reset) have a different orientation than the ones for LEDs.

My PiKVM keeps disconnecting from the Wi-Fi network

Try to edit /etc/conf.d/wireless-regdom and look for your region and uncomment it. For example: WIRELESS_REGDOM=\"US\".

PiKVM complains about low power warnings
  • Are you using a \"proper\" power supply? Not one you hacked together?
  • Some USB power bricks advertise 5V 2.1A or higher, but can't deliver consistent 5V. Best to use Raspberry Pi Foundation recommended power supplies.
PiKVM complains about a RTC low voltage detected, date/time is not reliable
  • This is mearly a warning that can be ignored however, the following resolves the issue:
  • Leave plugged in for 24+ hours and or
  • Connect to the internet using the eth cable, the internal NTP service will set the time accordlingly
  • Force a time sync: rw && hwclock --systohc\" or \"rw && hwclock -w\"
  • Set date and time manually can be found here.
"},{"location":"flashing_hid/","title":"Flashing hid","text":"

Legacy warning

This page describes the legacy keyboard and mouse emulator used in old DIY builds. There is no point using it today because there is a more modern and better replacement for the new Pico HID. This one can also serve as an in-place compatible replacement for the Arduino HID in the old build.

"},{"location":"flashing_hid/#flashing-the-arduino-hid","title":"Flashing the Arduino HID","text":""},{"location":"flashing_hid/#note-for-the-recent-images","title":"Note for the recent images","text":"

Current image no longer ships with necessary tools for flashing Arduino HID, therefore please install platformio-core and avrdude and continue:

pacman -Syu\npacman -S platformio-core avrdude\n
"},{"location":"flashing_hid/#serial-firmware-the-default-option","title":"Serial Firmware (the default option)","text":"

This operation can be done using your RPi (except Pi Zero W). Here the common steps:

  1. Disconnect the RESET wire from the Arduino board.

  2. Connect the Arduino and RPi with a suitable USB cable.

  3. Log in to the Raspberry Pi console using SSH or Web Terminal.

  4. Upload the firmware (USB keyboard & mouse is used by default, on this step you can choose PS/2 keyboard):

    # rw\n# systemctl stop kvmd\n# cp -r /usr/share/kvmd/hid/arduino ~\n# cd ~/arduino\n# make\n# make install\n# reboot\n
  5. Connect the RESET wire, disconnect the USB cable, and reboot the RPi.

With a Pi Zero W, you may consider building the firmware on a faster system and programming using USB or booting from another SD card and following the build steps using a clone of the KVMD repo.

"},{"location":"flashing_hid/#spi-firmware","title":"SPI Firmware","text":"

This operation can be done using your Raspberry Pi without disconnecting any wires:

  1. Connect the Arduino and RPi with a suitable USB cable.

  2. Log in to the Raspberry Pi console using SSH or Web Terminal.

  3. Execute rw, add line dtoverlay=spi0-1cs to /boot/config.txt and perform reboot.

  4. Build and upload the firmware (USB keyboard & mouse is used by default)

    # rw\n# systemctl stop kvmd\n# cp -r /usr/share/kvmd/hid/arduino ~\n# cd ~/arduino\n# make spi\n# make install\n# reboot\n
"},{"location":"flashing_hid/#common-errors","title":"Common Errors","text":""},{"location":"flashing_hid/#circuit-issues","title":"Circuit Issues","text":""},{"location":"flashing_hid/#common-reset-wire","title":"Common - Reset Wire","text":"

Different pins are used for the reset wire but serve a similar function. For programming the TTL firmware over USB, the reset wire should be disconnected. When programming using SPI, the reset wire needs to be connected through a transistor circuit and connected to GPIO25 (pin 22 on the GPIO header)

"},{"location":"flashing_hid/#spi-specific-wiring","title":"SPI-specific Wiring","text":"

The 3v3, ground, Reset (GPIO25), MISO, MOSI, SCLK, and CS1 need to be connected appropriately. SPIO_CS0 and SPIO_CS1 can both be used but the default configuration uses SPIO_CS1 for the Arduino Microcontroller (CS0 is used for another device on the V3). These generally follow a block as follows:

Pin  0        2         4\n      2        0         0\n      .........GR.C.......\nRow # 12345678901234567890\n      ........3MMS........\nPin   0       1          3\n       1       7          9\n

The most common error is an \"off-by-one\" error where pins are shifted by a row. Some cases have non-standard GPIO layouts so please be careful when following these instructions using a case that has a modified pinout.

"},{"location":"flashing_os/","title":"Flashing PiKVM OS image","text":"

Micro-SD Card Requirements

Minimum 32 Gb, Class 10 recommended.

"},{"location":"flashing_os/#download-the-image","title":"Download the image","text":"

Download the appropriate SD card image. Select it based on the board, platform, and the video capture device you are using.

Official PiKVM Devices

These images are not suitable for DIY and are intended only for our branded devices.

  • PiKVM V4 64-bit

    • PiKVM V4 Mini - sha1
    • PiKVM V4 Plus - sha1
  • PiKVM V3 64-bit

    • PiKVM V3 HAT BOX Image, OLED/FAN preactivated - sha1
    • PiKVM V3 HAT DIY Assembly - sha1

DIY PiKVM V2 Platform

  • Raspberry Pi 4 64-bit

    • For HDMI-CSI bridge - sha1
    • For HDMI-USB dongle - sha1
  • Raspberry Pi Zero 2 W 32-bit

    • For HDMI-CSI bridge - sha1

DIY PiKVM V1 Platform

  • Raspberry Pi 3 32-bit

    • For HDMI-CSI bridge - sha1
    • For HDMI-USB dongle - sha1
  • Raspberry Pi 2 32-bit

    • For HDMI-CSI bridge - sha1
    • For HDMI-USB dongle - sha1
  • Raspberry Pi Zero 2 W 32-bit

    • For HDMI-CSI bridge - sha1
    • For HDMI-USB dongle - sha1

Any other combinations for advanced users

Please check the file archives for ready-made image or build the image yourself.

"},{"location":"flashing_os/#flashing-the-image","title":"Flashing the image","text":"

Tip

After inserting the memory card into your computer, ignore request to format. This is not nessessary.

"},{"location":"flashing_os/#using-linux-cli-advanced-users","title":"Using Linux CLI (ADVANCED USERS)","text":"

Decompress (if nessessary) and flash the image. Be careful when choosing the device path, it may be different on your machine:

[user@localhost]$ xz --decompress v2-hdmi-rpi4-latest.img.xz\n[user@localhost]$ sudo dd if=v2-hdmi-rpi4-latest.img of=/dev/mmcblkX\n

You can also use dd_rescue or ddrescue.

"},{"location":"flashing_os/#using-rpi-imager-linux-macos-and-windows","title":"Using RPi Imager (Linux, MacOS and Windows)","text":"
  1. Download and install the latest version of RPi Imager.

  2. Run RPi Imager:

  3. Press NO FILTERING then CHOOSE OS and select Use custom image at bottom of the list:

  4. After clicking on this item, select the image file (*.img or *.img.xz), then click CHOOSE STORAGE:

    Warning

    This should already be set to blank though the flashing process from step 7 but its best to double check the advanced settings (CTRL+SHIFT+X), make sure they are blank or the flash will fail.

  5. Insert the memory card into the card reader. Choose the card reader from this list. Be careful and choose the right device:

  6. After choosing the memory card, press the WRITE button. Confirm the operation when you are asked about it:

  7. Refuse customization options.

    Warning

    The customization is designed for Raspberry OS and will not work in PiKVM OS. If you apply any custom settings, this will cause the image to malfunction.

    PiKVM OS has its own settings mechanism, please use it after the flashing if you need to configure Wi-Fi or something similar.

  8. Wait for the process to finish. Get yourself a coffee or do some stretching :) The process may hang at 99% for a long time, this is okay, just wait for it to complete.

  9. Remove the memory card after successful completion. If an error occurs during flashing or booting PiKVM, repeat the process. If the error persists, use a different memory card.

"},{"location":"gpio/","title":"GPIO","text":"

GPIO (general-purpose input/output) is a series of digital interfaces that can be used to connect relays, LEDs, sensors, and other components.

Warning

  • Before using GPIO on PiKVM v3 HAT, carefully study the purpose of its ports.
  • Using GPIO on a PiKVM was designed as a feature for advanced users, so please familiarize yourself with the topic to make sure you understand how to use use it before setting it up.
  • Careless usage of GPIO can damage your Raspberry Pi or components.

When talking about PiKVM and GPIO it refers not solely to the physical interface of the Raspberry Pi, but also to various plugins (for example, for USB relays) that can also be used transparently by emulating an abstract GPIO API.

"},{"location":"gpio/#basics","title":"Basics","text":"

Setting up GPIO is considerably complex. The interface is divided into several layers for flexibility. Any configuration is performed using a file /etc/kvmd/override.yaml which uses the YAML syntax. We will look at each part of the configuration individually with an example for each. Sections should be combined under shared keys.

  • Wrong:

    kvmd:\n    gpio:\n        drivers: ...\nkvmd:\n    gpio:\n        scheme: ...\n
  • Correct:

    kvmd:\n    gpio:\n        drivers: ...\n        scheme: ...\n
"},{"location":"gpio/#drivers","title":"Drivers","text":"

The first part of the configuration refers to the hardware layer, which defines which IO channels are used (standard GPIO pins of the Raspberry Pi, an USB relay, and so on). If you just want to use GPIO with the default settings you can skip to the next section Scheme.

Each hardware input/output requires a individual driver configuration entry. Each driver has a type (which refers to the plugin that handles the communication between PiKVM and the hardware) and a unique name. This allows you to either can add multiple drivers of the same type with different settings or connect multiple USB HID relays.

Note

Each driver requires a unique name. Names surrounded by double underscore are system reserved and should not be used.

The only exception to this is the default GPIO driver with the name __gpio__, representing the physical GPIO interface of the Raspberry Pi. The configuration section for __gpio__ is only required in your /etc/kvmd/override.yaml if you want to change the default settings. It can be omitted if you are fine with the defaults.

kvmd:\n    gpio:\n        drivers:\n            # This example shows how the default __gpio__ driver settings can be changed. It can be omitted if you are fine with the defaults.\n            __gpio__:  # Names surrounded by double underscore are system reserved\n                type: gpio  # Refers to the plugin name handling the communication\n\n            # You can define another gpio driver for some reason\n            my_gpio: \n                type: gpio\n\n            # Example for a USB HID relay connected to PiKVM\n            relay:\n                type: hidrelay\n                device: /dev/hidraw0  # The path to the linux device\n
"},{"location":"gpio/#scheme","title":"Scheme","text":"

The second part defines how the various driver channels are configured. Each channel has a unique name, a mode (input or output), a pin number, and a reference to the driver configured in the previous part.

Note

Names that starts and ends with two underscores (like __magic__) are reserved.

Two interaction modes are available for outputs: pulse and switch. In pulse mode, the output quickly switches its state to logical 1 and back (just like pressing a button). In switch mode, it saves (toggles) the state that the user set. When PiKVM is started/rebooted (any time the KVMD daemon is started or stopped) all output channels are reset to 0. This can be changed using the initial parameter. For example, initial=true for logic 1 on startup.

If you don't specify a driver for the channel in the scheme the default driver, __gpio__ will be used.

Parameter Type Allowed values Default Description led1, button1, relay1, etc. string a-Z, numbers, _, - A section for the named channel driver string a-Z, numbers, _, - Optional, Name of the section defined above in Drivers if not GPIO pin integer X >= 0 Refers to a GPIO pin or driver's pin/port mode enum input or output Defines if a channel is used for input or output, may be limited by driver plugin Input only debounce float x >= 0 0.1 Debounce time in seconds. 0 for disable debounce Output only switch bool true or false true Enables or disables the switch mode on the channel (enabled by default). initial nullable bool true, false or null false Defines the initial state of the switch upon boot, null for don't make changes (the last one does not supported by generic GPIO) inverted bool true or false false Inverts the active logical level pulse A section header to define switch pulse configuration delay float X >= 0 0.1 Defines the pulse time in seconds, 0 for disable pulsing min_delay float X >= 0.1 0.1 max_delay float X >= 0.1 0.1
kvmd:\n    gpio:\n        scheme:\n            # A certain device sends signals to the RPi and we want the PiKVM to display this as an led\n            led1:\n                pin: 19 # GPIO pin number on the RPi\n                mode: input \n            led2:\n                pin: 16\n                mode: input \n\n            # Two outputs of RPi's GPIO\n            button1:\n                pin: 26 # GPIO pin number on the RPi\n                mode: output\n                switch: false  # Disable switching, only pulse available\n            button2:\n                pin: 20\n                mode: output\n                switch: false\n\n            relay1:  # Channel 1 of the relay /dev/hidraw0\n                driver: relay  # Not GPIO, so add name from the above Drivers section\n                pin: 0  # Numerating starts from 0\n                mode: output  # Relays can't be inputs\n                initial: null  # Don't reset the state to 0 when initializing and terminating KVMD\n            relay2:  # Channel 2\n                driver: relay\n                pin: 1\n                mode: output\n                initial: null\n                pulse:\n                    delay: 2  # Default pulse value\n                    max_delay: 2  # The pulse interval can be between min_delay=0.1 (by default) and max_delay=2\n
"},{"location":"gpio/#view","title":"View","text":"

This is the last part of the required configuration. It defines how the previous driver and channel configuration is rendered on the Web interface. Here's an example for the example configuration above:

kvmd:\n    gpio:\n        view:\n            header:\n                title: Switches  # The menu title\n            table:  # The menu items are rendered in the form of a table of text labels and controls\n                - [\"#Generic GPIO leds\"]  # Text starting with the sharp symbol will be a label\n                - []  # creates a horizontal separator and starts a new table\n                - [\"#Test 1:\", led1, button1]  # Text label, one input, one button with text \"Click\"\n                - [\"#Test 2:\", led2, button2]\n                - []\n                - [\"#HID Relays /dev/hidraw0\"]\n                - []\n                - [\"#Relay #1:\", \"relay1|Boop 0.1\"]  # Text label and button with alternative text\n                - [\"#Relay #2:\", \"relay2|Boop 2.0\"]\n

This will be rendered as:

Some rules and customization options:

  • Text starting with the # symbol will be a label.
  • To place a channel in a cell, use the name you defined in the scheme.
  • Inputs are displayed as round LEDs.
  • Outputs are displayed as a switch AND a button.
  • If the switch mode is disabled, only a button will be displayed. If pulse is disabled, only a switch will be shown.
  • To change the LED's color specify it after the channel name like \"led1|red\". Available: green, yellow, red, blue, cyan, magenta, pink and white.
  • To change title of the button, write some its name like \"relay1|My cool relay\".
  • Buttons and switches can request confirmation on acting. To do this write its name like \"relay1|confirm|My cool relay\". The third argument with a title is required in this case.
  • The button can automatically close the menu when clicked. Use something like \"relay1|hide|My button\". It can be used with confirmation option: \"relay1|confirm,hide|My button\".

Also you can place some leds in the menu title using the similar syntax:

kvmd\n    gpio:\n        view:\n            header:\n                title: [\"#Test1:\", led1, \"Test2:\", led2]\n
"},{"location":"gpio/#hardware-modules-and-pseudo-drivers","title":"Hardware modules and pseudo-drivers","text":""},{"location":"gpio/#raspberrys-gpio","title":"Raspberry's GPIO","text":"Click to view

The driver gpio provides access to regular GPIO pins with input and output modes. It uses /dev/gpiochip0 and the libgpiod library to communicate with the hardware. Does not support saving state between KVMD restarts (meaning initial=null).

You can use the interactive scheme when selecting the pins to use. Please note that when selecting a pin for a channel, you need to use a logical number instead of a physical number. That is, if you want to use a physical pin with the number 40, the channel must have the number 21 corresponding to the logical GPIO21.

Channels should not use duplicate pins. You can also not use already used pins. To see which pins are currently used, run the command gpioinfo.

"},{"location":"gpio/#usb-hid-relay","title":"USB HID Relay","text":"Click to view

The driver hidrelay provides access to cheap managed USB HID relays that can be found on AliExpress. This driver does not support input mode, only output. To use it, you need to specify the path to the device file (like /dev/hidraw0) using the device parameter.

Additionally, we recommend to configure access rights and static device name using UDEV rules. For example, create /etc/udev/rules.d/99-kvmd-extra.rules:

KERNEL==\"hidraw[0-9]*\", SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"16c0\", ATTRS{idProduct}==\"05df\", GROUP=\"kvmd\"\n

Channels should not use duplicate physical numbers. The driver supports saving state between KVMD restarts (meaning initial=null).

"},{"location":"gpio/#ezcoo-kvm-switch","title":"ezCoo KVM switch","text":"Click to view

You can use GPIO to control KVM port switching. This usually requires the use of relays and buttons, but for the ezCoo switch there is a special ezcoo driver that simulates GPIO by sending commands to the switch via serial port. So you can make a menu in PiKVM to control the multiport switch.

"},{"location":"gpio/#ipmi","title":"IPMI","text":"Click to view

The driver ipmi provides the ability to send IPMI commands (on, off, reset) and show the power status of the remote host. In fact, this is not a hardware driver, but something like a pseudo-GPIO. Each \"pin\" is actually responsible for a specific IPMI operation of ipmitool:

Pin Type Command 0 input ipmitool ... power status, can be used to draw the LED in the menu 1 output ipmitool ... power on, sends the on command (and only this), so like all other outputs it should be a button 2 output ipmitool ... power off 3 output ipmitool ... power cycle 4 output ipmitool ... power reset 5 output ipmitool ... power diag 6 output ipmitool ... power soft

You are supposed to define one driver per host:

kvmd:\n    gpio:\n        drivers:\n            my_server:\n                type: ipmi\n                host: myserver.local\n                user: admin\n                passwd: admin\n        scheme:\n            my_server_status:\n                driver: my_server\n                pin: 0\n                mode: input\n            my_server_on:\n                driver: my_server\n                pin: 1\n                mode: output\n                switch: false\n            my_server_off:\n                driver: my_server\n                pin: 2\n                mode: output\n                switch: false\n        view:\n            table:\n                - [my_server_status, \"my_server_on|On\", \"my_server_off|Off\"]\n
"},{"location":"gpio/#wake-on-lan","title":"Wake-on-LAN","text":"Click to view

The driver wol provides a simple generator of Wake-on-LAN packages. One driver and one output are generated for one host if a simplified configuration method is used. However, you can define multiple drivers if you want to manage different hosts. One driver controls one host, and can only be used as an output. Pin numbers are ignored.

kvmd:\n    gpio:\n        drivers:\n            wol_server1:\n                type: wol\n                mac: ff:ff:ff:ff:ff:f1\n            wol_server2:\n                type: wol\n                mac: ff:ff:ff:ff:ff:f2\n                ip: 192.168.0.100\n                port: 9\n        scheme:\n            wol_server1:\n                driver: wol_server1\n                pin: 0\n                mode: output\n                switch: false\n            wol_server2:\n                driver: wol_server2\n                pin: 0\n                mode: output\n                switch: false\n        view:\n            table:\n                - [\"#Server 1\", \"wol_server1|Send Wake-on-LAN\"]\n                - [\"#Server 2\", \"wol_server2|Send Wake-on-LAN\"]\n
"},{"location":"gpio/#cmd","title":"CMD","text":"Click to view

The cmd driver allows you to run custom command on PiKVM OS.

Note

This driver does not support bash operators, that is, it is a direct call to commands with arguments. For more complex cases, write your own shell scripts.

Commands are executed from the user kvmd. If you want to run the command as root, then you need to configure sudo. Example of the /etc/sudoers.d/custom_commands:

Granular example

kvmd ALL=(ALL) NOPASSWD: /usr/bin/reboot\n

NON Granular example (Captures ALL commands)

kvmd ALL=(ALL) NOPASSWD: ALL\n

Example of the /etc/kvmd/override.yaml:

kvmd:\n    gpio:\n        drivers:\n            reboot:\n                type: cmd\n                cmd: [/usr/bin/sudo, reboot]\n        scheme:\n            reboot_button:\n                driver: reboot\n                pin: 0\n                mode: output\n                switch: false\n        view:\n            table:\n                - [\"reboot_button|confirm|Reboot PiKVM\"]\n

An example to help you get started:

  • cmd: [/usr/bin/sudo, kvmd-otgconf, --disable-function, mass_storage.usb0]
  • cmd: [(absolute path to sudo, command, flag, flag, absolute path to file]

Then run the following:

systemctl restart kvmd\n
"},{"location":"gpio/#pwm","title":"PWM","text":"Click to view

The pwm driver allows you to use some GPIO pins on the Raspberry Pi for PWM.

Note

Due to hardware limitations, this module conflicts with the kvmd-fan (the fan controller) on PiKVM V3 and V4 Plus. To use it, you have to use hardware PWM for kvmfan. To do this, add the following lines to /etc/kvmd/fan.ini:

[main]\npwm_soft = 80\n

Not needed for V4 Mini because it does not have a fan.

Here the small example with servo control:

  1. Add some params to /boot/config.txt:

    • For PiKVM V3 or DIY device to enable PWM0_0 on RPi GPIO18:

      dtoverlay=pwm\n
    • For PiKVM V4 to enable PWM0_0 on CM4 GPIO12 (CN5 NeoPixel Pin) and set the PWM function to 4 (ALT0):

      dtoverlay=pwm,pin=12,func=4\n
  2. Create /etc/udev/rules.d/99-kvmd-pwm.rules:

    SUBSYSTEM==\"pwm*\", ACTION==\"add\", RUN+=\"/bin/chgrp -R kvmd /sys%p\", RUN+=\"/bin/chmod -R g=u /sys%p\"\nSUBSYSTEM==\"pwm*\", ACTION==\"change\", ENV{TRIGGER}!=\"none\", RUN+=\"/bin/chgrp -R kvmd /sys%p\", RUN+=\"/bin/chmod -R g=u /sys%p\"\n
  3. Connect Servo motor like SG90 PWM connection to RPi GPIO18 or CM4 GPIO12, +5V and GND to a 5V and GND pin on header:

  4. Add to /etc/kvmd/override.yaml

    kvmd:\n    gpio:\n        drivers:\n            servo1:\n                type: pwm\n                chip: 0                      # PWM Chip Number\n                period: 20000000             # Servo Motor SG90 Period in nano-seconds\n                duty_cycle_push: 1500000     # Servo Motor SG90 duty_cycle for pushing button\n                duty_cycle_release: 1000000  # Servo Motor SG90 duty_cycle for releasing button\n        scheme:\n            __v4_locator__:  # v4-mini only\n                pin: 25      # v4-mini only\n            short_press:\n                driver: servo1\n                pin: 0  # Pin number is the PWM channel number on the PWM Chip\n                mode: output\n                switch: false\n                pulse:\n                    delay: 0.5\n                    max_delay: 2\n            long_press:\n                driver: servo1\n                pin: 0\n                mode: output\n                switch: false\n                pulse:\n                    delay: 2\n                    max_delay: 2\n            extra_long_press:\n                driver: servo1\n                pin: 0\n                mode: output\n                switch: false\n                pulse:\n                    delay: 10\n                    max_delay: 20\n        view:\n            header:\n                title: Controls\n            table:\n                - [\"#Servo - Short Press\", \"short_press|Press\"]\n                - [\"#Servo - Long Press\", \"long_press|Press\"]\n                - [\"#Servo - Extra Long Press\", \"extra_long_press|Press\"]\n
"},{"location":"gpio/#servo","title":"Servo","text":"Click to view

The servo module is built on top of the pwm module and allows user to define angles instead of duty_cyles to control a PWM enabled servo motor like SG90. When the button is pressed the servo motor moves to an angle defined by angle_push and when button is released it moves back to angle_release. In the example configuration for a cheap 5V SG90 Servo, the motor moves to an angle of 45 degrees when button is pressed and moves back to 20 degress when released.

Note

Due to hardware limitations, this module conflicts with the kvmd-fan (the fan controller) on PiKVM V3 and V4 Plus. To use it, you have to use hardware PWM for kvmfan. To do this, add the following lines to /etc/kvmd/fan.ini:

[main]\npwm_soft = 80\n

Not needed for v4-mini because it does not have a fan.

To use Servo motors in PiKVM you need to follow steps 1-3 for PWM Module and then use the following configuration.

Add to /etc/kvmd/override.yaml:

kvmd:\n    gpio:\n        drivers:\n            servo1:\n                type: servo\n                chip: 0                  # PWM Chip Number\n                period: 20000000         # Servo Motor SG90 Period in nano-seconds\n                duty_cycle_min: 350000   # Servo Motor SG90 duty_cycle for -90 degrees\n                duty_cycle_max: 2350000  # Servo Motor SG90 duty_cycle for +90 degrees\n                angle_max: 90            # Servo Motor SG90 angle at duty_cycle_max\n                angle_min: -90           # Servo Motor SG90 angle at duty_cycle_min\n                angle_push: 45           # Servo Motor SG90 angle to push button\n                angle_release: 20        # Servo Motor SG90 angle to release button\n        scheme:\n            __v4_locator__:  # v4-mini only\n                pin: 25      # v4-mini only\n            short_press:\n                driver: servo1\n                pin: 0  # Pin number is the PWM channel number on the PWM Chip\n                mode: output\n                switch: false\n                pulse:\n                    delay: 0.5\n                    max_delay: 2\n            long_press:\n                driver: servo1\n                pin: 0\n                mode: output\n                switch: false\n                pulse:\n                    delay: 2\n                    max_delay: 2\n            extra_long_press:\n                driver: servo1\n                pin: 0\n                mode: output\n                switch: false\n                pulse:\n                    delay: 10\n                    max_delay: 20\n        view:\n            header:\n                title: Controls\n            table:\n                - [\"#Servo - Short Press\", \"short_press|Press\"]\n                - [\"#Servo - Long Press\", \"long_press|Press\"]\n                - [\"#Servo - Extra Long Press\", \"extra_long_press|Press\"]\n
"},{"location":"gpio/#philips-hue","title":"Philips Hue","text":"Click to view

The hue module can control smartplugs and lamps over Philips Hue Bridge API. In general the plugin can switch any device on/off which is connected to the bridge. To use it you will need API token aka username:

  1. Open http://bridge/debug/clip.html.
  2. In the URL: Field type /api/.
  3. In the Message Body: Field type: {\"devicetype\": \"pikvm\"}.
  4. Hit the Get Button.
  5. As the Response you become the Username: {\"success\": {\"username\": \"apiusername\"}.

Example:

kvmd:\n    gpio:\n        drivers:\n            hue:\n               type: hue\n               url: http://bridge\n               token: YG-xxxxxxxxxxxx\n        scheme:\n            plug_button:\n                driver: hue\n                pin: 32\n                mode: output\n                initial: null\n                switch: true\n                pulse:\n                    delay: 0\n            plug_led:\n                driver: hue\n                pin: 32\n                mode: input\n        view:\n            table:\n                - [\"plug_led\", \"plug_button\"]\n
"},{"location":"gpio/#anel-net-pwrctrl","title":"ANEL NET-PwrCtrl","text":"Click to view

The anelpwr plugin allows you to use ANEL NET-PwrCrtl IP-PDUs (switchabel sockets) as gpios. There are up to 8 Ports per PDU. Input pulls the the current state from the PDU, Output switches the Socket.

kvmd:\n    gpio:\n        drivers:\n            anel_pdu_0:\n                type: anelpwr\n                url: http://IP:port\n                user: admin\n                passwd: anel\n        scheme:\n            pdu0_0_pwr:\n                pin: 0\n                driver: anel_pdu_0\n                mode: output\n                pulse:\n                    delay: 0\n            pdu0_0_led:\n                pin: 0\n                driver: anel_pdu_0\n                mode: input\n        view:\n            header:\n               title: \"PDUs\"\n            table:\n                - [\"#PDU0\"]\n                - []\n                - [\"#PDU0_Port0:\", pdu0_0_led, \"pdu0_0_pwr|confirm|test\"] \n
"},{"location":"gpio/#extron-sw-series-switchers","title":"Extron SW Series Switchers","text":"Click to view

The extron plugin allows you to control Extron SW series switchers (ex. SW4 USB, SW4 VGA, etc.). There are up to 4 Ports per switcher. Input pulls the the current state from the switcher, Output switches the active port.

kvmd:\n    gpio:\n        drivers:\n            extron_vga:\n                type: extron\n                device: /dev/ttyUSB0  # The path to the RS-232 serial adapter\n        scheme:\n            vga_port1_led:\n                pin: 0\n                driver: extron_vga\n                mode: input\n            vga_port2_led:\n                pin: 1\n                driver: extron_vga\n                mode: input\n            vga_port3_led:\n                pin: 2\n                driver: extron_vga\n                mode: input\n            vga_port4_led:\n                pin: 3\n                driver: extron_vga\n                mode: input\n            vga_port1_button:\n                pin: 0\n                driver: extron_vga\n                mode: output\n            vga_port2_button:\n                pin: 1\n                driver: extron_vga\n                mode: output\n            vga_port3_button:\n                pin: 2\n                driver: extron_vga\n                mode: output\n            vga_port4_button:\n                pin: 3\n                driver: extron_vga\n                mode: output\n        view:\n            header:\n               title: \"Extron SW4 VGA\"\n            table:\n                - [\"vga_port1_led|red\", \"vga_port1_button||Port 1\"]\n                - [\"vga_port2_led|red\", \"vga_port2_button||Port 2\"]\n                - [\"vga_port3_led|red\", \"vga_port3_button||Port 3\"]\n                - [\"vga_port4_led|red\", \"vga_port4_button||Port 4\"]\n
"},{"location":"id/","title":"Identifying PiKVM on the target host","text":"

This page explains how PiKVM is presented to the target host's operating system, and how this can be changed. This is useful for developers, testers and system administrators who need PiKVM to emulate a specific USB device or monitor.

Info

Before exploring this page, we recommend to read the PiKVM configuration guide so that you understand the terminology and how exactly the parameters described below change.

"},{"location":"id/#basics","title":"Basics","text":"

PiKVM is a combined emulator of several devices for user interaction. Simply put, your host sees the connected PiKVM not just as a single device, but as a set of multiple devices.

In the most default case out of the box, these are the following:

  • HDMI video display;
  • USB keyboard;
  • USB mouse (two mice for PiKVM V4);
  • USB mass storage drive (ejectable);

Thus, PiKVM emulates two types of devices: HDMI and USB. Each of them has a specific set of identifiers. For example, if you go to monitor settings on the host, you will see something like PiKVM V4 Plus. It works in a similar way with USB.

"},{"location":"id/#hdmi-identifiers","title":"HDMI Identifiers","text":"

Info

This applies to PiKVM V3, V4 and DIY based on CSI bridge. It is impossible to change the EDID for the HDMI-USB dongle.

The EDID (Extended Display Identification Data) is responsible for presenting the display. It also provides the host with information about the resolutions that PiKVM supports. More information about this is written on this page, and here we will provide brief information.

Quick IDs changing on PiKVM V4 Plus

PiKVM V4 Plus has a simple way read and adopt display identifiers like model and serial number from your physical display. See here for details.

Run kvmd-edidconf on PiKVM:

[root@pikvm ~]# kvmd-edidconf\nManufacturer ID: LNX\nProduct ID:      0x7773 (30579)\nSerial number:   0x01010101 (16843009)\nMonitor name:    PiKVM V4 Plus\nMonitor serial:  CAFEBABE\nAudio:           yes\n

The fields have obvious names and purposes. Note the two similar fields Serial number and Monitor serial. The first has a numeric value, and the second is ASCII. If you are using a custom EDID from some real display, some fields may be missing.

To change the values of the EDID fields, use the kvmd-edidconf with options, a complete list is available in kvmd-edidconfi --help.

Here the small example of changing all available fields from the previous listing:

[root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-edidconf --set-mfc-id=TTP --set-product-id=0x5B81 --set-serial=0x8DE11B79 --set-monitor-name=TOSHIBA --set-monitor-serial=ABCD1234 --apply\nManufacturer ID: TTP\nProduct ID:      0x5B81 (23425)\nSerial number:   0x8DE11B79 (2380340089)\nMonitor name:    TOSHIBA\nMonitor serial:  ABCD1234\nAudio:           yes\n...\n[root@pikvm ~]# ro\n

The full list of manufacturer IDs is available here.

For a detailed guide on customizing EDID, please visit this page. There you can also find out how to set the EDID from a real monitor, or quickly adopt your real monitor IDs with PiKVM V4 Plus.

"},{"location":"id/#usb-identifiers","title":"USB Identifiers","text":"

Info

This applies to PiKVM V2+. Identifiers on V1 and/or the Pico HID can't be changed without recompilation and reflashing of the firmware.

USB is a much more complex subsystem and another part of PiKVM is responsible for it. Be careful when changing the settings here, it may cause the USB to fail.

For information on how to control emulated devices see here. The identification is described below.

As you may have found out from the PiKVM configuration guide (if you haven't read it yet, now is the time), you can get the list of all configuration parameters using the kvmd -m command.

Below is a listing of all the parameters, from which the unrelated and those USB parameters that should not be changed have been removed. In the context of identifiers, we are interested in the following:

[root@pikvm ~]# kvmd -m\notg:\n    vendor_id: 7531\n    product_id: 260\n    manufacturer: PiKVM\n    product: PiKVM Composite Device\n    serial: CAFEBABE\n    device_version: -1\n    max_power: 250\n\n    devices:\n        drives:\n            default:\n                inquiry_string:\n                    cdrom:\n                        vendor: PiKVM\n                        product: Optical Drive\n                        revision: '1.00'\n\n                    flash:\n                        vendor: PiKVM\n                        product: Flash Drive\n                        revision: '1.00'\n\n        msd:\n            default:\n                inquiry_string:\n                    cdrom:\n                        vendor: PiKVM\n                        product: Optical Drive\n                        revision: '1.00'\n\n                    flash:\n                        vendor: PiKVM\n                        product: Flash Drive\n                        revision: '1.00'\n

Pay attention to the nesting levels. The parameters are always located in certain sections. All numeric values are displayed in decimal form, but in the config you can use a hex form. The generally accepted names from the USB specifications are shown too.

Parameter USB Spec Description vendor_id idVendor Unique vendor ID assigned by USB.org. product_id idProduct Just an ID for the product assigned by this vendor. manufacturer iManufacturer to 0x409 ASCII name of the vendor. product iProduct to 0x409 ASCII name of the product. serial iSerialNumber to 0x409 ASCII serial number of the product. device_version bcdDevice Kinda the revision of the device. Assigned automatically. It can be changed to 256, 257, 258 or something like this

These IDs are also used for the microphone on PiKVM V4.

The strings under otg/drives and otg/msd sections deserve a special description. They relate to virtual media emulation and are separate parts of the SCSI inquiry string, the drive identifier used by the OS driver. All three parameters vendor, product, and revision are short ASCII strings responsible for CD/DVD or Flash representation.

The msd refers to a virtual drive accessible from the Web UI, and the drives describes all additional drives if you have configured them (disabled by default). Note that mass storage drive can be completely disabled.

To change the parameters, use the /etc/kvmd/override.yaml, for example, like this:

otg:\n    vendor_id: 0x6940\n    product_id: 0x6973\n    manufacturer: Corsair\n    product: Gaming RGB\n    serial: 1000\n\n    devices:\n        msd:\n            default:\n                inquiry_string:\n                    cdrom:\n                        vendor: Corsair\n                        product: DVD\n                        revision: '1.00'\n\n                    flash:\n                        vendor: Corsair\n                        product: STICK\n                        revision: '1.00'\n

After changing validate the config using kvmd -m. You will see the full config list with changed and default values, or a message about configuration error.

If everything is fine, perform the soft reboot.

"},{"location":"id/#replicating-setups","title":"Replicating setups","text":"

You can use kvmd-edidconf and kvmd-otgconf to replicate an entire host configuration for testing or other purposes. What you can do will vary depending on the PiKVM device you have:

  • V4 Plus: you can import both EDID and USB IDs.
  • V4 Mini: you must manually edit override.yaml, as there is neither a second HDMI Out or additional USB ports on your PiKVM.
  • V3: you can import USB IDs only, as there is no second HDMI output on your PiKVM.

Assuming you have PiKVM V4 Plus, follow these steps:

  1. Connect the host's display to one of the two HDMI Out ports on the rear panel of your PiKVM.
  2. Connect the host's USB keyboard and mouse to USB ports on the front and the rear panel of you PiKVM.
  3. Run rw to switch to read-write mode.
  4. Run kvmd-edidconf --import-display-ids --apply as root on the PiKVM. This will fetch EDID information from the connected physical display and place it into the /etc/kvmd/override.yaml configuration file.
  5. Run kvmd-otgconf --import-usb-ids as root on the PiKVM. This will fetch IDs of the connected physical USB devices and place them into the /etc/kvmd/override.yaml configuration file.
  6. Run ro to switch to read-only mode.
  7. Run reboot to reboot your PiKVM and apply newly the added customization.
  8. Reconnect the host's display and keyboard/mouse back to the host.
"},{"location":"ipmi/","title":"IPMI & Redfish","text":"

Info

This page is about the server-side IPMI emulation if you want to manage PiKVM using ipmitool or something similar. If you want to use the PiKVM Web UI to manage the server using IPMI (that is, as an IPMI client), see GPIO functions with IPMI plugin.

Warning

Although PiKVM supports the IPMI protocol, we strongly recommend that you DO NOT USE IT outside of trusted networks due to the protocol's insecurity.

Please consider to using the Redfish or KVMD API instead of it.

"},{"location":"ipmi/#ipmi-bmc","title":"IPMI BMC","text":"

IPMI is a legacy protocol for remote server management. It can be useful for managing a large number of machines with PiKVM. Its advantage is that it is supported by many enterprise systems.

Step by step: Enabling IPMI server on PiKVM
  1. Switch the filesystem to the RW-mode:

    [root@pikvm ~]# rw\n
  2. Set up IPMI account in file /etc/kvmd/ipmipasswd (see the comment inside it).

  3. Enable the kvmd-ipmi daemon:

    [root@pikvm ~]# systemctl enable --now kvmd-ipmi\n
  4. Switch the filesystem back to the RO:

    [root@pikvm ~]# ro\n
  5. Try some commands on the client PC:

    $ ipmitool -I lanplus -U admin -P admin -H pikvm power status\n$ ipmitool -I lanplus -U admin -P admin -H pikvm power on\n
"},{"location":"ipmi/#ipmi-sol","title":"IPMI SoL","text":"

IPMI supports the ability to get console access to the server using Serial-over-LAN. With this feature PiKVM will act as a proxy for your server's COM port.

To use this feature, you will need a USB-COM adapter that you need to connect to the PiKVM. The COM port of the adapter need to be connected to the server.

Step by step: Enabling IPMI SoL for USB-COM adapter

As with IPMI BMC, you need to configure kvmd-ipmi server (see the previous chapter about IPMI BMC) and add the following configuration to /etc/kvmd/override.yaml:

ipmi:\n    sol:\n        device: /dev/ttyUSB0  # Path of your USB-COM adapter\n        speed: 115200\n

Then restart the kvmd-ipmi server: systemctl restart kvmd-ipmi.

All requests that it receives over the network regarding the COM port will be forwarded to your server. For example:

[root@pikvm ~]$ ipmitool -I lanplus -U admin -P admin -H pikvm sol activate\n
"},{"location":"ipmi/#redfish","title":"Redfish","text":"

Redfish is a more modern server management protocol designed to replace IPMI. It is based on HTTP and fixes many security issues. If possible, we recommend using it instead of IPMI, or using the KVMD API.

PiKVM supports the Redfish natively and provides a power management handles with it.

To access the Redfish API, use HTTP Basic Auth methods. Also you can use the redfishtool:

[root@pikvm ~]$ redfishtool -S Never -r pikvm root\n[root@pikvm ~]$ redfishtool -S Never -u admin -p admin -r pikvm Systems\n[root@pikvm ~]$ redfishtool -S Never -u admin -p admin -r pikvm Systems reset ForceOff\n
"},{"location":"letsencrypt/","title":"Let's Encrypt certificates","text":"

PiKVM uses self-signed SSL certificates out of the box. If you have a domain name, you can use Let's Encrypt certificates.

Usually Let's Encrypt certificates are issued and updated automatically using Certbot, however, since PiKVM uses a read-only file system, special tools around Certbot are required to work with certificates. KVMD 3.117 provides them.

Note

This feature is available on images as old as 2022.06.19 since it requires PST storage partition on SD card. Ports 80+443 need to be opened if you are port forwarding for this to work properly.

"},{"location":"letsencrypt/#basic-setup","title":"Basic setup","text":"
  1. Update the OS and make sure that you are using a new image with PST storage.

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

    # kvmd-pstrun -- true\n

    If the storage is not available, you need to reflash the OS image to the latest one from our official website.

  2. Switch filesystem to RW and obtain the certificate (for example, pikvm.example.com. The method depends on the network configuration. In the simplest case, if PiKVM is open for access from the Internet, it is recommended to use the webroot. Another examples will be described below.

    # rw\n# kvmd-certbot certonly_webroot --agree-tos -n --email user@example.com -d pikvm.example.com\n
  3. Install the certificate for KVMD-Nginx and (optionally) KVMD-VNC. Running services will be restarted/reloaded automatically. Switch filesystem to RO.

    # kvmd-certbot install_nginx pikvm.example.com\n# kvmd-certbot install_vnc pikvm.example.com\n# ro\n
  4. Check the renewal immediately, just for testing:

    # kvmd-certbot renew --force-renewal\n
  5. Enable automatic certificate renewal:

    # rw\n# systemctl enable --now kvmd-certbot.timer\n# ro\n
"},{"location":"letsencrypt/#cloudflare-dns","title":"Cloudflare DNS","text":"

This example shows that PiKVM may not be accessible from the internet, but you can still get a certificate if you use Cloudflare DNS.

  1. Switch filesystem to RW and install the Cloudflare DNS plugin:

    # rw\n# pacman -S certbot-dns-cloudflare\n
  2. Prepare the environment for the DNS plugin (place the auth data):

    # kvmd-pstrun -- mkdir -p /var/lib/kvmd/pst/data/certbot/runroot\n# kvmd-pstrun -- nano /var/lib/kvmd/pst/data/certbot/runroot/.cloudflare.auth\n# kvmd-pstrun -- chmod 600 /var/lib/kvmd/pst/data/certbot/runroot/.cloudflare.auth\n# kvmd-pstrun -- chown kvmd-certbot: /var/lib/kvmd/pst/data/certbot/runroot/.cloudflare.auth\n
    See certbot-dns-cloudflare's doc here about the content of .cloudflare.auth.
  3. Obtain the certificate:

    # kvmd-certbot certonly \\\n   --dns-cloudflare \\\n   --dns-cloudflare-propagation-seconds 60 \\\n   --dns-cloudflare-credentials /var/lib/kvmd/pst/data/certbot/runroot/.cloudflare.auth \\\n   --agree-tos \\\n   -n \\\n   --email user@example.com \\\n   -d pikvm.example.com\n
  4. Next follow the basic guide starts at step 3.

"},{"location":"letsencrypt/#route53-dns","title":"Route53 DNS","text":"

This example shows that PiKVM may not be accessible from the internet, but you can still get a certificate if you use AWS Route53 DNS. Make sure you are running an image newer than 2022.06.20 and kvmd version 3.119-1 or greater.

  1. Switch filesystem to RW and install the Route53 DNS plugin:

    # rw\n# pacman -S certbot-dns-route53\n
  2. Configure Your AWS User For the certbot_dns_route53 plugin to work it needs to be able to connect to AWS using an access key with the correct permissions.

    To do this securely you\u2019ll want to create a new AWS user that only has the necessary permissions it needs to work.

    You can find instructions for creating a user here. The basics of it is you\u2019ll want a user with Programmatic access (not console), add it to a group (I created a new one just for this user and any future certbot users I might need).

    The user will need specific permissions that are required to allow the certbot plugin to create the necessary CNAME records. These can be added by manually selecting them from a very long list or you can use the json view to give it the following permissions.

    {\n\"Version\": \"2012-10-17\",\n\"Statement\": [\n   {\n      \"Effect\": \"Allow\",\n      \"Action\": [\"route53:ListHostedZones\", \"route53:GetChange\"],\n      \"Resource\": [\"*\"]\n   },\n   {\n      \"Effect\": \"Allow\",\n      \"Action\": [\"route53:ChangeResourceRecordSets\"],\n      \"Resource\": [\"arn:aws:route53:::hostedzone/YOURHOSTEDZONEID\"]\n   }\n]\n}\n

    Make sure you replace YOURHOSTEDZONEID with the instance ID of your hosted zone.

    Once the user is created don\u2019t forget to download and save your access key and secret access key (somewhere secure, these are as sensitive as your passwords).

  3. Setup credentials:

    We now need to put the AWS credentials on the PiKVM so the certbot can use them.

    # kvmd-pstrun -- mkdir -p /var/lib/kvmd/pst/data/certbot/runroot\n

    Copy and paste your AWS credentials into the nano editor and save the file.

    # kvmd-pstrun -- nano /var/lib/kvmd/pst/data/certbot/runroot/.route53.auth\n

    Here is an example .route53.auth file. Replace the placeholders with the access key and secret access key that you just saved from AWS and fill them in.

    [default]\naws_access_key_id=XXXXXX\naws_secret_access_key=XXXX/XXXXX\n

    Update permissions:

    # kvmd-pstrun -- chmod 600 /var/lib/kvmd/pst/data/certbot/runroot/.route53.auth\n# kvmd-pstrun -- chown kvmd-certbot: /var/lib/kvmd/pst/data/certbot/runroot/.route53.auth\n
  4. Obtain the certificate:

    # export AWS_SHARED_CREDENTIALS_FILE=\"/var/lib/kvmd/pst/data/certbot/runroot/.route53.auth\"\n# kvmd-certbot certonly \\\n   --dns-route53 \\\n   --agree-tos \\\n   -n \\\n   --email user@example.com \\\n   -d pikvm.example.com\n
  5. Enable automatic certificate renewal:

    Create the file: /etc/conf.d/kvmd-certbot with the following contents so the renewall service can find the authentication file containing the AWS credentials:

    AWS_SHARED_CREDENTIALS_FILE=\"/var/lib/kvmd/pst/data/certbot/runroot/.route53.auth\"\n

    Now enable the renewal service:

    # systemctl enable --now kvmd-certbot.timer\n
"},{"location":"letsencrypt/#acme-dns","title":"ACME DNS","text":"

ACME DNS is a \"Limited DNS server with RESTful HTTP API to handle ACME DNS challenges easily and securely.\" The acme-dns-client works, in conjunction, with Certbot (kvmd-certbot) to enable DNS-01 challenge support via ACME DNS.

These instructions are for how to install and use the acme-dns-client with ACME DNS for PiKVM.

"},{"location":"letsencrypt/#assumptions","title":"Assumptions","text":"
  • ACME DNS is already set up and functioning in the environment
  • ACME DNS Server is auth.example.org
  • PiKVM Fully Qualified Domain Name (FQDN) is pikvm.example.org
  • PiKVM is running on a supported Raspberry Pi using the PiKVM OS (which is 32-bit as of the writing of this documentation)
  • All configuration examples below are as user root via a terminal session to PiKVM
"},{"location":"letsencrypt/#not-in-scope","title":"Not in Scope","text":"
  • Installation and Setup of ACME DNS Server
"},{"location":"letsencrypt/#instructions","title":"Instructions","text":"
  1. Ensure that Step 1 from Basic Setup has been completed
  2. Visit the Releases page to get the download URL for the latest acme-dns-client release (PiKVM OS is 32-bit, which is linux_armv6)
  3. Install acme-dns-client

    The acme-dns-client is not distributed by pacman and is a manual installation. The steps below are for:

    • Creating a folder for acme-dns-client
    • Downloading and extracting the acme-dns-client TAR from Github
    • Moving the acme-dns-client binary to the created folder
    • Cleaning up files from the download
    • Creating the necessary persistent symbolic link to allow acme-dns-client to be ran
    • Initialize acme-dns-client

    Note

    Make sure to replace the URL below with the one gathered from Step 1. As of the writing of this documentation: - The latest (and demonstrated) version is v0.3 - (Demonstrated) Platform is linux-armv6

    # mkdir /etc/acmedns\n# curl -LO https://github.com/acme-dns/acme-dns-client/releases/download/v0.3/acme-dns-client_0.3_linux_armv6.tar.gz\n# tar -zxvf acme-dns-client_0.3_linux_armv6.tar.gz\n# mv acme-dns-client /etc/acmedns/acme-dns-client\n# ln -sf /etc/acmedns/acme-dns-client /usr/local/bin/acme-dns-client\n# rm LICENSE README.md acme-dns-client_0.3_linux_armv6.tar.gz\n# acme-dns-client\n
  4. Register acme-dns-client with ACME DNS

    Note

    This is interactive, follow instructions for creating and verifying the appropriate CNAME record.

    # acme-dns-client register -d pikvm.example.org -s http://auth.example.org\n

    Once registration is complete ownership of clientstorage.json must be changed to kvmd-certbot.

    # chown kvmd-certbot:kvmd-certbot /etc/acmedns/clientstorage.json\n

    Note

    If using acme-dns-client on an internal/private domain with an ACME compatible Certificate Authority do not forget to add -ns <dns-server-ip>:<dns-server-port> to acme-dns-client register

  5. Register Certbot

    # kvmd-certbot register\n
  6. Request Certificate via Certbot

    # kvmd-certbot certonly --manual --preferred-challenges dns --manual-auth-hook 'acme-dns-client' -d pikvm.example.org\n

    Note

    If using an ACME compatible Certificate Authority (other than Let's Encrypt) do not forget to add --server https://ca.example.org/acme/acme/directory to kvmd-certbot

  7. Follow steps 3 through 5 under Basic Setup to complete setup and renewal of certificates

"},{"location":"letsencrypt/#wireguard-proxy","title":"Wireguard proxy","text":"

If you don't have public IP, and you don't want to put your API keys in PiKVM, you can forward HTTP traffic over wireguard. To Let's Encrypt you'll appear to serve ACME challenges from a host they can reach from the Internet (e.g. VPS), to which you'll connect over wireguard.

"},{"location":"letsencrypt/#assumptions_1","title":"Assumptions","text":"
  • FQDN of your pikvm is pikvm1.int.example;
  • FQDN of the proxy VPS is acme-proxy.example;
  • public IP addresses of VPS are 198.51.100.1 and 2001:db8::1;
  • internal (wireguard) IPv4 address of the PiKVM is 10.11.12.13.
"},{"location":"letsencrypt/#instructions_1","title":"Instructions","text":"
  1. Setup wireguard and ensure it's working.

  2. Setup public DNS zone to point the domain address at the public VPS:

    acme-proxy.example. IN A      198.51.100.1\nacme-proxy.example. IN AAAA   2001:db8::1\npikvm1.int.example. IN CNAME  acme-proxy.example.\n
  3. On the public VPS, configure HTTP proxy to forward /.well-known/acme-challenge to PiKVM. For example in nginx:

    server {\n   listen 80;\n   listen [::]:80;\n\n   server_name pikvm1.int.example;\n\n   location ^~ /.well-known/acme-challenge {\n      proxy_pass http://10.11.12.13:80;\n      proxy_set_header Host $host;\n   }\n\n   location / {\n      return 404;\n   }\n}\n
  4. Now you can use kvmd-certbot certonly_webroot as in basic scenario above.

"},{"location":"modem/","title":"Setting up 3G/4G/LTE modem","text":"

With PiKVM, you can create a portable device to work in a distant environment without a permanent wired internet connection. A cellular modem in combination with any VPN like Tailscale is also an excellent backup for emergency access to the host.

"},{"location":"modem/#choosing-a-modem","title":"Choosing a modem","text":"

PiKVM supports a huge number of USB modems. If the modem works with a desktop Linux, it will work with PiKVM as well.

"},{"location":"modem/#mini-pci-on-pikvm-v4-plus","title":"Mini-PCI on PiKVM V4 Plus","text":"

PiKVM V4 Plus has an internal Mini-PCI and built-in SIM card slot for installing a modem. Please note that only modems with USB data lines are supported.

Here is a list of good modems that you can start with:

  • SIMCom SIM7600G-H
  • Sierra Wireless MC7700
  • Huawei EM820W
  • Quectel EG25-G

An antenna and an SMA pigtail are also required to use the modem.

When choosing an antenna, check the supported frequency list of your cellular ISP and the antenna itself.

"},{"location":"modem/#setting-up-the-connection","title":"Setting up the connection","text":"

Change default passwords if you haven't done so earlier. It's very important for the security.

Cellular networks can open your device to the big world. PiKVM is safe if you use a strong password, so...

Changing PiKVM Passwords

PiKVM comes with the following default passwords:

  • Linux OS-level admin (SSH, console...):

    • Username: root
    • Password: root
  • KVM user (Web Interface, API, VNC...):

    • Username: admin
    • Password: admin
    • No 2FA code

They are two separate accounts with independent passwords.

To change passwords, you will need to use the console access via SSH or the Web Terminal. If you are using the Web Terminal, enter the su - command to get the root access (enter the root user password).

[root@pikvm ~]# rw\n[root@pikvm ~]# passwd root\n[root@pikvm ~]# kvmd-htpasswd set admin\n[root@pikvm ~]# ro\n

If you require additional user for the Web UI access, use the following:

[root@pikvm ~]# kvmd-htpasswd add <user> # Add a new user with password\n[root@pikvm ~]# kvmd-htpasswd del <user> # Remove/delete a user\n

Optionally you can enable the two-factor authentication for more security.

Changing the VNCAuth key and IPMI password at the first start of PiKVM is not required, since these services are disabled by default. But it is here just so that you remember their existence.

  1. Update the OS and reboot.

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  2. Make filesystem writable using rw command.

  3. Install NetworkManager and ModemManager:

    [root@pikvm ~]# pacman -S modemmanager networkmanager\n
  4. Create file /etc/NetworkManager/conf.d/pikvm-unmanaged.conf with following content:

    [keyfile]\nunmanaged-devices=*,except:type:gsm\n
  5. Run the services:

    [root@pikvm ~]# systemctl enable --now NetworkManager ModemManager\n
  6. Make sure that ModemManager detects your modem. You will see something similar after mmcli, modem 0 is detected here:

    [root@pikvm ~]# mmcli --list-modems\n    /org/freedesktop/ModemManager1/Modem/0 [QUALCOMM INCORPORATED] SIMCOM_SIM7600G-H\n
  7. View the modem 0 information:

    [root@pikvm ~]# mmcli -m 0\n  -----------------------------------\n  General  |                    path: /org/freedesktop/ModemManager1/Modem/0\n           |               device id: ...\n  -----------------------------------\n  Hardware |            manufacturer: QUALCOMM INCORPORATED\n           |                   model: SIMCOM_SIM7600G-H\n           |       firmware revision: LE20B04SIM7600G22\n           |          carrier config: ROW_Gen_VoLTE\n           | carrier config revision: ...\n           |            h/w revision: 10000\n           |               supported: gsm-umts, lte\n           |                 current: gsm-umts, lte\n           |            equipment id: ...\n  ...\n  -----------------------------------\n  Status   |                    lock: sim-pin\n           |          unlock retries: sim-pin (3), sim-puk (10), sim-pin2 (3), sim-puk2 (10)\n           |                   state: locked\n           |             power state: on\n  ...\n
  8. Set up the connection. You will need the APN value (from the mobile ISP) and PIN-code for the SIM:

    [root@pikvm ~]# nmcli c add type gsm ifname '*' con-name pikvm-lte gsm.apn cytamobile gsm.pin 1234\n
    • pikvm-lte is just a meaning name of the connection, use any you like.
    • gsm.apn cytamobile sets APN value to cytamobile (will be different for other ISP).
    • gsm.pin 1234 sets PIN for unlocking the SIM card. If the SIM is not locked, omit these words.

    Depending on the ISP, you may need to specify a password and/or some other parameters.

  9. Make the connection automatically connected:

    [root@pikvm ~]# nmcli connection modify pikvm-lte autoconnect yes\n
  10. The connection will already be working:

    [root@pikvm ~]# nmcli\ncdc-wdm0: connected to pikvm-lte\n        \"cdc-wdm0\"\n        gsm (option, qmi_wwan), hw, iface wwan0, mtu 1500\n        ip4 default\n        inet4 XXX.XXX.XXX.XXX/XX\n        route4 XXX.XXX.XXX.XXX/XX metric 700\n        route4 default via XXX.XXX.XXX.XXX/XX metric 700\n...\n
  11. Perform reboot.

To set up a Tailscale VPN, refer to this page.

"},{"location":"mouse/","title":"Mouse","text":"

There are two modes of pointer device: absolute and relative.

In absolute mode, the input device transmits the exact coordinates (X,Y) where the cursor should be moved. This is how touchscreens or drawing tablets work.

In relative mode, only the relative offset (dX,dY) to the current position is transmitted, which is unknown to the input device itself. This is a regular mouse.

By default, PiKVM uses absolute positioning mode as the most convenient for the user and software. However, this is not always supported by the BIOS/UEFI. For such cases, support is provided for the relative mode of operation, which can be enabled in the config.

When using relative mode, the browser will exclusively capture your mouse when you click on the stream window in PiKVM once. When you press Esc, the browser releases the mouse.

"},{"location":"mouse/#important-notes","title":"Important notes","text":"

The relative mouse generates a huge number of events that can be poorly transmitted over the network or very slowly perceived by the BIOS/UEFI driver. To solve this problem, mouse events are optimized using a vector sum. This mode is enabled by activating the below first and is available in the web menu System -> Squash mouse moves. You can try disabling this if you have problems with mouse acceleration. This is the best and most reasonable compromise right now.

Also currently the relative mouse mode is not supported by PiKVM VNC server yet. The reason is that none of the recommended clients support the QEMU Pointer Motion Change extension. We expect to implement this in TigerVNC. The relative mode is also not supported by mobile browsers.

"},{"location":"mouse/#relative-mouse-on-v2-platform-otg-hid","title":"Relative mouse on V2+ platform (OTG HID)","text":"

Info

On PiKVM V4 dual mode is enabled by default. To disable it and enable single mode, set kvmd/hid/mouse_alt/device (see below) to empty string:

kvmd:\n    hid:\n        mouse_alt:\n            device: \"\"\n
"},{"location":"mouse/#dual-mode","title":"Dual mode","text":"

Using dual mouse mode you can switch between the absolute and relative mouse in the System menu without reloading. This is more convenient, but for compatibility reasons it is disabled by default. To enable it, do the following:

  1. Switch filesystem to RW-mode using command rw.

  2. Edit /etc/kvmd/override.yaml and add these lines:

    kvmd:\n    hid:\n        mouse_alt:\n            device: /dev/kvmd-hid-mouse-alt\n
  3. Perform reboot. After that reboot your PC.

"},{"location":"mouse/#single-relative-mode","title":"Single relative mode","text":"
  1. Switch filesystem to RW-mode using command rw.

  2. Edit /etc/kvmd/override.yaml and add these lines:

    kvmd:\n    hid:\n        mouse:\n            absolute: false\n
  3. Perform reboot. After that reboot your PC.

  4. If the mouse is still not detected by the BIOS/UEFI, try disabling horizontal scrolling to achieve the maximum compatibility:

    kvmd:\n    hid:\n        mouse:\n            absolute: false\n            horizontal_wheel: false\n
  5. Don't forget to perform reboot.

"},{"location":"mouse/#fixing-the-absolute-mouse-on-windows-98","title":"Fixing the absolute mouse on Windows 98","text":"

Due to an ancient buggy driver, the absolute mouse on Windows 98 moves only within the upper-left quarter of the screen. To fix this, you need to activate some magic workaround. Due to the specifics of the implementation, you will have to turn on the relative mouse too. Write it in /etc/kvmd/override.yaml:

kvmd:\n    hid:\n        mouse:\n            absolute_win98_fix: true\n        mouse_alt:\n            device: /dev/kvmd-hid-mouse-alt\n

... and run systemctl restart kvmd. After that, you will get 3 new buttons with mouse modes in the System menu in Web UI. Switch it to Abs-Win98.

"},{"location":"mouse/#relative-mouse-on-v0-v1-platform-picoarduino-hid","title":"Relative mouse on V0-V1 platform (Pico/Arduino HID)","text":"

Mode switching for the Pico HID or legacy Arduino HID can be performed on-the-fly starting with KVMD 2.6 and the corresponding firmware. No additional actions are required.

"},{"location":"mouse_jiggler/","title":"Mouse Jiggler","text":"

The mouse jiggler is a feature used to simulate the movement of a computer mouse. It prevents sleep mode, standby mode or the screensaver from activating. It is very useful when some lengthy process is going on on the target host (for example, installing software), and the user needs to monitor it with his side vision, without having to move the mouse manually to avoid the screensaver.

"},{"location":"mouse_jiggler/#using-the-jiggler","title":"Using the Jiggler","text":"

With a latest PiKVM OS, the jiggler is available in the Web UI:

If you don't see this switch, please update OS first:

Updating PiKVM OS

To update, run following commands under the root user:

[root@pikvm ~]# pikvm-update\n

If you encounter an error like:

[root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

It's most likely you have an old OS release. You can update the OS as follows:

[root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

Next time you will be able to use the usual method with pikvm-update.

"},{"location":"mouse_jiggler/#jiggler-settings","title":"Jiggler settings","text":"

This is not required usually, but it is possible to change some of the parameters of the jiggler or disable it completely.

Here are some examples to place it to /etc/kvmd/override.yaml.

  1. Make the jiggler unavailable in the menu:

    kvmd:\n    hid:\n        jiggler:\n            enabled: false\n
  2. Activate it by default after PiKVM reboot:

    kvmd:\n    hid:\n        jiggler:\n            active: true\n
"},{"location":"mouse_jiggler/#description-of-the-algorithm","title":"Description of the algorithm","text":"

When the Jiggler is active, PiKVM counts down the time that has elapsed since the last user input: that is, any action with the keyboard or mouse. If there have been no actions for more than 15 seconds, the Jiggler performs a mouse movement and waits another 15 seconds until the next iteration.

The Jiggler supports both mouse modes: absolute and relative.

Movement patterns looks like these:

  • Absolute: (+100, +100), wait, (-100, -100), wait...The coordinates are converted depending on the screen resolution.
  • Relative: (+10, +10), wait, (-10, -10), wait...

The Jiggler works on the PiKVM device side, even if the Web UI was closed.

An important feature of the Jiggler is that it does not interfere with normal user work. If the user is actively interacting with the keyboard and mouse, Jiggler will not introduce its interference until it notices that the period of inactivity has exceeded the threshold of 15 seconds.

"},{"location":"msd/","title":"Mass Storage Drive","text":"

This powerful feature that is available on all PiKVM V2+ devices. It allows PiKVM to emulate a virtual CD/DVD or Flash Drive for the target host which will be available even in BIOS/UEFI when you need live disk to revive the OS or even reinstall it.

Warning

This document is relevant for KVMD >= 4.49.

Also since this version, PiKVM supports DVD emulation!

If you are using an older version, please update the PiKVM OS:

Updating PiKVM OS

To update, run following commands under the root user:

[root@pikvm ~]# pikvm-update\n

If you encounter an error like:

[root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

It's most likely you have an old OS release. You can update the OS as follows:

[root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

Next time you will be able to use the usual method with pikvm-update.

Take a look at the Drive menu in the Web UI

The following actions are available here:

  • Uploading an image to the internal storage of PiKVM.
  • Selecting an image to connect to the target host.
  • Changing the media type and write availability mode.
  • Downloading an image from the PiKVM storage.
  • Drive connection management and much more.

Warning

Never turn off the power of the PiKVM while the image is being uploaded or while the image is connected to the target host in write mode. This may cause file corruption.

The rest of the time, power off is safe because the PiKVM filesystem will be in read-only mode.

Changing the media type between CD/DVD and Flash is possible only when the device is reconnected

On PiKVM V3 and V4, this can be done using the System -> Connect main USB switch in the Web UI.

In this case, the media type is determined at the time of connecting the image, and not by clicking on the switch. The switch affects the settings of the future connection. For non-V3/V4 devices, you need to either reboot your target host or otherwise reinitialize the drive.

"},{"location":"msd/#manual-images-uploading","title":"Manual images uploading","text":"

PiKVM stores images in a special memory card partition mounted in /var/lib/kvmd/msd.

Most of the time, the partition is read-only, and is remounted for writing automatically if the appropriate drive emulation mode is enabled, or to upload a new image. This protects the data from damage in the event of a sudden loss of power.

Step by step: Manual image uploading using SCP or rsync
  1. Remount internal storage to read-write mode manually:

    [root@pikvm ~]# kvmd-helper-otgmsd-remount rw\n
  2. Upload the image(s) to /var/lib/kvmd/msd using scp or some other tool.

  3. Remount internal storage back to safe read-only mode:

    [root@pikvm ~]# kvmd-helper-otgmsd-remount ro\n

Tip

An HTTP API for Mass Storage management is also available for advanced use.

"},{"location":"msd/#writable-flash-drive","title":"Writable Flash Drive","text":"

When emulating Flash Drive on PiKVM, you can allow the target host to write files to the image. After stopping the drive, this image can be downloaded and opened on the local host. This is useful if you need to get some files from the target host.

The file system image for the virtual Flash Drive must be prepared in advance. This can be done either on the local host or in the PiKVM console.

Here some options:

Step by step: Creating simple FAT32 image on PiKVM
  1. Remount internal storage to read-write mode manually:

    [root@pikvm ~]# kvmd-helper-otgmsd-remount rw\n
  2. Create an empty image file in /var/lib/kvmd/msd (this is the internal storage of PiKVM images) of desired size (512MB in this example) and format it to FAT32:

    [root@pikvm ~]# fallocate -l 512M /var/lib/kvmd/msd/flash.img\n[root@pikvm ~]# loop=$(losetup -f)\n[root@pikvm ~]# echo -e 'o\\nn\\np\\n1\\n\\n\\nt\\nc\\nw\\n' | fdisk /var/lib/kvmd/msd/flash.img\n[root@pikvm ~]# losetup -P $loop /var/lib/kvmd/msd/flash.img\n[root@pikvm ~]# mkfs.vfat ${loop}p1\n[root@pikvm ~]# losetup -d $loop\n[root@pikvm ~]# chmod 666 /var/lib/kvmd/msd/flash.img\n
  3. Remount internal storage back to safe read-only mode:

    [root@pikvm ~]# kvmd-helper-otgmsd-remount ro\n

Note

  • For PiKVM V3+ you'll need to toggle the USB connection using the Web UI: Switch System -> Connect Main USB to off, then on.
  • For V2 you'l need to reboot the target host.
Step by step: Creating an image on a local macOS
  1. Open Disk Utility.

  2. Click menu File -> New Image -> Blank Image.

  3. Set some options:

    Format and Partitions are very important
  4. Click Save. The drive will automatically be mounted.

  5. Copy files (such as BIOS updates) onto the new image (via terminal or drag and drop in Finder).

  6. Eject image.

  7. Rename the image file from .dmg to .img.

  8. Upload the image to PiKVM.

The image flash.img now should be available in the Drive menu in Web UI. Change drive mode to the Flash position and enable Writable switch. Connect the image, do whatever is necessary, with files, and disconnect it. The modified image containing your files can be downloaded to a local host by selecting it from the menu and clicking the floppy disk icon.

"},{"location":"msd/#nfs-storage","title":"NFS storage","text":"

It is possible to create a shared image storage for an entire fleet of PiKVMs using NFS.

If you have some shares, you can easily connect them to PiKVM by creating mount points and adding relevant records to /etc/fstab. At the same time, you will be able to upload images via PiKVM Web UI to NFS, and still use local storage.

Step by step: Connecting NFS storage
  1. Update OS:

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  2. Make some preparations:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -S nfs-utils\n[root@pikvm ~]# kvmd-helper-otgmsd-remount rw\n[root@pikvm ~]# mkdir -p /var/lib/kvmd/msd/NFS_Primary\n[root@pikvm ~]# mkdir -p /var/lib/kvmd/msd/NFS_Secondary\n[root@pikvm ~]# kvmd-helper-otgmsd-remount ro\n
  3. Add NFS shares to /etc/fstab:

    server:/srv/nfs/NFS_Primary    /var/lib/kvmd/msd/NFS_Primary    nfs vers=3,timeo=1,retrans=1,soft,nolock  0 0\nserver:/srv/nfs/NFS_Secondary  /var/lib/kvmd/msd/NFS_Secondary  nfs vers=3,timeo=1,retrans=1,soft,nolock  0 0\n
  4. Perform reboot to apply all changes.

Make sure that the kvmd user has the read access from these directories. You can also give the write access if needed. For the best performance, it is required to ensure reliable connectivity with NFS server and use minimum timeo and retrans values. Using the soft option is mandatory, nolock is recommended.

Note if an image is added to the NFS storage from the outside, PiKVM will not be able to track this event, so it is required to use Drive -> Reset in the Web UI to update the list of images.

Configuring an NFS server is beyond the scope of this guide.

"},{"location":"msd/#sambacifs-storage","title":"Samba/CIFS storage","text":"

If you already have a local samba server e.g. Unraid or another NAS you can use the isos from there.

To refresh the list of available isos on the share it is currently necessary to reboot.

Step by step: Connecting Samba/CIFS storage
  1. Update OS:

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  2. Make some preparations:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -S cifs-utils\n[root@pikvm ~]# kvmd-helper-otgmsd-remount rw\n[root@pikvm ~]# mkdir -p /var/lib/kvmd/msd/isos\n[root@pikvm ~]# kvmd-helper-otgmsd-remount ro\n
  3. Add Samba/CIFS shares to /etc/fstab:

    //192.168.0.1/isos   /var/lib/kvmd/msd/isos   cifs  guest,_netdev,nofail 0 0\n
  4. Perform reboot to apply all changes.

"},{"location":"msd/#exfat-filesystem-warning","title":"exFAT filesystem warning","text":"

Using the existing USB ports you can reduce writes to the internal SSD card by storing images on a USB thumb drive. This is mounted as would NFS or Samba, above. As recent drives are starting to come formatted with exfat instead of fat or NTFS, the linux kernel will default to 'root' ownership of the mountpoint. This means the volume will be visible in the 'Media' menu, but will be marked as [read-only], without any obvious reason.

The correct /etc/fstab entry for a USB drive that presents as /dev/sda1 with an exfat filesystem is:

    ```fstab\n    /dev/sda1   /var/lib/kvmd/msd/usb   exfat  auto,nofail,rw,umask=0000  0 0\n    ```\n

This says to mount it automatically, do not fail if it's missing, mount it read/write by default, and allow all users and groups access to it.

Don't forget to create /var/lib/kvmd/msd/usb directory:

[root@pikvm ~]# kvmd-helper-otgmsd-remount\n[root@pikvm ~]# mkdir -p /var/lib/kvmd/msd/usb\n[root@pikvm ~]# kvmd-helper-otgmsd-remount ro\n
"},{"location":"msd/#multiple-drives","title":"Multiple drives","text":"

By default, PiKVM creates one virtual drive for Mass Storage emulation. However, if necessary, you can create additional ones and manage them using console utility. This is useful if there is a need to boot the target host from the first drive, and then connect the second to exchange files.

Note

The first virtual drive is available for management both in the Web UI (the Drive menu) and using the kvmd-otgmsd console utility (see below). Extra drives are controlled only from console.

The issue of additional drives concerns compatibility. There is an assumption that multiple drives on the same USB may confuse some BIOS/UEFI. So for paranoid reasons, this feature requires manual activation. It is recommended setting up the drives in advance, making sure that booting from ISO CD or Flash is still working with your specific target host, and then using the drives as planned.

Also additional drives consumes extra endpoints, read more under the spoiler:

USB limitations

Each emulated USB device consumes a limited hardware resource called endpoints.

Short info: by default, you can add only one additional USB device.

To get more information about the endpoints, add more devices, and flexibly manage the configuration on the fly, see here.

So, to add a second virtual drive, follow this:

Step by step: Enabling an additional drive
  1. Switch the filesystem to read-write mode:

    [root@pikvm ~]# rw\n
  2. Edit /etc/kvmd/override.yaml and add the extra drive config section:

    otg:\n    devices:\n        drives:\n            enabled: true  # Set it to true to enable\n            count: 1  # +1 drive, default value\n            default:  # Default configuration for the all extra drives\n                cdrom: false  # Default value (false for the generic flash drive, true for CD/DVD)\n                rw: false # Read-only by default\n

    The count parameter determines the number of additional drives (remember the limit on endpoints). Each of the drives will be created with the same initial parameters described in the default section.

  3. Perform reboot:

    [root@pikvm ~]# reboot\n
"},{"location":"msd/#manual-drives-management","title":"Manual drives management","text":"

The kvmd-otgmsd console utility is used to manage additional (and the first main one) drives. The full list of options can be found by running kvmd-otgmsd --help.

Step by step: Creating the flash drive image to get some files from the target host
  1. Switch the filesystem to read-write mode:

    [root@pikvm ~]# rw\n
  2. Create an empty image file with desired size (1GB in this example):

    [root@pikvm ~]# fallocate -l 1000M /root/flash.img\n
  3. Connect it to the drive 1 (the creation process is described in the previous section):

    [root@pikvm ~]# kvmd-otgmsd -i 1 --set-rw=1 --set-cdrom=0 --set-image=/root/flash.img\n

    Note

    • Index 0 represents the main drive that is controlled via the Web UI and API.

    • If --set-cdrom=1, the drive will work as CD-ROM for small images, and as DVD-ROM for big. Please note that CD/DVD can't be writable (you should use --set-rw=0 in this case).

  4. On this step, you will be able to access the flash drive from the target host and format the it in the usual way.

  5. View the drive state:

    [root@pikvm ~]# kvmd-otgmsd -i 1\nImage file:  /root/flash.img\nCD/DVD flag: no\nRW flag:     yes\n
  6. To disable the flash drive and view the files on it from the PiKVM, run:

    [root@pikvm ~]# kvmd-otgmsd -i 1 --unlock --eject\n
  7. Don't forget to remount the root filesystem to read-only mode:

    [root@pikvm ~]# ro\n
  8. You can download the resulting image via SCP or mount it as a loop device on the PiKVM:

    [root@pikvm ~]# mount -o loop /root/flash.img /mnt\n[root@pikvm ~]# ls /mnt\n[root@pikvm ~]# umount /mnt\n

Tip

The main drive can also be switched to read-write mode, this can be done from the Web UI.

In this case, the image will have to be prepared outside of PiKVM, and upload it to use, then download it back to your local host for files extraction.

"},{"location":"msd/#disabling-mass-storage","title":"Disabling Mass Storage","text":"

In rare cases, it may be necessary to disable Mass Storage emulation if the BIOS/UEFI does not recognize it correctly and even refuses to work with USB keyboard and mouse.

Step by step: Permanent disabling Mass Storage
  1. Switch the filesystem to read-write mode:

    [root@pikvm ~]# rw\n
  2. Edit /etc/kvmd/override.yaml and add the extra drive config section:

    kvmd:\n    msd:\n        type: disabled\n
  3. Perform reboot:

    [root@pikvm ~]# reboot\n

Tip

As an alternative method may be to use the dynamic USB configuration, which allows you to temporarily disable any of the emulated devices, including Mass Storage Drive.

"},{"location":"msd/#big-dvd-images-on-old-pikvm","title":"Big DVD images on old PiKVM","text":"

Since KVMD 4.49, PiKVM is able to emulate DVD images.

Before that, users had to use Ventoy and other utilities to pre-convert large DVD images such as the official Windows ISO to Flash.

We strongly recommend updating the PiKVM OS to simplify your Mass Storage experience when using DVDs:

Updating PiKVM OS

To update, run following commands under the root user:

[root@pikvm ~]# pikvm-update\n

If you encounter an error like:

[root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

It's most likely you have an old OS release. You can update the OS as follows:

[root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

Next time you will be able to use the usual method with pikvm-update.

Anyway, you can still view all these legacy recipes.

"},{"location":"msd_legacy/","title":"Big DVD images on old PiKVM","text":"

Since KVMD 4.49, PiKVM is able to emulate DVD images.

Before that, users had to use Vento and other utilities to pre-convert large DVD images such as the official Windows ISO to Flash.

We strongly recommend updating the PiKVM OS to simplify your Mass Storage experience when using DVDs:

Updating PiKVM OS

To update, run following commands under the root user:

[root@pikvm ~]# pikvm-update\n

If you encounter an error like:

[root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

It's most likely you have an old OS release. You can update the OS as follows:

[root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

Next time you will be able to use the usual method with pikvm-update.

"},{"location":"msd_legacy/#making-windows-boot-flash-image","title":"Making Windows Boot Flash Image","text":"

An alternative version of this can be found below that does not require a physical usb flash

This procedure will create a disk image of a USB stick. This is mostly required for Windows based images since they are larger than the CDROM based limit of 2.2GB. You can create a bootable USB stick with the normal Microsoft tools, e.g. Media Creation Tool. Creating a bootable USB stick can also be made from an ISO file with other tools like Rufus.

Without resizing, the full size of the USB stick will be used, so keep the stick as small as possible (e.g. 4GB or 8GB) but still large enough for all Windows files. The Media Creation tool will tell you what the minimum size is.

Before creating the image file, you can use a tool like EaseUS Partition Master Free or GParted to resize the main FAT32 partition on the USB stick. This will save space on PiKVM.

You can also perform these steps on a separate UNIX machine and transfer the image over to PiKVM. Or, on Windows you could use a program like PassMark ImageUSB (only for full USB size images) or dd for Windows to create the image.

Once you have the desired USB stick perform the following on the RPi to create the image directly to the PiKVM image storage folder.

  1. Insert Windows based USB stick into Pi4, generated with Microsoft USB creation tool. SSH to PiKVM as root.

    # dmesg\n[ 3025.025401] usb-storage 2-1:1.0: USB Mass Storage device detected\n[ 3025.038911] scsi host0: usb-storage 2-1:1.0\n[ 3026.132248] scsi 0:0:0:0: Direct-Access     Kingston DataTraveler 3.0 PMAP PQ: 0 ANSI: 6\n[ 3026.771425] sd 0:0:0:0: [sda] 15360000 512-byte logical blocks: (7.86 GB/7.32 GiB)\n[ 3026.790276] sd 0:0:0:0: [sda] Write Protect is off\n[ 3026.802530] sd 0:0:0:0: [sda] Mode Sense: 23 00 00 00\n[ 3026.804450] sd 0:0:0:0: [sda] No Caching mode page found\n[ 3026.814082] sd 0:0:0:0: [sda] Assuming drive cache: write through\n[ 3026.908712]  sda: sda1\n[ 3026.922794] sd 0:0:0:0: [sda] Attached SCSI removable disk\n[root@pikvm ~]#\n

    USB devices shows as sda. We will use sda1 as the Windows partition.

  2. mount msd folder as read/write

    # kvmd-helper-otgmsd-remount rw\n
  3. Create image of USB data PARTITION to an image file, this will take some time, in this case about 12 minutes (RPi4).

    # dd if=/dev/sda1 of=/var/lib/kvmd/msd/windows10-2004.bin bs=8M status=progress\n4458545152 bytes (4.5 GB, 4.2 GiB) copied, 736 s, 6.1 MB/s\n531+1 records in\n531+1 records out\n4458545152 bytes (4.5 GB, 4.2 GiB) copied, 736.213 s, 6.1 MB/s\n
  4. Correct ownership of new image and make sure the website reports the file as complete.

    # chown kvmd:kvmd /var/lib/kvmd/msd/windows10-2004.bin\n
  5. Remount msd folder as read only

    # kvmd-helper-otgmsd-remount ro\n
  6. On PiKVM webpage, under Storage select the new image and connect it in Drive Mode: Flash to the server.

Boot the server and select boot device like you normally would. E.g. in a AMI BIOS the boot device is called \"Linux File-CD Gadget 0504\".

"},{"location":"msd_legacy/#an-alternative-to-making-a-windows-boot-image-that-does-not-require-a-physical-usb-flash-drive","title":"An alternative to making a Windows boot image that does not require a physical usb flash drive","text":"
  • Physical USB is not needed but external system is mandatory.
  • Create Ventoy image (on Ubuntu x86 machine) (Unaware of a windows version).
  • There is an assumption that you know basic linux to understand that not all dev devices are named exactly like the below
# dd if=/dev/zero of=ventoy.img bs=1M count=4700 status=progress\n
  • This makes a ventoy.img file, I would name this what it is EG: ventoy_win10.img
  • At the same time, download Media Creation Tool and select iso

  • On the Ubuntu machine

  • At the time of this, it was 1.0.51, change to latest version
# wget https://github.com/ventoy/Ventoy/releases/download/v1.0.51/ventoy-1.0.51-linux.tar.gz\n# tar zxvf ventoy-1.0.51-linux.tar.gz\n# sudo losetup -f ventoy.img\n# sudo losetup -l | grep ventoy (To locate which loop device was used)\n# sudo sh ~/ventoy-1.0.51/Ventoy2Disk.sh -i /dev/loopXX (This will make a loopXXp1 and a loopXXp2 and will format both partitions\n# cd /media/XXX (Usually your login)\n# mkdir ventoy\n# sudo mount /dev/loopXXp1 /media/XXX/ventoy\n
  • Either cp/scp over the .iso you downloaded from the Media tool or use a NFS mount
sudo cp windows.iso /media/XXX/ventoy\nsudo umount /dev/loopXX \n# This is going to be different for everyone, please choose the same one you mounted earlier\nsudo losetup -d /dev/loopXX \n# This may or may not work for everyone, if it doesnt work, skip and move forward#\n

ssh into the Ubuntu system (Or whatever OS you are using)

  • On PiKVM
# cd /var/lib/kvmd/msd\n# mount -o remount,rw .\n
  • On Ubuntu
# scp ventoy.img root@pikvm:/var/lib/kvmd/msd\n
  • Mount ventoy.img as normal flash and select the PiKVM boot device, it should popup with the VenToy logo with the window.iso as a selection
"},{"location":"msd_legacy/#an-alternative-to-making-a-windows-boot-image-that-does-not-require-a-physical-usb-flash-drive-on-a-single-windows-machine","title":"An alternative to making a Windows boot image that does not require a physical usb flash drive on a single windows machine","text":"
  • Physical USB is not needed
  • Requires Administrator rights on the windows machine

  • Testing was done on a Windows 11 machine with a Windows 11 23H2 ISO

  • Requires a windows ISO (can be downloaded from the microsoft website), Rufus (To write the ISO to the VHD) and VirtualBox (Uses VBoxManage to convert VHD to IMG)

  • Create a VHD in Windows, This can be done in two ways that i know of.

    Method 1: Open up the windows settings, go to storage, press advanced storage settings and press Disks & Volumes Press the Create VHD button, Give the disk a name, set a storage location and set the Virtual hard disk size (for 23H2 i used 6300MB). Set the Virtual hard disk format to VHD and set it to Fixed Size. Press Create and then you will get a menu to initialize the disk, press cancel

    Method 2: Open up the windows partition manager, make sure you don't have any partitions or disks selected by pressing on empty space, Go to Action and select Create VHD. Select a location for the VHD file, set the VHD size (for 23H2 i used 6300MB), Set the Virtual hard disk format to VHD and set it to Fixed Size. Press OK

2. Download the Windows ISO and Rufus (i use the portable version), open rufus select the NO_LABEL disk that should roughly match size selected when creating the VHD (MiB vs MB). Select the ISO you downloaded and press start Once it is done close rufus (optionally delete rufus)

  1. Unmount the VHD by either opening up windows explorer, right clicking on the windows installer drive and pressing eject or opening up the windows partition manager, right clicking on the virtual disk and detaching the VHD

4. Download and install Virtualbox Open up a command prompt in the location where you stored the VHD

VBoxManage clonehd input.vhd output.img --format raw\n
Or if virtualbox didn't get added to the system environment variables
\"C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe\" clonehd input.vhd output.img --format raw\n
This will convert the VHD to the IMG ready to be uploaded to the pikvm
  • using vboxmanage does have a slight quirk where it writes every conversion to .VirtualBox\\VirtualBox.xml so if you make changes to the vhd and try to convert it again it throws and error that the uuid doesn't match the stored value in VirtualBox.xml and you need to either throw away VirtualBox.xml or edit it and delete the line that matches the error
  • this method has also been tested using the windows installer for ventoy (needs enabling show all devices in the windows installer)
"},{"location":"multiport/","title":"Multiport KVM-over-IP","text":"Note

V4 MINI can ONLY be used with the TESmart or other KVMs with LAN control, the TESmart has a convenience driver for easier setup

If you need to connect multiple hosts to a single PiKVM, then the best way to do this is to use our PiKVM Switch. It is designed specifically for PiKVM and has many advantages and features compared to regular desktop multiport switches.

  • ATX control on each port.
  • Per-port EDID configuration.
  • HDMI dummy plug functionality.
  • True Plug-n-Play with no need for override.yaml setups and complete control via Web UI.
  • Multifunctional RGB LEDs with beacon mode and customizable color schemes.
  • Firmware update directly from PiKVM and ready for future hardware extensions.
  • Compatible with V4 Plus, V3 and DIY devices based on Pi2-Pi4 except Zero and V4 Mini.

And now the best part: the switches can be chained! Need four ports? Get a PiKVM Switch. As your server fleet expands to eight, simply add another switch and link it to the first one. Need even more? No worries \u2014 connect up to five switches and enjoy 20 fully functional ports on your PiKVM.

Just take a look!.

You can order PiKVM Switch Multiport Extender from our international store.

Canadian customers can place an order at PiShop.ca.

"},{"location":"multiport/#list-of-tested-third-party-kvms","title":"List of tested third-party KVMs","text":"

There are many ways to do this with third-party switches. For example you can choose a switch with USB control connection like ezCoo KVM switch.

Also, PiKVM can be connected to a multi-port HDMI/USB switch and the switch's buttons can be connected via optocouplers to the Pi's GPIO to switch channels.

If your KVM switches channels using keyboard shortcuts, there is a chance that it will not be able to work with OTG (v2+ platform, see below), since it does not fully implement the USB stack. In this case, you will have to use the Pico HID to emulate the keyboard & mouse (PiKVM supports this configuration).

Warning

If you choose AIMOS, be aware that it has a back powering issue that you need to use work arounds for. Limitations are are listed below. Also please be aware that Pico's will not work with the AIMOS KVM's.

Here the status is:

  • \u2714 - Everything is working as expected. There may be some subtleties.
  • \u2639 - Not everything works. Additional work is needed for some functions to work, like MSD.
  • \u2718 - The keyboard or mouse does not work at all, the switch loses the image, etc.
Model Status Notes ezCoo EZ-SW41HA-KVMU3L 4x1 switch ezCoo SW41HA HDMI 4x1 switch (legacy) \u2714 Using with PiKVM - 4 Port is the ONLY supported KVM, 2 Port does not work the same and is not supported, the same can be said about any of the HDMI splitters 1-in-2 Out eccoo EZ-SW41HA-KVMU3P 4x1 switch \u2714 Using with PiKVM. Make sure you buy the with hotkey version as that has the control port ezcoo EZ-SW41H21-KVMU3P 8K 4x1 switch \u2714 Does NOT have a control port. MSD Works. Can be managed through key combo (ctrl+ctrl+#) Level1Techs KVM switches \u2714 Just working pretty good TESmart 8 or 16 PORT - HDMI KVM SWITCH \u2714 Use OTG with USB 2.0 Hub only, limited hotkey support on certain models, but MSD only works through Hub ports. Switching available with serial (DIY/v4Plus) or IP-to-serial interface using fixed IP (v4mini et al) (/31 peer-to-peer addressing supported). Can be managed via WebUI or CLI tool XH-HK4401 4-port HDMI USB KVM Switch \u2714 Using with PiKVM - USB MSD works, requires the HDMI backpower solutions found below AIMOS 8-port HDMI USB-C KVM Switch \u2639 Similar to Ali's noname model, available in 4/8port editions, has same HDMI bridge boot problem/solution using a Marmitek 312 UHD HDMI splitter. ONLY supports HotKey switching. Limitations are are listed below Aten CS1758 8-port PS/2 / USB VGA KVM switch \u2639 Older Aten switches can be had for cheap and can be a viable alternative. Devices are connected via PS/2 so USB media support does not work. The setup relies on a VGA-> HDMI adapter to make the video signal work and there can be issues with unsupported VGA resolutions with some adapters. KVM hotkeys and switching all work and so does mouse and keyboard.

Limitations:

  • HDMI backpower solutions:
    • See here
    • See here - Advanced soldering required
    • This loop capture device
    • v3 HAT v3.3 (Kickstarter model and later) also takes care of the back power issue
  • Mass Storage Device (MSD) workaround (will not work OOB)
    • RPi4 OTG needs to be in the KB port for mouse and KB funtionality, ZeroW is required and needs to be connected to the HUB port for MSD functionality - \u2714KNOWN WORKING\u2714
    • AIMOS 4/8-port: See here - Advanced soldering required - allows use of GPIO menu to change input by cycling
    • AIMOS 8-port: See here - Advanced soldering required - allows use of GPIO menu to change input directly
"},{"location":"ocr/","title":"OCR","text":"

This feature allows you to select a screen region, recognize it as text and copy this text to the clipboard. Recognition works locally on your PiKVM and does not use any cloud services. It uses the Tesseract OCR library. Tesseract does not see your image until you explicitly give the recognition command. The evil AI is not watching your screen.

"},{"location":"ocr/#language-support","title":"Language support","text":"

For any language, you will have to install its support. It is very easy to do this (English language for example):

# rw\n# pacman --assume-installed tessdata -S tesseract-data-eng\n# ro\n

List all available languages in the repository:

# pacman -Ss tesseract-data\n
"},{"location":"ocr/#disabling-ocr","title":"Disabling OCR","text":"

If you want to get rid of this feature completely, you need to delete Tesseract and all its data:

# rw\n# pacman -R tesseract\n# reboot\n
"},{"location":"on_boot_config/","title":"On-boot configuration & production deployment","text":"

At the first boot, PiKVM generates encryption keys and performs other actions necessary to configure the device.

Some parameters, such as connecting to Wi-Fi, or configuring a static interface for wired Ethernet, can be easily changed by the user if there is physical access to the memory card. This is convenient for quick customization of your device before the first use.

All settings are made using a file pikvm.txt on the first section of the memory card. After applying the settings, the file is automatically deleted.

"},{"location":"on_boot_config/#setting-up-wi-fi","title":"Setting up Wi-Fi","text":"

Note

Devices based on Raspberry Pi Zero 2 W does not support 5GHz Wi-Fi.

  1. Remove the PiKVM memory card. The device must be turned off.

  2. Insert the memory card into the computer and mount the first FAT32 partition.

  3. Among the system files you will see the file pikvm.txt.

    • If you haven't powered up PiKVM yet, this file will contain a single line FIRST_BOOT=1. Do not remove it, just add following lines from the next step.

    • If the file does not exist, create an empty file (don't add FIRST_BOOT option).

  4. To connect to Wi-Fi with DHCP, you will need an ESSID (network name) and a password. Add this to pikvm.txt. If the file doesn't exists, just create it. Like following:

    WIFI_ESSID='mynet'\nWIFI_PASSWD='p@s$$w0rd'\n

    Note that backslash in the password should be escaped: \\ should be written as \\\\.

    If there was a string FIRST_BOOT=1 in the file, do not remove it. This is the trigger needed to initialize the OS at the first boot. On the contrary, if the file pikvm.txt does not exist, you should not add this line.

  5. Unmount partition and return the memory card to PiKVM.

  6. A few things to keep in mind:

    • Note that after applying the settings, the pikvm.txt file will be deleted.
    • WPA3 is not supported. Enable WPA2 on your router, while AES is supported, some aspects of it is not and you may need to disable AES for it to connect.
    • There is a possibility that, in countries that support channel 13, the device will not connect. You will need to configure your router to disable channels 12-14 or disable Auto scan mode.
"},{"location":"on_boot_config/#other-available-options","title":"Other available options","text":"

A number of other parameters can be applied in the same way as with Wi-Fi.

Note

The parameters must be specified strictly each on a separate line.

  • FIRST_BOOT=1 Triggers initialization of the first OS startup. The following actions are performed:

    • Generates unique /etc/machine-id for internal systemd machinery.
    • Generates unique SSH host keys.
    • Generates unique SSL certificates for HTTPS and VNC.
    • Generates Avahi ZeroConf service /etc/avahi/services/pikvm.service with Pi's serial number. But keeps Avahi disabled by default.
    • Mass Storage image partition is reformatted to fill the available space at the end of SD card (only for V2+).
    • Different minor things are performed like fc-cache update.

    Note that this option does not reset the OS to factory defaults. There is no way to do this other than reflashing.

  • ENABLE_AVAHI=1 Triggers Avahi service generation (if needed) and enables avahi-daemon. It's disabled by default.

  • ENABLE_OTG_SERIAL=1 Only for V2+. Enables a virtual serial port on a USB emulator, that can be used to log in to PiKVM from the target host side. Disabled for security reasons.

  • SSH_PORT=1234 Changes SSH server port to 1234 instead of 22.

  • ETH_DHCP=1 Configures Ethernet port for DHCP. This is a default for PiKVM OS.

  • ETH_ADDR=192.168.0.100/24ETH_DNS=8.8.8.8ETH_GW=192.168.0.1 Configures a static IP on the Ethernet port. Only IPv4 is available here. For IPv6 you'll need to change systemd configuration files on the live OS. All three options must be set simultaneously to avoid incorrect configuration.

  • WIFI_ESSID=fooWIFI_PASSWD=bar Configures Wi-Fi with DHCP, described in more detail in previous paragrpah. Both options must be set simultaneously to avoid incorrect configuration. Can be followed by several options:

    • WIFI_WPA23=1 Allows to connect to mixed WPA2/WPA3 network. Available only on new images >= 2025.03.03.

    • WIFI_HIDDEN=1 Allows to connect to hidden Wi-Fi network. Available only on new images >= 2024.03.12.

    • WIFI_ADDR=192.168.0.100/24WIFI_DNS=8.8.8.8WIFI_GW=192.168.0.1 Configures a static IP on the Wifi. Only IPv4 is available here. For IPv6 you'll need to change systemd configuration files on the live OS. All three options must be set simultaneously with WIFI_ESSID and WIFI_PASSWD to avoid incorrect configuration.

  • WIFI_REGDOM=US Changes Wi-Fi regulatory domain to the US. Other domains available by ISO 3166-1 alpha-2 country codes.

"},{"location":"on_boot_config/#advanced-production-deployment","title":"Advanced production deployment","text":"

For a production environment, it may be important to integrate PiKVM into an existing infrastructure automatically. Usually, such actions are performed by special scripts written by the administrator.

To run such scripts, PiKVM OS suggests placing them in pikvm-scripts.d directory (/boot/pikvm-scripts.d on the system itself) on the same partition next to pikvm.txt file.

If pikvm.txt exists, all the parameters described there will be applied, and the contents inside pikvm-scripts.d will be checked if this directory exists. Scripts in this directory are run in alphabetical order, the failure will be ignored, it is assumed that the script author should handle this situation.

If the script needs to reboot the OS, it should create an empty file /boot/pikvm-reboot.txt. The reboot is performed once after all scripts.

In order not to copy scripts manually on each memory card on each PiKVM, it may make sense to build a custom OS image containing everything you need.

"},{"location":"pass/","title":"HDMI Video Passthrough","text":""},{"location":"pass/#hdmi-video-passthrough","title":"HDMI Video Passthrough","text":"

This feature allows directing the video stream from the host to a display attached directly to the HDMI output of PiKVM V4 Plus. This simplifies accessing the host locally while retaining the remote access to the host via the Web UI or VNC. This feature is limited to PiKVM V4 Plus because it\u2019s the only PiKVM version with an HDMI Out port. It also works best with USB passthrough enabled.

Info

  • The passthrough feature supports a screen resolution up to 1920x1200 pixels.

This is shown more clearly below:

"},{"location":"pass/#setting-up-the-passthrough","title":"Setting up the passthrough","text":"

Connect the display to OUT2 port on the back side of PiKVM V4 Plus. This feature should be enabled by default on new images.

If not, follow two simple steps:

  1. Update OS and reboot:

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  2. After rebooting, you will see an image on the physical display.

"},{"location":"pass/#my-monitor-does-not-support-the-1920x1200-mode","title":"My monitor does not support the 1920x1200 mode","text":"

PiKVM V4 supports the advanced capture mode of 1920x1200. If your physical monitor is limited to 1920x1080, then part of the image from the bottom will be cropped.

To avoid this, you can change the resolution of the host OS, or if the OS does not support this, disable the 1920x1200 mode on PiKVM itself:

[root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-edidconf --import-preset=v4plus.no-1920x1200\n[root@pikvm ~]# reboot\n
"},{"location":"pass/#current-limitations","title":"Current limitations","text":"

Please note the feature is pretty new and will be improved.

  • Display resolution must be greater than or equal to that used by PiKVM capture. If the maximum display resolution is 720p and the signal has a 1080p resolution, you will not see the image. PiKVM does not perform any downscaling.

  • At the same time, PiKVM will try to show at least something than nothing. If the input signal has a resolution of 1920x1200, and the display supports only 1920x1080, the image will be shown but cropped from the bottom so that you at least have the opportunity to adjust the image parameters of the host.

  • Audio is not supported at the moment.

"},{"location":"pass/#disabling-the-passthrough","title":"Disabling the passthrough","text":"
  1. Add few lines to /etc/kvmd/override.yaml:

    kvmd:\n    streamer:\n        forever: false\n        cmd_remove:\n            - \"--v4p\"\n
  2. Perform reboot.

"},{"location":"pico_hid/","title":"The Pico HID","text":"

A fast way to get PS/2 on PiKVM V2+

If you need PS/2 keyboard & mouse on PiKVM V2, V3 and V4 Plus (but not V4 Mini or DIY based on Zero 2 W boards), you can use a faster and easier way: The Pico HID Bridge.

Pico requirements

Raspberri Pi Pico (the first model) based on RP2040 microcontroller is required. Pico 2 is not supported right now.

The Pico HID is a part of DIY PiKVM V1 platform that performs keyboard and mouse emulation. It has excellent compatibility, and emulates USB by default, including two mouse modes: absolute and relative.

Full list of features:

Feature Enabled by default USB Keyboard, absolute & relative mouse Yes USB Absolute Mouse for Windows 95 No PS/2 Keyboard & mouse No

The scope of the Pico HID is not limited to V1 platform, it can also be used with V2 and V3, if you need to emulate a PS/2 keyboard and mouse or use a legacy multiport KVM switch which does not fully support USB standards.

This page explains how to build, connect and use all the features of the Pico HID.

Software requirements

KVMD >= 3.241 is required for the Pico HID. For new builds, this will be the case, but if you want to use the Pico HID on the old PiKVM, you will need to update OS.

"},{"location":"pico_hid/#making-the-pico-hid","title":"Making the Pico HID","text":"

If you are building PiKVM V1, then the hardware should already be assembled. Skip this step unless you need PS/2 support.

But if you are making the Pico HID for V2 or V3, then follow this guide:

The Pico HID from scratch

Parts list:

  • x1 Raspberry Pi Pico board with soldered pins. Pico 2 is not supported right now.

  • x1 USB-A to Micro-USB cable.

  • x10 dupont wires female-female.

  • x1 1N5819 diode. It's optional but strongly recommended. Any similar one will do.

    Warning

    The diode is needed to provide power to the Pico HID regardless of the target host state, which prevents the backpowering problem. It will allow you to keep the keyboard buttons pressed during the target host power cycle, which is, for example, important for MacOS to get into the boot menu.

    Do not connect the red wire (the VSYS (Pico) -> 5V (Pi) line) without a diode. If you can't find a diode, don't connect this wire at all.

Connect all the parts according to this scheme:

Simple wiring diagram

Electrical schematic diagram for advanced users

"},{"location":"pico_hid/#ps2-keyboard-mouse","title":"PS/2 Keyboard & Mouse","text":"Additional steps for PS/2 support

If you need PS/2 keyboard and mouse support, you will need a few additional components. Soldering skills will also come in handy.

  • x1 3.3V/5V bi-directional logic level shifter like this.
  • x2 PS/2 cable with male connector (can be salvaged from the an keyboard or mouse).

Make sure that the level shifter pinout matches the scheme, and connect everything according to the Pico pinout.

                                   >>> To the PC <<<\n                 _________________\n                |                 |\nPico GP11 ______| LV1         HV1 |______ PS/2 keyboard data\nPico GP12 ______| LV2         HV2 |______ PS/2 keyboard clock\nPico GP13 ______| LV          HV  |______ PS/2 5V\nPico  GND ______| GND         GND |______ PS/2 GND\nPico GP14 ______| LV3         HV3 |______ PS/2 mouse data\nPico GP15 ______| LV4         HV4 |______ PS/2 mouse clock\n                |_________________|\n

You can take the 5V power line from one of the PS/2, for example from the keyboard, or from both at once, but use a multimeter to make sure that both PS/2 female connectors have the same line.

PS/2 female socket pinout on the motherboard is the same for the keyboard and the mouse. A purple socket usually corresponds to the keyboard, and a green one to the mouse. If your motherboard only has one port, it's probably universal and can be used for both the keyboard and the mouse. Most likely, it will be painted both colors.

Use a multimeter to determine the purpose of the wires in your PS/2 cables.

A good idea is to mount the level shifter on top of the Pico, as in this photo:

Note

Don't forget to enable PS/2 mode support as described in the next paragraph

Optional: PS/2 passthrough

This optional addon allows to use a real PS/2 keyboard and mouse together with emulated by PiKVM.

These two ports work as PS/2 inputs and are passed through to the PS/2 output ports.

                                   >>> To the REAL keyboard and mouse <<<\n                 _________________\n                |                 |\nPico GP26 ______| LV1         HV1 |______ PS/2 keyboard data\nPico GP27 ______| LV2         HV2 |______ PS/2 keyboard clock\nPico GP13  _____| LV          HV  |______ PS/2 5V\nPico  GND ______| GND         GND |______ PS/2 GND\nPico GP16 ______| LV3         HV3 |______ PS/2 mouse data\nPico GP17 ______| LV4         HV4 |______ PS/2 mouse clock\n                |_________________|\n
"},{"location":"pico_hid/#configuring-the-hid-modes","title":"Configuring the HID modes","text":"

By default, Pico HID emulates a USB keyboard and an absolute or relative mouse (read here about the difference between mouse modes). For most cases, nothing needs to be changed here. However, if you need something special (like Windows 98 support), you can do it without reflashing the current firmware.

To achieve this, the Pico HID uses a runtime configuration, which is set by connecting some GPIOs with Ground (GND) lines.

Pin name on the Pico board Description GP2 Enable PS/2 keyboard & mouse support (see below). GP3 Prefer the PS/2 keyboard over USB when turning on the HID (if PS/2 is enabled). GP4 Prefer the PS/2 mouse over USB (if PS/2 is enabled) GP6 Disable USB keyboard & mouse support. This is useful if you only want to use PS/2. GP7 Enable the special USB absolute mouse for Windows 98. GP8 Prefer the relative USB mouse over the absolute one. GP9 Prefer the Windows 98 USB absolute mouse over the regular absolute one (if enabled).

Example

To enable Windows 98 absolute mouse, just connect pin GP9 to any GND on the Pico.

"},{"location":"pico_hid/#flashing-the-firmware","title":"Flashing the firmware","text":"

To upload the firmware to Pico HID, you can use any computer with a USB port.

  1. Download the latest release of the firmware. The file is called pico-hid.uf2.
  2. Press and hold the white button on the Pico board.
  3. While still holding the button, plug it in the computer using a USB cable.
  4. Release the button.
  5. The Pico board appears as a flash drive on your computer.
  6. Copy the pico-hid.uf2 file to this flash drive.
  7. Safely eject the USB device.

If you want to compile the firmware yourself, you can find the source code here.

"},{"location":"pico_hid/#the-final-steps","title":"The final steps","text":"

Connect the Pico HID to the target host using the USB cable.

If you are building PiKVM V1, no further action with the Pico HID is required.

If you are making the Pico HID for V2 or V3, add the following lines to the PiKVM configuration and reboot it:

  • /boot/config.txt

    dtoverlay=spi0-1cs\n
  • /etc/kvmd/override.yaml:

    kvmd:\n    hid:\n        type: spi\n        chip: 0\n        bus: 0\n        sw_cs_pin: 7\n        sw_cs_per_byte: true\n        reset_pin: 25\n        reset_inverted: true\n        reset_self: true\n        power_detect_pin: 16\n        power_detect_pull_down: true\n
"},{"location":"pico_hid/#replacing-the-arduino-hid","title":"Replacing the Arduino HID","text":"

Warning

This section is intended for advanced users of the legacy Arduino HID.

It may seem tempting, but don't to use the Arduino HID for new PiKVM builds just because you have it at your fingertips. Connecting and flashing Arduino is much more time consuming than Pico. In addition, different Arduino board work with different voltages, they may or may not have SPI (for the Pico, we use SPI to free up the UART on Raspberry Pi for the console and other useful things), etc.

Using the Pico HID is the recommended fast and standard way in the PiKVM world.

The Pico HID can be used to replace the legacy Arduino HID. It can use both Serial (UART) port and the SPI. The connection scheme is also much simpler, getting rid of the transistor for the Reset line and the level shifter for RX/TX (MOSI/MISO).

For the Arduino HID over SPI

Throw away the Reset transistor and level shifter, and follow this guide from the very beginning, as if you were connecting Pico HID to PiKVM V2 or V3.

For the classic Serial (UART) HID

Get rid of the transistor and level shifter, and follow this guide from the very beginning, but the schemes and configs will be slightly different.

  • The GP22 on the Pico is connected directly to the GND. This enables UART mode instead of the default SPI.

  • In the good old PiKVM V0, GPIO4 on the Raspberry Pi was used for the Reset line. Now we recommend to use GPIO25 for consistency reasons. However, you can use GPIO4 by changing the reset_pin value in the config example below. On the scheme, this is a yellow wire, the RUN (Pico) -> GPIO25 (Pi) line.

Simple wiring diagram

Electrical schematic diagram

Configs
  • Don't add line dtoverlay=spi0-1cs to the /boot/config.txt file. It's only needed for SPI.

  • /etc/kvmd/override.yaml:

    kvmd:\n    hid:\n        type: serial\n        device: /dev/kvmd-hid\n        reset_pin: 25\n        reset_inverted: true\n        reset_self: true\n        power_detect_pin: 16\n        power_detect_pull_down: true\n
"},{"location":"pico_hid_bridge/","title":"The Pico HID - PS/2 Bridge","text":"

Pico requirements

Raspberri Pi Pico (the first model) based on RP2040 microcontroller is required. Pico 2 is not supported right now.

The Pico HID Bridge is a special version of the generic Pico HID. It is a PS/2 keyboard and mouse emulator that connects to PiKVM via USB-A. Unlike generic Pico HID and legacy Arduino HID, it doesn't require SPI wiring with GPIO.

It is suitable for all devices except V4 Mini and DIY based on Zero 2 W board.

At one end it connects to USB-A on PiKVM, on the other side it has two PS/2 connectors for keyboard and mouse:

In addition, on PiKVM V2+, the use of Pico the HID Bridge does not exclude the use of a regular USB OTG port with Mass Storage emulation. Thus, on V2+ you will be able to use PS/2 and USB Mass Storage at the same time, and even switch between OTG HID and Pico HID.

"},{"location":"pico_hid_bridge/#making-the-bridge","title":"Making the Bridge","text":"
  • x1 Raspberry Pi Pico board with soldered pins.
  • x1 USB-A to Micro-USB cable.
  • x1 3.3V/5V bi-directional logic level shifter like this.
  • x2 PS/2 cable with male connector.
  • x2 Small dip jumpers.

Make sure that the level shifter pinout matches the scheme, and connect everything according to the Pico pinout.

                                   >>> To the PC <<<\n                 _________________\n                |                 |\nPico GP11 ______| LV1         HV1 |______ PS/2 keyboard data\nPico GP12 ______| LV2         HV2 |______ PS/2 keyboard clock\nPico GP13 ______| LV          HV  |______ PS/2 5V\nPico  GND ______| GND         GND |______ PS/2 GND\nPico GP14 ______| LV3         HV3 |______ PS/2 mouse data\nPico GP15 ______| LV4         HV4 |______ PS/2 mouse clock\n                |_________________|\n

You can take the 5V power line from one of the PS/2, for example from the keyboard, or from both at once, but use a multimeter to make sure that both PS/2 female connectors have the same line.

PS/2 female socket pinout on the motherboard is the same for the keyboard and the mouse. A purple socket usually corresponds to the keyboard, and a green one to the mouse. If your motherboard only has one port, it's probably universal and can be used for both the keyboard and the mouse. Most likely, it will be painted both colors.

Use a multimeter to determine the purpose of the wires in your PS/2 cables.

A good idea is to mount the level shifter on top of the Pico, as in this photo:

Finally, install DIP jumpers to soldered pins of the Pico to enable PS/2 and Bridge modes:

  • GP2 <-> GND
  • GP5 <-> GND

Like this:

"},{"location":"pico_hid_bridge/#ps2-passthrough","title":"PS/2 passthrough","text":"

This optional addon allows to use a real PS/2 keyboard and mouse together with emulated by PiKVM.

These two ports work as PS/2 inputs and are passed through to the PS/2 output ports.

                                   >>> To the REAL keyboard and mouse <<<\n                 _________________\n                |                 |\nPico GP26 ______| LV1         HV1 |______ PS/2 keyboard data\nPico GP27 ______| LV2         HV2 |______ PS/2 keyboard clock\nPico GP13  _____| LV          HV  |______ PS/2 5V\nPico  GND ______| GND         GND |______ PS/2 GND\nPico GP16 ______| LV3         HV3 |______ PS/2 mouse data\nPico GP17 ______| LV4         HV4 |______ PS/2 mouse clock\n                |_________________|\n
"},{"location":"pico_hid_bridge/#flashing-the-firmware","title":"Flashing the firmware","text":"

To upload the firmware to Pico HID, you can use any computer with a USB port.

  1. Download the latest release of the firmware. The file is called pico-hid.uf2.
  2. Press and hold the white button on the Pico board.
  3. While still holding the button, plug it in the computer using a USB cable.
  4. Release the button.
  5. The Pico board appears as a flash drive on your computer.
  6. Copy the pico-hid.uf2 file to this flash drive.
  7. Safely eject the USB device.

If you want to compile the firmware yourself, you can find the source code here.

"},{"location":"pico_hid_bridge/#the-final-steps","title":"The final steps","text":"

Connect the Pico HID to the target host using PS/2 cable and USB to USB-A port on PiKVM.

Add following lines to the PiKVM configuration and reboot it:

  • /etc/kvmd/override.yaml:
    kvmd:\n    hid:\n        type: serial\n        device: /dev/kvmd-hid-bridge\n        reset_pin: -1\n
"},{"location":"port_forwarding/","title":"Port forwarding","text":"

If you need to make PiKVM accessible from Internet, the easiest way to achieve this is by forwarding a port on the router. In this case, an external (global) IP address must be assigned to the router. This service is provided by the ISP.

Tip

If using an external IP address is not possible, it is recommended to try the Tailscale VPN.

  • To configure port forwarding, refer to the documentation of the router.
  • The Web UI listening ports are 80 (HTTP) and 443 (HTTPS).
  • By default, port 80 performs permanent forwarding to 443 for security reasons.
  • Forwarding the port 443 is sufficient in most cases.
  • If enabled, the VNC server runs on port 5900 (disabled by default).

Warning

  • Set strong passwords and enable two-factor authorization before opening access to PiKVM from the Internet!
  • It is strongly recommended to obtain a valid HTTPS certificate, for example via Let's Encrypt.
  • A good practice is using a custom port number instead of 443 from the Internet side, for example 14438, to avoid common port scanners.
  • If you still decide to use the 443 port number, you may want to forward port 80 to get a convenient redirect.

Port forwarding is a powerful and convenient tool, but remember that security depends entirely on your configuration. In most cases, a VPN is a more secure, but less convenient option (since it requires a VPN client on all devices that access PiKVM).

"},{"location":"prometheus/","title":"Prometheus metrics","text":"

Prometheus is one of the popular monitoring systems. It pulls service's endpoint to get metrics in a simple text format. PiKVM has the ability to export some information to this system such as the server's ATX state, Pi's temperature, GPIO state and some other things.

"},{"location":"prometheus/#configure-prometheus","title":"Configure Prometheus","text":"

To enable Prometheus getting metrics from pikvm following config could be used:

scrape_configs:\n  - job_name: \"pikvm\"\n    metrics_path: \"/api/export/prometheus/metrics\"\n    basic_auth:\n      username: admin\n      password: admin\n    scheme: https\n    static_configs:\n    - targets: [\"pikvm\"]\n    tls_config:\n      insecure_skip_verify: true # For self-signed certificate\n
"},{"location":"prometheus/#output-example","title":"Output example","text":"

This example includes the GPIO from the PiKVM's test config.

$ curl -k -HX-KVMD-User:admin -HX-KVMD-Passwd:admin https://pikvm/api/export/prometheus/metrics\n\n# TYPE pikvm_atx_enabled gauge\npikvm_atx_enabled 1\n\n# TYPE pikvm_atx_power gauge\npikvm_atx_power 0\n\n# TYPE pikvm_gpio_input_online_led1 gauge\npikvm_gpio_input_online_led1 0\n\n# TYPE pikvm_gpio_input_state_led1 gauge\npikvm_gpio_input_state_led1 0\n\n# TYPE pikvm_gpio_input_online_led2 gauge\npikvm_gpio_input_online_led2 0\n\n# TYPE pikvm_gpio_input_state_led2 gauge\npikvm_gpio_input_state_led2 0\n\n# TYPE pikvm_gpio_output_online_button1 gauge\npikvm_gpio_output_online_button1 0\n\n# TYPE pikvm_gpio_output_state_button1 gauge\npikvm_gpio_output_state_button1 0\n\n# TYPE pikvm_gpio_output_online_button2 gauge\npikvm_gpio_output_online_button2 0\n\n# TYPE pikvm_gpio_output_state_button2 gauge\npikvm_gpio_output_state_button2 0\n\n# TYPE pikvm_gpio_output_online_relay1 gauge\npikvm_gpio_output_online_relay1 0\n\n# TYPE pikvm_gpio_output_state_relay1 gauge\npikvm_gpio_output_state_relay1 0\n\n# TYPE pikvm_gpio_output_online_relay2 gauge\npikvm_gpio_output_online_relay2 0\n\n# TYPE pikvm_gpio_output_state_relay2 gauge\npikvm_gpio_output_state_relay2 0\n\n# TYPE pikvm_hw_temp_cpu gauge\npikvm_hw_temp_cpu 36.511\n\n# TYPE pikvm_hw_temp_gpu gauge\npikvm_hw_temp_gpu 35.0\n\n# TYPE pikvm_hw_throttling_freq_capped_now gauge\npikvm_hw_throttling_freq_capped_now 0\n\n# TYPE pikvm_hw_throttling_freq_capped_past gauge\npikvm_hw_throttling_freq_capped_past 0\n\n# TYPE pikvm_hw_throttling_throttled_now gauge\npikvm_hw_throttling_throttled_now 0\n\n# TYPE pikvm_hw_throttling_throttled_past gauge\npikvm_hw_throttling_throttled_past 0\n\n# TYPE pikvm_hw_throttling_undervoltage_now gauge\npikvm_hw_throttling_undervoltage_now 0\n\n# TYPE pikvm_hw_throttling_undervoltage_past gauge\npikvm_hw_throttling_undervoltage_past 0\n\n# TYPE pikvm_hw_throttling_raw_flags gauge\npikvm_hw_throttling_raw_flags 0\n* Connection #0 to host localhost left intact\n
"},{"location":"pst/","title":"Persistent storage","text":"

Note

This feature is available on images newer than 2022.06.20

Sometimes advanced use of PiKVM requires storing some data on disk like API keys, config files, or something like that. For example, you want to have a script that will update SSL certificates once a week. However, the root file system is in a read-only state and does not involve remounting automatically by user scripts.

To solve this problem, new versions of PiKVM have a small 256MiB storage partition that can be used to store that data. A special kvmd-pst daemon makes sure that this partition is mounted in read-only all the time, and remounts it to RW only when some user script requires it. This also solves the problems of simultaneous access, so the RW mode will be kept as long as at least one client is working with the storage.

"},{"location":"pst/#usage","title":"Usage","text":"

Below is an example of a script /root/test.sh that wants to save a certain file in PST:

#!/bin/bash\necho `date` + $@ > $KVMD_PST_DATA/foo\ncat $KVMD_PST_DATA/foo\n

To run it use:

# kvmd-pstrun -- /root/test.sh --some --script --args\n--    INFO -- Opening PST session ...\n--    INFO -- PST write is allowed: /var/lib/kvmd/pst/data\n--    INFO -- Running the process ...\nMon Jun 20 04:23:14 MSK 2022 + --some --script --args\n--    INFO -- Process finished: returncode=0\n

So, what's going on here:

  1. kvmd-pstrun connects to the kvmd-pst daemon, which manages the mounting of the storage.

  2. If everything is fine, the daemon will remount the storage to RW mode and report the data root to kvmd-pstrun.

  3. kvmd-pstrun runs the script and pass the data root path using the environment variable KVMD_PST_DATA (/var/lib/kvmd/pst/data).

  4. If the kvmd-pst daemon stops or any other daemon error occurs, the script will be killed.

  5. After the script is finished, the daemon will remount the storage to RO mode.

To be able to write to the storage, the user must be a member of kvmd-pst group, or have to be root.

The return code will be equal to the script code if it was run, or 1 if a remount error occurred.

"},{"location":"reverse_proxy/","title":"Reverse proxy","text":"

A reverse proxy allows you to pass requests through your web server to another site or program. The reverse proxy will make it look like PiKVM Web UI is a page within your existing site.

This is especially useful if:

  • You need to access the WebUI on port 80 or 443 but you already host a website on the same device.

  • You want to share SSL certificates with an existing site.

  • You want to share authentication with an existing setup.

"},{"location":"reverse_proxy/#pikvm-configuration","title":"PiKVM Configuration","text":"

PiKVM supports reverse proxying since KVMD 4.51. For older version, please update OS first:

Updating PiKVM OS

To update, run following commands under the root user:

[root@pikvm ~]# pikvm-update\n

If you encounter an error like:

[root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

It's most likely you have an old OS release. You can update the OS as follows:

[root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

Next time you will be able to use the usual method with pikvm-update.

By default, PiKVM redirects all requests from HTTP port 80 to HTTPS port 443 with self-signed certificate. For the simplest configuration, you can leave it as it is, and terminate SSL traffic from PiKVM on your web server.

Alternatively, you can change the HTTP and HTTPS ports on PiKVM or disable HTTPS at all to deliver HTTP-only traffic to your server.

In both cases you should take care of your own SSL certificate for your web server because when using HTTP-only access to your website, you will lose the ability to use some features such as Direct H.264 streaming, because browser security policies will require HTTPS for them.

Various examples with changing HTTP/HTTPS settings

PiKVM uses Nginx internally, so don't be confused by its own configuration, it has nothing to do with your reverse proxy if you're using Nginx too.

  • Changing HTTP and HTTPS ports. Place this config to /etc/kvmd/override.yaml on PiKVM:

    nginx:\n    https:\n        port: 4430\n    http:\n        port: 8080\n
  • Disabling HTTPS. All requests will be handled via HTTP port 80.

    nginx:\n    https:\n        enabled: false\n

Don't forget to run systemctl restart kvmd-nginx to apply your changes.

"},{"location":"reverse_proxy/#server-configuration","title":"Server Configuration","text":"

If you have access to your web server\u2019s configuration use the following examples to pass the location /pikvm on the server to PiKVM Web UI hosted on https://pikvm.local on HTTPS port 443.

"},{"location":"reverse_proxy/#nginx","title":"Nginx","text":"

Nginx does not validate certificates by default and PiKVM's self-signed certificate is fine for it.

location /pikvm {\n    rewrite ^/pikvm$ / break;\n    rewrite ^/pikvm\\?(.*)$ ?$1 break;\n    rewrite ^/pikvm/(.*)$ /$1 break;\n    proxy_redirect ~^(/.*)$ /pikvm$1;\n    proxy_pass https://pikvm.local;\n\n    proxy_set_header Host $host;\n    proxy_set_header X-Real-IP $remote_addr;\n    proxy_set_header X-Scheme $scheme;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    proxy_set_header X-Forwarded-Port $server_port;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n\n    # For some handles (like MJPEG) buffering should be disabled\n    postpone_output 0;\n    proxy_buffering off;\n    proxy_ignore_headers X-Accel-Buffering;\n\n    # Some handles (ends with /ws) are WebSockets\n    proxy_set_header Upgrade $http_upgrade;\n    proxy_set_header Connection \"upgrade\";\n    proxy_connect_timeout 7d;\n    proxy_send_timeout 7d;\n    proxy_read_timeout 7d;\n\n    # Some other handles requires big POST payload\n    client_max_body_size 0;\n    proxy_request_buffering off;\n}\n
"},{"location":"reverse_proxy/#caddy","title":"Caddy","text":"

Caddy doesn't like self-signed certificates, so we'll have to convince it that it's okay.

handle_path /pikvm/* {\n    reverse_proxy https://pikvm.local {\n        transport http {\n            tls_insecure_skip_verify  # Same behaviour as Nginx\n        }\n        header_up Host {upstream_hostport}\n        header_down Location \"^(/.*)$\" \"/pikvm$1\"\n    }\n}\n
"},{"location":"switch/","title":"PiKVM Switch Multiport Extender Quickstart Guide","text":""},{"location":"switch/#pikvm-switch-multiport-extender","title":"PiKVM Switch Multiport Extender","text":"

Where to buy?

  • International store.
  • Canadian store.
  • EU is coming!

PiKVM Switch Datasheet (PDF)

The PiKVM Switch Multiport Extender enables one PiKVM device to view and control multiple target computers connected to each port. Target computers are viewed using HDMI video capture and then controlled via USB and ATX connections. Up to five Switch Multiport Extenders can be daisy-chained for a total of 20 ports. This is the maximum number of target computers that can be controlled by each supported PiKVM device.

Thanks to the modularity of PiKVM and the new Switch, you can build up your infrastructure gradually, adding new Switches as needed, without replacing the KVM entirely.

One target system at a time can be selected for HDMI video capture and USB control. ATX statuses and controls are available for all connected targets simultaneously. Video inputs include dedicated EDID (HDMI information and display parameters) and full control of the video connection state of each port.

The PiKVM Switch is fully plug-and-play.

It is compatible with PiKVM V4 Plus, PiKVM V3, DIY V2 and DIY V1 devices.

Please note that it's not compatible with PiKVM V4 Mini and DIY devices based on Raspberry Pi Zero boards because of the lack of available USB host ports.

"},{"location":"switch/#installation-requirements","title":"Installation requirements","text":"
  • Head device: PiKVM V4 Plus (recommended) or any other PiKVM except V4 Mini and Zero-based DIY.

  • The PiKVM Switch box includes:

    • Switch device
    • Power supply unit
    • DC Barrel Jack Cable
    • HDMI 2.0 Cable
    • USB-A Male To USB-C Female Adapter
    • 2x USB Cable, USB-C Male
    • 4x ATX kit with brackets and wires
  • Some cables are not included in the kit, but are required to connect each target host port:

    • HDMI 2.0 cable (no shorter than 30 centimeters).
    • USB-A to USB-C cable
    • Straight Ethernet cable for ATX connection.
"},{"location":"switch/#setup","title":"Setup","text":"
  1. Turn off the head PiKVM device.

  2. Unpack the box. Turn Switch in your hands and study the purpose of the ports. Lovingly pat the top cover to show it that you want to be friends.

    • The numbered ports on the front can be used to connect to the target hosts.
    • UPLINK ports should be connected to PiKVM or to the superior chained Switch.
    • DOWNLINK ports should be connected to a lower-level Switch.
  3. Connect Switch to PiKVM according to the following diagram. Example connections with PiKVM V4 Plus are shown, but similar connections can be made for any supported model.

    • (1) OTG connection for USB emulation (using Type-C cable).
    • (2) Video (using HDMI cable).
    • (3) USB control connection (using Type-C cable and included C-to-A adapter).
    • (4) Optional power chaining. If you're using PiKVM V4 Plus, both PiKVM and Switch can be powered from a single 12V power supply. Use the supplied two-way power cable to connect the PiKVM and Switch.
    • (5) Connect the supplied 12V power supply here.

    Double power supply is not allowed

    • When power chaining (4), never use your own 5V power port on the PiKVM V4.

    • The two 12V connectors on the Switch are designed for chaining only. Never connect two power supplies to your Switch.

    If you want to connect multiple Switches in a chain, use the following diagram. Two connected units can be considered as a single device, and the left group of UPLINK ports areused in a similar way: either connect it to a PiKVM as in the previous step, or connect to another Switch to.

    Chaining limit

    A maximum of 5 Switch units can be connected in a chain.

  4. Connect the target hosts to the numbered ports on the front panel of Switch.

    • HDMI for a video (don't use a cable shorter than 50 centimeters).
    • USB-C for USB emulation.
    • Optional ATX for power management of the host.
  5. PiKVM Switch is a Plug-n-Play device, so you don't need to write any complex configs. All you need is a fresh PiKVM OS and drivers that can be obtained by updating.

    Check the OS image

    To store the settings, Switch uses the Persistent Storage feature, which is presented in images older than 2022.06.20. To check if your PiKVM OS supports this, use the following command:

    [root@pikvm ~]# mount | grep '\\<pst\\>'\n/dev/mmcblk0p2 on /var/lib/kvmd/pst type ext4 (ro,nosuid,nodev,noexec,relatime,errors=remount-ro)\n

    If the output is similar to the above (/var/lib/kvmd/pst), then everything is fine. Otherwise on empty output, you need to reflash the OS.

    Do the update anyway (even if you did reflashing):

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  6. It's done! PiKVM will automatically configure all your Switches.

"},{"location":"switch/#working-with-the-switch","title":"Working with the Switch","text":"

All the functions of the Switch are available through the menu, which you will see in the PiKVM interface. The attached example uses two Switches, and switching between their ports works transparently.

  • The menu title shows the current active port (1.4) in unit.port format, and the status of the ATX power and HDD LEDs for its host.

  • (1) The Settings button shows the common chain settings window (see below).

  • (2) The ports are grouped by physical units, the sub-header of the table shows the unit 1 and the ports following it: 1.1, 1.2, 1.3 and 1.4.

  • (3) Beacon activation buttons for the UPLINK and DOWNLINK ports on the back of the Switch unit 1. When activated, the corresponding multifunction LED on the back of the Switch will start flashing to make it easier to find its connectors. This is especially useful if you have several Switches in a chain.

  • (4) The port switching button. The green color indicates the current active port.

  • (5) A button for configuring individual port parameters such as name, EDID, and more.

  • (6) The beacon activation button for the selected port activates the flashing LED on the numbered group of connectors on the front of the Switch unit.

    There are four indicators to the right: host video detected, USB detected, ATX power and HDD LEDs. Next, three ATX action buttons.

  • (7) The title of the sub-table of the Switch unit 2. The units are numbered according to the closeness to PiKVM device: Switch number 1 is connected directly to PiKVM, unit 2 is connected to downlink of unit 1.

In the settings menu, you can access the EDIDs Collection and customize the color scheme of the Switch LEDs.

"},{"location":"switch/#chain-settings","title":"Chain settings","text":"

In the settings menu, you can access the EDIDs Collection and customize the color scheme of the Switch LEDs.

Each port can use its own EDID which must be preloaded into the Collection, otherwise it will use the default EDID (taken from PiKVM). Binary and text EDID in HEX format are supported.

EDIDs Collection Color scheme"},{"location":"switch/#port-settings","title":"Port settings","text":"

In the port settings, you can set the display name (can be used for the name of the connected host) and the individual EDID from the Collection.

Other parameters relate to the ATX intervals for pressing the power and reset buttons of the target host.

"},{"location":"switch/#firmware-updating","title":"Firmware updating","text":"

Sometimes we release firmware updates for the Switch, which are distributed along with PiKVM OS updates. When the software detects that your switch has an old firmware, it will inform you about it via the web interface. After that, you will be able update the Switch.

If you have several switches in the chain, then all devices will be updated: first, PiKVM uploads the update to the first switch, then it updates the next one, and so on. This is very convenient because you don't have to perform complex manual manipulations to maintain your equipment. The Switches are intelligent and save you time.

Warning

We recommend updating the firmware only if you have physical access to the hardware.

Switches are extremely difficult to brick, but if there is a power failure during updating, you will need physical access to restore the device. So don't worry, it can't be bricked forever.

It is also recommended to perform all the operations described below via SSH, and not via a web terminal.

"},{"location":"switch/#performing-update","title":"Performing update","text":"

Just run these commands via SSH under root:

[root@pikvm ~]# cd /usr/share/kvmd/switch\n[root@pikvm switch]# systemctl stop kvmd   # This will stop the KVM web service\n[root@pikvm switch]# make install          # Flash the first switch\n[root@pikvm switch]# systemctl start kvmd  # Start it again\n

The switches will show the progress of the update on the front LEDs and will gradually return to service.

"},{"location":"switch/#known-issues","title":"Known issues","text":"A DIY PiKVM device based on HDMI-CSI board does not receive a video through the Switch

Some HDMI-CSI boards does not follow the HDMI specification correctly. We have provided a special compatibility mode for them, which should be enabled using the following configuration:

  1. Switch filesystem to RW-mode:

    [root@pikvm ~]# rw\n
  2. Add some lines to /etc/kvmd/override.yaml:

    kvmd:\n    switch:\n        ignore_hpd_on_top: true\n
  3. Restart KVMD:

    [root@pikvm ~]# systemctl restart kvmd\n
  4. Switch filesystem back to RO-mode:

    [root@pikvm ~]# ro\n
"},{"location":"tailscale/","title":"Tailscale VPN","text":"

The Tailscale VPN can be used to access PiKVM from the Internet if configuring port forwarding is not possible or more security is desired. Tailscale is a convenient and free (for private use) tool for organizing a small VPN network.

The basic Tailscale configuration commands are shown below. For detailed instructions, refer to Tailscale support.

"},{"location":"tailscale/#configuring-the-pikvm","title":"Configuring the PiKVM","text":"
  1. Update OS:

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  2. Install the Tailscale client, run tailscaled service and register it in the network:

    [root@pikvm ~]# rw\n# If you were afraid to pikvm-update above first run pacman -Syy\n[root@pikvm ~]# pacman -S tailscale-pikvm\n[root@pikvm ~]# systemctl enable --now tailscaled\n[root@pikvm ~]# tailscale up\n
  3. Follow the link to authorize this installation. You likely want to disable key expiry!

  4. After authorization success, reboot to make sure that everything works correctly:

    [root@pikvm ~]# reboot\n
  5. Now, you can view the IP address of the Tailscale network interface:

    [root@pikvm ~]# ip addr show tailscale0\n

If everything is successful, PiKVM will become a member of your VPN network.

Do not update Tailscale if you don't have access to PiKVM without VPN

Unfortunately, sometimes, updating the Tailscale client can cause problems due to breaking changes. These are compatibility issues on the Tailscale side. Remember this when updating.

"},{"location":"tailscale/#configuring-a-client-device","title":"Configuring a client device","text":"
  • Download and install the Tailscale client to the system you are using (not to the system you want to control).
  • Check the Tailscale admin page to view your VPN network.
  • Follow the URL in the web browser: https://<tailscale_kvm_ip> and you will see the PiKVM web interface.
"},{"location":"tailscale/#using-tailscale-certificates","title":"Using Tailscale Certificates","text":"

PiKVM uses self-signed SSL certificates out of the box. You can also use Tailscale certificates in place of the default one.

Warning

Tailscale certificates are provided by Let's Encrypt and has a default expiry of 90 days. There is currently no mechanism available to auto-renew Tailscale certificate. You may put the commands below in a script to simplify process.

  1. Switch filesystem to RW if in ReadOnly mode and delete existing PiKVM certificates for nginx and vnc.

    [root@pikvm ~]# rw\n[root@pikvm ~]# rm -v /etc/kvmd/{nginx,vnc}/ssl/*.{crt,key}\n
  2. Provision new certificates using tailscale cert command. Optionally you may create a directory to store the certificates.

    [root@pikvm ~]# mkdir .cert\n[root@pikvm ~]# cd .cert\n[root@pikvm .cert]# tailscale cert <tailscale_hostname>\n
  3. Copy the certificates to nginx's and vnc's ssl directories.

    [root@pikvm ~]# cp /root/.cert/<tailscale_hostname>.key /etc/kvmd/nginx/ssl/server.key\n[root@pikvm ~]# cp /root/.cert/<tailscale_hostname>.crt /etc/kvmd/nginx/ssl/server.crt\n

    Repeat the same steps for vnc if you have configured it.

    [root@pikvm ~]# cp /root/.cert/<tailscale_hostname>.key /etc/kvmd/vnc/ssl/server.key\n[root@pikvm ~]# cp /root/.cert/<tailscale_hostname>.crt /etc/kvmd/vnc/ssl/server.crt\n
  4. Grant file ownership to nginx and vnc services. Switch filesystem to ReadOnly again

    [root@pikvm ~]# chown :kvmd-nginx /etc/kvmd/nginx/ssl/*\n[root@pikvm ~]# chown :kvmd-vnc /etc/kvmd/vnc/ssl/*\n[root@pikvm ~]# ro\n
  5. Restart nginx and vnc services

    [root@pikvm ~]# systemctl restart kvmd-nginx\n[root@pikvm ~]# systemctl restart kvmd-vnc\n
"},{"location":"tailscale/#automated-ephemeral-tailscale-certificates-renewal","title":"Automated Ephemeral Tailscale Certificates Renewal","text":"

Tailscale has a nice option of running an HTTPS on your behalf within your tailnet: tailscale serve. It is using Let's Encrypt certificates and renews them every 90 days. The issue is that PiKVM\u2019s filesystem is read-only. While tailscale will diligently request new certificates, it will fail to write it on the disk and hence will try to request new certificates next time you access your web server. Let's Encrypt has a limit of 5 certificates for the server per week, so you will end up with an inoperable server and rate-limited by Let's Encrypt for a day or so.

Here's the command that allows you to seamlessly run HTTPS proxy for your PiKVM:

[root@pikvm ~]# tailscale serve --bg https+insecure://localhost:443\n
And if you want to stop tailscale from serving HTTPS, you can do this by running:
[root@pikvm ~]# tailscale serve --https=443 off\n````\n\n### Root cause\nTailscale needs to refresh TLS certificates and write state under `/var/lib/tailscale`.  \nOn PiKVM, the root filesystem is read-only, so direct writes fail.  \n\nWe can fix this by mounting an **ephemeral overlay filesystem (tmpfs) in RAM** for `/var/lib/tailscale`, backed by a persistent lowerdir (`/root/tailscale-state`).\n\nThis ensures that certificate rotation and state writes work without breaking PiKVM\u2019s read-only state.\n\n!!! warning\n    The **caveat** is that renewed certificates exist only in RAM. After a reboot, Tailscale falls back to the older certificates on disk, requests fresh ones, and stores them in RAM again.\n    If you reboot PiKVM too frequently, this can trigger Let's Encrypt's rate limits.\n\n### Solution\n\nCore idea:\n- Mount a **tmpfs** over Tailscale's state folder stored in root's home: /root/tailscale-state. \n- Mount the resulting *merged* layer onto the actual Tailscale state folder at /var/lib/tailscale.\n- An **overlayfs** will transparently present this folder to Tailscale, while changes are kept in the RAM-based overlay layer.\n\n**Note**: Overlayfs requires that the upperdir and workdir exist before creating the overlay.\nSince these directories live in RAM, they disappear after every reboot.\nThis means we cannot use fstab to declare the mount points.\nInstead, we implement this with a systemd service that runs a setup script during boot, before tailscaled starts.\n\n1. Switch filesystem to RW and copy Tailscale state:\n\n```console\n[root@pikvm ~]# rw\n[root@pikvm ~]# cp -a /var/lib/tailscale /root/tailscale-state\n````\n\n2. Create a helper script, save as `/usr/local/bin/setup-tailscale-overlay.sh`:\n\n```bash\n#!/bin/bash\nset -e\n\n# Make tmpfs for tailscale overlay\nmkdir -p /tmp/tailscale-tmpfs\nmountpoint -q /tmp/tailscale-tmpfs || mount -t tmpfs tmpfs /tmp/tailscale-tmpfs\n\n# Prepare overlay dirs\nmkdir -p /tmp/tailscale-tmpfs/upper\nmkdir -p /tmp/tailscale-tmpfs/work\nmkdir -p /tmp/tailscale-merged\n\n# Mount overlay (lowerdir = persistent readonly state in /root)\nmountpoint -q /tmp/tailscale-merged || mount -t overlay overlay \\\n  -o lowerdir=/root/tailscale-state,upperdir=/tmp/tailscale-tmpfs/upper,workdir=/tmp/tailscale-tmpfs/work \\\n  /tmp/tailscale-merged\n\n# Bind merged to /var/lib/tailscale\nmountpoint -q /var/lib/tailscale && umount /var/lib/tailscale || true\nmount --bind /tmp/tailscale-merged /var/lib/tailscale\n

Make it executable:

[root@pikvm ~]# chmod +x /usr/local/bin/setup-tailscale-overlay.sh\n
  1. Create a systemd unit

We need to run the overlay setup after /tmp is mounted but before tailscaled.service.

Save as /etc/systemd/system/tailscale-overlay.service:

[Unit]\nDescription=Setup overlayfs for Tailscale\nAfter=local-fs.target tmp.mount\nBefore=tailscaled.service\n\n[Service]\nType=oneshot\nExecStart=/usr/local/bin/setup-tailscale-overlay.sh\nRemainAfterExit=yes\n\n[Install]\nWantedBy=multi-user.target\n

Notes:

  • local-fs.target ensures all local filesystems (including /tmp tmpfs from fstab) are mounted.
  • tmp.mount is added explicitly in case your system defines it.
  • Overlay is mounted and bound before tailscaled starts.

  • Enable and reload

[root@pikvm ~]# systemctl daemon-reload\n[root@pikvm ~]# systemctl enable tailscale-overlay.service\n[root@pikvm ~]# ro\n
"},{"location":"tailscale/#boot-sequence-recap","title":"Boot sequence recap:","text":"
  1. tmpfs is mounted at /tmp/tailscale-tmpfs
  2. upper + work dirs are recreated inside tmpfs
  3. overlay is mounted with /root/tailscale-state as lowerdir
  4. overlay bind-mounted to /var/lib/tailscale
  5. tailscaled.service starts with writable state
"},{"location":"tailscale/#troubleshooting","title":"Troubleshooting","text":"
  • If something does not work, the usual advice is to completely remove Tailscale from PiKVM and perform a clean installation:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Rscnd tailscale\n[root@pikvm ~]# rm -rf /var/lib/tailscale /var/cache/tailscale\n[root@pikvm ~]# reboot\n

Now, follow the instructions from the beginning to re-install Tailscale.

  • In case of certificate issues you can try the following steps to debug and fix.

  • Check if the services are running. If not please start them. For example, web UI service can be checked using:

    [root@pikvm ~]# systemctl status kvmd-nginx\n

    For VNC:

    [root@pikvm ~]# systemctl status kvmd-vnc\n
  • If the services are running but not accessible or showing a warning, check the respective logs. For web UI:

    [root@pikvm ~]# journalctl -xeu kvmd-nginx\n
  • If the logs shows TLS/certificate/permissions errors, the issue may be with file ownership. The services must have at least the group ownership of the certificates. The ownership should look similar to this:

    [root@pikvm ~]# ls -l /etc/kvmd/{nginx,vnc}/ssl\n/etc/kvmd/nginx/ssl:\ntotal 8\n-r--r--r-- 1 root kvmd-nginx 2872 Jan  3 16:07 server.crt\n-r--r----- 1 root kvmd-nginx  227 Jan  3 16:07 server.key\n\n/etc/kvmd/vnc/ssl:\ntotal 8\n-r--r--r-- 1 root kvmd-vnc 2872 Jan  3 16:07 server.crt\n-r--r----- 1 root kvmd-vnc  227 Jan  3 16:07 server.key\n
"},{"location":"tesmart/","title":"TESMART managed multiport KVM switch","text":"

The TESMART managed switch can be controlled by PiKVM to allow it to connect to multiple hosts. A typical scenario is a single PiKVM device which can control and switch between multiple hosts or servers using the TESMART switch. UI elements can be added to the GPIO dropdown to allow switching between hosts from the PiKVM webpage.

The instructions here were tested with the TESMART HKS1601A10 HDMI 16x1 switch. This should work with any of the other TESMART variants which have a LAN port - there is both a 8x1 and 4x1 variant. This was tested with an RPI4, but as this is executed over a network protocol, this should with almost anything.

"},{"location":"tesmart/#connections","title":"Connections","text":"

From a high level, the TESMART switch uses standard connections to the host machines (USB-A to USB-B and HDMI). The Raspberry Pi OTG connector (the one coming from the USB-C port on a Pi 4 via the custom splitter cable or device) should be connected to one of the USB 2 output ports on the TESMART switch (not the keyboard/mouse port). Based on your specific devices, and to get boot images to mount, you may need to connect this through a USB 2 hub.

  1. Connect the USB-A cable from the Raspberry Pi OTG port to one of the TESMART switch USB 2 output ports on the back of the switch (not the keyboard/mouse ports).

  2. Connect the HDMI out from the TESMART switch to the Raspberry Pi CSI-2 to HMDI input.

  3. Connect the LAN port on the front of the switch using standard ethernet cable into one of your network switches.

  4. Connect host USB and HDMI cables from the TESMART switch to the machines to be managed per the switch instructions.

Warning

There is a limitation in the underlying PiKVM software related to plugging video cables from a host which is already powered and connected to a monitor to a Raspberry Pi CSI2-HDMI encoder. These limitations apply equally when using the TESMART KVM switch. If video is not present in PiKVM, try keeping all host machines off and connecting them directly to the TESMART switch before powering the hosts on.

"},{"location":"tesmart/#setting-the-ip-address-of-the-tesmart-switch","title":"Setting the IP Address of the TESMART switch","text":"

In some ways, this is the most complex part of this. The default IP address of the TESMART switch is 192.168.1.10. If that happens to work with your IP addressing scheme and current set of addresses, then you may be all set. This IP address is not configurable via DHCP or other standard mechanisms. The only way to change it is with a Windows utility available on the TESMART Downloads Page.

If you need to change it, you will first need to connect to the switch with a Windows machine, most easily directly through an ethernet cord, with your Windows laptop (or VM) up and assigned to a fixed IP address, such as 192.168.1.5. Once you've launched the utility you will see this screen:

On this screen, ensure you are on the \"General\" tab. Click the radio button for \"Network control\". Change the IP address to the default for the switch (may already be this -- 192.168.1.10). Press the \"Connect\" button. Should make the status light go green, as well as the selected port. If you do not get a connection here, you cannot proceed to change the IP address. To change the IP address, change to the \"Settings\" tab at the top. You will then see this screen:

On this screen, change to your desired IP address, gateway, mask, and port. Then press apply. Watch the box on the right to see if it applied OK. Press Query again to double-check. The actual IP address will not be changed until you power off/power on the switch. Make sure you have these settings correct, because if you get them wrong you would have to connect over RS232/serial and not the network.

There may be alternatives other than changing the IP address in this manner if you don't have access to a Windows machine or if this address doesn't work for you. See this README for other options (Images and concepts from the bash file were borrowed for creation of this plugin). This also contains a summary of the protocol, which is also available on the TESMART downloads page.

"},{"location":"tesmart/#adding-ui-elements-to-control-the-kvm-switch","title":"Adding UI elements to control the KVM switch","text":"

The UI can be updated to add buttons to switch between KVM inputs and indicators for which input is currently selected. The instructions below will make these available in the PiKVM UI after clicking the \"Switches\" menu button in the KVM view.

  1. Enable read-write mode on the SD card via rw

  2. Edit the /etc/kvmd/override.yaml file and include the following:

    kvmd:\n    gpio:\n        drivers:\n            tes:\n                type: tesmart\n                host: 10.10.1.10\n                port: 5000\n        scheme:\n            server0_led:\n                driver: tes\n                pin: 0\n                mode: input\n            server0_switch:\n                driver: tes\n                pin: 0\n                mode: output\n                switch: false    \n            server1_led:\n                driver: tes\n                pin: 1\n                mode: input\n            server1_switch:\n                driver: tes\n                pin: 1\n                mode: output\n                switch: false    \n            server2_led:\n                driver: tes\n                pin: 2\n                mode: input\n            server2_switch:\n                driver: tes\n                pin: 2\n                mode: output\n                switch: false    \n            server3_led:\n                driver: tes\n                pin: 3\n                mode: input\n            server3_switch:\n                driver: tes\n                pin: 3\n                mode: output\n                switch: false    \n        view:\n            table:\n                - [\"TESMART Switch\"]\n                - []\n                - [\"#Server 1\", server0_led, server0_switch|Switch]\n                - [\"#Server 2\", server1_led, server1_switch|Switch]\n                - [\"#Server 3\", server2_led, server2_switch|Switch]\n                - [\"#Server 4\", server3_led, server3_switch|Switch]\n
  3. Return to read-only mode for the sd card via ro

  4. Restart the kvmd service: systemctl restart kvmd

"},{"location":"tesmart/#switching-between-hosts-in-the-ui","title":"Switching between hosts in the UI","text":"

To switch between hosts, enter the KVM UI and click the \"Switches\" menu. You should see your inputs, one of which will have a green circle indicating it is currently selected. Click the other inputs to change the selected host.

"},{"location":"usb/","title":"USB configuration","text":"

PiKVM V2+ emulates a small set of USB devices to ensure normal operation: a keyboard, mouse and mass storage drive. However, the possibilities are not limited to this. Optionally, you can add a USB ethernet, serial port, or (exclusive to PiKVM V3 and V4 Mini/Plus) a microphone to support two-way audio.

In rare cases, the target host's BIOS/UEFI may not understand such a large number of emulated devices on single USB port, and some of them may need to be disabled.

A complete USB configuration changing (adding or removing devices) requires a reboot, but it is possible to temporarily disable and then re-enable existing emulated devices in preset.

"},{"location":"usb/#basics","title":"Basics","text":"

Each emulated USB device consumes a limited hardware resource called endpoints.

Depending on the device, the number of required endpoints varies:

Device Endpoints Keyboard, mouse 1 for each Mass Storage Drive 2 for each USB Microphone 2 USB Ethernet, USB Serial 3 for each

In total, PiKVM provides 9 endpoints for USB emulation, some of which are used by default:

  • PiKVM V2-V3 emulates one absolute mouse and one mass storage and uses 4 of 9 endpoints.

  • PiKVM V4 Mini/Plus also adds a relative mouse by default so it uses 5 of 9 endpoints.

You can add other devices remaining endpoints, disable existing ones at all to free some endpoints, or do this only temporarily.

Moreover, you can configure the preset with a large number of devices (more than PiKVM allows by endpoints), and then dynamically enable only the necessary ones.

If you have configured too many devices that consume more than 9 endpoints in total, the least important of them will be inactive. You can enable them using dynamic configuration.

To configure additional devices, please refer to the corresponding pages:

  • USB Microphone - Two-way audio communication for voice applications on the target host. Exclusive to PiKVM V3 and V4 Mini/Plus.

  • Absolute and relative mouse - The most convenient type of mouse is an absolute mouse, but some BIOSes may not understand it. In this case, the relative one will help you.

  • USB Ethernet - An FTP or Samba server on PiKVM can be configured, and the target host will see this over the network. It is also possible that PiKVM can work as a router to connect a host to a big network.

  • USB Serial Port - It can be used for terminal access from the target host to the PiKVM, or for any other purpose that requires a serial connection.

For information on how emulated devices are represented on the target host and how to change it, read here.

"},{"location":"usb/#default-preset","title":"Default preset","text":"

Device setup includes two stages: adding to config and starting.

When you add a device as described on the pages above, it automatically turns on after PiKVM reboot and becomes available on the target device. This behaviour can be changed: the device will be created, but not active until you turn it on dynamically.

The /etc/kvmd/override.yaml file is used for such changes. In the following example, there are USB Serial Port and Microphone enabled, but the serial port is not started by default:

otg:\n    devices:\n        serial:\n            enabled: true\n            start: false\n        audio:\n            enabled: true\n

The start parameter is also available for all USB devices, see kvmd -m for the entire configuration tree.

"},{"location":"usb/#dynamic-configuration","title":"Dynamic configuration","text":""},{"location":"usb/#command-line-utility","title":"Command-line utility","text":"

The kvmd-otgconf utility allows you to view and modify the USB configuration on the fly.

It will also inform you about the number of endpoints used.

Changing requires root permissions.

Let's take a look at the configuration:

[root@pikvm ~]# kvmd-otgconf \n# Endpoints used: 5 of 9\n# Endpoints free: 4\n+ hid.usb0  # [1]  Keyboard  # otg/devices/hid/keyboard/start\n+ hid.usb1  # [1]  Absolute Mouse  # otg/devices/hid/mouse/start\n+ hid.usb2  # [1]  Relative Mouse  # otg/devices/hid/mouse_alt/start\n+ mass_storage.usb0  # [2]  Mass Storage Drive  # otg/devices/msd/start\n

Each line represents an emulated device, left to right:

  • Plus or minus sign: the state (enabled or not).
  • The device name (e.g., hid.usb0).
  • The number of required endpoints (e.g., [2]).
  • The description (e.g., Absolute mouse).
  • Path to the relevant configuration parameter (e.g., otg/devices/hid/mouse/start) you can use to boot or not boot a service when kvmd launches.

Sometimes it's impossible to get into the UEFI/BIOS due to their bugs in USB support, and you need to boot from the PiKVM mass storage.

In this case, you can disable all devices except keyboard and relative mouse, and enter the BIOS:

[root@pikvm ~]# kvmd-otgconf -d mass_storage.usb0 uac2.usb0 hid.usb1\n# Endpoints used: 2 of 9\n# Endpoints free: 7\n+ hid.usb0  # [1]  Keyboard  # otg/devices/hid/keyboard/start\n- hid.usb1  # [1]  Absolute Mouse  # otg/devices/hid/mouse/start\n+ hid.usb2  # [1]  Relative Mouse  # otg/devices/hid/mouse_alt/start\n- mass_storage.usb0  # [2]  Mass Storage Drive  # otg/devices/msd/start\n

Then change the boot order in the BIOS by setting the USB sticks as first priority.

Exit the BIOS, and turn on mass storage again. Use it as usual to boot the image from PiKVM mass storage:

[root@pikvm ~]# kvmd-otgconf -e mass_storage.usb0\n# Endpoints used: 4 of 9\n# Endpoints free: 5\n+ hid.usb0  # [1]  Keyboard  # otg/devices/hid/keyboard/start\n- hid.usb1  # [1]  Absolute Mouse  # otg/devices/hid/mouse/start\n+ hid.usb2  # [1]  Relative Mouse  # otg/devices/hid/mouse_alt/start\n+ mass_storage.usb0  # [2]  Mass Storage Drive  # otg/devices/msd/start\n

You can also enable uac2.usb0 and hid.usb1 again.

"},{"location":"usb/#web-ui-menu","title":"Web UI menu","text":"

Using the pseudo-GPIO driver, you can USB control devices via the menu in the web interface. Read about GPIO basics here.

To setup the menu, use kvmd-otgconf --make-gpio-config to generate the configuration, and merge it with your existing one in /etc/kvmd/override.yaml in a usual way.

The example of kvmd-otgconf --make-gpio-config output
# kvmd-otgconf --make-gpio-config\nkvmd:\n    gpio:\n        drivers:\n            otgconf:\n                type: otgconf\n        scheme:\n            hid.usb0:\n                driver: otgconf\n                mode: output\n                pin: hid.usb0\n                pulse: false\n            hid.usb1:\n                driver: otgconf\n                mode: output\n                pin: hid.usb1\n                pulse: false\n            hid.usb2:\n                driver: otgconf\n                mode: output\n                pin: hid.usb2\n                pulse: false\n            mass_storage.usb0:\n                driver: otgconf\n                mode: output\n                pin: mass_storage.usb0\n                pulse: false\n        view:\n            table:\n                - [\"#Keyboard\", \"#hid.usb0\", hid.usb0]\n                - [\"#Absolute Mouse\", \"#hid.usb1\", hid.usb1]\n                - [\"#Relative Mouse\", \"#hid.usb2\", hid.usb2]\n                - [\"#Mass Storage Drive\", \"#mass_storage.usb0\", mass_storage.usb0]\n

Please note that this menu is not dynamically generated, you need to update the configuration if you added or deleted devices.

"},{"location":"usb_ethernet/","title":"Ethernet-over-USB network","text":"

Specifically to PiKVM V2+. When combined with configuring a DNS server, FTP, or SMB (for example), this is a powerful way to extend the capabilities of PiKVM.

"},{"location":"usb_ethernet/#basic-configuration","title":"Basic configuration","text":"

USB limitations

Each emulated USB device consumes a limited hardware resource called endpoints.

Short info: by default, you can add only one additional USB device.

To get more information about the endpoints, add more devices, and flexibly manage the configuration on the fly, see here.

Info

Before exploring this page, we recommend to read the PiKVM configuration guide so that you understand the terminology and how exactly the parameters described below change.

  1. Edit /etc/kvmd/override.yaml and add these lines:

    otg:\n    devices:\n        ethernet:\n            enabled: true\n            driver: ecm\n            host_mac: 48:6f:73:74:50:43\n            kvm_mac: 42:61:64:55:53:42\n

    The enable: true option was used for activation the USB network. The values of the remaining options are described in the tables.

    Parameter Default Description host_mac <random> The MAC address of the host's network interface. kvm_mac <random> The MAC address of the network interface on the PiKVM side called usb0. driver ecm Protocol driver of the USB network. Different drivers are required for different OS. See below. Driver Compatibility with Operating Systems ecm Linux; Mac OS eem Linux rndis5 Windows XP...7 1; Linux > 2.6.13 rndis Windows >= 7 2; Linux > 2.6.13 ncm Windows >= 10; Linux > 2.6.37; Mac OS

    1: Manual driver installation is required. Download RNDIS 5 Windows 2: Automatic driver installation since KVMD 3.53.

  2. To automatically configure the USB network on the host recommended using the service kvmd-otgnet. It configures the firewall, assigns an address to the local PiKVM interface usb0 and starts DHCP so the target host can get the IPv4 address.

    By default, the address 172.30.30.1/24 to interface usb0 will be assigned. One of the other addresses from the network 172.30.30.0/24 will be assigned to the host when it requests it via DHCP.

    For security reasons, all incoming connections from the host to the PiKVM side are blocked (except for ICMP and UDP port 67 which is used for DHCP). If you want to allow access from the host to the PiKVM interface, you will need to add ports 80 and 443 to the whitelist using /etc/kvmd/override.yaml file like this:

    otgnet:\n    firewall:\n        allow_tcp: [80, 443]\n

    Other useful firewall options are listed here:

    Parameter Default Description allow_icmp true Optional ICMP allowed to PiKVM. allow_tcp [] List of allowed TCP connections from the host to PiKVM. allow_udp [] List of allowed UDP connections from the host to PiKVM. forward_iface <none> Default gateway interface on PiKVM for network forwarding (see below).

    See other parameters and command hooks in kvmd -m.

  3. To enable the service, use the command systemctl enable kvmd-otgnet.

  4. Perform reboot.

"},{"location":"usb_ethernet/#routing-via-pikvm","title":"Routing via PiKVM","text":"

By default, kvmd-otgnet will configure network connection between PiKVM and the host only. The target host controlled by PiKVM will not be able to reach other hosts beyond PiKVM. If the full network access is required from the host through the USB-Ethernet feature (access all hosts PiKVM can access), additional settings are needed in /etc/kvmd/override.yaml.

  1. Add network interface to forward requests to (default gateway) by adding a line forward_iface: <interface name> under the firewall section. Typically it would be eth0 if the built-in ethernet port is used::

    otgnet:\n    firewall:\n        forward_iface: eth0\n
  2. Add DNS server to provide host name resolution service. For example, adding 8.8.8.8 as DNS server requires addition of dnsmasq dhcp options. This can be done by adding following lines:

    otgnet:\n    commands:\n        post_start_cmd_append:\n        - \"--dhcp-option=6,8.8.8.8\"\n
  3. Combining above two together::

    otgnet:\n    firewall:\n        forward_iface: eth0\n    commands:\n        post_start_cmd_append:\n        - \"--dhcp-option=6,8.8.8.8\"\n
  4. To enable internet access for the target host, add the following to the otgnet configuration::

     otgnet:\n    iface:\n        net: 10.65.0.0/28\n

    The 'net' parameter defines the network address range of the usb0 network. The host will automatically receive an IP address within this network including the DNS servers defined under 'post_start_cmd_append'. Note: This network should not be same as the network PiKVM is connected to.

    See other parameters and command hooks in kvmd -m.

  5. Don't forget to reboot.

An example of what the config would look like for a host that can access PiKVM and has internet access:
otgnet:\n    firewall:\n        allow_tcp: [80, 443]\n        forward_iface: wlan0\n    commands:\n        post_start_cmd_append:\n            - \"--dhcp-option=6,1.1.1.1,1.0.0.1\"\n    iface:\n        ip_cmd:\n            - /usr/bin/ip\n        net: 10.65.0.0/28\n
"},{"location":"usb_ethernet/#working-with-windows-computers","title":"Working with Windows Computers","text":"

This has been proven to work with Windows:

  1. Set the driver type to rndis (see above).

  2. Download this driver on the Windows machine and unzip it somewhere.

  3. Open the devices manager:

  4. Select Properties of the Composite KVM Device:

  5. Select the RNDIS Device and click properties:

  6. Switch to the Driver tab and then click Update driver.

  7. Click Browse my computer for driver software:

  8. Click Let me pick from a list of available drivers on my Computer:

  9. From the list of available hardware types, scroll down and select Network adapters, then click Next:

  10. Click Have disk:

  11. Click Browse, navigate to the folder where you've stored the driver and select the RNDIS.inf, press Open and then OK:

  12. Select Acer Netchip RNDIS/Ethernet Gadget and click Next:

  13. Dismiss the warning about non-compatible drivers by clicking Yes:

  14. You're done - the device should now be recognized:

  15. Verify the card is working by pinging your PiKVM in a console: ping 172.30.30.1:

"},{"location":"usb_pass/","title":"USB Passthrough","text":""},{"location":"usb_pass/#usb-passthrough","title":"USB Passthrough","text":"

For USB keyboards and mice connected to PiKVM directly, USB passthrough allows forwarding their input to the host system. This feature is available for all versions of PiKVM except the v4 Mini (no available USB ports) or a DIY version based on Pi Zero/Pi Zero 2 (using a USB hub prevents utilizing the OTG which the passthru expects to be available). It works best with HDMI passthrough available on PiKVM V4 Plus.

Let's consider this setup:

  • PiKVM V4 Plus connected to PiKVM switch;
  • A keyboard and a mouse connected to USB A ports on the PiKVM;
  • An external display connected to the PiKVM directly using HDMI out.

With both HDMI passthrough and USB passthrough enabled, you would be able to do this:

  • Switch between Computer 1 and Computer 2 connected to PiKVM Switch;
  • Control them directly from this single keyboard/mouse pair (in addition to remote control);
  • See the video output from the selected host on the local display.
"},{"location":"usb_pass/#enabling-usb-passthrough","title":"Enabling USB passthrough","text":"

Follow these steps to enable USB passthrough on your PiKVM:

  1. Log into your PiKVM as root, either via SSH, web console, or USB serial connection.

  2. You need KVMD 4.74+ to be able to use this feature. Update the PiKVM OS as root:

    [root@pikvm ~]# pikvm-update\n
  3. PiKVM will reboot, log in as root again.

  4. Run the following command to change acces to read-write, enable USB passthrough, and change acces to read-only again:

    [root@pikvm ~]# rw; systemctl enable --now kvmd-localhid; ro\n

Once you've done that, you should be able to use your USB keyboard and mouse connected directly to your PiKVM to control the host.

"},{"location":"usb_pass/#toggling-usb-passthrough","title":"Toggling USB passthrough","text":"

Every once in a while you may want using keyboard/mouse to control your PiKVM instead of controlling a host. Once USB passthrough is enabled in the system, you can switch it on and off with shortcuts:

  • LeftAlt, LeftAlt, K (mnemonic KVM) disables keyboard/mouse grabbing and allows using the input devices with PiKVM locally, for example, for the console operating.

  • LeftAlt, LeftAlt, H (mnemonic Host) switches back to the passthrough mode and passes keyboard-mouse events to the host.

Press these keys immediately one after another: LeftAlt, then LeftAlt again, then the mnemonic key.

"},{"location":"usb_pass/#switching-the-pikvm-switch-channels","title":"Switching the PiKVM Switch channels","text":"

If you have one or two PiKVM Switches, you can use LeftAlt, LeftAlt, 1 (1-8) to switch between up to 8 channels.

For three or more PiKVM Switches, you need to use double numbers, e.g., LeftAlt, LeftAlt, 3, 2 (unit 3, channel 2).

"},{"location":"usb_serial/","title":"Serial-over-USB connection","text":"

Specifically to V2+. This can be used for terminal access from the target host to the PiKVM, or for any other purpose that requires a serial connection. In the last case, you only need to perform step 1 and reboot.

USB limitations

Each emulated USB device consumes a limited hardware resource called endpoints.

Short info: by default, you can add only one additional USB device.

To get more information about the endpoints, add more devices, and flexibly manage the configuration on the fly, see here.

  1. Edit /etc/kvmd/override.yaml and add these lines:

    otg:\n    devices:\n        serial:\n            enabled: true\n
  2. Run the following command:

    # echo ttyGS0 >> /etc/securetty\n
  3. Create the directory /etc/systemd/system/getty@ttyGS0.service.d and add a file file named override.conf into it. Afterwards edit the file and copy this into it:

    [Service]\nTTYReset=no\nTTYVHangup=no\nTTYVTDisallocate=no\n
  4. Run these comands:

    # systemctl enable getty@ttyGS0.service\n# reboot\n
  5. Once PiKVM is rebooted you will have access to a virtual serial port on the server that the USB is connected to. Use mingetty, screen, putty, or something like this to access the kvm from the server. The port is called /dev/ttyAMA0.

"},{"location":"v1/","title":"DIY PiKVM V1 quickstart guide","text":""},{"location":"v1/#diy-pikvm-v1-quickstart-guide","title":"DIY PiKVM V1 quickstart guide","text":"

So many choices!

There are many different options with sub-items, so you can choose what will suit you. However, we marked the recommended way by sign \u272e \u272e \u272e

"},{"location":"v1/#required-parts","title":"Required parts","text":"
  1. MicroSD card minimum 8Gb class 10.

  2. Official USB-Micro Power Supply.

  3. Raspberry Pi board:

    • \u272e \u272e \u272e Raspberry Pi 3.
    • ... or Raspberry Pi 2. Does not support H.264 even with HDMI-CSI bridge.
    • ... or Raspberry Pi Zero 2 W. Compact and cheap, but not so reliable solution because of lack of the wired Ethernet. Note that the better way to use Pi Zero is making PiKVM V2 - it supports more USB features.
  4. Video capture device:

    • \u272e \u272e \u272e HDMI-CSI bridge based on TC358743 chip. Supports H.264 video encoding on Raspberry Pi 3, automatic resolution selection and the lowest possible latency.
    • ... or HDMI-USB dongle. Only heavy MJPEG video, no resolution detection, big latency compared to HDMI-CSI. Some users report hardware problems: the dongle may not work in the BIOS or simply stop working after a while. It's a black box, and no one knows what's inside it. If you have problems with it, it will not be possible to fix them.
  5. The Pico HID Keyboard & mouse emulator:

    • x1 Raspberry Pi Pico board with soldered pins. Pico 2 is not supported right now.

    • x1 USB-A to Micro-USB cable.

    • x10 dupont wires female-female.

    • x1 1N5819 diode. It's optional but strongly recommended. Any similar one will do.

      Warning

      The diode is needed to provide power to the Pico HID regardless of the target host state, which prevents the backpowering problem. It will allow you to keep the keyboard buttons pressed during the target host power cycle, which is, for example, important for MacOS to get into the boot menu.

      Do not connect the red wire (the VSYS (Pico) -> 5V (Pi) line) without a diode. If you can't find a diode, don't connect this wire at all.

  6. Board-specific parts:

    \u272e \u272e \u272e \"Nothing special for Raspberry Pi 2 or 3

    Raspberry Pi Zero 2 W \u272e \u272e \u272e HDMI-CSI bridge
    • x1 Raspberry Pi Zero Camera Cable. Not compatible with Auvidea B101.
    ... or HDMI-USB dongle
    • x1 USB-A socket to USB-Micro adapter (female-male).
  7. Optional features:

    \u272e \u272e \u272e ATX controller to manage the target host's power

    With this part, you will be able to remotely turn on, turn off and restart your computer!

    • x4 optocouplers TLP241BF(F or PC817X2NSZ9F (the input polarity must be observed) or OMRON G3VM-61A1 or OMRON G3VM-61AY1 Don't use random relay modules or random optocouplers! Some of these may not be sensitive enough for the Raspberry Pi, some others may be low-level controlled. Either use relays that are activated by a high logic level, or follow the design provided. See details here.
    • x4 390 Ohm resistors (see here for alternatives).
    • 2x 4.7 kOhm resistors.
    • x10+ dupont wires male-male.
    • x1 a breadboard.
    • various wires for the breadboard.

    This can be partially replaced by using Wake-on-LAN in the software, but it will not allow to reboot a hung system, and it is not as reliable as an ATX controller. Sometimes the Wake-on-LAN on the host just stops working, for its own or network reasons.

    PS/2 Keyboard & mouse

    The use of PS/2 is intended for advanced users. Check out the additional list of details in advance in the corresponding paragraph of the Pico HID manual.

    VGA video capture

    If you want to capture VGA from your server instead of HDMI, buy the VGA-to-HDMI converter. Some converters have issues with not supporting all resolutions and refresh rates.

"},{"location":"v1/#setting-up-the-hardware","title":"Setting up the hardware","text":"
  1. Video capture device:

    \u272e \u272e \u272e HDMI-CSI bridge

    Insert the flexible flat cable of the HDMI-CSI bridge into the narrow white connector on the Raspberry Pi (the closest one to big USB sockets). It is labeled CAMERA. To insert you need to open the connector first. On the Raspberry Pi side you can gently lift the black part up and a little bit sideways:

    Opening the MIPI CSI slot on the Raspberry Pi

    For the HDMI-CSI bridge this operation depends on the version you bought. Either pull it gently up as on the Raspberry or push it sideways. Make sure that the cable is inserted on the correct side and until it stops, and then push the black latch back. Avoid using force when pushing the cable in, as the slots bond to the PCB is quite fragile. Never connect or disconnect the flat cable from a powered device. This is not Plug-and-Play, and you can damage it. Also use only the cable that was included with the device package, or make sure that the third-party cable has the correct pinout.

    HDMI-CSI bridge connected to Raspberry Pi 4 HDMI-CSI bridge connected to Raspberry Pi 2 W (using the adapter cable) ... or HDMI-USB dongle Raspberry Pi 2 & 3

    Connect USB dongle to exactly this port. It is bound in the software so the OS does not confuse the video device with something else.

    Raspberry Pi 2 and 3 Raspberry Pi 4

    There are many revisions of the Raspberry Pi boards and you may come across one that we haven't tested. If the binding fails, the device will be available for all ports. Everything will work, but if you use a webcam and Linux mistakes it for a dongle, write to us and we will fix it.

    Raspberry Pi Zero 2 W

    Connect the USB dongle to USB-to-Micro adapter, and connect it to the USB port marked as USB (not PWR) on the Pi Zero board:

  2. The Pico HID and ATX controller:

    Connect all the parts according to this scheme:

    \u272e \u272e \u272e With ATX controller Simple wiring diagram

    Electrical schematic diagram for advanced users

    ... or without ATX controller Simple wiring diagram

    Electrical schematic diagram for advanced users

  3. Flash firmware to the Pico HID.

  4. Flash the memory card with PiKVM OS and insert it to Raspberry Pi.

"},{"location":"v1/#wiring","title":"Wiring","text":"

Warning

Double check that the circuit is assembled correctly to avoid any damage of the hardware.

PiKVM V1 requires several items available separately:

  • Ethernet cable (Raspberry Pi 2 and 3 only)

  • HDMI cable

Let's connect all the wires before you power up the device.

  1. Connect the HDMI video capture device to the video output port on the target host.

  2. Connect the Pico HID to the USB port on the target host.

  3. Raspberry Pi 2/3: connect Ethernet to the network, e.g., to the Wi-Fi router.

  4. Connect the ATX controller if you built it

    To control the power, two display LEDs (power and HDD activity) and two buttons (power and reset) are provided on the front panel of the computer case. They are connected by wires to pins on the motherboard.

    All you have to do is connect the PiKVM ATX controller to their wires by making a parallel connection. Please note that the pinout differs on different motherboards, so before you continue, check the documentation on your motherboard for correct pinout.

    The following illustration shows how the connection between the power LED and the power button should be performed:

    On the left are the wires from the PiKVM ATX controller, the pad in the middle indicates the pins on the motherboard, and on the right are the LED and button of the target host. The implementation of this scheme is left to your discretion and can be performed, for example, by cutting wires and performing twisting, followed by insulation with duct tape.

    Be careful and respect the polarity of the LEDs. The polarity of the button does not matter (they have no polarity at all). The connection of HDD LED and reset switch is performed in the same way.

"},{"location":"v1/#power-up","title":"Power up","text":"

If everything is assembled correctly, attach the power supply to the Raspberry Pi.

After turning on the power, PiKVM OS generates unique SSH keys and certificates and performs all necessary operations on the memory card. It takes a few minutes.

Do not turn off the device until it's fully booted for the first time.

"},{"location":"v1/#configure-the-display","title":"Configure the display","text":"

The operating system on your remote computer will treat PiKVM as an additional display and use it in the Extend mode by default. That's why you will see an empty desktop when you first connect.

To avoid that, go to the display settings in your remote computer's operating system and enable the mirror mode for the external screen that you operating system identifies as PiKVM. Refer to your operating system's documentation on that.

"},{"location":"v1/#access-pikvm","title":"Access PiKVM","text":"

You need to know PiKVM's IP address in the network to be able to access it. Unlike PiKVM V3 and V4, PiKVM V1 doesn't have an OLED to display the IP address it receives automatically. You need to discover it manually. There are several ways to do that.

  • Common way: Open the web interface of your router and find the list of issued IP addresses there.
  • Linux-only: Use the arp-scan --localnet command.
  • Linux, MacOS, Windows: Download and run Angry IP Scanner.
  • Windows PowerShell: Use the arp -a command.

Let's assume that PiKVM has received the address 192.168.0.26 and has also been assigned a hostname pikvm.

Type the URL in the browser's address bar and press Enter: https://192.168.0.26/ or https://pikvm/.

Submit the default credentials and click Login:

  • Username: admin
  • Password: admin
  • 2FA Code: disabled by default, skip this field

You will see the initial dashboard screen of the PiKVM where you can access the remote host, connect to the PiKVM command line, or log out:

"},{"location":"v1/#change-the-default-passwords","title":"Change the default passwords","text":"

For security's sake, it's best to change the default passwords immediately after running PiKVM for the first time.

Passwords are important!

Please ensure that you change both passwords: for Web UI access and for the Linux superuser (root).

To do that:

  1. On the initial dashboard screen, click the Terminal button to open the web terminal. You will see this command line interface:

  2. Gain Linux superuser privileges:

    $ su -\n

    When prompted for password, use root.

  3. Run rw to change the access to the SD card to the write mode:

    [root@pikvm ~]# rw\n
  4. Change the password for the Linux superuser:

    [root@pikvm ~]# passwd root\n

    Submit the new password, retype it the second time to confirm, press Enter, and you should see this:

    passwd: password updated successfully\n
  5. Change the password for web access:

    [root@pikvm ~]# kvmd-htpasswd set admin\n

    Submit the new password, retype it the second time to confirm, and press Enter.

  6. Run ro to change the access to the SD card back to the read-only mode:

    [root@pikvm ~]# ro\n
  7. Press Ctrl+D or type \"exit\" and press Enter to drop the root privileges.

  8. Go back one page in the browser. You should be back to the initial dashboard screen.

"},{"location":"v1/#access-the-remote-system","title":"Access the remote system","text":"
  1. On the initial dashboard screen, click the KVM button to access the remote host.

  2. You should now see the host system's display and interact with it remotely using a keyboard and a mouse.

"},{"location":"v1/#important-next-steps","title":"Important next steps","text":"
  • We strongly recommend to update the PiKVM OS after the first launch:

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  • Learn about basics of PiKVM OS Configuration: where to find configs, how to edit the, etc.

    Configuring PiKVM OS

    Need more info? We have it!

    The following is a brief guide to configuring PiKVM. For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), please refer to this page.

    Most of the PiKVM configuration files are located in the /etc/kvmd directory.

    The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. To redefine system parameters use the file /etc/kvmd/override.yaml. All other files that are also not recommended for editing have read-only permissions.

    You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory to split your customization into logical parts. The override.yaml file definitions takes precedence over the override.d directory.

    A complete list of all parameters can be viewed using the kvmd -m command.

    Files with the *.yaml suffix uses the YAML syntax and describes a parameter tree with key-value pairs of different types. To define the parameters within one section, an indent of 4 spaces is used. Comments starts with the # symbol.

    Only 4 spaces should be used for indentation

    Be careful when editing YAML and follow this rule. Invalid indentation or tabs instead of spaces will cause an error when starting the services.

    Sections under the same keys should be merged:

    • Wrong:

      kvmd:\n    gpio:\n        drivers: ...\nkvmd:\n    gpio:\n        scheme: ...\n
    • Correct:

      kvmd:\n    gpio:\n        drivers: ...\n        scheme: ...\n

    In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

  • Get to know PiKVM Web UI: read this help section to better understand all the possibilities of the web user interface.

  • Tune the HDMI dongle capture device if you're using it:

    Persistent HDMI cable connection with USB dongle

    Many USB video capture devices tell the server's video card that the HDMI cable is supposedly disconnected. This may lead to the fact that if you boot the server without an active stream, the server will not detect your capture card. This is easy to fix:

    • Switch filesystem to RW-mode:

      [root@pikvm ~]# rw\n
    • Edit file /etc/kvmd/override.yaml and add these lines:

      kvmd:\n    streamer:\n        forever: true\n        cmd_append: [--slowdown]\n
    • Finish:

      [root@pikvm ~]# ro\n[root@pikvm ~]# systemctl restart kvmd\n
    • Check that everything is working.

"},{"location":"v1/#further-recommendations","title":"Further recommendations","text":"
  • Harden the remote access by enabling 2FA and setting session expiration time.
  • Configure access to PiKVM from the Internet using port forwarding or Tailscale VPN.
  • Learn how configuration files are structured.
  • Read how PiKVM is identified on the target host.
"},{"location":"v1/#known-issues-and-limitations","title":"Known issues and limitations","text":"
  • Max resolution.PiKVM V1 with CSI bridge can only handle the maximum resolution 1920x1080@50Hz, 60Hz is not supported due hardware limitation. You can use any other resolution less than the specified one, for example 1280x720@60Hz. If you have any problems with video on CSI bridge, follow this guide.
"},{"location":"v1/#basic-troubleshooting","title":"Basic troubleshooting","text":"
  • Ensure that you are using the right OS image for your platform by running the following command: pacman -Q | grep kvmd-platform.

  • If you are not getting a display, run the two following commands:

    • dmesg | egrep 'tc35|1-1.4|uvc'
    • systemctl status kvmd-tc358743

    If you see a failed message on that output, be sure verify the orientation of the CSI cable or try reseating it.

    Note that this is not a hotplug device, and you must first turn off the power.

"},{"location":"v1/#getting-user-support","title":"Getting user support","text":"

If something doesn't work, check out our FAQ. Otherwise, head straight to our Support.

"},{"location":"v2/","title":"DIY PiKVM V2 quickstart guide","text":""},{"location":"v2/#diy-pikvm-v2-quickstart-guide","title":"DIY PiKVM V2 quickstart guide","text":"

So many choices!

There are many different options with sub-items, so you can choose what will suit you. However, we marked the recommended way by sign \u272e \u272e \u272e

"},{"location":"v2/#required-parts","title":"Required parts","text":"
  1. MicroSD card minimum 16Gb class 10.

  2. Raspberry Pi board:

    • \u272e \u272e \u272e Raspberry Pi 4 2Gb. It makes no sense to buy a Pi 4 with more memory than 2Gb, since PiKVM software uses very few resources.
    • ... or Raspberry Pi Zero 2 W. Compact and cheap, but not so reliable solution because of lack of the wired Ethernet.
    • ... Raspberry Pi 5 is not supported right now. It doesn't have GPU video encoders, therefore, there is no point in using it for PiKVM, it will not give any performance boost for this case. The Pi 5 is a great device, just not suitable for PiKVM.
  3. Video capture device:

    • \u272e \u272e \u272e HDMI-CSI bridge based on TC358743 chip. Supports H.264 video encoding, automatic resolution selection and the lowest possible latency.
    • ... or HDMI-USB dongle (not available for Pi Zero 2). Only heavy MJPEG video, no resolution detection, big latency compared to HDMI-CSI. Some users report hardware problems: the dongle may not work in the BIOS or simply stop working after a while. It's a black box, and no one knows what's inside it. If you have problems with it, it will not be possible to fix them.
  4. Board-specific: Power supply, USB connectivity, etc.

    \u272e \u272e \u272e Raspberry Pi 4

    On a Raspberry Pi 4 only the USB-C port that receives power is capable of acting as a USB Device. The other USB ports are capable only of acting as USB Hosts. Therefore a special cable must be used on the USB power port that it can simultaneously act as USB Device for the target host and receive external power from an power supply.

    \u272e \u272e \u272e Variant #1: Power supply + ready-made Y-splitter module
    • x1 USB-C/Power Splitter Module (US/UK/CA).
    • x1 USB-C to USB-C cable (male-male) for connecting the Raspberry Pi to the splitter.
    • x1 USB-A to USB-C cable (male-male) for connecting the target host to the splitter.
    • x1 Official USB-C Power Supply.
    ... or Variant #2: Power supply + Y-splitter based on power blocker
    • x1 USB-A to USB-C cable (male-male).
    • x1 USB splitter.
    • x1 USB Power Blocker - Will go into the USB-A end towards the target host.
    • x1 Raspberry Pi Official USB-C Power Supply.
    ... or Variant #3: Power supply + DIY Y-splitter for soldering
    • x1 USB-A to USB-C cable (male-male).
    • x1 Another cable USB-A to any (male-any).
    • x1 Any 5V 3A power supply with USB-A socket.
    ... or Raspberry Pi Zero 2 W
    • x1 USB-A to USB-Micro cable (male-male).
    • x1 Raspberry Pi Zero Camera Cable. Not compatible with Auvidea B101.
    • x1 Raspberry Pi Official USB-Micro Power Supply.
  5. Optional features:

    \u272e \u272e \u272e ATX controller to manage the target host's power

    With this part, you will be able to remotely turn on, turn off and restart your computer!

    • x4 optocouplers TLP241BF(F or PC817X2NSZ9F (the input polarity must be observed) or OMRON G3VM-61A1 or OMRON G3VM-61AY1 Don't use random relay modules or random optocouplers! Some of these may not be sensitive enough for the Raspberry Pi, some others may be low-level controlled. Either use relays that are activated by a high logic level, or follow the design provided. See details here.
    • x4 390 Ohm resistors (see here for alternatives).
    • 2x 4.7 kOhm resistors.
    • x10+ dupont wires male-male.
    • x1 a breadboard.
    • various wires for the breadboard.

    This can be partially replaced by using Wake-on-LAN in the software, but it will not allow to reboot a hung system, and it is not as reliable as an ATX controller. Sometimes the Wake-on-LAN on the host just stops working, for its own or network reasons.

    VGA video capture

    If you want to capture VGA from your server instead of HDMI, buy the VGA-to-HDMI converter. Some converters have issues with not supporting all resolutions and refresh rates.

Kit parts suitable for assembly are also on sale in Poland.

"},{"location":"v2/#setting-up-the-hardware","title":"Setting up the hardware","text":"
  1. Video capture device:

    \u272e \u272e \u272e HDMI-CSI bridge

    Insert the flexible flat cable of the HDMI-CSI bridge into the narrow white connector on the Raspberry Pi (the closest one to big USB sockets). It is labeled CAMERA. To insert you need to open the connector first. On the Raspberry Pi side you can gently lift the black part up and a little bit sideways:

    Opening the MIPI CSI slot on the Raspberry Pi

    For the HDMI-CSI bridge this operation depends on the version you bought. Either pull it gently up as on the Raspberry or push it sideways. Make sure that the cable is inserted on the correct side and until it stops, and then push the black latch back. Avoid using force when pushing the cable in, as the slots bond to the PCB is quite fragile. Never connect or disconnect the flat cable from a powered device. This is not Plug-and-Play, and you can damage it. Also use only the cable that was included with the device package, or make sure that the third-party cable has the correct pinout.

    HDMI-CSI bridge connected to Raspberry Pi 4 HDMI-CSI bridge connected to Raspberry Pi 2 W (using the adapter cable) ... or HDMI-USB dongle

    Connect USB dongle to exactly this port. It is bound in the software so the OS does not confuse the video device with something else.

    Raspberry Pi 2 and 3 Raspberry Pi 4

    There are many revisions of the Raspberry Pi boards and you may come across one that we haven't tested. If the binding fails, the device will be available for all ports. Everything will work, but if you use a webcam and Linux mistakes it for a dongle, write to us and we will fix it.

  2. USB cable and power supply

    \u272e \u272e \u272e Raspberry Pi 4 \u272e \u272e \u272e Variant #1: Power supply + ready-made Y-splitter module

    ... or Variant #2: Power supply + Y-splitter based on power blocker

    ... or Variant #3: Power supply + DIY Y-splitter for soldering

    It is assumed that if you have followed this path, you know how to handle a soldering iron and a multimeter.

    The Y-splitter can be soldered from two suitable USB cables. Check the attached diagram. The appropriate USB pinout(s) can easily be found on Google.

    Please note that if you make a Y-cable from two no-name cables, the colors of the wires may not match those shown. Use a multimeter to make sure the connections are correct.

    Video How-To: Making a USB Y-splitter cable

    ... or Raspberry Pi Zero 2 W

    This board has two USB micro connectors: one for power supply (marked as PWR) and the second for emulating a USB gadget (marked as USB). Both connectors have a common power line, so to prevent Raspberry power from entering the USB port of the target host, it is required to make a special USB A-to-Micro cable without power line.

    One way is to physically cut the power wire inside the USB cable.

    An easier way is to stick a piece of duct tape, as shown in this picture:

    Connect the power supply to the PWR, and your magic cable to the USB. The magic cable will be used to connect the device to the target host.

  3. \u272e \u272e \u272e Optional feature: ATX controller

    Connect all the parts according to this scheme:

    Simple wiring diagram

    Electrical schematic diagram for advanced users

  4. Flash the memory card with PiKVM OS and insert it to Raspberry Pi.

"},{"location":"v2/#wiring","title":"Wiring","text":"

Warning

Double check that the circuit is assembled correctly to avoid any damage of the hardware.

PiKVM V2 requires several items available separately:

  • Ethernet cable (Raspberry Pi 4 only)
  • HDMI cable

Let's connect all the wires before you power up the device.

  1. Connect the HDMI video capture device to the video output port on the target host.

  2. Using the Y-cable, connect the Pi's OTG port to the USB on the target host.

  3. Raspberry Pi 4: connect Ethernet to the network, e.g., to the WiFI router.

  4. Connect the ATX controller if you built it

    To control the power, two display LEDs (power and HDD activity) and two buttons (power and reset) are provided on the front panel of the computer case. They are connected by wires to pins on the motherboard.

    All you have to do is connect the PiKVM ATX controller to their wires by making a parallel connection. Please note that the pinout differs on different motherboards, so before you continue, check the documentation on your motherboard for correct pinout.

    The following illustration shows how the connection between the power LED and the power button should be performed:

    On the left are the wires from the PiKVM ATX controller, the pad in the middle indicates the pins on the motherboard, and on the right are the LED and button of the target host. The implementation of this scheme is left to your discretion and can be performed, for example, by cutting wires and performing twisting, followed by insulation with duct tape.

    Be careful and respect the polarity of the LEDs. The polarity of the button does not matter (they have no polarity at all). The connection of HDD LED and reset switch is performed in the same way.

"},{"location":"v2/#power-up","title":"Power up","text":"

If everything is assembled correctly, attach the power supply to the Raspberry Pi.

After turning on the power, PiKVM OS generates unique SSH keys and certificates and performs all necessary operations on the memory card. It takes a few minutes.

Do not turn off the device until it's fully booted for the first time.

"},{"location":"v2/#configure-the-display","title":"Configure the display","text":"

The operating system on your remote computer will treat PiKVM as an additional display and use it in the Extend mode by default. That's why you will see an empty desktop when you first connect.

To avoid that, go to the display settings in your remote computer's operating system and enable the mirror mode for the external screen that you operating system identifies as PiKVM. Refer to your operating system's documentation on that.

"},{"location":"v2/#access-pikvm","title":"Access PiKVM","text":"

You need to know PiKVM's IP address in the network to be able to access it. Unlike V3 and V4, PiKVM V2 doesn't have an OLED to display the IP address it receives automatically. You need to discover it manually. There are several ways to do that.

  • Common way: Open the web interface of your router and find the list of issued IP addresses there.
  • Linux-only: Use the arp-scan --localnet command.
  • Linux, MacOS, Windows: Download and run Angry IP Scanner.
  • Windows PowerShell: Use the arp -a command.

Let's assume that PiKVM has received the address 192.168.0.26 and has also been assigned a hostname pikvm.

Type the URL in the browser's address bar and press Enter: https://192.168.0.26/ or https://pikvm/.

Submit the default credentials and click Login:

  • Username: admin
  • Password: admin
  • 2FA Code: disabled by default, skip this field

You will see the initial dashboard screen of the PiKVM where you can access the remote host, connect to the PiKVM command line, or log out:

"},{"location":"v2/#change-the-default-passwords","title":"Change the default passwords","text":"

For security's sake, it's best to change the default passwords immediately after running PiKVM for the first time.

Passwords are important!

Please ensure that you change both passwords: for Web UI access and for the Linux superuser (root).

To do that:

  1. On the initial dashboard screen, click the Terminal button to open the web terminal. You will see this command line interface:

  2. Gain Linux superuser privileges:

    $ su -\n

    When prompted for password, use root.

  3. Run rw to change the access to the SD card to the write mode:

    [root@pikvm ~]# rw\n
  4. Change the password for the Linux superuser:

    [root@pikvm ~]# passwd root\n

    Submit the new password, retype it the second time to confirm, press Enter, and you should see this:

    passwd: password updated successfully\n
  5. Change the password for web access:

    [root@pikvm ~]# kvmd-htpasswd set admin\n

    Submit the new password, retype it the second time to confirm, and press Enter.

  6. Run ro to change the access to the SD card back to the read-only mode:

    [root@pikvm ~]# ro\n
  7. Press Ctrl+D or type \"exit\" and press Enter to drop the root privileges.

  8. Go back one page in the browser. You should be back to the initial dashboard screen.

"},{"location":"v2/#access-the-remote-system","title":"Access the remote system","text":"
  1. On the initial dashboard screen, click the KVM button to access the remote host.

  2. You should now see the host system's display and interact with it remotely using a keyboard and a mouse.

"},{"location":"v2/#important-next-steps","title":"Important next steps","text":"
  • We strongly recommend to update the PiKVM OS after the first launch:

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  • Learn about basics of PiKVM OS Configuration: where to find configs, how to edit the, etc.

    Configuring PiKVM OS

    Need more info? We have it!

    The following is a brief guide to configuring PiKVM. For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), please refer to this page.

    Most of the PiKVM configuration files are located in the /etc/kvmd directory.

    The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. To redefine system parameters use the file /etc/kvmd/override.yaml. All other files that are also not recommended for editing have read-only permissions.

    You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory to split your customization into logical parts. The override.yaml file definitions takes precedence over the override.d directory.

    A complete list of all parameters can be viewed using the kvmd -m command.

    Files with the *.yaml suffix uses the YAML syntax and describes a parameter tree with key-value pairs of different types. To define the parameters within one section, an indent of 4 spaces is used. Comments starts with the # symbol.

    Only 4 spaces should be used for indentation

    Be careful when editing YAML and follow this rule. Invalid indentation or tabs instead of spaces will cause an error when starting the services.

    Sections under the same keys should be merged:

    • Wrong:

      kvmd:\n    gpio:\n        drivers: ...\nkvmd:\n    gpio:\n        scheme: ...\n
    • Correct:

      kvmd:\n    gpio:\n        drivers: ...\n        scheme: ...\n

    In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

  • Get to know PiKVM Web UI: read this help section to better understand all the possibilities of the web user interface.

  • Tune the HDMI dongle capture device if you're using it:

    Persistent HDMI cable connection with USB dongle

    Many USB video capture devices tell the server's video card that the HDMI cable is supposedly disconnected. This may lead to the fact that if you boot the server without an active stream, the server will not detect your capture card. This is easy to fix:

    • Switch filesystem to RW-mode:

      [root@pikvm ~]# rw\n
    • Edit file /etc/kvmd/override.yaml and add these lines:

      kvmd:\n    streamer:\n        forever: true\n        cmd_append: [--slowdown]\n
    • Finish:

      [root@pikvm ~]# ro\n[root@pikvm ~]# systemctl restart kvmd\n
    • Check that everything is working.

"},{"location":"v2/#further-recommendations","title":"Further recommendations","text":"
  • Harden the remote access by enabling 2FA.
  • Configure access to PiKVM from the Internet using port forwarding or Tailscale VPN.
  • Learn how configuration files are structured.
  • Read how PiKVM is identified on the target host.
"},{"location":"v2/#known-issues-and-limitations","title":"Known issues and limitations","text":"
  • Max resolution.PiKVM V2 with CSI bridge can only handle the maximum resolution 1920x1080@50Hz, 60Hz is not supported due hardware limitation. You can use any other resolution less than the specified one, for example 1280x720@60Hz. If you have any problems with video on CSI bridge, follow this guide.

  • Motherboards compatibility.There may be compatibility issues with some motherboards, such as HP or DELL. If there is no image from the BIOS, you can fine-tune the HDMI settings, but it is possible that the mass storage devices will not be available in the BIOS. In the latter case, USB dynamic configuration will solve the problem.

"},{"location":"v2/#basic-troubleshooting","title":"Basic troubleshooting","text":"
  • Ensure that you are using the right OS image for your platform by running the following command: pacman -Q | grep kvmd-platform.

  • If you are not getting a display, run the two following commands:

    • dmesg | egrep 'tc35|1-1.4|uvc'
    • systemctl status kvmd-tc358743

    If you see a failed message on that output, be sure verify the orientation of the CSI cable or try reseating it.

    Note that this is not a hotplug device, and you must first turn off the power.

"},{"location":"v2/#getting-user-support","title":"Getting user support","text":"

If something doesn't work, check out our FAQ. Otherwise, head straight to our Support.

"},{"location":"v3/","title":"PiKVM V3 HAT & pre-assembled quickstart guide","text":""},{"location":"v3/#pikvm-v3-hat-pre-assembled-quickstart-guide","title":"PiKVM V3 HAT & pre-assembled quickstart guide","text":"

PiKVM is a feature-rich, production-grade, open-source, Raspberry Pi based KVM-over-IP device. It allows you to turn your computer on or off, restart it, configure the UEFI/BIOS, and even reinstall the OS using the Virtual CD-ROM or flash drive.

PiKVM uses your remote keyboard and mouse to simulate a local keyboard, mouse, and monitor, which are then presented in a web browser as if you were working on a remote system directly.

PiKVM V3 is available in two version:

  • An assembly kit (HAT).
  • A pre-assembled unit in a metallic box.

The two versions have the same ports and functionality.

"},{"location":"v3/#whats-in-the-box","title":"What's in the box","text":"HATPre-Assembled
  • The PiKVM V3 HAT for Raspberry Pi 4
  • USB-C bridge board
  • ATX adapter board with mounting brackets and motherboard interface wiring
  • 2x Flat CSI-2 cables
  • 7x jumpers
  • 8x brass standoffs
  • 8x screws
  • PiKVM V3.3 pre-assembled
  • ATX adapter board with mounting brackets and motherboard interface wiring
  • A 32 GB MicroSD card pre-imaged with the PiKVM OS
"},{"location":"v3/#hat-setup","title":"HAT setup","text":"

If you have an assembly kit without a metal case, you can use our free 3D printing case drawing:

  • V3.2 is the pre-release model.
  • V3.3 is the Kickstarter/Store model.

Once you have that, do the following:

  1. Flash the memory card. Please use the V3 image, V2 image is not compatible.

  2. Build PiKVM according to the illustrated instructions.

"},{"location":"v3/#interface","title":"Interface","text":"Front viewRear viewLeft viewTop view
  1. 2x USB 2.0
  2. 2x USB 3.0
  3. RJ45 1Gb Ethernet port
  4. RJ45 Serial console port
  5. Serial console active LED / Beacon LED (Green)
  6. USB 2.0 Serial console port
  7. Activity LED (Red)
  8. Power LED (Green)
  9. Power Input 5.1V 3A
  1. Micro SD card slot
  2. HDMI video input port
  3. USB 2.0 OTG connector
  4. RJ45 ATX control port
  1. Mini-HDMI output port
  1. Display
"},{"location":"v3/#flashing-the-os","title":"Flashing the OS","text":"

Most of the time, this step is not necessary. However, if there is a possibility that your device had a previous owner (e.g. \"Used - Like New\" on Amazon), we recommend reflashing the OS to ensure a clean start. Please follow this guide.

"},{"location":"v3/#wiring","title":"Wiring","text":"

Both the HAT and the pre-assembled V3 require several items available separately:

  • Ethernet cable
  • RJ-45 cable for ATX (optional)
  • USB-C cable
  • HDMI cable
  • 5V USB power adapter

Let's connect all the wires before you power up the device.

"},{"location":"v3/#network","title":"Network","text":"

Connect Ethernet (bottom right on the front side) to the network, e.g., to the WiFI router.

"},{"location":"v3/#hdmi-and-usb-c","title":"HDMI and USB-C","text":"

HDMI input (the top right on the rear side) and OTG port (USB emulation) should be connected to the computer.

Optionally, the ATX port can be connected to control the power. There should be no USB hub between PiKVM and the computer, as some UEFI/BIOS cannot detect them at the boot stage.

"},{"location":"v3/#power-up","title":"Power up","text":"

V3 comes has a USB-C 5V power supply. Attach the appropriate connector on the front side (top left). Do not block the ventilation holes on the sides of the device.

After turning on the power, PiKVM OS generates unique SSH keys and certificates and performs all necessary operations on the memory card. It takes a few minutes. Do not turn off the device until it's fully booted for the first time. Once it's done, the PiKVM will show a greeting on the built-in display.

"},{"location":"v3/#connect-and-set-up","title":"Connect and set up","text":""},{"location":"v3/#configure-the-display","title":"Configure the display","text":"

The operating system on your remote computer will treat PiKVM as an additional display and use it in the Extend mode by default. That's why you will see an empty desktop when you first connect.

To avoid that, go to the display settings in your remote computer's operating system and enable the mirror mode for the external screen that you operating system identifies as PiKVM. Refer to your operating system's documentation on that.

"},{"location":"v3/#access-pikvm","title":"Access PiKVM","text":"

By default, PiKVM receives a dynamic IP address via DHCP and shows it in the top row of the OLED display:

192.168.0.26\n(|) iface: eth0\ncpu: 1% mem: 13%\n

Let's assume that PiKVM has received the address 192.168.0.26 and has also been assigned a hostname pikvm.

Type the URL in the browser's address bar and press Enter: https://192.168.0.26/ or https://pikvm/.

Submit the default credentials and click Login:

  • Username: admin
  • Password: admin
  • 2FA Code: disabled by default, skip this field

You will see the initial dashboard screen of the PiKVM where you can access the remote host, connect to the PiKVM command line, or log out:

"},{"location":"v3/#change-the-default-passwords","title":"Change the default passwords","text":"

For security's sake, it's best to change the default passwords immediately after running PiKVM for the first time.

Passwords are important!

Please ensure that you change both passwords: for Web UI access and for the Linux superuser (root).

To do that:

  1. On the initial dashboard screen, click the Terminal button to open the web terminal. You will see this command line interface:

  2. Gain Linux superuser privileges:

    $ su -\n

    When prompted for password, use root.

  3. Run rw to change the access to the SD card to the write mode:

    [root@pikvm ~]# rw\n
  4. Change the password for the Linux superuser:

    [root@pikvm ~]# passwd root\n

    Submit the new password, retype it the second time to confirm, press Enter, and you should see this:

    passwd: password updated successfully\n
  5. Change the password for web access:

    [root@pikvm ~]# kvmd-htpasswd set admin\n

    Submit the new password, retype it the second time to confirm, and press Enter.

  6. Run ro to change the access to the SD card back to the read-only mode:

    [root@pikvm ~]# ro\n
  7. Press Ctrl+D or type \"exit\" and press Enter to drop the root privileges.

  8. Go back one page in the browser. You should be back to the initial dashboard screen.

"},{"location":"v3/#access-the-remote-system","title":"Access the remote system","text":"
  1. On the initial dashboard screen, click the KVM button to access the remote host.

  2. You should now see the host system's display and interact with it remotely using a keyboard and a mouse.

"},{"location":"v3/#important-next-steps","title":"Important next steps","text":"
  • We strongly recommend to update the PiKVM OS after the first launch:

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  • Learn about basics of PiKVM OS Configuration: where to find configs, how to edit the, etc.

    Configuring PiKVM OS

    Need more info? We have it!

    The following is a brief guide to configuring PiKVM. For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), please refer to this page.

    Most of the PiKVM configuration files are located in the /etc/kvmd directory.

    The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. To redefine system parameters use the file /etc/kvmd/override.yaml. All other files that are also not recommended for editing have read-only permissions.

    You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory to split your customization into logical parts. The override.yaml file definitions takes precedence over the override.d directory.

    A complete list of all parameters can be viewed using the kvmd -m command.

    Files with the *.yaml suffix uses the YAML syntax and describes a parameter tree with key-value pairs of different types. To define the parameters within one section, an indent of 4 spaces is used. Comments starts with the # symbol.

    Only 4 spaces should be used for indentation

    Be careful when editing YAML and follow this rule. Invalid indentation or tabs instead of spaces will cause an error when starting the services.

    Sections under the same keys should be merged:

    • Wrong:

      kvmd:\n    gpio:\n        drivers: ...\nkvmd:\n    gpio:\n        scheme: ...\n
    • Correct:

      kvmd:\n    gpio:\n        drivers: ...\n        scheme: ...\n

    In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

  • Get to know PiKVM Web UI: read this help section to better understand all the possibilities of the web user interface.

  • Set up ATX connection if you need to control the power of the remote system.

"},{"location":"v3/#further-recommendations","title":"Further recommendations","text":"
  1. Customize the system:

    • Harden the remote access by enabling 2FA.
    • Configure access to PiKVM from the Internet using port forwarding or Tailscale VPN.
    • Enable a microphone for two-way audio.
    • Learn how configuration files are structured.
    • Read how PiKVM is identified on the target host.
  2. Configure hardware:

    • If you bought V3 HAT Assembly Kit and it includes the OLED display and/or the fan, you'll need to turn them on. Note this is only needed for the older V3 image for the HAT, in the box image everything is enabled by default:

      Enabling the OLED and the fan

      Log in to PiKVM and run these commands:

      [root@pikvm ~]# rw\n[root@pikvm ~]# systemctl enable --now kvmd-oled kvmd-oled-reboot kvmd-oled-shutdown\n[root@pikvm ~]# systemctl enable --now kvmd-fan\n[root@pikvm ~]# ro\n
    • Choose Fahrenheit over Celsius to display on the OLED:

      How to set up Fahrenheit on the OLED

      Create a directory for a configuration file:

      [root@pikvm ~]# mkdir -p /etc/systemd/system/kvmd-oled.service.d\n

      Create file /etc/systemd/system/kvmd-oled.service.d/override.conf:

      [Service]\nExecStart=\nExecStart=/usr/bin/kvmd-oled --clear-on-exit --fahrenheit\n
"},{"location":"v3/#known-issues-and-limitations","title":"Known issues and limitations","text":"
  • Max resolution.PiKVM V3 supports maximum resolution 1920x1080@50Hz, 60Hz will not work. You can use any other resolution less than the specified one, for example: 1600x1200@60Hz, 1280x720@60Hz, etc. If you have problems with the video, follow this guide.

  • Motherboards compatibility.There may be compatibility issues with some motherboards, such as HP or DELL. If there is no image from the BIOS, you can fine-tune the HDMI settings, but it is possible that the mass storage devices will not be available in the BIOS. In the latter case, USB dynamic configuration will solve the problem.

  • HDMI backpowering.Under specific circumstances, PiKVM may hang during the boot. Turn off the PiKVM, disconnect all cables from it, take a close look at the diagram of its ports and jumpers below, and remove jumper #14 (it is to the right of the CSI connector, not available on the V3.2 board). Then you can connect and power up PiKVM again. (Technical background s described here.)

  • IO ports.Before using GPIO pins to control a relay, KVM switch, or anything else, be sure to check the HAT pinout below. Many ports are busy with internal functions. Before using them for your own use, you must disable them, otherwise you may damage the PiKVM WebTerm

The ports and jumpers diagram

  1. ATX controller interface (power on/off, reboot control, PWR and HDD ACT LEDs).
  2. HDMI reset jumper. Connects GPIO 17 and RESET pin to HDMI capture chip. Currently not used, don't touch it.
  3. SPI and GPIO for the custom extension boards.
  4. Audio capture jumpers. Connects I2S pins 18, 19, 20 to HDMI capture chip.
  5. UART access jumpers. Connects GPIO 14 and 15 to the RJ-45 and USB console ports.
  6. Serial console port (default: /dev/ttyAMA0, RS232 input, outputs +6V/-6V, for the Raspberry Pi or server console access, use the Cisco/Mikrotik-style cable).
  7. USB-C console port (shared with #6 above, takes priority over RJ45).
  8. Power and activity LEDs. On the left of the LEDs the watchdog jumper is located. Don't touch it.
  9. USB-C power input.
  10. I2C display connector.
  11. Alternate +5V power input/output header pins.
  12. RTC clock supercapacitor (rechargeable).
  13. FAN connector - PWM controlled.
  14. CSI-2 interface and HDMI backpowering jumper, see Step 9 of the Basic Setup. Open: (jumper removed) diode will stop current from HDMI input (backpower will be fixed), closed: (jumper connected to both pins) will allow current from HDMI device.
  15. Built-in power splitter port.
  16. HDMI capture port (max 1080p @ 50Hz) with sound capture support.
  17. USB emulation pins for alternative access.
  18. USB-C emulation port - this port is doing the emulation of a USB keyboard, mouse, Virtual CD-ROM or USB Flash Drive, USB-Ethernet, USB-Serial port and a lot of other Linux-supported features.
  19. 1-Wire & Neo-pixel interface (under, advanced user feature).
The GPIO pinout

Warning

Before proceeding, make sure that the mb you are using has normal ATX headers

  • ATX control
  • power led = GPIO 24 - Used for reading the host power state.
  • hdd led = 22 - Same for the HDD activity.
  • power switch = 23 - Used for pressing the power button of the host.
  • reset switch = 27 - Same for the reset button.

These pins can't be used for any other purposes even if ATX function is disabled.

  • I2C bus - GPIO 2, 3 - Can be used as I2C ONLY (OLED/RTC).

  • 1-Wire [19] - GPIO 4 - Also available under ATX RJ-45 port (point [19] on the above) as bi-directional buffered open-drain 5V for regular 1-Wire usage.

  • UART - GPIO 14, 15 - Can be used as UART only for the serial console. When jumpers [5] are removed, you can connect to pins 14 and 15 directly using GPIO header. Also you can remove jumper [5] and disable UART console in the /boot/config.txt and /boot/cmdline.txt to use this pins for any purpose. But it's not recommended.

  • Red activity led on the front [8] - GPIO 13 - Can be disabled in /boot/config.txt and available on the Neo-pixel port [19].

  • PWM fan controller - GPIO 12. Can be used for custom purposes if the fan disconnected and kvmd-fan service is stopped.

  • I2S HDMI sound - GPIO 18, 19, 20, 21. Can be used for custom purposes if the tc358743-audio overlay in /boot/config.txt is disabled AND jumpers [4] are removed.

  • USB breaker - GPIO 5 - Can't be used for any other purposes.

The standard Raspberry Pi HDMI output (marked as VIDEO OUT on the PiKVM case) displays its own PiKVM OS console.

"},{"location":"v3/#basic-troubleshooting","title":"Basic troubleshooting","text":"
  • Ensure that you are using the right OS image for your platform by running the following command: pacman -Q | grep kvmd-platform.

  • If you are not getting a display, run the two following commands:

    • dmesg | egrep 'tc35|1-1.4|uvc'
    • systemctl status kvmd-tc358743
"},{"location":"v3/#getting-user-support","title":"Getting user support","text":"

If something doesn't work, check out our FAQ. Otherwise, head straight to our Support.

"},{"location":"v3_illustrated_install_instructions/","title":"Assembling PiKVM V3 HAT","text":""},{"location":"v3_illustrated_install_instructions/#assembling-pikvm-v3-hat","title":"Assembling PiKVM V3 HAT","text":"

PiKVM V3 HAT is an assembly kit. You can build it without any case whatsoever, order a metallic case separately, or 3D-print a case yourself. These videos cover all those use cases.

Video guide: Assembly with a metal case

NOTE: OLED will not light up till step 5 is performed, video was performed after it was already configured, heat sinks NOT included.

Video guide: Assembly with or without a 3D-printed case

"},{"location":"v3_illustrated_install_instructions/#step-1","title":"Step 1","text":"

Get the parts that are not in the assembly kit:

  • Raspberry Pi 4 with 1Gb RAM or more
  • Heat sinks (Optional)
  • MicroSD card (at least 16Gb, class 10 recommended)
  • USB-C to USB-A cable
  • HDMI cable
  • Straight Ethernet cable
  • Power supply unit (5.1V 3A USB-C, recommended by the Raspberry Pi)

Tip

  • Please review the back of the box. All parts are required before the HAT is fully functional.
  • The USB-C bridge is located in with the ATX end which includes a pink foam spacer.
  • Please assemble the HAT onto the RPi and test all of the parts before installing in the case, it's easier to install in the case than to dissasemble it.
  • If going from a V2 to a V3, the splitter is no longer needed.
"},{"location":"v3_illustrated_install_instructions/#step-2","title":"Step 2","text":"

Remove contents from assembly kit box:

  • 8x M.2 5x12mm screws for the case
  • 4x M.2 5x12mm screws for the fan
  • 4x bolts for the fan
  • 1x fan (30x30x7mm 5v)
  • 1x case top
  • 1x case bottom
  • 1x OLED display (0.91 IIC 128x32 LCD)
  • 2x bottom plastic risers
  • 1x plastic top riser
  • 1x plastic OLED holder that is also a front riser
  • 2x small FCC ribbon cables
  • 1x small rubber square that break out to 4x small rubber feet

OLED is sensitive to pressure, do NOT push down on the very thin glass as it will crack and become non-functional

"},{"location":"v3_illustrated_install_instructions/#step-3","title":"Step 3","text":"

Take bottom part of the case, insert the RPI4 into the bottom case at an angle, you will need to flex the other side ever so slightly to get it to slot in.

IF you bought heatsink's (sold seperatly), it's advised to install them now before installing the HAT"},{"location":"v3_illustrated_install_instructions/#step-4","title":"Step 4","text":"

Insert HAT at the same angle, take care to line up the pins on the Rpi with the HAT pin sleeve, the trick to this is to push the Rpi all of the way to the left then all of the way to the right for proper alignment, do NOT force till the pins are aligned. If properly aligned the pins will match up without issue.

ALTERNATIVE: As an alternative to the above, you can pre assemble the hat+fcc cable onto the RPI4, then insert them into the bottom portion of the case however you will need to flex the sides more whereby creating a bigger gap when fully assembled."},{"location":"v3_illustrated_install_instructions/#step-5","title":"Step 5","text":"

There are 2 ways to insert the FCC cable, you can add it when you insert the RPI in Step 2 OR wait till you also have the HAT installed and slide it into the slot.

The blue stripes on the ends of the cable will ALWAYS face the side that will be used to tighten the FCC to the camera port or have it positioned towards the power - Ignore the smaller FCC cable that plugs into the USB, was phased out during the KS campaign. This image was used as a means of illustrating FCC placement and orientation"},{"location":"v3_illustrated_install_instructions/#step-6","title":"Step 6","text":"

Install the USB-C bridge.

This is packaged with the ATX board

If you do not install this bridge, mouse/kb will not work HAT will still power on without this bridge installed"},{"location":"v3_illustrated_install_instructions/#step-7","title":"Step 7","text":"

Turn the bottom of the case upside down, install the 2 bottom plastic risers, it's best to install in a wing formation. Top first by inserting the top screws then slide the bottom part aligning the plastic to the holes then inserting the screws. At this point its OK to tighten the bottom screws. There is no need to use force, just tighten enough to prohibit movement.

"},{"location":"v3_illustrated_install_instructions/#step-8","title":"Step 8","text":"

Take the plastic OLED holder, turn the OLED over where the back side is facing you and insert at an angle so as to create a space between the OLED and holder arm, take a flat head screwdriver (medium normal) and twist it enough so you can clear the electronics on the bottom of the OLED and continue to gently slide in the remaining OLED till its fully inserted.

Be careful on handling this display, slight pressure will damage the OLED, however in the event that this does happen, replacements are cheap and can be found in most electronic stores or Amazon, look for any IIC (I2C) .91 inch display for Arduino

"},{"location":"v3_illustrated_install_instructions/#step-9","title":"Step 9","text":"

Insert the OLED holder with the OLED display into the plug by gently rocking it back and forth till it's fully inserted.

"},{"location":"v3_illustrated_install_instructions/#step-10","title":"Step 10","text":"

Install plastic spacer.

"},{"location":"v3_illustrated_install_instructions/#step-11","title":"Step 11","text":"

Install the screws and bolts to secure the fan, it does not matter the orientation of the fan, push or pulling air will result in the same behavior, its personal preference.

"},{"location":"v3_illustrated_install_instructions/#step-12","title":"Step 12","text":"

Insert the fan leads and align Red with positive and Black with negative.

You can damage the fan if installed incorrectly

"},{"location":"v3_illustrated_install_instructions/#step-13","title":"Step 13","text":"

Install the top of the case to the bottom, use the 4 remaining screws to secure the top.

"},{"location":"v3_illustrated_install_instructions/#step-14","title":"Step 14","text":"

Please follow the V3 quick start guide to activate your PiKVM.

"},{"location":"v4/","title":"PiKVM V4 Mini & Plus quickstart guide","text":""},{"location":"v4/#pikvm-v4-mini-plus-quickstart-guide","title":"PiKVM V4 Mini & Plus quickstart guide","text":"

PiKVM is a feature-rich, production-grade, open-source, Raspberry Pi based KVM-over-IP device. It allows you to turn your computer on or off, restart it, configure the UEFI/BIOS, and even reinstall the OS using the Virtual CD-ROM or flash drive.

PiKVM uses your remote keyboard and mouse to simulate a local keyboard, mouse, and monitor, which are then presented in a web browser as if you were working on a remote system directly.

Datasheets:

PiKVM V4 Mini PiKVM V4 Plus

"},{"location":"v4/#whats-in-the-box","title":"What's in the box","text":"
  • PiKVM V4 Mini or Plus device
  • Micro SD card with pre-imaged PiKVM software
  • ATX control board
  • ATX connection cables
  • ATX installation brackets
  • 1 x Ethernet cable
  • 1 x ATX cable
  • 1 x USB C to USB A cable
  • 12V 2A Power Supply (international adapters)
"},{"location":"v4/#interface","title":"Interface","text":"Front viewRear viewRight viewTop view
  1. Power LED (Green)
  2. Power Input 5.1V 3A
  3. Activity LED (Red)
  4. Micro SD card slot
  5. USB 2.0 Serial console port
  6. Serial console active LED / Beacon LED (Green)
  7. RJ45 1Gb Ethernet port
  8. RJ45 Serial console port (V4 Plus only)
  9. USB 3.0 port 1 (V4 Plus only)
  10. Power Input 12V 2A (V4 Plus only)
  1. RJ45 ATX control port
  2. USB 2.0 OTG connector
  3. Beacon LED
  4. Video source ready status LED
  5. HDMI video input port
  6. Video capture ready status LED
  7. Optional antenna mounting hole (only one in V4 Mini)
  8. HDMI video output port 2 (V4 Plus only)
  9. HDMI video output port 1 (V4 Plus only)
  10. USB 3.0 port 2 (V4 Plus only)
  11. Optional antenna mounting hole (only one in V4 Mini)
  1. Service switches
  2. Kensington Security Slot
  1. Display
"},{"location":"v4/#flashing-the-os","title":"Flashing the OS","text":"

Most of the time, this step is not necessary. However, if there is a possibility that your device had a previous owner (e.g. \"Used - Like New\" on Amazon), we recommend reflashing the OS to ensure a clean start. Please follow this guide.

"},{"location":"v4/#wiring","title":"Wiring","text":"

Let's connect all the wires before you power up the device.

"},{"location":"v4/#network","title":"Network","text":"

Connect Ethernet (bottom right on the front side) to the network using the cable from the kit. The kit includes two Ethernet cables of different colors: one for the network, the second for ATX. Use whichever one you like best.

"},{"location":"v4/#hdmi-and-usb-c","title":"HDMI and USB-C","text":"

HDMI input (the bottom right on the rear side) and OTG port (USB emulation) should be connected to the computer.

Optionally, the ATX port can be connected to control the power. There should be no USB hub between PiKVM and the computer, as some UEFI/BIOS cannot detect them at the boot stage.

"},{"location":"v4/#power-up","title":"Power up","text":"

V4 Mini and V4 Plus have different power supplies:

  • The Mini comes with USB-C 5V power supply
  • The Plus comes with with Barrel 12V

The Plus can also work from 5V. In that case, avoid creating a significant power load on USB (external flash sticks, cameras, and so on).

Attach the appropriate connector on the front side. Do not block the ventilation holes on the sides of the device.

After turning on the power, PiKVM OS generates unique SSH keys and certificates and performs all necessary operations on the memory card. It takes a few minutes. Do not turn off the device until it's fully booted for the first time. Once it's done, the PiKVM will show a greeting on the built-in display.

"},{"location":"v4/#connect-and-set-up","title":"Connect and set up","text":""},{"location":"v4/#configure-the-display","title":"Configure the display","text":"

The operating system on your remote computer will treat PiKVM as an additional display and use it in the Extend mode by default. That's why you will see an empty desktop when you first connect.

To avoid that, go to the display settings in your remote computer's operating system and enable the mirror mode for the external screen that your operating system identifies as PiKVM. Refer to your operating system's documentation on that.

"},{"location":"v4/#access-pikvm","title":"Access PiKVM","text":"

By default, PiKVM receives a dynamic IP address via DHCP and shows it in the top row of the OLED display:

192.168.0.26\n(|) iface: eth0\ncpu: 1% mem: 13%\n

Let's assume that PiKVM has received the address 192.168.0.26 and has also been assigned a hostname pikvm.

Type the URL in the browser's address bar and press Enter: https://192.168.0.26/ or https://pikvm/.

Submit the default credentials and click Login:

  • Username: admin
  • Password: admin
  • 2FA Code: disabled by default, skip this field

You will see the initial dashboard screen of the PiKVM, where you can access the remote host, connect to the PiKVM command line, or log out:

"},{"location":"v4/#change-the-default-passwords","title":"Change the default passwords","text":"

For security's sake, it's best to change the default passwords immediately after running PiKVM for the first time.

Passwords are important!

Please ensure that you change both passwords: for Web UI access and for the Linux superuser (root).

To do that:

  1. On the initial dashboard screen, click the Terminal button to open the web terminal. You will see this command line interface:

  2. Gain superuser privileges:

    $ su -\n

    When prompted for a password, use root.

  3. Run rw to change the access to the SD card to the write mode:

    [root@pikvm ~]# rw\n
  4. Change the password for the superuser:

    [root@pikvm ~]# passwd root\n

    Submit the new password, retype it the second time to confirm, press Enter, and you should see this:

    passwd: password updated successfully\n
  5. Change the password for web access:

    [root@pikvm ~]# kvmd-htpasswd set admin\n

    Submit the new password, retype it the second time to confirm, and press Enter.

  6. Run ro to change the access to the SD card back to the read-only mode:

    [root@pikvm ~]# ro\n
  7. Press Ctrl+D or type \"exit\" and press Enter to drop the root privileges.

  8. Go back one page in the browser. You should be back to the initial dashboard screen.

"},{"location":"v4/#access-the-remote-system","title":"Access the remote system","text":"
  1. On the initial dashboard screen, click the KVM button to access the remote host.

  2. You should now see the host system's display and interact with it remotely using a keyboard and a mouse.

"},{"location":"v4/#important-next-steps","title":"Important next steps","text":"
  • We strongly recommend updating the PiKVM OS after the first launch:

    Updating PiKVM OS

    To update, run following commands under the root user:

    [root@pikvm ~]# pikvm-update\n

    If you encounter an error like:

    [root@pikvm ~]# pikvm-update\nbash: pikvm-update: command not found\n

    It's most likely you have an old OS release. You can update the OS as follows:

    [root@pikvm ~]# rw\n[root@pikvm ~]# pacman -Syy\n[root@pikvm ~]# pacman -S pikvm-os-updater\n[root@pikvm ~]# pikvm-update\n

    Next time you will be able to use the usual method with pikvm-update.

  • Learn the basics of PiKVM OS Configuration: where to find configs, how to edit the, etc.

    Configuring PiKVM OS

    Need more info? We have it!

    The following is a brief guide to configuring PiKVM. For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), please refer to this page.

    Most of the PiKVM configuration files are located in the /etc/kvmd directory.

    The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. To redefine system parameters use the file /etc/kvmd/override.yaml. All other files that are also not recommended for editing have read-only permissions.

    You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory to split your customization into logical parts. The override.yaml file definitions takes precedence over the override.d directory.

    A complete list of all parameters can be viewed using the kvmd -m command.

    Files with the *.yaml suffix uses the YAML syntax and describes a parameter tree with key-value pairs of different types. To define the parameters within one section, an indent of 4 spaces is used. Comments starts with the # symbol.

    Only 4 spaces should be used for indentation

    Be careful when editing YAML and follow this rule. Invalid indentation or tabs instead of spaces will cause an error when starting the services.

    Sections under the same keys should be merged:

    • Wrong:

      kvmd:\n    gpio:\n        drivers: ...\nkvmd:\n    gpio:\n        scheme: ...\n
    • Correct:

      kvmd:\n    gpio:\n        drivers: ...\n        scheme: ...\n

    In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

  • Get to know PiKVM Web UI: read this help section to better understand all the possibilities of the web user interface.

  • Set up an ATX connection if you need to control the power of the remote system.

"},{"location":"v4/#further-recommendations","title":"Further recommendations","text":"
  1. Customize the system:

    • Harden the remote access by enabling 2FA.
    • Configure access to PiKVM from the Internet using port forwarding or Tailscale VPN.
    • Enable a microphone for two-way audio.
    • Enable HDMI pass-through and USB passthrough.
    • Learn how configuration files are structured.
    • Read how PiKVM is identified on the target host.
  2. Configure hardware:

    • Install and set up the Wi-Fi antenna:

      Quick WiFi antenna how-to

      The PiKVM V4 has a robust metal case that protects your device from physical damage and electromagnetic interference. This also means that an external antenna must be used for Wi-Fi. We recommend the official Antenna Kit for Raspberry Pi.

      To install the antenna, fix it in the round hole in the back side of the PiKVM, and connect the wire to the connector on the Compute Module 4, as described in the instructions.

      Next, to activate the antenna, add line dtparam=ant2 to the /boot/config.txt file on PiKVM.

      Here is a video:

      Follow this guide to configure Wi-Fi in PiKVM OS.

    • Install and set up LTE/5G modem (only for PiKVM V4 Plus).

    • Set up internal USB port for USB 3.0 (only for PiKVM V4 Plus):

      Enable USB 3.0 on the internal port

      PiKVM V4 Plus has an internal USB port. It supports USB 3.0, but only works with USB 2.0 devices by default to minimize the power consumption. You need to flash the USB controller to enable USB 3.0. To do so, follow these steps:

      1. Open a terminal window and log into the PiKVM via SSH:

        $ ssh user@host\n
      2. Flash the USB controller using the built-in flashrom utility. Choose usb3 for USB 3.0 support:

        [root@pikvm ~]# flashrom-vl805 usb3\n

        If you need to disable USB 3.0 support at any time later, run the same command, but use default instead:

        [root@pikvm ~]# flashrom-vl805 default\n
      3. Perform the soft reboot:

        [root@pikvm ~]# reboot\n
      4. After the soft reboot, perform the reboot by power: unplug and plug again the power cable.

    • Learn about DIP switches:

      DIP switches purpose The left switch [1]: When pulled down (ON state), the advanced backpower protection is used. On the default state is OFF (up), \"diode protection\" is used. This is required for debugging at the request of technical support. Under normal conditions, it is not necessary to change the mode. The right switch [2]: When pulled down (ON state), the Power Delivery chip is activated on the USB OTG port. The default state is OFF (up).

      To change the position of switches:

      1. Turn the PiKVM off.
      2. Change the position of the switched.
      3. Turn the PiKVM on.

      Warning

      Do not do that change the state of the DIP switched while the device is turned on. This may cause irreparable damage.

    • Choose Fahrenheit over Celsius to display on the OLED:

      How to set up Fahrenheit on the OLED

      Create a directory for a configuration file:

      [root@pikvm ~]# mkdir -p /etc/systemd/system/kvmd-oled.service.d\n

      Create file /etc/systemd/system/kvmd-oled.service.d/override.conf:

      [Service]\nExecStart=\nExecStart=/usr/bin/kvmd-oled --clear-on-exit --fahrenheit\n
"},{"location":"v4/#known-issues-and-limitations","title":"Known issues and limitations","text":"
  • There may be compatibility issues with certain motherboards, such as HP or DELL. If there is no image from the BIOS, you can fine-tune the HDMI settings, but it is possible that mass storage devices may not be available in the BIOS. In the latter case, USB dynamic configuration will solve the problem.

  • While the V4 Plus features a Mini-PCIe slot, it was only designed for LTE modems. An NVME card will not work.

"},{"location":"v4/#basic-troubleshooting","title":"Basic troubleshooting","text":"
  • Ensure that you are using the right OS image for your platform by running the following command: pacman -Q | grep kvmd-platform.

  • If you are not getting a display, run the two following commands:

    • dmesg | egrep 'tc35|1-1.4|uvc'
    • systemctl status kvmd-tc358743
"},{"location":"v4/#getting-user-support","title":"Getting user support","text":"

If something doesn't work, check out our FAQ. Otherwise, head straight to our Support.

"},{"location":"video/","title":"Video modes","text":""},{"location":"video/#video-modes","title":"Video modes","text":"

PiKVM V3, V4 Plus/Mini and all DIY devices based on HDMI-CSI bridge provides three video streaming modes. This page explains the key differences between them and helps you to achieve optimal video performance.

The video mode can be switched in the System menu in the Web UI. If you don't see the switch, probably your browser does not support H.264 video.

Quick tips

  • Good network: use WebRTC or Direct mode, set H.264 gop = 0.

  • Bad network and WebRTC mode: Set H.264 gop = 30.

  • Bad network and Direct mode: Set H.264 gop = 0.

  • If the WebRTC mode is not working, try the Direct.

  • The Direct mode doesn't support audio yet. If you need audio, but WebRTC is not working, follow this guide.

"},{"location":"video/#settings","title":"Settings","text":"
  • H.264 kbps (Bitrate) - with a large value, the video quality will be better, but the network traffic will increase.

  • H.264 gop (Group of Pictures) - the number of frames between which a reference frame must be forcibly added. The recommended values are described above.

"},{"location":"video/#webrtc-h264-mode","title":"WebRTC H.264 mode","text":"

This is the default mode. It'is using the efficient H.264 encoding to save traffic. The video is streamed over WebRTC protocol which you may have encountered when you used video calls in Discord or Google Chat. Since WebRTC does not use HTTP for video, establishing a connection is quite tricky (but PiKVM automates 99% of cases). If you have problems with the WebRTC mode, please check this guide.

Advantages / Disadvantages

  • \u2705 Supported by all modern browsers.

  • \u2705 Provides two-way audio on PikVM V3 and V4 Plus/Mini.

  • \u274c The video may be lost due to a poor connection (like mobile internet, bad Wi-Fi, etc.), or because of the router settings, when WebRTC is given low priority.

  • \u274c It may be blocked at all in some networks.

  • \u274c Sometimes the latency may increase slightly due to the peculiarities of WebRTC processing in all browsers.

"},{"location":"video/#direct-h264-mode","title":"Direct H.264 mode","text":"

The new experimental mode for real-time streaming, introduced by PiKVM. It also uses H.264 encoding, but streams the video over regular HTTP (WebSocket).

Advantages / Disadvantages

  • \u2705 Very stable on poor networks, better than WebRTC (based on our tests and user reviews).

  • \u2705 It is not blocked by firewalls because it appears to be regular HTTPS traffic.

  • \u2705 The latency is low and stable too.

  • \u274c No audio support right now (but it will).

  • \u274c Some older browsers doesn't have the WebCodes support needed for this mode.

"},{"location":"video/#legacy-mjpeg-mode","title":"Legacy MJPEG mode","text":"

Good old Motion JPEG. This is the way IP cameras have been streaming videos to browsers since ancient times. The stream is just infinite queue of JPEGs that replace each other in <img> HTML tag. There is no point in using it now if one of the previous modes is working.

Advantages / Disadvantages

  • \u2705 Sometimes the H.264 is disabled in a browser by OS license limitations (for example, in Red Had Linux or Debian). But MJPEG is working always.

  • \u2705 It is not blocked by firewalls because it appears to be regular HTTPS traffic.

  • \u2705 Low latency if you have a good network.

  • \u274c No audio support.

  • \u274c\u274c\u274c Consumes a HUGE amount of traffic. No Wi-Fi, no mobile, nothing but cable connection will work.

"},{"location":"video/#what-if-h264-is-not-supported-by-browser-at-all","title":"What if H.264 is not supported by browser at all","text":"

There are some Linux distro's that require more work to be able to use H.264, this may include any RedHat or Debian variant. Here some examples:

  • In case of Chromium on Fedora, you can connect the RPM Fusion repo and then install the chromium-freeworld package instead of chromium.

  • On Debian GNU/Linux and Firefox, make sure the OpenH264 Plugin both exists and is enabled. Press Ctrl+Shift+A to open the Add-on Manager, then press Plugins. There you should see OpenH264 Video Codec provided by Cisco Systems, Inc. Make sure it is enabled by pressing the \"more options\" button (tree dots), then pressing Always Activate.

"},{"location":"video/#video-recording","title":"Video recording","text":"

At the moment, it is not possible to record videos in a convenient way from the Web UI, but a small trick in the console can be used to record videos without sound. It's only available on all PiKVM models which support H.264 video.

Available since KVMD 4.110

Recording video from terminal on Linux or Mac OS
  1. Install ffmpeg and websocat.

  2. Let's assume that your PiKVM is located on https://pikvm and uses a self-signed certificate. Request the stream from it from the first opened console on your PC (not PiKVM):

    [user@host ~]$ websocat -k wss://pikvm/api/ws?stream=1 -H X-KVMD-User:admin -H X-KVMD-Passwd:admin\n
  3. Keeping the previous command running, open a new terminal and run the video recording process:

    [user@host ~]$ websocat -b -B 10000000 -k wss://pikvm/api/media/ws?video=h264 -H X-KVMD-User:admin -H X-KVMD-Passwd:admin | ffmpeg -use_wallclock_as_timestamps 1 -i pipe: -c:v copy my_captured_video.mp4\n
  4. Same can be done on PiKVM itself, locally.

  5. Press Ctrl+C to stop the recording.

Take a screenshot from terminal on PiKVM

To take a screenshot, switch filesystem to RW-mode like in previous example and run the stream.

Next, take a screenshot:

[root@pikvm ~]# curl --unix-socket /run/kvmd/ustreamer.sock http://localhost/snapshot -o /tmp/screen.jpg\n
"},{"location":"vnc/","title":"VNC","text":""},{"location":"vnc/#vnc","title":"VNC","text":"

As an alternative to the Web UI, a regular VNC client can be used to access to the PiKVM.

The main advantage of VNC over the browser is the ability to expand the image to the full screen, as well as complete interception of all keyboard shortcuts. In some cases, VNC will be more responsive than the browser, especially on weak client computers.

Warning

Don't use VNC without X.509 or TLS encryption on untrusted networks! Otherwise your password will be transmitted over the network in plain text. Unfortunately, this is the reality of the VNC protocol.

Note

The performance of VNC on PiKVM does not make sense to compare with regular VNC servers or a similar remote access tool at the OS level. PiKVM will run a little slower due to the fact that access is done at the hardware level.

A typical video processing chain looks like this:

  • Regular VNC/RDP/TeamViewer/Etc: OS -> Remote access server -> Network -> Client.
  • PiKVM: OS -> Video card -> PiKVM video capture -> PiKVM server -> Network -> Client.
"},{"location":"vnc/#enabling-vnc-on-the-pikvm-side","title":"Enabling VNC on the PiKVM side","text":"
  1. The recommended client is TigerVNC.

  2. Switch the PiKVM filesystem to read-write mode using command rw.

  3. Optional for non-TigerVNC clients: Change the keybobard layout for non-US keyboard

    This step is nessessory if you're using a client that does not support the direct keyboard access.

    In this case you can force the client layout in /etc/kvmd/override.yaml:

    vnc:\n    keymap: /usr/share/kvmd/keymaps/ru\n

    All available keymaps are located in /usr/share/kvmd/keymaps:

  4. Optional for non-TigerVNC and NOT RECOMMENDED: Enable VNCAuth method

    This step is nessessory if you're using a client that does not support the user/password auth method like TightVNC (don't confuse it with TigerVNC).

    In this case you can enable VNCAuth passphrases mode in /etc/kvmd/override.yaml:

    vnc:\n    auth:\n        vncauth:\n            enabled: true\n

    To set passphrases edit the file /etc/kvmd/vncpasswd.

    But once again: THIS IS AN UNSAFE AUTHORIZATION METHOD and it is better to use TigerVNC.

  5. Enable kvmd-vnc daemon. VNC will be available on the port 5900: systemctl enable --now kvmd-vnc.

  6. Switch filesystem back to read-only: ro.

Note

With enabled 2FA, you will need to append the one-time code to the password without spaces. That is, if the password is foobar and the code is 123456, then the string foobar123456 should be used as a password.

"},{"location":"vnc/#configuring-the-client","title":"Configuring the client","text":"

We recommend TigerVNC for a better experience on a desktop.

If you're using PiKVM V3+ or DIY based on CSI bridge, you can try the latest version (>= 1.13.0) of TigerVNC with H.264 support. It will improve performance and save traffic.

H.264 video mode is available in binary builds for Windows, for other OS it needs to be compiled manually (ffmpeg libraries required to build).

Here are our recommended settings for TigerVNC:

Compression tab Security tab If your client does not support H.264, choose Tight

For iOS and Android the recommended application is bVNC:

  • Google Play
  • App Store
"},{"location":"vnc/#hotkeys","title":"Hotkeys","text":"

Inside a VNC session, you can use several hotkeys related to PiKVM, independent of the VNC client. Hotkeys are triggered by quickly pressing and releasing each key sequentially (that is, you don't need to hold them down like Ctrl+Alt+Del).

  • LeftAlt, LeftAlt, P - Paste text from the clipboard. PiKVM does not have access to the clipboard, so pasting works as if you had typed this text. ASCII always works, layout switching is not supported. To type text in a different language, you need the layout on the host to match the one you are using (and keymap is also configured as described above for some VNC clients)

  • LeftAlt, LeftAlt, 1 (1-8) - Switch to channel 1 with PiKVM Switch, when you have one or two switches.

  • LeftAlt, LeftAlt, 3, 2 - Switch to unit 3, channel 2 of PiKVM Switch chain, when you have more than two switches. Single-key port numbers do not work if there are more than two candles.

"},{"location":"vnc/#unsupported-clients","title":"Unsupported clients","text":"
  • RealVNC - Does not support most widely used open VNC protocol extensions.
  • Remmina - Slightly imperfect algorithms for matching settings with the server, we are working on it.
  • Guacamole - Incorrectly implements vencrypt, no JPEG compression.
  • Vinagre - Incorrectly implements vencrypt, dead.
"},{"location":"webrtc_config/","title":"WebRTC H.264","text":""},{"location":"webrtc_config/#webrtc-h264","title":"WebRTC H.264","text":"

This is the default mode. It'is using the efficient H.264 encoding to save traffic. The video is streamed over WebRTC protocol which you may have encountered when you used video calls in Discord or Google Chat.

It is available on PiKVM V3, V4 Plus/Mini and all DIYdevices based on HDMI-CSI bridge.

The video mode can be switched in the System menu in the Web UI. If you don't see the switch, probably your browser does not support H.264 video.

"},{"location":"webrtc_config/#how-its-working","title":"How it's working","text":"

The Direct H.264 or MJPEG video is streaming video using the similar HTTP connection like to get the Web UI. This means that for remote access, you just need to forward only ports 80 and 443 on your router it has public external IP address.

In contrast, WebRTC is a completely different way of transmitting video. It uses a P2P connection and UDP. This reduces network load, but makes it difficult to connect\u2014the PiKVM needs to know your network configuration in order to use it correctly: public IP, NAT type and so on.

To achieve this, the PiKVM checks which of the network interfaces is used for the default gateway, and tries to find out your external IP address using the Google STUN server.

Tip

Google STUN servers was choosen for reliability reasons.

If you don't want to use it, you can choose any other public STUN server you like, or set up your own.

To change the STUN server, edit /etc/kvmd/override.yaml (an example):

janus:\n    stun:\n        host: stun.stunprotocol.org\n        port: 3478\n

... and restart kvmd-janus service using systemctl restart kvmd-janus.

"},{"location":"webrtc_config/#custom-janus-config","title":"Custom Janus config","text":"

Janus is a WebRTC gateway that is used to transmit the video from PiKVM uStreamer. PiKVM has a special service named kvmd-janus which is a wrapper for Janus that monitors the network configuration and applies changes.

However, if your PiKVM is not connected to the Internet and/or you want to use a custom Janus configuration, you should run the kvmd-janus-static service instead.

The configuration is located in /etc/kvmd/janus/janus.jcfg. You can change all you need according to the Janus Documentation, stop the kvmd-janus and start the kvmd-janus-static service:

[root@pikvm ~]# systemctl disable --now kvmd-janus\n[root@pikvm ~]# systemctl enable --now kvmd-janus-static\n
"},{"location":"webrtc_config/#troubleshooting","title":"Troubleshooting","text":"

In some cases, WebRTC may not work. Here some common tips:

  • Clear the browser cache.

  • Try any other browser, incognito or private window without any extensions.

  • Tricky IPv6 configuration on the network can be a problem. IPv6 support for WebRTC in PiKVM is still in its infancy, so if your network has IPv4, it will be easiest to disable IPv6 on PiKVM. To do this, switch the file system to write mode using rw command, add option ipv6.disable_ipv6=1 to /boot/cmdline.txt and perform reboot. Also see here.

  • A paranoid firewall can interfere too when you try to connect to the PiKVM by forwarding port 443 to the Internet from the internal network. WebRTC is not enough of this, it uses UDP on ports 20000-40000 for a P2P connection. Make sure that the Firewall does not block them.

  • If nothing helps, open the browser's JavaScript console, look at the log and contact our Support. Developers and/or experienced users will definitely help you.

"},{"location":"webui/","title":"Getting to know the web UI","text":""},{"location":"webui/#logging-in","title":"Logging in","text":"

After following the first steps document on setup, you will be presented with the following pages (Chrome is being used in the following examples)

Click Advanced

Click Proceed

Credentials are found in the first steps document that is located to the left

This is where you fill in the login credentials, please be sure to review the first steps document first. This is also where you configure the 2FA token.

"},{"location":"webui/#initial-screen","title":"Initial screen","text":"Please expand to see what each number represents
  1. This is where your PiKVM name will go - Please reference the first steps document on how to change this
  2. This is where you can access the display for the Target system
  3. You can open a web terminal and put in commands that you will find within these documents
  4. By default this will not show up till its activated, this will tell you the VNC address you need to use
  5. This is so you can logout of your PiKVM
  6. Please read carefully
  7. These are links to the PiKVM project, current documentation and support
  8. NOT SHOWN, in the lower left of the KVM screen is some information that when you mouse over, will let you know what they are for
"},{"location":"webui/#web-ui-toolbar","title":"Web UI toolbar","text":"Please expand to see what each number represents
  1. This is the system setting, more details will be shown below
  2. This is the interface to controlling the ATX, will ONLY work if wired up correctly
  3. This is part of the MSD and will show you what images/iso's are available
  4. This is where you can program in a Macro (Ex. Hitting F2 to get into the bios, setting Infinite loop playback to on and doing other tasks)
  5. This is where you can SEND text to the Target or using OCR, you can copy FROM the target, be mindful that OCR can make mistakes, please review before finalizing
  6. This is where you can find most Shortcuts (Windows only, for now) (Not editable)
  7. This is placed here to give you an idea what you can achieve if you make your own menu item
"},{"location":"webui/#the-system-menu","title":"The System menu","text":"

The following is self explanatory but will highlight the important parts

Please expand to see what each number represents
  1. System Icons

    ETH Icon = PiKVM network connectivity

    Monitor Icon = Shows if the target is sending an active signal

    KeyBoard Icon = Shows if data for the KB is active, will likely show Orange/Green as data is passed and goes idle

    Mouse Icon = Same as above

  2. These are additional buttons for important acitivies

    Term = Can launch a quick Web Terminal along with the active KVM

    About = Shows everything About your PiKVM, including PiKVM Hardware and version

    Log = Shows the current log from your PiKVM

  3. ONLY for MJPEG mode

  4. ONLY for H.264 (WebRTC) mode
"},{"location":"webui/#the-atx-menu","title":"The ATX menu","text":"

This ONLY works if you have the hardware connected to the MB, otherwise will not work

"},{"location":"webui/#the-drive-menu","title":"The Drive menu","text":"

This is where you can select the IMG or ISO's that are stored

"},{"location":"webui/#the-macro-menu","title":"The Macro menu","text":"
  1. Please read and understand this section
  2. This is where you can upload or download your scripts
"},{"location":"webui/#the-text-menu","title":"The Text menu","text":"

Note

This is not like VNC/AnyDesk/TeamViewer as these are software solutions, this is a hardware solution therefor cannot change the behavior of the target system. This does not act like a clipboard

  1. This will allow you to paste text to the target system\u2014be mindful whats being pasted to the target and how.

  2. This will allow you to ONLY copy text from the target\u2014be mindful that OCR will do its best to recognize text but may fail at it.

"},{"location":"webui/#the-shortcuts-menu","title":"The Shortcuts menu","text":"

This is an expanded view and shows the shortcuts mostly for Windows.

"},{"location":"wifi/","title":"Setting up Wi-Fi","text":"

Tip

  • There is nothing more reliable than wired Ethernet, so it's better to use it. Wi-Fi with the steel case (on PiKVM V3 and V4) results in poor performance. But who are we to stop you... :)
  • Devices based on Raspberry Pi Zero 2 W does not support 5GHz Wi-Fi.

The following describes how to setup a Wi-Fi connection. We recommend to do this while having a display and keyboard or a serial console connected directly to the Raspberry Pi as you will loose network connectivity once you connect to a Wi-Fi. Alternatively you can connect to the PiKVM via SSH. The built-in Web Terminal (available through the browser) should also work.

Take a look at the easiest way

This guide describes how to manually set up a Wi-Fi. An easier way is to use On-boot config. It is also mandatory for Zero 2 W board.

"},{"location":"wifi/#setting-up-wi-fi-manually","title":"Setting up Wi-Fi manually","text":"
  1. Make filesystem writable using the rw command.

  2. Create the Wi-Fi settings file /etc/systemd/network/wlan0.network with the following content:

    [Match]\nName=wlan0\n\n[Network]\nDHCP=yes\nDNSSEC=no\n\n[DHCP]\nClientIdentifier=mac\nRouteMetric=50\n
  3. Set network ESSID and password:

    [root@pikvm ~]# wpa_passphrase 'MyNetwork' 'P@assw0rd' > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf\n[root@pikvm ~]# chmod 640 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf\n

    WPA2 and WPA3 support

    Add options key_mgmt=WPA-PSK-SHA256 WPA-PSK and ieee80211w=1 to /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

    Using Wi-Fi with hidden ESSID

    Add option scan_ssid=1 to /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

    Using 5GHz Wi-Fi in the USA

    Add option country=US to /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

    Block 2ghz or 5ghz

    Add option bssid=xx:xx:xx:xx:xx:xx to /etc/wpa_supplicant/wpa_supplicant-wlan0.conf within the network={ block

  4. Enable WPA-supplicant service:

[root@pikvm ~]# systemctl enable wpa_supplicant@wlan0.service\n
  1. Make filesystem read-only again using ro command
"},{"location":"wifi/#multiple-wi-fi-networks","title":"Multiple Wi-Fi networks","text":"

You can configure PiKVM to connect to one of several known Wi-Fi networks. To do this, just simply add the configuration of these networks. Pay attention to the symbol >>, it is used to append at the end of configuration, while a single > will overwrite the entire configuration.

  1. Make the filesystem writeble with rw command.

  2. Add some new networks:

    [root@pikvm ~]# wpa_passphrase 'Wifi1' 'P@assw0rd' >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf\n[root@pikvm ~]# wpa_passphrase 'Wifi2' 'P@assw0rd' >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf\n[root@pikvm ~]# wpa_passphrase 'Wifi3' 'P@assw0rd' >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf\n
  3. Restart the service: systemctl restart wpa_supplicant@wlan0.service.

  4. Make the filesystem read-only again using ro command

"},{"location":"wifi/#useful-console-commands","title":"Useful console commands","text":"
  • iwconfig - Manipulate the basic wireless parameters.
  • iwlist - Allow's you to initiate scanning and list frequencies, bit-rates, encryption keys, etc.
  • iwspy - Displays per node link quality.
  • iwpriv - Allow's you to manipulate the Wireless Extensions specific to a driver (private).
Some examples
[root@pikvm ~]# iw dev wlan0 scan | egrep \"signal:|SSID:\" | sed -e \"s/\\tsignal: //\" -e \"s/\\tSSID: //\" | awk '{ORS = (NR % 2 == 0)? \"\\n\" : \" \"; print}' | sort\n
[root@pikvm ~]# iwlist wlan0 scan | egrep \"Cell|ESSID|Signal|Rates\"\n
[root@pikvm ~]# iwlist wlan0 scan\n
[root@pikvm ~]# iw wlan0 info\n
"},{"location":"wifi/#additional-resources","title":"Additional resources","text":"
  • Arch Linux Wiki for systemd-networkd
"},{"location":"wiring_examples/","title":"Some example wiring setups","text":""},{"location":"wiring_examples/#hdmi-csi","title":"HDMI-CSI","text":"

List of items: (WARNING! Links may dissappear or no longer work, this just gives you an idea)

  • USB-A male to USB-A male (For data)
  • PortaPow USB Power Blocker
  • USB C OTG Splitter
  • Normal HDMI Cable
  • DisplayPort TO HDMI pigtail (Cable) (Pic is displayed wrong)
  • TARGET (Anything you want to control)
"},{"location":"wiring_examples/#another-csi-example-using-the-pcb-splitter","title":"Another CSI example using the PCB splitter","text":""},{"location":"wiring_examples/#hdmi-usb","title":"HDMI-USB","text":""},{"location":"wiring_examples/#direct-connect-to-target","title":"Direct connect to target","text":"

Explanation of pic - USB-C from PI to USB-A onto target which also powers the PI

Use case: - Trying to determine if the data cable is truly a data cable and not just a power cable - Testing to see if the splitter or cable is defective - Basic troubleshooting

"},{"location":"wiring_examples/#ezcoo-wiring-example","title":"EZCOO wiring example","text":""},{"location":"wol/","title":"Wake-on-LAN","text":""},{"location":"wol/#wake-on-lan","title":"Wake-on-LAN","text":""},{"location":"wol/#simplified-method-one-host","title":"Simplified method (one host)","text":"

To use Wake-on-LAN with your server you must define some options such as the server's MAC address and (optionally) IP address. Use /etc/kvmd/override.yaml. The format is:

kvmd:\n    wol:\n        mac: ff:ff:ff:ff:ff:ff\n

Replace ff:ff:ff:ff:ff:ff with the MAC of your server. By default, a packet is sent via a broadcast request to the entire IPv4 network (255.255.255.255, port 9), but you can address it to a specific static address:

kvmd:\n    wol:\n        mac: ff:ff:ff:ff:ff:ff\n        ip: 192.168.0.100\n        # port: 9  # By default\n

... then restart kvmd using systemctl restart kvmd. It will now show up in the system button in the upper right corner.

"},{"location":"wol/#gpio-method-multiple-hosts","title":"GPIO method (multiple hosts)","text":"

Follow the manual for building the GPIO menu and use the wol driver to build a menu with many buttons tied to different hosts.

"},{"location":"xh_hk4401/","title":"XH-HK4401 4-port HDMI USB KVM Switch","text":""},{"location":"xh_hk4401/#xh-hk4401-4-port-hdmi-usb-kvm-switch","title":"XH-HK4401 4-port HDMI USB KVM Switch","text":"

This document was supplied by a community member, thus it is not officially endorsed or supported.

PiKVM + Multiport Switches compatibility

Please note that this switch requires a USB port for control. The following devices can provide this:

  • PiKVM V3 & V4 Plus.
  • DIY devices based on Raspberry Pi 2, 3 and 4.

The following devices are not compatible:

  • PiKVM V4 Mini - it doesn't have a USB host port and cannot control switches, it's a single-host device.
  • DIY based on Raspberry Pi Zero 2 W - it doesn't have USB host port too.

This KVM is sold under many names, and comes in two versions. The only way these two versions differ is that one has one of its USB ports replaced with a PS/2 port. The identifying feature is that they come with a small external control unit with 4 buttons. This controller is connected to the main KVM via a micro USB cable, however this is NOT as USB connection.

Warning

Audio was not tested, it is assumed to be non-functional

"},{"location":"xh_hk4401/#connections","title":"Connections","text":"
  1. Connect the USB-A cable from the Raspberry Pi OTG port to to any of the USB ports on the XH-HK4401 switch. All 3/4 USB ports work exactly the same, internally they are just connected to a USB HUB.

  2. Connect the HDMI out from the XH-HK4401 switch to the Raspberry Pi CSI-2 to HDMI input.

  3. Connect host USB and HDMI cables from the XH-HK4401 switch to the machines to be managed per the switch instructions.

  4. Finally see below for details about connecting to the control micro USB port. This it not a normal USB micro port.

Warning

There is a limitation in the underlying PiKVM software related to plugging video cables from a host which is already powered and connected to a monitor to a Raspberry Pi HDMI-CSI bridge. These limitations apply equally when using the XH-HK4401 KVM switch. If video is not present in PiKVM, try keeping all host machines off and connecting them directly to the XH-HK4401 switch before powering the hosts on.

"},{"location":"xh_hk4401/#rs-232-control-cable","title":"RS-232 control cable","text":"

The control unit communicates to the KVM using the RS-232 protocol (at 5v) not USB, and one of the following solutions must be used.

"},{"location":"xh_hk4401/#inverting-usb-uart-adapter-ft-232-the-easy-way","title":"Inverting USB UART adapter (FT-232) - The easy way","text":"

Some USB UART adapters have the rare feature to invert the logic level of the RX/TX signals. For example the FTDI FT232 can be configured via the FTDI configuration GUI to do this. With such an adapter, the circuit above is not required. All you need is to connect it to a micro-USB connector.

Warning

These options will only work on UART adapters with genuine FTDI chips. There are a lot of cheap fakes on the market that either lack this option, or will prevent you from changing the settings. To avoid getting a fake ensure you always purchase from a reputable store and brand (Adafruit, Sparkfun, etc.), Amazon is not a reputable store.

"},{"location":"xh_hk4401/#linux-instructions","title":"Linux Instructions","text":"References I used to get my FTDIs working:
  • https://waterpigs.co.uk/articles/ftdi-configure-mac-linux/
  • https://manpages.debian.org/testing/ftdi-eeprom/ftdi_eeprom.1.en.html
  • https://manpages.ubuntu.com/manpages/bionic/man1/ftdi_eeprom.1.html
  • http://developer.intra2net.com/git/?p=libftdi;a=blob;f=src/ftdi.h
  • http://developer.intra2net.com/git/?p=libftdi;a=blob;f=src/ftdi.c
  • http://developer.intra2net.com/git/?p=libftdi;a=tree;f=ftdi_eeprom
  • http://developer.intra2net.com/git/?p=libftdi;a=blob;f=ftdi_eeprom/example.conf
  • http://developer.intra2net.com/git/?p=libftdi;a=blob;f=ftdi_eeprom/main.c

Warning

Steps were performed on Debian-like installation (Pop!_OS 21.10)

This workflow has worked for a self-described NON-genuine FTDI FT232RL chip. The other MAY be genuine, but it is also working.

Neither of the following FTDI UART adapters are recommended. Purchasing both chips was an error (only 1 intended). However, having two (potentially non-genuine) FTDI UART adapters helped to create these instructions.

  • Possibly genuine, but working regardless, (DSD TECH) FTDI

  • Not genuine (HiLetGo) FTDI

Warning

The HiLetGo UART adapter comes with a USB MINI female connector and necessitates another adapter/cable for interfacing with the Pi.

  1. Get info from FTDI
    • Plug the FTDI into a USB port on your Linux device and run lsusb to verify that the device is found
      lsusb\n
    • Ensure the device is recognized as FTDI
      sudo lshw | grep -B 10 ftdi\n
    • Record hardware information (not sure if needed, but was saved to prevent overwriting critical data in the EEPROM)
  2. Blacklist ftdi_sio kernel module
    • The kernel module ==ftdi_sio== is currently enabled (and how you saw the device in the previous step). We need to disable this module to read/write to the EEPROM.
    • The following command creates a file to blacklist the ==ftdi_sio== module.
      echo \"blacklist ftdi_sio\" | sudo tee /etc/modprobe.d/bl-ftdi.conf > /dev/null\n
  3. Reboot machine
    • We need to reboot into an environment without ftdi_sio active.
      shutdown -r 0\n
  4. Install ftdi_eeprom if not already installed
    • Install ==ftdi_eeprom== with the following command.
      sudo apt install ftdi_eeprom\n
  5. Make a folder to work from and change it to our working directory
    mkdir ./ftdi_config\ncd ./ftdi_config\n
  6. Create a valid FTDI configuration file for ftdi_eeprom consumption
    • The below command (copy/paste all lines) will create a valid configuration file. Change parameters as required.
      tee ./ftdi.conf > /dev/null <<EOF\nfilename=eeprom.bin\nvendor_id=0x0403\nproduct_id=0x6001\nmanufacturer=\"FTDI\"\nproduct=\"FT232 Serial (UART)\"\nserial=\"SERIAL\"\nuse_serial=true\nmax_power=500\nself_powered=false\ninvert_txd=true\ninvert_rxd=true\ncha_type=\"UART\"\nEOF\n
    • This configuration is trimmed from the example due to size of the EEPROM on the FTDIs used.
    • The example configuration at ==/usr/share/doc/ftdi-eeprom/example.conf== describes possible configuration options for the FTDI and is well-documented.
    • The above configuration worked for the mentioned devices. The ==filename==, ==vendor_id==, ==product_id==, ==invert_txd==, and ==invert_rxd== variables are required. The others might not be, but seemed applicable.
    • If you're using a different FTDI chip than used here, please update that in the above configuration. Ensure that vendor_id and product_id are what was obtained from the output of the initial lsusb command.
    • ==max_power==, ==serial==, and ==product== were updated to reflect the output of the initial lshw. These updates may not be required and were done to avoid overwriting anything important. ==cha_type== was updated to ==UART== where both of the devices were originally designated as FIFO.
  7. Test the configuration and read the eeprom initially before flashing
    • Read the EEPROM with the following command
      sudo ftdi_eeprom --read-eeprom ./ftdi.conf\n
    • If you get an error here, there's something wrong with your configuration. Check that the device is properly identified and try again.
  8. Rename/preserve and review the contents of the binary read from the EEPROM
    • First, rename the output binary file so we don't overwrite it when we flash (flashing writes the flashed binary to the ==filename== path)
      mv ./eeprom.bin ./original_eeprom.bin\n
    • Then, display the outputs of the binary
      hexdump -C original_eeprom.bin\n
    • You can rename the binary in the configuration file by editing the ==filename== variable. If you can't be bothered to edit the file, rename it as detailed above.
  9. Flash the configuration
    • Run the following command to flash the EEPROM of the FTDI
      sudo ftdi_eeprom --flash-eeprom ./ftdi.conf\n
    • Optional: compare the flashed configuration to the initial configuration with the below command. If there is no output, the files are the same. You will likely need to re-flash.
      diff <(xxd original_eeprom.bin) <(xxd eeprom.bin)\n
    • Alternatively, you can manually compare the files by running hexdump -C original_eeprom.bin and hexdump -C eeprom.bin
  10. Your FTDI should be flashed and working to control the KVM!
    • Plug it into one of the Pi's USB slots (if not already), and it's good to go.
    • The KVM will sink power from the FTDI (Pi) if Vcc is connected. If Vcc is disconnected, ensure that grounds between the Pi and KVM are tied.
  11. Clean up the ftdi blacklist to reenable the ftdi_sio module
    • Comment out the line but leave the file with the following command:
      sudo sed -i 's/blacklist ftdi_sio/#blacklist ftdi_sio/g' /etc/modprobe.d/bl-ftdi.conf\n
    • If you'd need to read/flash FTDI EEPROM in the future, you can use the following command (followed by a reboot) to blacklist the ==ftdi_sio== module again.
      sudo sed -i 's/#blacklist ftdi_sio/blacklist ftdi_sio/g' /etc/modprobe.d/bl-ftdi.conf\n
    • If you want to wash your hands of FTDI flashing, then delete the blacklist file with the following command:
      sudo rm /etc/modprobe.d/bl-ftdi.conf\n
  12. Reboot the machine to reset to initial state (with ftdi_sio loaded)
    • ==ftdi_sio== should reload as the driver, and the FTDI should be able to be seen with lshw / dmesg once again. If you tried to run either command while ==ftdi_sio== was blacklisted, you probably would have come up empty.
"},{"location":"xh_hk4401/#windows-instructions","title":"Windows Instructions","text":"

In order to invert the RX/TX signals, you can use ft_prog and set the following settings:

Once the UART is configured, please fully disconnect it and connect it back to the computer. Relaunch ft_prog and ensure the settings are still set. If they are not, you have a fake FTDI chip.

"},{"location":"xh_hk4401/#ftdi-terminal-configuration","title":"FTDI Terminal Configuration","text":"

Finally, you will need to connect it to the micro USB port (This it not a normal USB micro port.) like so:

Signal Colour FT232 Pin Vbus Red 5v (if you want to power the KVM from the Pi's USB) D- White RX D+ Green TX Gnd Black GND"},{"location":"xh_hk4401/#an-inverter-circuit-the-cheap-way","title":"An inverter circuit - The cheap way","text":"

For this you will need:

  • 1x 74HC14
  • 1x USB A socket, or sacrificial micro USB cable
  • Optional 1x Diode - If you want to power the KVM from the Raspberry Pi
  • 1x 5-pin header
  • 5x Female - Female jumper cables

Note

Please search online for USB pinouts to ensure you connect it properly.

"},{"location":"xh_hk4401/#adding-ui-elements-to-control-the-kvm-switch","title":"Adding UI elements to control the KVM switch","text":"

The UI can be updated to add buttons to switch between KVM inputs and indicators for which input is currently selected. The instructions below will make these available in the PiKVM UI after clicking the \"GPIO\" menu button in the KVM view.

  1. SSH into PiKVM

  2. Enable read-write mode on the sd card via rw

  3. Edit the /etc/kvmd/override.yaml file and include the following.

Method Device FT-232 /dev/ttyUSB0 Inverter /dev/ttyAMA0
kvmd:\n    gpio:\n        drivers:\n            hk:\n                type: xh_hk4401\n                device: /dev/ttyUSB0\n        scheme:\n            ch0_led:\n                driver: hk\n                pin: 0\n                mode: input\n            ch1_led:\n                driver: hk\n                pin: 1\n                mode: input\n            ch2_led:\n                driver: hk\n                pin: 2\n                mode: input\n            ch3_led:\n                driver: hk\n                pin: 3\n                mode: input\n            ch0_button:\n                driver: hk\n                pin: 0\n                mode: output\n                switch: false\n            ch1_button:\n                driver: hk\n                pin: 1\n                mode: output\n                switch: false\n            ch2_button:\n                driver: hk\n                pin: 2\n                mode: output\n                switch: false\n            ch3_button:\n                driver: hk\n                pin: 3\n                mode: output\n                switch: false\n        view:\n            table:\n                - [\"#Input 1\", ch0_led, ch0_button]\n                - [\"#Input 2\", ch1_led, ch1_button]\n                - [\"#Input 3\", ch2_led, ch2_button]\n                - [\"#Input 4\", ch3_led, ch3_button]\n
  1. Return to read-only mode for the sd card via ro

  2. Restart the kvmd service: systemctl restart kvmd

"},{"location":"xh_hk4401/#switching-between-hosts-in-the-ui","title":"Switching between hosts in the UI","text":"

To switch between hosts, enter the KVM UI and click the \"GPIO\" menu. You should see 4 inputs, one of which will have a green circle indicating it is currently selected. Click the other inputs to change the selected host.

Please review this latest issue for an update to the existing instructions

"},{"location":"blog/","title":"Blog","text":""},{"location":"blog/#blog","title":"Blog","text":"

Welcome to the PiKVM Blog. Here you'll find updates, tutorials, release notes, and insights into KVM-over-IP development.

"},{"location":"blog/2020/06/01/kvmd-1-65-vnc-improvements-and-new-api/","title":"KVMD 1.65: VNC improvements and new API","text":"

What time is it? Release time! Meet the new version of KVMD: 1.65

  • If you haven't updated to previous intermediate builds, this release will provide many VNC improvements: for example, you can now insert text from the client to the server. In addition, we fixed an annoying bug related to interrupting the broadcast when it is impossible to resume it without restarting the server.

  • A new API was added for inserting text with the ability to select the keyboard layout of the target computer. For example: curl -k -X POST -H 'Content-Type: text/plain' -H 'X-KVMD-User: admin' -H 'X-KVMD-Passwd: admin' --data \"some text\" https://pikvm/api/hid/print?keymap=en-us. To get a list of supported layouts, use /api/hid/keymaps. You can change the default layout in the settings using /etc/kvmd/override.yaml like this:

kvmd:\n    hid:\n        keymap: /usr/share/kvmd/keymaps/en-gb\n

This does not currently affect the virtual keyboard in the web interface, but this issue will be resolved in the future. Also please note that language switching is not supported yet.

  • Extended API for getting screenshots and previewing screenshots: /api/streamer/snapshot. The last screenshot can be saved in the memory of the KVM. Unfortunately, we have not yet reached the stage of drawing up detailed documentation, so you can find the full list of parameters in the sources: https://github.com/pikvm/kvmd/blob/master/kvmd/apps/kvmd/api/streamer.py#L57

  • A large refactoring of internal libraries has been carried out, so that now it is easier to add an alternative protocol for communication with KVM, such as RDP.

  • Work has been carried out to improve security. No vulnerabilities were found in the process, but the added additional checks will help me avoid them in the future.

And this is the first release in which I included a list of all those who decided to support the Pi-KVM project. Just as I promised. Thank you again to all these kind people. You make the world of open source a better place and help me survive \ud83d\ude04

To update use rw; pacman -Syu; reboot. If pacman will report a problem with kernel dependencies, you will need to add them to IgnorePkg in /etc/pacman.conf. Find the IgnorePkg string, uncomment it, and add two packages that pacman swore at, like IgnorePkg = linux-raspberrypi linux-raspberrypi-headers for zero or IgnorePkg = linux-raspberrypi4 linux-raspberrypi4-headers. After that re-run pacman -Syu again and reboot.

"},{"location":"blog/2020/06/08/kvmd-1-67-numpad-support/","title":"KVMD 1.67: NumPad support","text":"

We added NumPad support, including for configurations with Arduino HID.

The Arduino firmware is backward compatible so nothing will break if you don't update it, but it's still worth rewiring your device. You can find out how to do this in the user's guide: https://github.com/pikvm/pikvm.

KVM on the basis of the ZeroW parameter and RPi4 will receive support NumPad once after upgrading and rebooting.NumPad also works in VNC, but the keys are not represented in the web interface, because there is no space for them now. I'm saving this issue for the future when I'm improving the UI.

For Arduino HID, communication logging over the serial port has been reworked, so that the log shows fewer unimportant connection errors. The logic there is quite complex, and although I have checked everything ten times, please let me know if there are any problems with the Arduino.

IPMI and VNC logs are made slightly more readable. The IPMI log shows the IP address of the client from which the request was sent.

This release also includes improvements to the About window of the web interface, which now shows more information about the system.

To update:

rw\npacman -Syu\nreboot\n

If you have problems installing packages, see the previous news.

PS: The situation with the new kernel has become a little clearer. Another bug that I found has been fixed, so there is a chance for a quick system update. In the meantime, we'll continue enjoying the stability of the 4.x branch

"},{"location":"blog/2020/06/20/kvmd-1-71-vnc-improvements/","title":"KVMD 1.71: Improved IPMI server","text":"

The new version comes with two improvements.

First off, we improved the IPMI server. The ipmiutil health command is now supported.

Secondly, in the web interface, you can now record a macro of your keyboard and mouse actions on the server, save it, and play it back.

This is convenient if you need to perform a sequence of similar actions. The downloaded macro has a convenient json format, so you can independently write scripts with macros in any convenient language to play them remotely.

For example, this is a Python script that plays a macro on the specified PiKVM.

"},{"location":"blog/2020/07/17/kvmd-1-75-hardware-health-monitoring/","title":"KVMD 1.75: Hardware health monitoring","text":"

Today's big release KVMD 1.75 includes several important features.

1) Hardware health monitoring. If your Pi-KVM suffers from overheating or lack of power, you will see the corresponding icons and messages in the interface. Don't ignore them! The problems, if any, are not caused by the update, they have always been there, but you have not seen them before, because they were hidden in the kernel logs.

2) Partially fixed an issue with the jumping stream quality slider in the Web UI. This is sometimes found on FireFox. The slider still jumps, but it doesn't lose your settings.

3) Hand-written HTML has finally been eradicated in favor of Pug templates (here is one example. Future commiters will find it easier to live.

4) Reworked streamer settings\u2014preparing for official support of the USB-HDMI dongle. Since it does not know how to adjust the stream quality and determine resolutions, the corresponding submenus will be and added to the Web UI.

5) Fixed a bug that caused the mouse to work incorrectly on the Arduino HID. Update the firmware (see https://github.com/pikvm/pikvm).

6) Added a handler for the Power key, which is sometimes found on the keyboard. There is no such button in the interface (yet?) it is not necessary, but if necessary, you can call it via the websocket API.

"},{"location":"blog/2020/07/23/kvmd-1-78-vnc-improvements/","title":"KVMD 1.78: VNC improvements","text":"

Two important VNC improvements: client connections that have hung up are now terminated correctly using TCP_KEEPALIVE; applying the TCP_NODELAY parameter slightly improved responsiveness.

  • Improved compatibility with FireFox.

  • Minor fixes and codebase cleanup.

This release also updated the list of project sponsors, who donated via Patreon (https://patreon.com/pikvm) or PayPal (https://www.paypal.me/mdevaev). The names of these good people are forever immortalized on the project page and in the web interface in the About window.

Thanks to them, I was able to buy a couple of new devices, support for which will appear in one of the next releases of Pi-KVM, and also bought food for my cat!

"},{"location":"blog/2020/07/26/kvmd-1-82-hdmi-usb-dongle-support/","title":"KVMD 1.82: HDMI-USB dongle support","text":"

The main change is to add support for an HDMI-USB dongle out of the box.

For the dongle, the quality settings option was removed from the interface (does not supported by the device) and dropdown was added with manual resolution selection.

The best way to use a dongle is to rebuild the operating system with PLATFORM=v2-hdmiusb. This way you will get a configuration that can be easily updated. The use of HDMI-CSI bridge and USB dongle is also available for RPi and RPi3 (with Arduino HID).

Please note that the video capture device is linked to a strictly defined USB port. This is necessary so that the OS does not confuse the USB device with something else.

Check the updated instructions.

"},{"location":"blog/2020/07/31/kvmd-1-83-security-fix-for-the-v2-platform/","title":"KVMD 1.83: Security fix for the V2 platform","text":"

After a little discussion, I decided to disable OTG Serial Console for security reasons.

The option otg.acm.enabled now is false by default. Additionally, the new OS build environment does not perform the steps for setting up the console.

It is important to note that if you set a strong password on your Pi-KVM, this problem is not so significant. Attackers will not be able to exploit it from the outside. However, I want to provide the most secure default settings. I'm sorry about this mess. This feature was very useful for development and users of ZeroW devices that don't have Ethernet, but it's not good enough for general installations.

  • To disable this feature permanently on older Pi-KVMs, follow the instructions above (the override.yaml will not need to be edited after KVMD is updated).

  • If you have an old Pi-KVM installation and you want to continue using this feature, use override.yaml and set option otg.acm.enabled to true.

  • To enable this feature for the v2 platform again in the build environment, add to the config.mk this line: STAGES ?= __init__ os pikvm-repo watchdog ro no-audit pikvm pikvm-otg-console ssh-keygen __cleanup__

As a new feature, you can disable VNC TLS if you need compatibility with strange VNC clients. Use /etc/kvmd/override.yaml for this (remove {} before):

vnc:\n    server:\n        tls:\n            ciphers: \"\"\n

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/07/31/security-note-for-v2/","title":"Security note for v2","text":"

After installation, Pi-KVM will be available via USB OTG from the managed server via the virtual serial console port.

This is very helpful if SSH is unavailable (and you don't have a UART cable), so you can login to the device using something like mingetty or PuTTY and find out what's wrong. The login is protected by the same password that is used for the root login. In some cases (if different networks are used for servers and KVM for security reasons), you may want to disable this feature. To do this:

  • Run rw.
  • Edit file /etc/securetty and remove line ttyGS0.
  • Edit file /etc/kvmd/override.yaml and add these lines (remove {} before):
otg:\n    acm:\n        enabled: false\n
  • Run:
[root@pikvm ~]# systemctl enable getty@ttyGS0.service\n[root@pikvm ~]# rm -rf /etc/systemd/system/getty@ttyGS0.service.d\n[root@pikvm ~]# reboot\n

This setting is enabled by default so that you are not left alone with an unmanaged device if it does not receive an address on the network for some reason\u2014for example, if you choose a Wi-Fi connection.

If you have a reasonable argument for disabling default, I will be happy to hear it.

"},{"location":"blog/2020/08/02/ready-made-images-for-raspberry-pi4/","title":"Ready-made images for Raspberry Pi4","text":"

The big update! Now we provide the ready-made images for Raspberry Pi 4. You no longer need to build OS manually!

You can flash the Pi-KVM OS to SD card under Linux, Mac, and Windows using the graphical installer.

Downloads are here: https://pikvm.org/download/.

The manual is here: https://docs.pikvm.org/flashing_os/.

Oh, and as you can see, now we have a small website: https://pikvm.org/. I would appreciate it if you share this link with your colleagues or friends in social networks.

"},{"location":"blog/2020/08/07/kvmd-1-86-ps2-keyboards-support/","title":"KVMD 1.86: PS/2 keyboards support","text":"

Great news for fans of retro computers and tech priests. Now Pi-KVM supports PS/2 keyboard.

This is useful for older hardware KVM switches and industrial computers. It is very simple to use, I wrote a small guide: https://github.com/pikvm/pikvm/blob/master/pages/arduino_hid.md

Over the past few days, many people have supported my work on Pi-KVM, and I am very grateful to them. The names of all sponsors are included in the documentation and in the \"About\" dialog window in the Pi-KVM interface.

PS: Mouse jiggler was not included in this release due to the fact that there is still some logic improvement required, and I decided that it is better to release the PS/2 functionality separately than to stall for time. This will be included in the next release.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/08/13/kvmd-1-88-tailscale-support/","title":"KVMD 1.88: Tailscale support","text":"

We added Tailscale to the OS repository for easy access to KVM from an external network via VPN. Updated documentation is here.

For very old computers a new mixed Arduino HID mode has been added: PS/2 keyboard + USB mouse. This is a great alternative to the PS/2 keyboard only mode that was added earlier.

All new project supporters are added to the thank you list in the About dialog in Pi-KVM and to the github. Thanks again!

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/08/17/kvmd-1-90-closing-the-stream-window-in-the-web-ui/","title":"KVMD 1.90: Closing the stream window in the web UI","text":"

One small, but very important feature. Now you can close the stream window in the web interface.

Two things will happen: the browser will stop recieving the video stream, reducing traffic consumption, and the streamer on the Pi-KVM side will still work, so when you open the window again, the video stream will be restored.

This is useful if you want to upload an image to mass storage while all the traffic goes to the video. This is especially useful for the ZeroW because of the weakness of it. Note that changing the screen resolution will raise a closed window.

This is a feature that will be removed later along with the stream size slider.

We also introduced various minor fixes. Don't forget to clean the browser cache after upgrading:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/08/19/kvmd-1-92-support-for-mouse-buttons-4-and-5/","title":"KVMD 1.92: Support for mouse buttons 4/5","text":"

This release brings support for mouse buttons 4 and 5 (back/forward) in the web interface for all Pi-KVM platforms.

If you are using an Arduino HID, then you need to update the firmware to use the additional buttons. However, if you do not update the firmware, nothing terrible will happen: the Protocol is backward compatible, and Arduino will simply ignore the new buttons.

  • Note that these buttons will not work in VNC, since the RFB protocol does not support them by design.

  • Fixed race condition on HID reset.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/08/21/kvmd-1-98-ustreamer-1-22/","title":"KVMD 1.93 & uStreamer 1.22","text":"

This is a double release of KVMD and uStreamer with improvements and fixes.

KVMD:

  • Improved error message in login window.

  • Added HTTP API for HID. For example, press and release the Shift key:

curl -k -XPOST -HX-KVMD-User:admin -HX-KVMD-Passwd:admin 'https://kvm/api/hid/events/send_key?key=ShiftLeft'`\n

uStreamer:

  • Added timeout to vcos semaphore to prevent unexpected hanging of the OMX encoder (this should not happen about ever, but it is better to be safe).

  • Fixed fallback to the CPU encoder when the OMX fails.

  • Improved compatibility with some USB 3.0 video capture devices that may produce incorrect frames. The minimum frame size for encoding is set to 128 bytes.

  • Added options to flip image and accept some color effects provided by webcams.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/08/31/kvmd-1-98-technical-preview-for-gpio/","title":"KVMD 1.98: Technical preview for GPIO","text":"

I've been working on a new big important feature: the ability to use custom GPIO pins for any purpose, such as connecting sensors or relays.

This release is technical preview (but stable ofc) so that you can try out the features that will then be introduced into production.

  • In this release the GPIO API was added. Now you can configure any number of switches, leds and buttons connected to Pi-KVM and act with it using API: \u2060#chat\u2060. In one of the next releases, these switches will be available in the web interface and I will write the documentation.

  • Added HTTP export handle for the Prometheus system to monitor the pi's and server's state: /api/export/prometheus/metrics with basic auth.

  • Added support for HTTP header Authorization: Basic ... to support basic auth for Prometheus (and other monitoring systems).

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/09/03/pikvm-now-available-on-rpi-1/","title":"Pi-KVM is now available on Raspberry Pi 1","text":"

In the last release, I added the ability to use this board. This is still unofficial and not reflected in the documentation, but you can already build the system using the build environment if you use the BOARD=rpi and PLATFORM=v0-hdmi or v0-hdmiusb parameters.

At the moment, you can only use the A or B board. In B+, the network card does not working because of some glitches related to the new kernel (after all, this is very legacy hardware).

To emulate the keyboard and mouse, you will need an Arduino HID, like for rpi2 or rpi3. In addition, the USB port binding for the HDMI dongle is disabled for rpi1.

"},{"location":"blog/2020/09/11/kvmd-1-100-gpio-and-usb-relays/","title":"KVMD 1.100: GPIO and USB relays","text":"

This release introduces a feature that I have been working on for a long time and that will significantly expand the functionality of Pi-KVM: the ability to use GPIO and USB relays.

Now you can connect any number of relays and configure GPIO to control anything using the convenient customizable menu in the Pi-KVM interface. If you wanted to make a smart server power switch, or control a multiport HDMI switch via the menu - now you have all the tools to do it: https://docs.pikvm.org/gpio/.

Some other features:

  • The API for integration with the Prometheus monitoring system has been finally stabilized and documented. By the way, you can get data about the status of GPIO ports in it: https://docs.pikvm.org/prometheus/.

  • KVMD is now compatible with Python 3.7, allowing enthusiasts to create custom builds for other operating systems.

  • Looped playback is now available for user action macros in the web interface.

  • Fixed a minor Nginx issue that could cause the Could not build optimal types_hash message in the logs. You will probably have to look at the diff between the /etc/kvmd/nginx/nginx.conf and /etc/kvmd/nginx/nginc.conf.pacnew files and make the appropriate changes to the first one, then manually delete the second one. But if you don't do any of this, it's not a big deal, it won't affect the functionality of the system.

  • New images are available in the archive: https://pikvm.org/download/.

Thank you to everyone who helped with the documentation and testing of new features. In addition, this release includes an updated list of thanks to those who donated to the project.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/09/17/kvmd-1-101-improvement-for-the-hdmi-usb-dongle/","title":"KVMD 1.101: Improvement for the HDMI USB dongle","text":"

The main change in this release concerns the internals of Pi-KVM.

About a year ago, the Linux kernel interface, which is used by most applications on the Raspberry Pi that work with GPIO, was deprecated (sysfs/gpiomem). This was replaced by the character device /dev/gpiochipX.

It is stated that the old interface will be removed in 2020, that is, very soon. Existing GPIO libraries for Python and C will also stop working: RPi.GPIO, pigpio, wiringpi and other.

It seems that the coming year will be fun for many projects that use the old library. For this reason, I got rid of RPi.GPIO and now KVMD uses libgpiod, a library for working with GPIO recommended and supported by kernel developers.

GPIO changes will not affect those who simply use this to control the ATX or control the KVM switch. However, those who use custom GPIO in Pi-KVM should know that it is no longer possible to save the pin state for GPIO (this is the kernel limitation) using option initial=null. In other words, when KVMD is restarted, the state of the relay connected to the GPIO will be reset to logic 0.

With the exception of this, the new library allowed KVMD to get rid of active GPIO state polling cycles, as well as crutches around kvmd-cleanup (does anyone even know what this is lol?). I have thoroughly tested this release and everything should be OK. However, if you notice any oddities, please let me know.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/09/18/kvmd-1-102-improvement-for-the-hdmi-usb-dongle/","title":"KVMD 1.102: Improvement for the HDMI USB dongle","text":"

The new version features further work on libgpiod and an improvement for the HDMI USB dongle.

  • Continue working with libgpiod. It turned out that I didn't use the correct symbolic names for the IO ports. This does not affect the operation, but the kernel warns that it does not like it. Fixed in the this version. If you are interested in more details, then we are talking about the fact that libgpiod allows you to view active ports using the gpioinfo command:
gpiochip0 - 54 lines:\n... \n        line  20:     \"GPIO20\"       unused   input  active-high \n        line  21:     \"GPIO21\"       unused   input  active-high \n        line  22:     \"GPIO22\" \"kvmd::atx-gpio::leds\" input active-high [used]\n        line  23:     \"GPIO23\" \"kvmd::atx-gpio::power_switch\" output active-high [used]\n        line  24:     \"GPIO24\" \"kvmd::atx-gpio::leds\" input active-high [used]\n...\n

I used names like kvmd/foo/bar, but the correct names are kvmd::foo::bar.

  • Slight improvement for the HDMI USB dongle. Now you can always keep the stream active, regardless of whether you have a browser or VNC open. This may be necessary because the server recognizes the dongle only when it is actually streaming. If not, the video card does not see the dongle. I'm not sure if this is the case with all dongles, but the one I have behaves exactly like this.

To include the everlasting stream use file /etc/kvmd/override.yaml:

kvmd:\n    streamer:\n        forever: true\n

To reduce power consumption and CPU usage, you can use the --slowdown option for ustremaer (rewrite the cmd section from main.yaml and add a line with the option).

"},{"location":"blog/2020/09/22/we-need-help-testing-ustreamer/","title":"We need help testing uStreamer","text":"

I need the community's help in testing the new version of ustreamer (the video server of Pi-KVM).

I found that some drivers for capture devices and cameras contain a bug that causes video buffers that are already used by the application to be given to it twice from the queue (TL;DR kernel magic). This can potentially corrupt memory, at least the part of it where the image is contained.

I investigated this issue and added code to ustreamer that prevents access to such a memory area. Now I want to know if our video capture devices (CSI bridge and USB dongle) are really affected by this problem. And if so, how often does this occur?

Therefore, I need the maximum cooperation of all users. You don't need to conduct comprehensive testing, just need to check your case. If you find the time to help me, you need to install ustreamer from source. This is very easy to do.

# rw\n# mv /usr/bin/ustremer /usr/local/bin/ustreamer.bak\n# git clone https://github.com/pikvm/ustreamer\n# cd ustreamer\n# make -j5 WITH_OMX=1\n# make PREFIX=/usr install\n# ro\n

After that reboot Pi-KVM (or just restart stream using web ui system menu).

If a memory problem occurs, ustreamer will quickly restart the video. In other words, you will see the NO SIGNAL message for a couple of seconds (or a gray screen). This situation will be reflected in the log with a message V4L2 error: grabbed device buffer is already used. It is useful to check the presence of this entry in the log every few hours using the command journalctl -u kvmd | grep 'grabbed device'.

Depending on whether this problem occurs and how often, I will look for some other solution for it, or keep the current one if it doing well.

If the problem suddenly appears and prevents you from working, please let me know and restore the old ustreamer: mv /usr/local/bin/ustreamer.bak /usr/bin/ustreamer.

Thank you to everyone who responds!

"},{"location":"blog/2020/09/24/ustreamer-2-0-memory-protection/","title":"uStreamer 2.0: Memory protection","text":"

Given the previous changes, I believe that there are already enough changes for version 2.0 :)

  • wiringPi replaced to libgpiod (reasons: \u2060news\u2060)

  • Added protection from memory corruption on usage of buggy webcam drivers (details)

  • Disabled cross-domain requests by default for security reasons (details)

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/10/04/kvmd-2-0-redfish-support-hid-driver-improvements/","title":"KVMD 2.0: Redfish support and HID driver improvements","text":"

This is a major new release with important improvements.

Let's take a look at the changes:

  • The first and most important change is updating the kernel to 5.4.69. Fixed the critical Linux bug with USB that could cause the Pi to reboot when using the keyboard and mouse on a rebooting host. I spent a few days debugging this problem and now it is solved in the Raspbian upstream.

  • The kernel update is also unlocked for ZeroW boards. The new kernel fixed an old bug that caused the kernel to hang on CSI HDMI at Zero. Yea, another kernel bug that I was directly involved in solving.

  • On the Pi-KVM side, the HID driver has been significantly improved, and now it clearly detects the USB state: the yellow color in web ui clearly shows when the cable is disconnected. Also added support for the NonUs and AltGr keys, fixed Win key in VNC.

  • Implemented basic support for Redfish as an improved and secure IPMI replacement for enterprise use (see here for documentation. Redfish requires no additional configuration and is available directly in KVMD. It uses the same authorization mechanism as the rest of the Pi-KVM. The only handle available /redfish/v1 without authorization produces a small static document for service discovery required by standard.

  • Added the ability to request confirmation for actions on custom GPIO buttons and switches (see View rules).

  • Now you can create USB Ethernet for direct communication between the Pi-KVM and the server (see here for more information). This release does not include a tool for address configuration and firewall, expect soon.

  • Improved the Web Socket API which no longer makes unnecessary broadcasts when connecting new clients. This is now convenient to use for getting the entire state of the Pi-KVM by the batch.

  • Config sections otg/msd, otg/acm and otg/drives were moved to otg/devices/msd, otg/devices/serial and otg/devices/drives. Of course, the old config will continue to work.

  • ... And many minor changes.

Note: Before upgrading ZeroW, you will probably need to remove the IgnorePkg = linux-raspberrypi and linux-raspberrypi-headers parameter from /etc/pacman.conf, if you added it earlier.

To update, follow:

rw\npacman -Syu\n

If you changed the file /etc/kvmd/override.yaml, you will see a new file: /etc/kvmd/override.yaml.pacnew. You can simply delete it or merge its contents with your own configuration. The new file contains commented-out usage examples and no longer contains (and requires) the {} row for an empty config.

After all perform reboot.

"},{"location":"blog/2020/10/05/another-test-request-for-v2-users-of-rpi4-and-zerow/","title":"Another test request for v2 users of RPi4 and ZeroW","text":"

I found a way to improve USB HID/Mass Storage compatibility with some motherboards. I would like to ask you to check if there are any problems because of this. If successful, if you didn't have MSD working, it may work after this change.

Please check this on your configurations: whether HID/MSD worked before, whether it works after the patch. I will be happy to hear about any changes (both positive and negative).

Run on Pi-KVM:

rw\nsed -i -e 's|^dtoverlay=dwc2$|dtoverlay=dwc2,dr_mode=peripheral|g' /boot/config.txt\nreboot\n

This can be easily undone if problems occur.

"},{"location":"blog/2020/10/08/kvmd-2-1-bug-fixes/","title":"KVMD 2.1: Bug fixes","text":"

This is mainly a bugfix release.

  • Fixed incorrect keys mapping in VNC. Also implemented QEMU Extended Key Events protocol which provides messages with hardware keycodes for VNC. This input method is preferred, and clients which can use it (yea-yea, I'm advertising TigerVNC again) will not have any problems with the layouts. Configuring keymap in override.yaml also becomes unnecessary in this case.

  • For v2 builds (RPi and ZeroW) the peripheral device mode for the USB-gadget controller is forced by default. This improves compatibility with some strange motherboards. Testing has not revealed any negative effects, but if something goes wrong, let me know.

  • Fixed GPIO switches in Web UI menu for the case when pulsing is disabled.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/10/17/kvmd-2-2-improved-hid-modules-for-arduino-and-otg/","title":"KVMD 2.2: Improved HID modules for Arduino and OTG","text":"

We have made several important improvements in this release.

  • Improved HID modules for Arduino and OTG. Now, if the server is disabled, the event queue will not grow, and irrelevant events (such as keystrokes for a disabled server) will be deleted.

  • Added an experimental service for configuring the USB network (issuing addresses to the server, firewall, and so on): kvmd-otgnet. Now you can up the FTP server on Pi-KVM and share files with the server using it.

  • For all KVMD daemons the startup method has been changed: the --run option is required to prevent accidental startup. Updated systemd services. Migration will be transparent for users.

  • Fixed a very rare VNC bug that could cause the server to stop transmitting an image and require a restart.

  • Minor UI improvements (more compact menubar, etc).

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/10/31/kvmd-2-3-workaround-for-dhcpd-crashes/","title":"KVMD 2.3: Workaround for dhcpcd crashes","text":"

A problem was found in the distro due to which the new dhcpcd (client) crashes when trying to get a Wi-Fi address (it's not me!).

So that you don't get a broken KVM after random update, in this release I forced the use of dhclient instead of dhcpcd. You should not notice any changes or problems. If there is anything strange, please let me know.

Now about pleasant things.

  • Added support for IPMI Serial-over-LAN. Now you can use ipmitool to access your server's console on the hardware COM port, see here for information.

  • Added the ability to edit streamer options without having to copy the entire list to /etc/kvmd/override.yaml. Now you can write something like:

kvmd:\n    streamer:\n        cmd_append: [--slowdown]\n

The other features I'm currently working on are in experimental mode. Due to the urgency of the release, I didn't have time to finish it. But I will soon :)

"},{"location":"blog/2020/11/11/kvmd-2-4-relative-mouse-bluetooth/","title":"KVMD 2.4: The Relative mouse & Bluetooth","text":"

This release added a great new feature that will please those who did not work the mouse in the BIOS/UEFI.

Previously, Pi-KVM only emulated absolute mouse mode, and some UEFIs didn't understand this. Now you can enable relative mouse mode. In this mode, the browser will completely capture your cursor (until you press Esc) and transmit all events to the server.

Testing has shown that on all UEFI in which the PI-KVM mouse did not work before, when the relative mode is enabled, the cursor works. This is a significant breakthrough in improving compatibility with various hardware. See here for details.

A very interesting feature has appeared: now Pi-KVM can emulate Bluetooth keyboard & mouse. The usecases of this may be specific, but I'm sure there will be a use for it. For example, you can control the cursor and keyboard of an iPad or other pieces. Bluetooth mouse works in relative mode, see here.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/11/27/ustreamer-2-2-better-video-performance/","title":"uStreamer 2.2: Better video performance","text":"

This is a bugfix release, albeit an important one.

We fixed an issue where video performance could degrade due to NTP system clock tweaking. A small but useful fix.

PS: If you missed the KVMD updates, I'm currently working on improvements to the Arduino HID, which will allow you to switch mouse modes in real time, as well as support for the SPI Protocol instead of UART. This is a very big change, but the work is almost done.

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2020/12/11/kvmd-2-6-completely-rewritten-arduino-hid/","title":"KVMD 2.6: Completely rewritten the Arduino HID subsystem","text":"

This is a very big release with a lot of changes, which took me a whole month.

Here is what's new:

  • Completely rewritten the Arduino HID subsystem. Now you can switch between relative and absolute mouse modes directly from the web interface. Arduino HID can be used with both v0 and v2, in which case it provides improved compatibility with strange devices and BIOSes. Some BIOSes don't understand absolute mouse and they need relative mouse: https://github.com/pikvm/pikvm/blob/master/pages/mouse.md

  • Now Arduino HID is compatible with Mac UEFI and is able to provide access to its menu at boot. If you need full Mac UEFI support, use Arduino HID. This is the recommended method.

  • Implemented an alternative way to connect the Arduino HID to the Raspberry using SPI. This is not yet documented and little bit tricky, but this method will free up the UART for other needs.

  • Migrated to Python 3.9. A big task which required patching and rebuilding of many packages.

rw\npacman -Syu\npacman -S tailscale-pikvm\nreboot\n

To use the new features of the Arduino HID, you will need to perform a flash. However, if you don't do this, nothing will break, the new KVMD is fully compatible with all older firmware versions. See here for more informaiton.

"},{"location":"blog/2020/12/20/some-news-about-v3/","title":"Some news about v3","text":"

We have some news about v3. The prototypes are almost ready. Since the last release, they have included several changes and additional features.

In addition to the ones we announced earlier, we added:

  • HDMI Audio. Practice has shown that all existing CSI bridges except for the expensive Auvidea B101 model have a hardware circuit error, due to which they are not able to capture sound. Our v3 does not have this drawback. This feature is already implemented in hardware, and the software will be ready a little later. Most likely, we will offer h264 video compression + audio.

  • Built-in fan controller. Since RPi has some cooling issues, we thought it would be great to solve this somehow.

  • Arduino HID with USB and PS/2 keyboard and mouse. The software for PS/2 mouse will be completed later, the hardware is already ready. Also, this thing is necessary to work with Apple UEFI.

  • The board uses only USB-C connectors (standardization!) and fully compatible with the official RPi power supply, which we will recommend for use.

A limited batch of 30 pieces will be sold to commercial customers and some interested parties in this chat. We'll probably sell to the first applicants, but we haven't decided yet. The kit will include: the v3 board, arduino HID board, adapter boards, small fan, and (probably) a 3D-printed case. RPi and power supply will NOT be included.

Since this is a trial batch of manual assembly, the cost of one set will be $200-250 (we have not yet calculated exactly). The sale of prototypes should start before the new year. In January, we will start selling production models much cheaper (~$100).

PS: Discussing welcome in the \u2060chat!

"},{"location":"blog/2021/01/12/ustreamer-3-0-h264-video-recording/","title":"uStreamer 3.0: H264 video recording","text":"

Currently, Pi-KVM uses MJPEG for video transmission. This is a simple and widely supported, but not very effective video format. In the near future, it is planned to support H264, and then switch to it as the main one.

The H264 implementation is still under development, but right now you can use it to record video from your server. To do this, uStreamer supports simultaneous MJPEG and H264 encoding.

See here for more information.

We also have some news about Tailscale support.

Previously, Tailscale was in its own pikvm repository and contained fixed versions of the startup scripts. Now it was accepted in upstream and the default startup scripts were broken.

If you upgrade the system and want to keep Tailscale working, you need to install the tailscale-pikvm package:

rw\npacman -Syu\npacman -S tailscale-pikvm\nreboot\n
"},{"location":"blog/2021/01/19/implementing-h264-support-for-vnc/","title":"Implementing H264 support for VNC","text":"

For those who use VNC and want to reduce the traffic using H264.

I want to implement H264 support for VNC, but the problem is that no VNC client supports H264. I'm ready to write a server and I already have a stable H264 encoder, but I need help with the client.

I'm going to negotiate with the developers of TigerVNC to work together on this: we will agree on a new protocol, I will implement the server, and they will implement the client. Since this is clearly a low-priority task for them, I suggest that anyone who needs this functionality should chip in for a beer for these guys.

If you are willing to participate and want to have H264 in VNC, please report yourself in \u2060h264_vnc_funding with an indication of how much you are willing to donate. Any contribution is important! If we collect an acceptable amount (I think $500 is reasonable), I will notify everyone and you can throw this money on BountySource (a site with rewards for developers).

Once again: I'm not asking for myself, but to pay for the work of other people. This is a very large-scale task, and if it is done by several people, everyone will benefit.

"},{"location":"blog/2021/02/21/kvmd-2-27-critical-bug-fix/","title":"KVMD 2.27: Critical bug fix","text":"

A lot of changes have accumulated since the last announced release. Mostly finally fixed wifi support on Zero and RPi4.

  • Added new udev rules for USB HDMI for latest RPi4 board revisions

  • Improved handling of VNC frames. It should get a little faster.

  • Added support for VNC X.509 encryption. Now you can use some mobile clients (such as bVNC) to access the Pi-KVM.

  • Now the Arduino HID is rebooted when the KVMD is restarted, this prevents the Arduino from possibly hanging due to the slow build-up of the supply voltage.

  • Changed the default JPEG compression quality on Zero. Now it is 50 (FPS has become higher, the quality remains acceptable).

  • The web interface now allows to upload MSD images with spaces. Some more minor improvements to the web interface. Also it's now available over IPv6.

  • For USB Ethernet (v2 only), we added the ability to configure Pi-KVM as a router for the server, see here.

  • A lot of work has been done to use H.264 with VNC. At the moment, we have registered our new protocol in IANA and are waiting for the applying of patches in TigerVNC and the fixing of some bugs in the kernel related to HDMI and H.264.

To update:

rw\npacman -Syy\npacman -S linux-firmware=20210221.b79d239-1\npacman -Su\nreboot\n
"},{"location":"blog/2021/03/13/kvmd-2-31-critical-bug-fix/","title":"KVMD 2.31: Critical bug fix","text":"

In recent weeks, I have been mainly working on H264 and have achieved significant results \u2060h264_vnc_funding. A critical bug has been fixed in the kernel that prevents the H264 encoder from being enabled by default, so now everyone can try H264 for VNC for v2 and CSI bridge (only).

This is not yet the final official implementation, but everything should work well. The work on H264 support in the web interface is far from complete, but it will be implemented.

Among other things:

  • Improved keyboard handling in the web interface on Mac OS.
  • When you close the stream window, the interface now asks for user confirmation.
  • Fixed a build bug for v0 related to disabling UART console.
  • Work has been carried out to standardize the H264 RFB (VNC) protocol. The standard is waiting for confirmation.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2021/04/13/kvmd-2-42-fullscreen-mode-web-ui/","title":"KVMD 2.42: Fullscreen mode in the web UI","text":"

Introducing a big update to the web interface!

Full-screen mode! It works in all browsers, but most of all-in Chrome/Chromium, where it allows you to capture system keys like Ctrl+W and so on.

Other changes:

  • Changing the size of the stream window using the window corner. No more ugly \"Stream size\" slider!
  • The ability to expand the window to the entire workspace with a single button.
  • Added the ability to manage remote hosts via IPMI from the Web UI menu: view the power status, turn on/off, and so on. See here for details.
  • Work continues on implementing H264. Many components of the system needed to be improved. Not everything is ready yet, but we are one step closer to replacing MJPEG with H264 in the browser.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2021/04/17/kvmd-2-53-web-terminal-in-web-ui-window/","title":"KVMD 2.53: Web terminal in a web UI window","text":"

You can now have the web terminal in a window above the video stream if you like. The focus works a little strange, but it is quite functional and even supports changing the size.

Another recent change is that you can now select the keyboard layout of the target machine in the paste-as-keys menu, so this solves the problem of German, British, and other layouts.

And a few more changes:

  • You can disable confirmation in the paste-as-keys menu
  • Full-screen mode now works in Safari on Mac.
  • Some minor UI fixes and improvements.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2021/04/23/kvmd-2-55-arduino-hid-improvements/","title":"KVMD 2.55: Arduino HID imrpovements","text":"

This release delivers a significant improvement of the Arduino HID when you control a computer with a MacOS.

Now you don't need to spam the Command+R or Option keys on boot to hope to get to the UEFI menu or Recovery mode\u2014just hold down the shortcut on boot, as on a real keyboard, and everything will work.

We also improved the behavior of the stream window: now it will not try to establish a connection several times due to a race on a slow channel, but works more stably. This is part of the work on future H.264 support\u2014cleaning the ancient Augean stables.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2021/05/09/kvmd-2-65-ezcoo-fix-for-usb3/","title":"KVMD 2.65: Ezcoo fix for USB 3.0","text":"

If you bought an Ezcoo switch for USB 3.0, then in order for it to work with Pi-KVM, you need to upgrade to the new version and add one option to the config.

The fact is that the Ezcoo guys for some reason changed the management protocol. The update adds support for this.

Ah, and if you're wondering where the rest of the versions disappeared between release 2.59 and 2.65, then these were some things for the upcoming H.264 support \ud83d\ude42

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2021/05/20/kvmd-2-71-massive-internal-changes/","title":"KVMD 2.71: Massive internal changes","text":"

This is a very important release. In addition to new features and fixes, a large number of internal changes have been made for the upcoming H264/WebRTC support.

As usual, I tested everything very carefully, but anyway. If you notice anything strange (for example, with the stream), let me know.

  • Added module for new managed KVM switch Tesmart (as an Ezcoo alternative): https://github.com/pikvm/pikvm/blob/master/pages/tesmart.md. It can be used in a same way from Web UI.

  • Fixed the Bluetooth HID emulation module.

  • Improved text insertion via the Web UI: typographic quotes are now replaced with ASCII quotes. Many sites where scripts can be copied from like to break quotes, so I decided to make life a little easier for sysadmins.

  • Due to a bug in systemd/udev, port binding for USB HDMI is disabled. This is temporary for now, but I'm considering getting rid of it altogether, because no one seems to be using multiple video devices on the Pi-KVM.

  • Redesigned the System menu in the Web UI to make it more compact, as due to H264 and v3 there will be a lot of new settings.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2021/05/30/store-update/","title":"Store update","text":"

There is good and bad news about our store.

A couple of days ago, we tried to make test sales and faced a huge number of refusals when making payments. In most cases, US and European banks consider the payment to Russia to be a fraudulent operation. There's nothing we can do about it. Well, it's probably well deserved, given the stories about Russian hackers.

Obviously, we can't sell our devices under these conditions, so we decided to sell most of the batch to wholesale suppliers in the US. These are two good stores that sell Raspberry Pi and accessories for them. The advantage of this approach is that it will be easier for you to buy it, if you want to add some things (Raspberry, memory card, cables, if you don't have one) and you will get delivery faster than from Russia. Minus - it will be a little more expensive.

The second batch will be sold through resellers for retail. To companies we will sell directly with deliveries via DHL.

So I'm doing customs clearance this week. Most likely, this will be delayed for another three weeks, taking into account the delivery to the reseller.

"},{"location":"blog/2021/06/08/kvmd-2-83-uploading-large-images/","title":"KVMD 2.83: Uploading large images","text":"

We have improved the behavior of mass storage when uploading large images.

Previously, the progress bar could be displayed incorrectly due to the features of different browsers (for example, chrome on some win 10), so now the download progress is calculated on the server side and transmitted to the client.

We also recently accelerated the uploading of images to Mass Storage by two to three times.

Work continues on the implementation of H264 and WebRTC. Presumably, the release will be within a week.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2021/06/10/kvmd-3-0-big-h264-release/","title":"KVMD 3.0: The big H.264 release!","text":"

I'm happy to introduce you to a feature I've been working on for the last six months. Now, instead of using bold MJPEG for video, you can use fast WebRTC with H.264.

This allows you to significantly reduce traffic consumption and improve the responsiveness of Pi-KVM on bad networks, and all in the regular Web UI! The MJPEG and H.264 modes are left to choose from and you can switch them at any time using the menu.

It was a huge job, as I had to understand the intricacies of WebRTC functioning, integrate it with uStreamer, develop a way to automatically configure the WebRTC gateway, and so on.

To try the new super video mode, upgrade your system (rw; pacman -Syu; reboot) and read the simple user guide.

Please note that right now H.264 is only available for Raspberry Pi 4 with CSI bridge.

"},{"location":"blog/2021/07/04/kvmd-3-7-some-v3-news/","title":"KVMD 3.7 + Some V3 news","text":"

This release comes with several improvements, we also have some V3 news for you.

  • Now the video mode is saved in the browser. If you have chosen WebRTC by default, then it will remain the same for this browser.

  • The Yen key in the Japanese keyboard now works.

  • Added a link to the configuration documentation and possible problems with WebRTC (right next to the mode switch).

  • The OS images on the site will be updated in the near future. Now the size of rootfs has been increased from 4 to 6 gigabytes to avoid problems with updates. The size of the partition in old images on already installed OS will not be increased.

To update:

rw\npacman -Syu\nreboot \n

As for the first batch of v3: it was delayed at russian customs. Let's wish health to these wonderful people. I'll deal with it. Btw the second batch is planned for September. There will be no such problems with this since it will be produced in China.

"},{"location":"blog/2021/07/10/kvmd-3-8-epic-apple-fix/","title":"KVMD 3.8: The Epic Apple fix!","text":"

For a long time, Pi-KVM had several problems related to the mouse and keyboard on Apple. Previously, you could not use the mouse in the boot menu, and recovery mode also required you to connect the mouse, despite the fact that the cursor was functioning. Because of these bugs, it was impossible to fully remotely control your Mac. Now all this is fixed!

  • For an Intel-based Mac, you can use the Arduino HID to enter different boot menus (Option or Cmd+R). In boot manager, a relative mouse now works, and in recovery mode, both relative and absolute work.

  • For Mac with M1, you can use default OTG HID. You will no longer be shown a screen with an absurd requirement to connect another mouse in recovery mode.

Since this problem was hidden somewhere inside the Apple drivers, I needed to buy a hardware USB protocol analyzer to understand how to get around it (because Mac is a closed source and there is no other way to find out what is happening there). Fixing this cost me almost $1500. So if it will be useful to someone, you can support me with a donation, because developing Pi-KVM software as Open Source is my main and only job.

  • https://patreon.com/pikvm
  • https://www.paypal.me/mdevaev

To update:

rw\npacman -Syu\nreboot \n

And don't forget reflash your Arduino HID!

"},{"location":"blog/2021/07/14/kvmd-3-9-paste-as-keys-update/","title":"KVMD 3.9: Paste-as-Keys update","text":"

For the Paste-as-Keys function, the state of the confirmation switch and the selected keymap are saved. You asked for it\u2014I did it.

Also, after solving the problems with HID on Apple, I sent patches to the upstream HID library. I know of at least one other project for which these problems were a thorn. Let's hope that we will make life easier for people \ud83d\ude42

To update:

rw\npacman -Syu\nreboot \n
"},{"location":"blog/2021/07/17/kvmd-3-11-for-workgroups/","title":"KVMD 3.11 For Workgroups","text":"

More new features in this new release.

Now Wake-on-LAN can be configured not for one, but for a whole list of hosts. Now you can use this as another method of managing multiple hosts connected to an HDMI switch: https://github.com/pikvm/pikvm/blob/master/pages/wol.md

This change required a complete rewrite of the WoL subsystem, which has now become a pseudo-GPIO driver. Your old settings in override.yaml will work and the button for one host is still in the System menu, since I took care of backward compatibility, but the /api/wol handle has been removed, you need to use the GPIO API instead it (if anyone has used it at all).

We also made some improvements in the interface. The interval between hotkeys was increased to 100 milliseconds (since 50 was sometimes not enough for reliable operation), the shortcuts menu was separated from the paste menu in preparation for the implementation of custom keyboard shortcuts.

To update:

rw\npacman -Syu\nreboot \n
"},{"location":"blog/2021/08/02/kvmd-3-13-upload-images-by-url-dual-mouse-mode/","title":"KVMD 3.13: Upload images by URL + dual mouse mode","text":"

Two new great features!

  • Now you can tell Pi-KVM to download the image for mass storage from the HTTP(S) URL, and not just upload from your local computer. The new MSD API has also become more convenient if you are a curl guru.

  • For v2/v3/OTG, you will no longer have to choose between relative and absolute mouse, you will be able to use both modes and switch between them without changing the config and reboot. This is very convenient if your BIOS does not understand the absolute mouse and only wants a relative one, while the absolute one is more convenient for everyday work in the OS. This dual mouse mode is disabled by default for compatibility reasons (perhaps, especially buggy bioses may not support two mice at once), to enable it, after updating, add to /etc/kvmd/override.yaml:

kvmd:\n    hid:\n        mouse_alt:\n            device: /dev/kvmd-hid-mouse-alt\n

Turn off the relative mode for the mouse in the config if it was enabled earlier. And make sure that you merged files /etc/udev/99-kvmd.rules.pacnew with /etc/udev/99-kvmd.rules.

To update:

rw\npacman -Syu\nreboot \n
"},{"location":"blog/2021/08/08/big-testing-request/","title":"Big testing request","text":"

I have a very important request. We are preparing for a big update that will improve compatibility with BIOS and UEFI on many devices, and I need as many people as possible to check out the new build of the kernel and core packages.

How to test:

  1. Switch filesystem to RW-mode using the rw command.
  2. Open the /etc/pacman.conf file for editing and go to its end.
  3. Change the repository URL like this (add testing component path): Server = https://pikvm.org/repos/testing/rpi4-arm. Don't change the last component (rpi4-arm, zerow-arm, etc).
  4. Run pacman -Syu && reboot

Please make sure that everything works as usual, I mean video and USB. I am particularly interested in the CSI bridge.

"},{"location":"blog/2021/08/17/kvmd-3-18-sensitivity-adjustment-for-relative-mouse/","title":"KVMD 3.18: Sensitivity adjustment for relative mouse","text":"

There are several improvements in this release.

  • The relative mouse now has a sensitivity adjustment. The setting is remembered in the browser.

  • We added a PWM and Servo module for GPIO. Now you can control servos using the GPIO menu.

  • The most important change! We added the absolute mouse compatibility mode for Windows 98 for both OTG and Arduino HID.

To update:

rw\npacman -Syu\nreboot \n
"},{"location":"blog/2021/08/31/kvmd-3-23-keyboard-mouse-wakeup/","title":"KVMD 3.23 + kernel fix: keyboard/mouse wakeup","text":"

Previously, when using v2+/OTG on Pi4 and ZeroW, you could not wake up the host if it was in suspend. Now this problem is solved.

At the moment, this feature is experimental and disabled by default, since it was implemented blindly without documentation for the USB controller (no one gave it to me lol). It would be great if as many people as possible test it and tell if everything works fine.

Although the feature is experimental, the update must be safe.

To update you will need our own stable kernel build (if you are using a very old image and have not installed it, in new images it is out of the box):

  1. Check if it is installed: pacman -Q | grep pikvm-os-raspberrypi
  2. If this command didn't show you anything, install our kernel (\u2060news\u2060)
  3. After reboot, make this: rw; pacman -Syu; reboot
  4. To enable wakeup feature edit /etc/kvmd/override.yaml and add this:

otg:\n    remote_wakeup: true\n
... and reboot"},{"location":"blog/2021/09/26/kvmd-3-26-philips-hue-gpio-plugin/","title":"KVMD 3.26: Philips Hue GPIO plugin","text":"

This releases comes with several new features and improvements.

  • Started rebranding Pi-KVM -> PiKVM. Everyone is constantly confused about how to write it correctly, so we will write the name in one word. And it's easier to google, too.

  • Added Philips Hue GPIO plugin for smartplugs and lamps. We also changed the GPIO HTTP API accordingly: pin numbers are strings now, which is a requirement for named pins.

  • ATX and GPIO actions are now also recorded in macros.

  • The IPMI GPIO plugin no longer calls ipmitool twice when a button is clicked in the interface.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2021/10/03/kvmd-3-27-mouse-polling-rate/","title":"KVMD 3.27: Mouse polling rate","text":"

The new version ships with a new feature: configurable mouse polling rate.

Previously it was a fixed 100ms, now it can be reduced to 10ms, so on good communication channels it makes the mouse more responsive.

Other changes:

  • Added tests to check whether the browser supports WebRTC/H.264.
  • Added a GPIO driver for a new KVM switch XK-HK4401.

To update:

rw\npacman -Syu\nreboot\n

We also fixed the use of new Tailscale versions. Install the tailscale-pikvm package.

"},{"location":"blog/2021/10/19/kvmd-3-33-new-wifi-configuration-method/","title":"KVMD 3.33: New Wi-Fi configuration method","text":"

Starting from today, the old way to configure Wi-Fi using netctl is deprecated. Instead, it is proposed to use a more native way with systemd-networkd, which is already used to configure Ethernet.

To update:

rw\npacman -Syu\nreboot\n

All new OS images will use this feature. In addition, I have prepared documentation for you on how to set up wifi in a new way: https://docs.pikvm.org/wifi

Additionally, even if you don't use Wi-Fi, do this:

rw\nsystemctl disable pikvm-bootconfig\nrm /etc/systemd/system/pikvm-bootconfig.service /usr/local/bin/_pikvm-bootconfig.sh\nsystemctl enable kvmd-bootconfig\nreboot\n
"},{"location":"blog/2021/10/24/kvmd-3-36-custom-command-button/","title":"KVMD 3.36: Custom command button in the menu","text":"

We have just implemented the long-awaited feature\u2014adding a custom command button to the menu.

I don't know why this is necessary, but it's been asked so often, so why not do it. To use it, you will need a pseudo-GPIO CMD driver. See this help page for details.

We also improved the behavior of stream quality sliders on Firefox.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2021/08/12/kvmd-3-14-epic-apple-fix-vol2/","title":"KVMD 3.14: The Epic Apple fix, Vol.2","text":"

I continue to eliminate ancient bugs from USB. So great news for Apple and v2/v3/OTG users: you no longer need to use the Arduino HID to get into the Boot Menu or Recovery Mode.

It took a long and thoughtful study, but now this problem has been resolved. In addition, compatibility with some strange HP and DELL motherboards has improved, so if you didn't have a keyboard there before, now it has all the chances to work! Note: wakeup from suspend using keyboard has not yet worked, but it's a matter of time.

Before updating: If you used testing repository, cancel this and use the usual settings.

To update:

rw\npacman -Syu\nreboot \n

You will also need my own stable kernel build (if you are using a very old image and have not installed it, in new images it is out of the box):

  1. Check if it is installed: pacman -Q | grep pikvm-os-raspberrypi
  2. If this command didn't show you anything, install my kernel
"},{"location":"blog/2022/01/08/kvmd-3-53-oled-and-fan-updates-for-v3/","title":"KVMD 3.53: OLED and fan updates for V3","text":"

The new KVMD update ships with a few major OLED changes.

First off, the OLED screen now displays the temperature, CPU and memory usage. You can control that with a new kvmd-oled tool. American users can now turn on the temperature display in Fahrenheit, see Step 5 in the quickstart guide for details.

The next new feature is kvmd-fan. This new utility implements automatic fan speed control depending on temperature.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2022/02/11/zero-w-1-and-rpi-1-end-of-life/","title":"Zero W 1 and RPi 1 end-of-life","text":"

Since Arch Linux ARM has discontinued support for the ARMv6 architecture , we are discontinuing support for PiKVM based on Zero W and RPi 1, because we don't have the ability to maintain our own fork of the whole distro for this architecture.

It is proposed to use Zero W 2 and RPi 2 for supported replacement. I know this will upset a lot of users, but there's nothing we can do about it right now. The current plan is as follows:

  1. We will build the last image with the current packages for Zero W 1. It will not receive updates, but will continue to work as before.

  2. In the long term, we plan to create a package repository for Raspbian. When this happens, support for Zero W 1 and RPi 1 will be returned, but not for the Arch Linux ARM, but for the Raspbian / Raspberry Pi OS.

RPi 2 and the rest of the devices continue to be supported as before.

"},{"location":"blog/2022/02/21/kvmd-3-55-copying-text-from-target-machine/","title":"KVMD 3.55: Copying text FROM the target machine","text":"

Introducing a new big feature\u2014the ability to copy text from a managed machine to the clipboard.

As you know, the clipboard inside the machine is a system feature and has no hardware connection with PiKVM. Therefore, in order to copy the text, we made it possible to recognize the selected image on the screen using the Tesseract OCR library, which converts it into text.

Image recognition works locally on your Raspberry Pi and does not use any Skynet clouds. In addition, recognition works ONLY on your demand, that is, the OCR library does not see the image until you give it to it explicitly, so if you are afraid to raise an evil AI, then you can relax.

For reasons of concern about paranoids, OCR library are not installed by default yet \ud83d\ude42

rw\npacman -Syu\npacman --assume-installed tessdata -S tesseract tesseract-data-eng\nreboot\n

Install any OCR language by searching it in pacman -Ss tesseract-data.

"},{"location":"blog/2022/03/06/new-testing-branch-available/","title":"New testing branch available","text":"

A few months ago, due to the release of Bullseye, the usual video encoding method used in PiKVM stopped working in the new kernel. OpenMAX and MMAL were deprecated and uStreamer has ben rewrited to use new M2M encoder. Now the work is almost completed and everything seems to be working fine.

I am asking all interested users of v0, v2 and v3 to test this update before I make it available to everyone. Rememer: this is an experimental update, so don't install it unless you're ready to do a reflash.

To install:

rw\nsed -i -e 's|repos/arch/|repos/arch-testing/|g' /etc/pacman.conf\npacman -Syu\nreboot\n

Please report any problems to #\u2060dev on Discord. Also let me know if everything is working fine. I am interested in testing on RPi3, RPi4 and Zero2W boards with HDMI-CSI bridge or v3 HAT.

"},{"location":"blog/2022/04/01/kvmd-3-73-experimental-dynamic-usb-configuration/","title":"KVMD 3.73: Experimental dynamic USB configuration","text":"

First of all, although the release is experimental, it is NOT unstable. The new utility does not affect the performance of the system in any way if you do not use.

So, the idea is that now you can change the configuration of the USB emulator on the fly. For example, you can temporarily turn off the mouse or mass storage or USB network (if you have it configured) without restarting, and then turn it on again:

[root@pikvm ~]# kvmd-otgconf\n+ hid.usb0  # Keyboard\n+ hid.usb1  # Absolute Mouse\n+ mass_storage.usb0  # Mass Storage Drive\n[root@pikvm ~]# kvmd-otgconf --disable-function mass_storage.usb0\n+ hid.usb0  # Keyboard\n+ hid.usb1  # Absolute Mouse\n- mass_storage.usb0  # Mass Storage Drive\n[root@pikvm ~]# kvmd-otgconf --enable-function mass_storage.usb0\n+ hid.usb0  # Keyboard\n+ hid.usb1  # Absolute Mouse\n+ mass_storage.usb0  # Mass Storage Drive\n

Disabling the function means that the host will not see it in USB.

Important: Due to the imperfections of the kernel modules, in rare cases, a dynamic configuration change can lead to a kernel panic and reboot, so use this carefully. I will fix the kernel at some point.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2022/05/03/now-you-can-buy-a-pre-assambled-pikvm-v3-with-case/","title":"Now you can buy a pre-assambled PiKVM v3 with case","text":"

A \u201cPre-Assembled\u201d version of PiKVM has just been released!

It includes the PiKVM board, a Raspberry Pi 4B 2GB, and a pre-programmed 32GB SanDisk card. Each unit has been carefully built and tested \u2764\ufe0f

A limited quantity is available for this launch. We are expecting a high demand and will be doing our best to keep up! It\u2019s already in stock at PiShop.us and PiShop.ca and will be soon available at other resellers.

  • US: https://www.pishop.us/product/pikvm-v3-pre-assembled/
  • Canada: https://www.pishop.ca/product/pikvm-v3-pre-assembled/
  • Other: https://www.pikvm.io/#where-to-buy
"},{"location":"blog/2022/06/09/kvmd-3-101-audio-on-pikvm-v3/","title":"KVMD 3.101: PiKVM V3 + Audio = \u2764\ufe0f","text":"

This moment has come! We are finally ready to provide audio for testing by all V3 users.

Right now everything is working pretty stable, so if you really wanted to watch a movie on KVM or something like that\u2014this is your chance!

To start using audio, follow the simple instructions here: https://docs.pikvm.org/audio.

"},{"location":"blog/2022/06/11/introducing-new-tool-kvmd-edidconf/","title":"Introducing a new tool \u2014 `kvmd-edidconf`","text":"

For the happy owners of V2 and V3, we now offer a new utility, kvmd-edidconf. It will help you configure EDID (the display metadata) and provide import/export for EDID modification using advanced editors such as AW EDID Editor.

For example, with its help, you can easily change the manufacturer and model of the virtual display without external editor apps, if you want PiKVM to mimic real hardware:

$ kvmd-edidconf --set-mfc-id=LNX --set-monitor-name=PiKVM\n

See the full documentation here: https://docs.pikvm.org/edid.

"},{"location":"blog/2022/06/24/kvmd-3-116-lets-encrypt-certificates/","title":"KVMD 3.116: Let's Encrypt certificates","text":"

Usually Let's Encrypt certificates are issued and updated automatically using Certbot, however, since PiKVM uses a read-only file system, special tools around Certbot are required to work with certificates.

Now you can use it out of box. PiKVM will ensure that they are automatically renewed without affecting the root file system. Check out the documentation: https://docs.pikvm.org/letsencrypt/.

Here is what we recently changed to allow for this.

As you know, the file system uses read-only mode by default. However, sometimes user scripts (updating some certificates, keys, or something else) need to save some data to the memory card.

New versions of PiKVM after 20 June 2022 provide a small 256 Mb storage partition for this and a convenient tools of automatically managing it. The storage will always be in read-only mode, and will be writable only if requested. This is super handy if you want to make a cron job or a systemd timer. For details, please see here: https://docs.pikvm.org/pst/.

"},{"location":"blog/2022/07/03/small-request-for-v3-and-diy-builds-with-csi-bridge-owners/","title":"A small request for V3 and DIY builds with CSI bridge owners","text":"

We want to change some default values in the EDID (information about the virtual display) so that it looks not like Toshiba-H2C, but like PiKVM, and also change the vendor code.

If you have a minute, please change the EDID settings and test the PiKVM virtual display in your BIOS and OS.

Preparations:

rw\npacman -Syu\nkvmd-edidconf --set-mfc-id=LNX --set-monitor-name=PiKVM\nreboot\n

After this, check OS and BIOS. The current paranoid hypothesis is that perhaps some ugly BIOSes may rely on the manufacturer's code for monitor Plug-n-Playing.

Expected behavior: PiKVM video capture work as before without any problems. If something goes wrong, you can undo all the changes.

Please, if you have completed the testing and everything is fine, click the UP! under the message. If something doesn't work, please report to \u2060the #dev channel on Discord.

"},{"location":"blog/2022/07/24/kvmd-3-126-writable-flash-drive-storage/","title":"KVMD 3.126: Writable flash drive storage","text":"

Now you can upload the flash drive image to MSD, write some files to it, or even install entire OS to the PiKVM MSD drive (I don't know why, but you can), and download the image back. Use the new feature wisely.

Okay, here is an obvious question: is it possible to download not the entire image, but one file from it? This will be implemented later. For now, only the entire image.

Another recent change affects V3 and CSI bridges owners. I changed the display name from Toshiba-H2C to PiKVM and the manufacturer id from TSB to LNX. You may need to specify the preferred monitor resolution in your OS again. If you used a custom EDID (for example, turned on the sound), then nothing will change for you.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2022/10/07/kvmd-3-152-android-and-ios-tablets-support/","title":"KVMD 3.152: Android and iOS tablets support","text":"

Several latest releases of KVMD come with improved support for web UI running on tablets.

  • We now have working mouse buttons and mobile keyboard for Apple tablets running iOS.
  • We also fixed Shift key in iOS JUMP and bVNC clients and fixed key confusion in Apple Magic International Keyboard.
  • The mobile interface is now available for Android tablets. Maybe not perfect, but it works.

Some of the other changes are:

  • Workaround for paste-as-keys for en/em dashes.
  • Improved OCR.
  • Kernel updated to 5.15.68.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2022/11/03/kvmd-3-159-significant-vnc-improvement/","title":"KVMD 3.159: Significant VNC improvement","text":"

The VNC server has learned how to transmit video asynchronously to make it fast and smooth. Now, FPS can grow about twice, it will be especially noticeable with poor internet quality.

Some of the other recent changes:

  • Fixed H.264 stream corruption (it was a kernel bug).
  • Fixed the bug where the web interface considered a laptop with a touchscreen to be a mobile device.
  • Made it possible to use icon leds for GPIO menu title like this:
title: [\"#KVM\", \"#PC1\", pc1led, \"#PC2\", pc2led]\n

Here is how it looks:

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2022/11/06/kvmd-3-163-ustreamer-5-30-no-keyframes-mode/","title":"KVMD 3.163 + uStreamer 5.30: No-Keyframes mode","text":"

This is the second part of an experiment to improve the video streaming.

There is such a thing in H.264\u2014keyframes. In a normal situation, they are sent approximately once per second in order to ensure the stability of the video. If you were faced with the fact that your stream turned black, and then started working again after a couple of seconds, then you had a flow failure, but the keyframe fixed this.

So, the keyframe is our friend. But keyframes contain an entire frame of the screen, and unlike intermediate frames, which fill the entire remaining stream, they have a huge size. Next comes blah-blah-blah about WebRTC theory and flow correction algorithms in browsers, but in general, if we disable keyframes and send them only when the flow fails, you can make the stream faster, smoother and consuming less traffic.

You can test this mode in the new update. I've added the H.264 gop parameter that adjusts the interval between keyframes.

If you reduce it to zero, then keyframes will be sent only in exceptional cases. This mode is best suited for slow wired channels, but I will be interested in how well it will work in wireless communication.

I would appreciate if someone would test this and share their experience for me in \u2060dev \ud83d\ude4f

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2022/12/15/the-pikvm-v4-kickstarter-campaign-is-on/","title":"The PiKVM V4 Kickstarter campaign is on!","text":"

We've been working on this for a long time! The new PiKVM V4 is even more powerful, more convenient and more feature-rich!

  • We have two new devices\u2014V4 Mini and V4 Plus. They have different hardware features.
  • Both are based on Compute Module 4.
  • Two new video modes support added: 1920\u00d71080@60Hz and 1920\u00d71200@60Hz. This improves the UEFI/BIOS compatibility.
  • V4 Mini has a fanless design and efficient power consumption.
  • V4 Plus has a super-quiet cooling system with a custom-designed heatsink and intelligent fan controller.
  • Both devices are ready-made: CM4 included, as well as a case, screen, and even micro SD. Uh, and they are already assembled!

...and a lot of other nifty stuff \u26a1

Visit our Kickstarter page: https://www.kickstarter.com/projects/mdevaev/pikvm-v4

"},{"location":"blog/2023/01/23/kvmd-3-196-2fa-support/","title":"KVMD 3.196: 2FA support","text":"

Many have asked for this, so now you have the opportunity to increase the security of your PiKVM.

By the way, this is a great chance to see how the QR code is rendered in the terminal using ASCII \ud83d\ude04

Have fun: https://docs.pikvm.org/auth/#two-factor-authentication

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2023/03/05/kvmd-3-203-changes-in-msd/","title":"KVMD 3.203: Changes in MSD","text":"

This is an infrastructure release. The internal structure of the MSD image storage has changed.

Metadata and image directories have been merged into one:

Old:

/var/lib/kvmd/msd/images/foobar.iso\n/var/lib/kvmd/msd/meta/foobar.iso.complete\n

New:

/var/lib/kvmd/msd/foobar.iso\n/var/lib/kvmd/msd/.__foobar.iso.complete\n

If you use a standard configuration (or even MSD on a separate flash drive), the migration will be seamless for you. All you need is just to update and reboot, the files will be moved automatically. The change was needed for future MSD-over-network support.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2023/03/21/kvmd-3-206-nfs-storage-for-virtual-media/","title":"KVMD 3.206: NFS storage for virtual media","text":"

Now you can create NFS share for a common images storage for your PiKVMs fleet. The images will be available on all devices.

Here is the documentation for the new feature: https://docs.pikvm.org/msd/#nfs-storage

This release also comes with Mass Storage Device API (/api/msd and and WebSocket event msd_state) changes required for NFS support:

  • Removed the features field. The flags in it don't make sense since we dropped relay msd a year ago (does anyone even know what it is?)
  • Removed the storage.free and storage.size fields. Instead, use storage.parts[\"\"].free and storage.parts[\"\"].size. The new mechanism provides MSD placement on several local/NFS partitions at the same time. \"\" means the default partition.
  • Removed the storage.images[...].name field. Use the object key instead.

For those who use only Web UI or VNC, nothing changes.

To update:

rw\npacman -Syu\nreboot\n
"},{"location":"blog/2023/06/04/kvmd-3-225-performance-update/","title":"KVMD 3.225: Performance update","text":"

This is a performance update that improves multiple aspects of PiKVM OS.

  • Added a new very effective mouse events protocol.
  • Tuned some OS settings, so you will get a faster mass-storage image uploading.
  • Actually, there are many more things that I have fixed and improved, but it's too boring to describe them.

To update:

rw\npacman -Syu\nreboot\n

We would appreciate wider testing. There are two important parameters in Web UI that affect the latency. Try them out:

  • H.264 gop in the same location.
  • Mouse polling interval in the System menu;

Try to reduce it to tis minimum values (0 and 10 ms respectively). This should reduce latency and increase responsiveness. If you don't have a very reliable network (you're using VPN, or your host is a thousand kilometers away from you)\u2014check whether the mouse will work well and whether the video will not be interrupted often.

It is important for me to know this, because if everything is fine, I will change the default values. Let me know if you encounter any problems with the described parameters.

"},{"location":"blog/2023/07/30/diy-pikvm-v0-based-on-arduino-hid-becomes-legacy/","title":"DIY PiKVM V0 based on Arduino HID becomes legacy","text":"

I'm planning to replace V0 with a new V1 soon, which will be based on Raspberry Pico.

Here is what it boils down to:

  • No more transistors and level shifters for USB emulation, now only wires are needed.
  • Full-fledged PS/2 keyboard and mouse support for connoisseurs of antiquity.
  • Pico is much cheaper than Arduino.

Old DIY devices will continue to be supported, but the instructions will be marked as legacy. If you have any suggestions for the new Pico HID, please write to the #\u2060dev channel on Discord.

"},{"location":"blog/2023/08/19/kvmd-3-249-easier-uploading-over-ssh/","title":"KVMD 3.249: easier uploading over SSH","text":"

In addition to many minor improvements from the previous announcement, an important change has occurred in the new release for those who use advanced Mass Storage emulation features.

Now, when uploading an image via SSH, you no longer need to create a .complete file, since a manually placed image will be considered complete by default. This should simplify the operation of NFS shares for images and simplify console use.

Before updating, delete all your broken images. In theory, you should not have them, since PiKVM deletes it on uploading error, but anyway.

To update:

rw\npacman -Syu\nreboot\n

PS: A little bit about the state of things: PiKVM is an open source product and full-time work for several people, thanks to which we can maintain the proper level of quality and security. As you can see, even after the release of V3 and V4, we do not abandon the development of DIY devices and port all possible features there.

"},{"location":"blog/2023/08/23/ustreamer-5-42-reduced-stream-latency/","title":"uStreamer 5.42: Reduced stream latency!","text":"

While I was working on HDMI passthrough for V4 Plus (I didn't forget what we promised!), I found a way to reduce the stream latency.

Now 1080p stream with H.264 can reach ~110ms on LAN. That is, -50ms compared to the previous result.

BTW all PiKVMs, including V3 and DIY builds, will receive this update.

"},{"location":"blog/2023/10/23/kvmd-3-265-mouse-jiggler/","title":"KVMD 3.265: Mouse Jiggler!","text":"

This is a feature that many users have been asking for for a long time. So, mouse jiggler will allow you to prevent the monitor from falling asleep if it was turned on.

It performs short mouse movements every minute until you use PiKVM. Works with both mouse modes: absolute and relative. In addition, being enabled, it does not interfere with normal work with PiKVM: it will only interfere when you are not interacting with a virtual keyboard or mouse. The time of inactivity is counted from your last actions.

To update (see previous post):

curl https://files.pikvm.org/update-os.sh | bash\n

Or rw; pacman -Syu; reboot, if you have already updated the OS using the script earlier.

Howto enable it: https://docs.pikvm.org/mouse_jiggler/

"},{"location":"blog/2023/10/24/pikvm-just-got-full-ps2-support/","title":"PiKVM just got full PS/2 support","text":"

Previously, to support PS/2 keyboards (only), it was necessary to assemble a complex circuit on Arduino. With the transition to Raspberry Pi Pico, we finally have full support for both keyboard and mouse. The design has been greatly simplified, and is now compatible with V4 Plus.

HOWTO: https://docs.pikvm.org/pico_hid_bridge/

Let me know if you need a native support of the Sun SPARCstation Keyboard & Mouse!

"},{"location":"blog/2023/12/03/introducing-the-new-diy-pikvm-v1-build/","title":"Introducing the new DIY PiKVM V1 build","text":"

We've been working for a while to unify DIY builds and simplify instructions. The result was a new DIY platform V1, which replaced V0.

  • The old Arduino HID was replaced by a new one based on the Raspberry Pi Pico.
  • The Pico HID uses an SPI connection and leaves the UART on the Raspberry free so that you can connect a USB-TTL adapter and use a serial console. Hurray!
  • Also, the new HID has full PS/2 mouse support, not just the keyboard, as before.
  • It is much easier and faster to make than the old V0 build with Arduino.
  • Among other things, now we're providing ready-made OS images for all DIYs. You will no longer have to build them yourself.

From this day on, V0 on Arduino is declared obsolete and consigned to oblivion. Instructions for its assembly are no longer available, except for the Arduino HID page. If you need an Arduino HID for anything, use the new Pico HID. The Pico HID is also capable of working as an in-place replacement for the Arduino HID, in case you need to replace it on your old V0.

OS images and updates for V0 will still be coming out. That is, V0 support will be continued. We only deprecate the instructions.

The assembly instructions for the PiKVM V2 have also been updated\u2014this is greatly simplified and systematized.

  • https://docs.pikvm.org/v1
  • https://docs.pikvm.org/v2
"},{"location":"blog/2024/02/03/kvmd-3-301-generated-nginx-configs/","title":"KVMD 3.301: Generated Nginx configs","text":"

Starting from this version, the /etc/kvmd/nginx.conf config will be replaced with the /etc/kvmd/nginx.conf.mako template, which will be rendered to /run/kvmd/nginx.conf taking into account the /etc/kvmd/override.yaml parameters and network configurations.

This will make it very easy to turn off IPv6, HTTPS on and off and change ports using the standard override mechanism, like this:

nginx:\n    https:\n        enabled: false\n

If you had any changes in nginx.conf (for example, you previously disabled HTTPS manually), your Nginx configuration will roll back to the default, and HTTPS will be enabled again. To disable it, use the snippet above.

This will not affect the settings of certificates and Letsencrypt, nothing will break here. If you have not changed Nginx configs, you have nothing to worry about at all and the migration will be seamless.

To update:

$ curl https://files.pikvm.org/update-os.sh | bash\n
"},{"location":"blog/2024/02/15/kvmd-3-304-video-quality-and-compatibility-improvements/","title":"KVMD 3.304: Video quality and compatibility improvements","text":"

In this release, you will get many improvements regarding video quality and EDID.

"},{"location":"blog/2024/02/15/kvmd-3-304-video-quality-and-compatibility-improvements/#pikvm-v4","title":"PiKVM V4","text":"
  • Default resolution is 1920\u00d71080@60Hz.
  • Added native support of 1920\u00d71200@60Hz!
  • Fixed broken audio on Linux hosts.
"},{"location":"blog/2024/02/15/kvmd-3-304-video-quality-and-compatibility-improvements/#pikvm-v3","title":"PiKVM V3","text":"
  • Default resolution now is 1280\u00d7720@60Hz, it should improve BIOS compatibility.
  • Supported resolutions up to 1920\u00d71080@50Hz.
  • Fixed broken audio on Linux hosts.
"},{"location":"blog/2024/02/15/kvmd-3-304-video-quality-and-compatibility-improvements/#for-v4-v3-diy-based-on-csi-bridges","title":"For V4 + V3 + DIY based on CSI bridges","text":"
  • The color rendering quality has been significantly improved. Now the colors are bright and juicy, and not overexposed, see the attached picture.
  • Presumably, this release should put an end to shamanic dancing with EDID settings for different BIOSes.
  • Added several new supported resolutions like 1600\u00d7YYYY.
  • kvmd-edidconf --set-audio=1 now allows you to automatically add audio blocks for PiKVM, which are required by some particularly finicky OS.

To update:

$ curl https://files.pikvm.org/update-os.sh | bash\n

Important: if you are using a custom EDID, you will need to manually replace it with a new one after update. For example: rw; kvmd-edidconf --restore-default=v4plus; reboot (available: v0, v1, v2, v3, v4mini and v4plus)

"},{"location":"blog/2024/02/16/kvmd-3-305-new-option-to-hide-the-blue-dot/","title":"KVMD 3.305: New option to hide the blue dot","text":"

Now you can disable the blue mouse dot.

But I still don't recommend doing this, because using the blue dot you can not wait for the real cursor. Click events are instantly transmitted to where the blue dot points, not the lagging real cursor.

"},{"location":"blog/2024/02/23/hdmi-passthrough-on%20pikvm-v4-plus/","title":"HDMI passthrough on PiKVM V4 Plus","text":"

We promised it at the start and finally it's almost done. The V4 Plus will get an HDMI passthrough on one of its outputs. Right now It's working on my desk, and it's pretty good: 1080p 60 fps with vertical sync, perfect 24 bit color and zero-latency.

The first versions will pass the video if the online stream in the Web UI or VNC is not active. This is necessary to reduce all possible delays. I will finalize this in the future. I plan to release a public beta in the next week or two. In fact, it might happen sooner if I catch a wave.

"},{"location":"blog/2024/03/06/kvmd-ustreamer-performance-update/","title":"KVMD + uStreamer performance update","text":"

Today I have prepared a great update for you. After few weeks of research, I managed to increase the video performance slightly reduce the latency for all CSI devices (PiKVM V4, V3 and CSI-based V2).

In H.264 mode (WebUI and VNC), you will get stable 30fps on 1080p and 60fps on 720p In MJPEG mode it just works a little faster.

To update:

# pikvm-update`\n

If this command is not available, please use:

# curl https://files.pikvm.org/update-os.sh | bash`\n
"},{"location":"blog/2024/03/17/kvmd-3-319-display-orientation-options/","title":"KVMD 3.319: Display orientation options for H.264 stream","text":"

For the H.264 stream, there are now options to rotate the virtual screen.

Rotation is done in 90\u00b0 increments. The toggles are in the System menu in the web UI.

To update:

# pikvm-update`\n

If this command is not available, please use:

# curl https://files.pikvm.org/update-os.sh | bash`\n
"},{"location":"blog/2024/04/16/kvmd-3-333-hdmi-passthrough-now-available-on-v4-plus/","title":"KVMD 3.333: HDMI passthrough now available on V4 Plus","text":"

After a long and thorny path of research, we are pleased to present the promised HDMI passthrough feature for PiKVM V4 Plus.

The new feature allows you to connect PiKVM between the host and local display. PiKVM will not interfere with the normal operation of the display and passes the video signal through itself until you need remote access. In this case, PiKVM will copy the video stream to the Web UI or VNC.

But the most important thing is that the video will still be available on the local display at the same time as the stream! And of course it's zero-latency for the local display, with VSync support.

How-to: https://docs.pikvm.org/pass

Also, I'm glad that this release got a beautiful number, and I was finally able to make the Evangelion reference, which I forgot to do for 3.33 :)

"},{"location":"blog/2024/08/19/kvmd-4-4-stable-hdmi-passthrough-on-v4-plus/","title":"KVMD 4.4: HDMI passthrough on V4 Plus is stable now","text":"

Thanks to the work of the Raspberry kernel team, a bug related to incorrect colors in H.264 was finally fixed while working with passthrough.

With the new release, this feature is now enabled by default, and you will get great juicy colors both in the stream and on the external physical monitor. See the documentation for details on setting this up.

"},{"location":"blog/2024/12/20/announcing-pikvm-switch-multiport-extender/","title":"Announcing PiKVM Switch Multiport Extender","text":"

The PiKVM team is excited to present its new PiKVM Switch Multiport Extender - the most full-featured switch for PiKVM devices. After much anticipation, the PiKVM Switch is now available for order! The switch allows you to connect up to four target hosts to a single PiKVM and provides full control over them.

  • ATX control on each port.
  • Per-port EDID configuration.
  • HDMI dummy plug functionality.
  • True Plug-n-Play with no need for override.yaml setups and complete control via Web UI.
  • Multifunctional RGB LEDs with beacon mode and customizable color schemes.
  • Firmware update directly from PiKVM and ready for future hardware extensions.
  • Compatible with V4 Plus, V3 and DIY devices based on Pi2-Pi4 except Zero and V4 Mini.

And now the best part: the switches can be chained! Need four ports? Get a PiKVM Switch Multiport Extender. As your server fleet expands to eight, simply add another switch and link it to the first one. Need even more? No worries \u2014 connect up to five switches and enjoy 20 fully functional ports on your PiKVM. Say goodbye to replacing your entire KVM system!

You can order PiKVM Switch Multiport Extender from our international store.

Canadian customers can place an order at PiShop.ca.

See also the detailed technical descriptions and documentation on docs.pikvm.org.

The first batch will start shipping at the end of December 2024, and the second batch will be at the end of January 2025.

"},{"location":"blog/2024/12/25/kvmd-4-29-h264-over-http/","title":"KVMD 4.29: H.264 over HTTP","text":"

I know that some people have a problem using H.264 and WebRTC with firewalls, NAT, Tailscale and other things. Until recently, the only alternative was MJPEG, which consumes a lot of traffic. So I was constantly researching whether something could be done about it, and finally found a way.

Starting with KVMD 4.29, in addition to WebRTC, a new method of direct transmission of H.264 over HTTP will be available to you. Is the Web UI working? Then direct video transmission will also work. This completely solves the problem of WebRTC unavailability.

This new feature is available for free not only to PiKVM V4 and V3 users, but also to all DIY users with HDMI-CSI devices. Merry Christmas to everyone! \ud83e\udd73

A little tip: use H.264 gop 0 in settings.

To update just run pikvm-update. As usual, I advise you not to upgrade without physical access to the device. Also, you should not update PiKVM if the amount of alcohol in the blood on the occasion of the holiday is not zero or at least does not correspond to the level of the peak Ballmer.

PS: Our work on the open development of PiKVM is possible only through sales of hardware and donations. So if you want to support us, please consider [buying(https://pikvm.org/buy/) our official PiKVM or a Switch.

"},{"location":"blog/2025/01/12/switch-update-%20better-hdmi-compatibility/","title":"Switch update: better HDMI compatibility","text":"

An announcement for happy PiKVM Switch owners. We have released a firmware update that improves compatibility with some HDMI sources + audio.

You need to update the PiKVM OS using pikvm-update, and the firmware will be delivered with it. Next, follow the instructions in the Switch menu.

This is another cool feature of the PiKVM Switch: you don't need to take any complicated steps to update the firmware. A switch connected to PiKVM receives an update from PiKVM, and then updates all other switches in the chain automatically.

"},{"location":"blog/2025/01/20/kvmd-4-44-two-way-audio-with-microphone/","title":"KVMD 4.44: Two-way audio with microphone","text":"

PiKVM V3 and V4 Mini/Plus just got two-way audio with microphone! Now you can use voice applications remotely, or you can just emotionally tell the server what you think about it.

How to: https://docs.pikvm.org/audio

"},{"location":"blog/2025/01/24/kvmd-4-49-dvd-images-support/","title":"KVMD 4.49: DVD images support","text":"

Starting with KVMD 4.49, the old 2.2 GB CD limit is now removed.

PiKVM just learned how to support large DVD images natively, which means that you no longer need Ventoy to prepare Flash images for PiKVM. You can even use the official Windows ISO to install the OS! Small ISO images will be handled as CD as before, but for big images PiKVM will switch emulation to DVD mode automatically.

How to update: pikvm-update, as usual.

If you've been dreaming of getting DVD emulation, then your wish has been fulfilled \ud83d\ude42

"},{"location":"blog/2025/02/16/pikvm-switch-firmware-update/","title":"PiKVM Switch firmware update","text":"

At the request of Switch owners, we have improved the compatibility with DIY devices based on CSI bridge.

  • Fixed the problem of the HDMI backpowering.
  • Added compatibility mode if DIY PiKVM does not see the image through the switch.

As we promised, this is a new generation of multiport switches. It's so smart that we can fix any problems with it with a simple firmware update. No more \"Oh crap, my \" doesn't show any videos because of EDID \ud83d\ude2d \" Okay, okay, we just really proud of the design, sorry \ud83d\ude42

  • How to update: https://docs.pikvm.org/switch/#firmware-updating
  • How to enable the fix: next to the update chapter.

Where to buy:

  • Worldwide: https://shop.hipi.io/product/pikvm-switch-multiport-extender
  • Canada: https://www.pishop.ca/product/pikvm-switch-multiport-extender/
"},{"location":"blog/2025/03/11/kvmd-4-65-adopt-display-identifiers-on-v4-plus/","title":"KVMD 4.65: Adopt display identifiers on V4 Plus","text":"

PiKVM V4 Plus just got a new tool to read and adopt display identifiers like model and serial number from the physical monitor.

Install the updated OS using pikvm-update, connect the desired display to OUT2 port and use follows:

[root@pikvm ~]# rw\n[root@pikvm ~]# kvmd-edidconf --import-display-ids --apply\n[root@pikvm ~]# ro\n

V4 will read display identifiers and apply them to own EDID. The target host connected to PiKVM will recognize it as your display.

"},{"location":"blog/2025/05/18/kvmd-4-72-big-bunch-of-big-improvements/","title":"KVMD 4.72: A big bunch of big improvements","text":"

This release has gathered a whole bunch of features that some users have been asking. And this is a big step forward in terms of usability.

"},{"location":"blog/2025/05/18/kvmd-4-72-big-bunch-of-big-improvements/#web-ui","title":"Web UI","text":"
  • \u2b50 The maximized window continues to be maximized when the browser is resized or the resolution of the remote host is changed. It's meaning the stream will always occupy the maximum workspace without having to constantly press the dot button to remove the black bars from above or below the stream.
  • \u2b50 The text in the paste menu can now be sent using the hotkey Ctrl+Enter.
  • \u2b50 Added two-finger scrolling on touch devices.
  • \u2b50 The virtual keyboard supports the key lock mode by clicking the middle button. Hotkeys like REISUB are now much more convenient to enter. Long left or short right click for hold like right now, middle for lock.
  • Fixed the mouse positioning at the right and bottom edges of the screen.
  • Fixed incorrect scrolling inertia when changing the direction. The scrolling algorithm has been significantly improved.
  • Fixed the keys overlapping on the virtual keyboard on HiDPI screens.
"},{"location":"blog/2025/05/18/kvmd-4-72-big-bunch-of-big-improvements/#vnc","title":"VNC","text":"
  • \u2b50 Eliminated the mess with the clipboard. Now, to paste the text, you just need to copy it to the client PC, and then use the magic LeftAlt,LeftAlt,P hotkey (quickly in a row, without holding). No more accidental insertion when switching windows.
  • \u2b50 Hotkeys for switching channels on the PiKVM Switch on any VNC client. If you have one or two switches, you can use LeftAlt,LeftAlt,1 (1-8) to switch between 8 channels. For three or more Switches, you need to use double numbers, like LeftAlt,LeftAlt,3,2 (unit 3, channel 2).
  • \u2b50 VNC clients showing host information will now display the current active port of PiKVM Switch and KVM name.
  • VNCAuth no longer requires you to write the KVMD password in /etc/kvmd/vncpasswd and does not prevent you from using one-time passwords with KVMD. Now you can turn it on if you haven't done it before.
"},{"location":"blog/2025/05/18/kvmd-4-72-big-bunch-of-big-improvements/#ipmi","title":"IPMI","text":"
  • kvmd-ipmi no longer requires writing the KVMD password in /etc/kvmd/ipmipasswd and does not prevent you from using 2FA with KVMD. Now you can turn it on if you haven't done it before.
"},{"location":"blog/2025/05/18/kvmd-4-72-big-bunch-of-big-improvements/#pikvm-switch","title":"PiKVM Switch","text":"
  • \u2b50 Improved VNC integration (see the previous header).
  • Option to disable the dummy plug function.

To update:

pikvm-update

"},{"location":"blog/2025/05/23/kvmd-4-74-local-usb-mouse-passthrough/","title":"KVMD 4.74: Local USB keyboard & mouse passthrough","text":"

With this new mode, all USB keyboards and mice connected to PiKVM directly will be forwarded the host. If you're using PiKVM Switch, they will be forwarded via the Switch to the active selected host.

There are several hotkeys available that are always active:

  • LeftAlt, LeftAlt, K - (mnemonic KVM, quick hit) disable keyboard/mouse grabbing and allow them to use with PiKVM locally, for example, for the console operating.
  • LeftAlt, LeftAlt, H - (Host) - switch back to the passthrough mode and pass keyboard-mouse events to the host.
  • Switching the PiKVM Switch channels. If you have one or two switches, you can use LeftAlt, LeftAlt, 1 (1-8) to switch between 8 channels. For three or more Switches, you need to use double numbers, like LeftAlt, LeftAlt, 3, 2 (unit 3, channel 2).

Now you can set up your workplace so that all your input devices are connected via PiKVM, this is especially convenient with the V4 Plus, which can also passthrough a monitor. And if you use a switch, then you will no longer need to have a separate keyboard and mouse for local work. Your workplace behaves exactly the same locally as it does remotely.

To enable this feature, update OS with pikvm-update and run rw; systemctl enable --now kvmd-localhid; ro.

"},{"location":"blog/2025/05/27/kvmd-4-76-advanced-diagnostics-for-the-video-streams/","title":"KVMD 4.76: Advanced diagnostics for the video stream","text":"

Now you will see the reason why there is no signal. We reliably distinguish the condition of the cable from the absence of a signal or unsupported video mode.

"},{"location":"blog/2025/09/30/kvmd-4-99-oled-display-improvements-on-v3-and-v4/","title":"KVMD 4.99: OLED display improvements on V3 and V4","text":"
  • Now the display shows the number of users who use PiKVM via the Web UI and VNC. This number is located next to the cute spinning stick that we all love so much.
  • If there is at least one user, the display brightness will be reduced to a minimum to prolong its life.
"},{"location":"blog/2025/10/23/kvmd-4-107-configuration-changes/","title":"KVMD 4.107: Configuration changes","text":"

We have revamped the configuration system. If PiKVM customization concerns you, read on.

Here are the main changes:

  • We have moved /etc/kvmd/main.yaml to /usr/lib/kvmd/, because it's a platform config that should never be changed.

  • We have deprecated and removed /etc/kvmd/logging.yaml. It contained some Python-specific logging settings that no one had ever changed. Getting rid of this artifact will simplify the configuration structure for some future improvements.

  • We have deprecated /etc/kvmd/auth.yaml. This is a legacy auth configuration that existed before /etc/kvmd/override.yaml was introduced, and has never been suggested for use even in the documentation. If you have ever customized your PiKVM with auth.yaml (likely not), your changes will be carefully moved to /etc/kvmd/override.d/..., and the source file is auth.yaml should be deleted manually. Please see here for details.

  • The !include directive in /etc/kvmd/override* and /etc/kvmd/meta.yaml configs is now deprecated and removed. Instead, you can place your partial config files into the /etc/kvmd/override.d directory, which is described in the documentation. Automatic migration is not possible here, and if you used !include for some reason, pikvm-update will tell you to remove this from the configuration before updating.

Please note that if you stored all the configs only in override.d and override.yaml and did not use !include, the migration will be transparent for you.

"},{"location":"stl/atx/","title":"PiKVM v3 ATX mounting brackets for 3D printing","text":""},{"location":"stl/atx/#pikvm-v3-atx-mounting-brackets-for-3d-printing","title":"PiKVM v3 ATX mounting brackets for 3D printing","text":"

A good way to mount an ATX adapter in a computer case is to place it in a PCI slot. Here you can get drawings of PCI brackets for 3D printing.

Variant Description This is a standard bracket of common length, which will fit most personal computers The short bracket (low profile), for compact PCs or rack servers"},{"location":"stl/v3.2/","title":"3D printable case for PiKVM v3.2 HAT","text":""},{"location":"stl/v3.2/#3d-printable-case-for-pikvm-v32-hat","title":"3D printable case for PiKVM v3.2 HAT","text":"

When printing the case, you can choose the following options:

  • The presence or absence of an OLED screen (used to display the IP address and other information).
  • The presence or absence of holes for the AUM v3.3 (Advanced USB Module, most likely you don't have it).

Also take a look at the PCI bracket for ATX adapter board.

"},{"location":"stl/v3.2/#buy-options","title":"Buy options","text":"
  • Small 5v fan strongly recommended to avoid overheating in the case.
  • I2C OLED screen.
"},{"location":"stl/v3.2/#building","title":"Building","text":""},{"location":"stl/v3.2/#parts","title":"Parts","text":""},{"location":"stl/v3.2/#the-front-part","title":"The front part","text":"

Choose ONE of them.

Variant Description The front part of the case WITHOUT a hole for the OLED The front part of the case with a hole for installing the OLED"},{"location":"stl/v3.2/#the-back-part","title":"The back part","text":"

Choose ONE of them.

Variant Description The back part of the case WITHOUT AUM holes The back part of the case for installing the AUM"},{"location":"stl/v3.2/#spacers","title":"Spacers","text":"Type Description 6.2mm spacer, required TWO pieces 2mm spacer required TWO without AUM or ONE for AUM 1mm spacer required ONE for AUM only Low spacer required ONE"},{"location":"stl/v3.3/","title":"PiKVM v3.3 Plastic Case for 3D printing","text":""},{"location":"stl/v3.3/#pikvm-v33-plastic-case-for-3d-printing","title":"PiKVM v3.3 Plastic Case for 3D printing","text":"

When printing the case, you can choose the following options:

  • The presence or absence of an OLED screen (used to display the IP address and other information).

Also take a look at the PCI bracket for ATX adapter board and great unofficial case mod for Noctua fans

"},{"location":"stl/v3.3/#buy-options","title":"Buy options","text":"
  • Small 5v fan strongly recommended to avoid overheating in the case.
  • I2C OLED screen.
"},{"location":"stl/v3.3/#parts","title":"Parts","text":""},{"location":"stl/v3.3/#the-front-part","title":"The front part","text":"

Choose ONE of them.

Variant Description The front part of the case WITHOUT a hole for the OLED The front part of the case with a hole for installing the OLED"},{"location":"stl/v3.3/#the-back-part","title":"The back part","text":"Variant Description The back part of the case"},{"location":"stl/v3.3/#spacers","title":"Spacers","text":"Type Description 6.2mm spacer, required TWO pieces 1mm spacer required TWO pieces Low spacer required ONE piece"},{"location":"stl/v3.3/#fasteners-screws","title":"Fasteners (screws)","text":"

The official PiKVM v3.3 hat came with eight M2.5 x 12mm screws for countersunk holes. You can use these with the case.

"},{"location":"stl/v3.3/#assembly","title":"Assembly","text":"

Note: the spacers slide over the (short) hexagonal standoffs included in the official v3.3 hat:

To assemble:

  1. Ensure the hexagonal standoffs are all attached to the top side of the v3.3 hat. Tip: if you need to remove the case in the future, you don't want these hexagonal standoffs spinning while you loosen the screws - be sure to tighten the standoffs more than you tighten the screws in step 17. You could even use some thread-locking fluid on the standoffs now.
  2. Ensure the bottom side of the Pi has no screws present
  3. Ensure you have eight M2.5 x 12mm screws free for later use.
  4. Slide the two short spacers over the two standoffs on the side of the hat which contains the ATX, keyboard/mouse emulation, and HDMI connector. See Figure 1.
Figure 1: 1mm spacer placement
  1. Slide the two long spacers over the two standoffs on the opposite side of the HAT - near the LEDs, power input, and console-over-ethernet connector. See Figure 2.
Figure 2: Placement of 6.2mm spacers.
  1. Attach the fan to the two headers labeled \"fan\" located next to the CSI ribbon cable and large capacitor.
  2. Slide the fan into the slot on the front part of the case. The fan should move fan from outside to inside the case. For the fan in Figure 3, this means mounting with the label facing the inside of the case and the black lead connected to the negative (-) terminal on the PCB. Ensure the fan leads don't bind as you slide the fan in. See Figure 3.
Figure 3: Fan placement
  1. If you still have foam covering the GPI pins on the top side of the hat, now is a good time to remove them. Leaving this in place will restrict airflow.
  2. Flip the PiKVM over and set the low spacer bracket you printed on the bottomside of the Pi with the straight edge facing away from the SD card. See Figure 4.
Figure 4: Low spacer placement
  1. While allowing the low spacer to continue resting on the Pi, gently slide the PiKVM into the front part of the case. Ensure the spacers clear the top of the case (likely facing away from you) and that the fan leads don't bind on anything. The low spacer should remain mostly in place thanks to the solder joints on the Pi.
  2. If successful, the low spacer should be fairly close to aligning with the holes in the case. Use a small screwdriver or tweezers to fix the alignment. You may need to insert the screwdriver into the case along the inner face to push the low spacer towards the holes. See video for reference.
  3. Insert 4 screws into the holes of the case and tighten enough so things don't fall out, but leave plenty of slack - you might need to push the electronics around slightly to align the holes in the next steps.
  4. Now is a good time to power on the PiKVM and ensure the fan spins. It should come on automatically unless you explicitly disabled it yourself.
  5. Slide the back part over the PiKVM and align with the front part you assembled in previous steps.
  6. Ensure the case seats properly around the connectors.
  7. Insert the remaining four screws into the case and tighten. If the holes don't line up, you can hold the case while pushing on some of the PiKVM connectors to shift the electronics inside the case.
  8. Tighten all screws.
  9. Tip your bartender.
"},{"location":"blog/archive/2025/","title":"2025","text":""},{"location":"blog/archive/2025/#2025","title":"2025","text":""},{"location":"blog/archive/2024/","title":"2024","text":""},{"location":"blog/archive/2024/#2024","title":"2024","text":""},{"location":"blog/archive/2023/","title":"2023","text":""},{"location":"blog/archive/2023/#2023","title":"2023","text":""},{"location":"blog/archive/2022/","title":"2022","text":""},{"location":"blog/archive/2022/#2022","title":"2022","text":""},{"location":"blog/archive/2021/","title":"2021","text":""},{"location":"blog/archive/2021/#2021","title":"2021","text":""},{"location":"blog/archive/2020/","title":"2020","text":""},{"location":"blog/archive/2020/#2020","title":"2020","text":""},{"location":"blog/category/releases/","title":"Releases","text":""},{"location":"blog/category/releases/#releases","title":"Releases","text":""},{"location":"blog/category/products/","title":"Products","text":""},{"location":"blog/category/products/#products","title":"Products","text":""},{"location":"blog/category/development/","title":"Development","text":""},{"location":"blog/category/development/#development","title":"Development","text":""},{"location":"blog/page/2/","title":"Blog","text":""},{"location":"blog/page/2/#blog","title":"Blog","text":""},{"location":"blog/page/3/","title":"Blog","text":""},{"location":"blog/page/3/#blog","title":"Blog","text":""},{"location":"blog/page/4/","title":"Blog","text":""},{"location":"blog/page/4/#blog","title":"Blog","text":""},{"location":"blog/page/5/","title":"Blog","text":""},{"location":"blog/page/5/#blog","title":"Blog","text":""},{"location":"blog/page/6/","title":"Blog","text":""},{"location":"blog/page/6/#blog","title":"Blog","text":""},{"location":"blog/page/7/","title":"Blog","text":""},{"location":"blog/page/7/#blog","title":"Blog","text":""},{"location":"blog/page/8/","title":"Blog","text":""},{"location":"blog/page/8/#blog","title":"Blog","text":""},{"location":"blog/page/9/","title":"Blog","text":""},{"location":"blog/page/9/#blog","title":"Blog","text":""},{"location":"blog/page/10/","title":"Blog","text":""},{"location":"blog/page/10/#blog","title":"Blog","text":""},{"location":"blog/archive/2022/page/2/","title":"2022","text":""},{"location":"blog/archive/2022/page/2/#2022","title":"2022","text":""},{"location":"blog/archive/2021/page/2/","title":"2021","text":""},{"location":"blog/archive/2021/page/2/#2021","title":"2021","text":""},{"location":"blog/archive/2021/page/3/","title":"2021","text":""},{"location":"blog/archive/2021/page/3/#2021","title":"2021","text":""},{"location":"blog/archive/2020/page/2/","title":"2020","text":""},{"location":"blog/archive/2020/page/2/#2020","title":"2020","text":""},{"location":"blog/archive/2020/page/3/","title":"2020","text":""},{"location":"blog/archive/2020/page/3/#2020","title":"2020","text":""},{"location":"blog/category/products/page/2/","title":"Products","text":""},{"location":"blog/category/products/page/2/#products","title":"Products","text":""},{"location":"blog/category/releases/page/2/","title":"Releases","text":""},{"location":"blog/category/releases/page/2/#releases","title":"Releases","text":""},{"location":"blog/category/releases/page/3/","title":"Releases","text":""},{"location":"blog/category/releases/page/3/#releases","title":"Releases","text":""},{"location":"blog/category/releases/page/4/","title":"Releases","text":""},{"location":"blog/category/releases/page/4/#releases","title":"Releases","text":""},{"location":"blog/category/releases/page/5/","title":"Releases","text":""},{"location":"blog/category/releases/page/5/#releases","title":"Releases","text":""},{"location":"blog/category/releases/page/6/","title":"Releases","text":""},{"location":"blog/category/releases/page/6/#releases","title":"Releases","text":""},{"location":"blog/category/releases/page/7/","title":"Releases","text":""},{"location":"blog/category/releases/page/7/#releases","title":"Releases","text":""},{"location":"blog/category/releases/page/8/","title":"Releases","text":""},{"location":"blog/category/releases/page/8/#releases","title":"Releases","text":""}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 00000000..82b199b5 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,839 @@ + + + + https://pikvm.github.io/pikvm/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/3d_printing/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_basic_troubleshooting/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_config/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_device_guides/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_diy_parts_atx/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_diy_setup_video_csi/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_diy_setup_video_usb/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_diy_wiring_atx/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_edidconf_options/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_fahrenheit/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_multiport_usb/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_passwd/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_pico_hid_flashing/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_pico_hid_parts/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_update_os/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/_usb_limits/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/api/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/arduino_hid/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/atx_board/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/audio/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/auth/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/auth_advanced/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/auto_snapshots/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/bluetooth_hid/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/building_os/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/cheatsheet/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/cloudflared/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/compliance/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/config/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/edid/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/ezcoo/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/faq/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/flashing_hid/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/flashing_os/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/gpio/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/id/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/ipmi/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/letsencrypt/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/modem/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/mouse/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/mouse_jiggler/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/msd/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/msd_legacy/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/multiport/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/ocr/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/on_boot_config/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/pass/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/pico_hid/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/pico_hid_bridge/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/port_forwarding/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/prometheus/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/pst/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/reverse_proxy/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/switch/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/tailscale/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/tesmart/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/usb/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/usb_ethernet/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/usb_pass/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/usb_serial/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/v1/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/v2/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/v3/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/v3_illustrated_install_instructions/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/v4/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/video/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/vnc/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/webrtc_config/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/webui/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/wifi/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/wiring_examples/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/wol/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/xh_hk4401/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/06/01/kvmd-1-65-vnc-improvements-and-new-api/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/06/08/kvmd-1-67-numpad-support/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/06/20/kvmd-1-71-vnc-improvements/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/07/17/kvmd-1-75-hardware-health-monitoring/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/07/23/kvmd-1-78-vnc-improvements/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/07/26/kvmd-1-82-hdmi-usb-dongle-support/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/07/31/kvmd-1-83-security-fix-for-the-v2-platform/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/07/31/security-note-for-v2/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/08/02/ready-made-images-for-raspberry-pi4/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/08/07/kvmd-1-86-ps2-keyboards-support/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/08/13/kvmd-1-88-tailscale-support/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/08/17/kvmd-1-90-closing-the-stream-window-in-the-web-ui/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/08/19/kvmd-1-92-support-for-mouse-buttons-4-and-5/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/08/21/kvmd-1-98-ustreamer-1-22/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/08/31/kvmd-1-98-technical-preview-for-gpio/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/09/03/pikvm-now-available-on-rpi-1/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/09/11/kvmd-1-100-gpio-and-usb-relays/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/09/17/kvmd-1-101-improvement-for-the-hdmi-usb-dongle/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/09/18/kvmd-1-102-improvement-for-the-hdmi-usb-dongle/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/09/22/we-need-help-testing-ustreamer/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/09/24/ustreamer-2-0-memory-protection/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/10/04/kvmd-2-0-redfish-support-hid-driver-improvements/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/10/05/another-test-request-for-v2-users-of-rpi4-and-zerow/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/10/08/kvmd-2-1-bug-fixes/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/10/17/kvmd-2-2-improved-hid-modules-for-arduino-and-otg/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/10/31/kvmd-2-3-workaround-for-dhcpd-crashes/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/11/11/kvmd-2-4-relative-mouse-bluetooth/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/11/27/ustreamer-2-2-better-video-performance/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/12/11/kvmd-2-6-completely-rewritten-arduino-hid/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2020/12/20/some-news-about-v3/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/01/12/ustreamer-3-0-h264-video-recording/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/01/19/implementing-h264-support-for-vnc/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/02/21/kvmd-2-27-critical-bug-fix/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/03/13/kvmd-2-31-critical-bug-fix/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/04/13/kvmd-2-42-fullscreen-mode-web-ui/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/04/17/kvmd-2-53-web-terminal-in-web-ui-window/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/04/23/kvmd-2-55-arduino-hid-improvements/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/05/09/kvmd-2-65-ezcoo-fix-for-usb3/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/05/20/kvmd-2-71-massive-internal-changes/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/05/30/store-update/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/06/08/kvmd-2-83-uploading-large-images/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/06/10/kvmd-3-0-big-h264-release/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/07/04/kvmd-3-7-some-v3-news/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/07/10/kvmd-3-8-epic-apple-fix/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/07/14/kvmd-3-9-paste-as-keys-update/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/07/17/kvmd-3-11-for-workgroups/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/08/02/kvmd-3-13-upload-images-by-url-dual-mouse-mode/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/08/08/big-testing-request/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/08/17/kvmd-3-18-sensitivity-adjustment-for-relative-mouse/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/08/31/kvmd-3-23-keyboard-mouse-wakeup/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/09/26/kvmd-3-26-philips-hue-gpio-plugin/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/10/03/kvmd-3-27-mouse-polling-rate/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/10/19/kvmd-3-33-new-wifi-configuration-method/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/10/24/kvmd-3-36-custom-command-button/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2021/08/12/kvmd-3-14-epic-apple-fix-vol2/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/01/08/kvmd-3-53-oled-and-fan-updates-for-v3/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/02/11/zero-w-1-and-rpi-1-end-of-life/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/02/21/kvmd-3-55-copying-text-from-target-machine/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/03/06/new-testing-branch-available/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/04/01/kvmd-3-73-experimental-dynamic-usb-configuration/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/05/03/now-you-can-buy-a-pre-assambled-pikvm-v3-with-case/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/06/09/kvmd-3-101-audio-on-pikvm-v3/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/06/11/introducing-new-tool-kvmd-edidconf/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/06/24/kvmd-3-116-lets-encrypt-certificates/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/07/03/small-request-for-v3-and-diy-builds-with-csi-bridge-owners/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/07/24/kvmd-3-126-writable-flash-drive-storage/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/10/07/kvmd-3-152-android-and-ios-tablets-support/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/11/03/kvmd-3-159-significant-vnc-improvement/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/11/06/kvmd-3-163-ustreamer-5-30-no-keyframes-mode/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2022/12/15/the-pikvm-v4-kickstarter-campaign-is-on/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2023/01/23/kvmd-3-196-2fa-support/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2023/03/05/kvmd-3-203-changes-in-msd/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2023/03/21/kvmd-3-206-nfs-storage-for-virtual-media/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2023/06/04/kvmd-3-225-performance-update/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2023/07/30/diy-pikvm-v0-based-on-arduino-hid-becomes-legacy/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2023/08/19/kvmd-3-249-easier-uploading-over-ssh/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2023/08/23/ustreamer-5-42-reduced-stream-latency/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2023/10/23/kvmd-3-265-mouse-jiggler/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2023/10/24/pikvm-just-got-full-ps2-support/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2023/12/03/introducing-the-new-diy-pikvm-v1-build/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2024/02/03/kvmd-3-301-generated-nginx-configs/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2024/02/15/kvmd-3-304-video-quality-and-compatibility-improvements/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2024/02/16/kvmd-3-305-new-option-to-hide-the-blue-dot/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2024/02/23/hdmi-passthrough-on%20pikvm-v4-plus/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2024/03/06/kvmd-ustreamer-performance-update/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2024/03/17/kvmd-3-319-display-orientation-options/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2024/04/16/kvmd-3-333-hdmi-passthrough-now-available-on-v4-plus/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2024/08/19/kvmd-4-4-stable-hdmi-passthrough-on-v4-plus/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2024/12/20/announcing-pikvm-switch-multiport-extender/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2024/12/25/kvmd-4-29-h264-over-http/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2025/01/12/switch-update-%20better-hdmi-compatibility/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2025/01/20/kvmd-4-44-two-way-audio-with-microphone/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2025/01/24/kvmd-4-49-dvd-images-support/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2025/02/16/pikvm-switch-firmware-update/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2025/03/11/kvmd-4-65-adopt-display-identifiers-on-v4-plus/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2025/05/18/kvmd-4-72-big-bunch-of-big-improvements/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2025/05/23/kvmd-4-74-local-usb-mouse-passthrough/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2025/05/27/kvmd-4-76-advanced-diagnostics-for-the-video-streams/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2025/09/30/kvmd-4-99-oled-display-improvements-on-v3-and-v4/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/2025/10/23/kvmd-4-107-configuration-changes/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/stl/atx/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/stl/v3.2/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/stl/v3.3/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2025/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2024/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2023/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2022/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2021/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2020/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/releases/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/products/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/development/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/page/2/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/page/3/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/page/4/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/page/5/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/page/6/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/page/7/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/page/8/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/page/9/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/page/10/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2022/page/2/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2021/page/2/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2021/page/3/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2020/page/2/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/archive/2020/page/3/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/products/page/2/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/releases/page/2/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/releases/page/3/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/releases/page/4/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/releases/page/5/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/releases/page/6/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/releases/page/7/ + 2025-10-28 + + + https://pikvm.github.io/pikvm/blog/category/releases/page/8/ + 2025-10-28 + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 00000000..21764acd Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/stl/atx/index.html b/stl/atx/index.html new file mode 100644 index 00000000..3b62ab55 --- /dev/null +++ b/stl/atx/index.html @@ -0,0 +1,2618 @@ + + + + + + + + + + + + + + + + + + + + + + PiKVM v3 ATX mounting brackets for 3D printing - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

PiKVM v3 ATX mounting brackets for 3D printing

+

A good way to mount an ATX adapter in a computer case is to place it in a PCI slot. +Here you can get drawings of PCI brackets for 3D printing.

+ + + + + + + + + + + + + + + + + +
VariantDescription
This is a standard bracket of common length, which will fit most personal computers
The short bracket (low profile), for compact PCs or rack servers
+ + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/stl/atx/pci_long.jpg b/stl/atx/pci_long.jpg new file mode 100644 index 00000000..86beaa9d Binary files /dev/null and b/stl/atx/pci_long.jpg differ diff --git a/stl/atx/pci_long.stl b/stl/atx/pci_long.stl new file mode 100644 index 00000000..959e1542 Binary files /dev/null and b/stl/atx/pci_long.stl differ diff --git a/stl/atx/pci_short.jpg b/stl/atx/pci_short.jpg new file mode 100644 index 00000000..da0e117e Binary files /dev/null and b/stl/atx/pci_short.jpg differ diff --git a/stl/atx/pci_short.stl b/stl/atx/pci_short.stl new file mode 100644 index 00000000..84b80fec Binary files /dev/null and b/stl/atx/pci_short.stl differ diff --git a/stl/v3.2/case_a.png b/stl/v3.2/case_a.png new file mode 100644 index 00000000..65c313cd Binary files /dev/null and b/stl/v3.2/case_a.png differ diff --git a/stl/v3.2/case_a.stl b/stl/v3.2/case_a.stl new file mode 100644 index 00000000..162bb435 Binary files /dev/null and b/stl/v3.2/case_a.stl differ diff --git a/stl/v3.2/case_a_no_oled.png b/stl/v3.2/case_a_no_oled.png new file mode 100644 index 00000000..5972cfe8 Binary files /dev/null and b/stl/v3.2/case_a_no_oled.png differ diff --git a/stl/v3.2/case_a_no_oled.stl b/stl/v3.2/case_a_no_oled.stl new file mode 100644 index 00000000..320c7a38 Binary files /dev/null and b/stl/v3.2/case_a_no_oled.stl differ diff --git a/stl/v3.2/case_b.png b/stl/v3.2/case_b.png new file mode 100644 index 00000000..184361ec Binary files /dev/null and b/stl/v3.2/case_b.png differ diff --git a/stl/v3.2/case_b.stl b/stl/v3.2/case_b.stl new file mode 100644 index 00000000..58bdfd17 Binary files /dev/null and b/stl/v3.2/case_b.stl differ diff --git a/stl/v3.2/case_b_no_aum.png b/stl/v3.2/case_b_no_aum.png new file mode 100644 index 00000000..6085503b Binary files /dev/null and b/stl/v3.2/case_b_no_aum.png differ diff --git a/stl/v3.2/case_b_no_aum.stl b/stl/v3.2/case_b_no_aum.stl new file mode 100644 index 00000000..2b5f2d67 Binary files /dev/null and b/stl/v3.2/case_b_no_aum.stl differ diff --git a/stl/v3.2/index.html b/stl/v3.2/index.html new file mode 100644 index 00000000..4d2b5c80 --- /dev/null +++ b/stl/v3.2/index.html @@ -0,0 +1,2747 @@ + + + + + + + + + + + + + + + + + + + + + + 3D printable case for PiKVM v3.2 HAT - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

3D printable case for PiKVM v3.2 HAT

+

When printing the case, you can choose the following options:

+
    +
  • The presence or absence of an OLED screen (used to display the IP address and other information).
  • +
  • The presence or absence of holes for the AUM v3.3 (Advanced USB Module, most likely you don't have it).
  • +
+

Also take a look at the PCI bracket for ATX adapter board.

+

Buy options

+ +

Building

+

+

Parts

+

The front part

+

Choose ONE of them.

+ + + + + + + + + + + + + + + + + +
VariantDescription
The front part of the case WITHOUT a hole for the OLED
The front part of the case with a hole for installing the OLED
+

The back part

+

Choose ONE of them.

+ + + + + + + + + + + + + + + + + +
VariantDescription
The back part of the case WITHOUT AUM holes
The back part of the case for installing the AUM
+

Spacers

+ + + + + + + + + + + + + + + + + + + + + + + + + +
TypeDescription
6.2mm spacer, required TWO pieces
2mm spacer required TWO without AUM or ONE for AUM
1mm spacer required ONE for AUM only
Low spacer required ONE
+ + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/stl/v3.2/low_spacer.png b/stl/v3.2/low_spacer.png new file mode 100644 index 00000000..4a94893f Binary files /dev/null and b/stl/v3.2/low_spacer.png differ diff --git a/stl/v3.2/low_spacer.stl b/stl/v3.2/low_spacer.stl new file mode 100644 index 00000000..a3ba5b08 Binary files /dev/null and b/stl/v3.2/low_spacer.stl differ diff --git a/stl/v3.2/spacer_1mm.png b/stl/v3.2/spacer_1mm.png new file mode 100644 index 00000000..2f77de35 Binary files /dev/null and b/stl/v3.2/spacer_1mm.png differ diff --git a/stl/v3.2/spacer_1mm.stl b/stl/v3.2/spacer_1mm.stl new file mode 100644 index 00000000..f9f4b6a1 Binary files /dev/null and b/stl/v3.2/spacer_1mm.stl differ diff --git a/stl/v3.2/spacer_2mm.png b/stl/v3.2/spacer_2mm.png new file mode 100644 index 00000000..d6cfca51 Binary files /dev/null and b/stl/v3.2/spacer_2mm.png differ diff --git a/stl/v3.2/spacer_2mm.stl b/stl/v3.2/spacer_2mm.stl new file mode 100644 index 00000000..33f4016c Binary files /dev/null and b/stl/v3.2/spacer_2mm.stl differ diff --git a/stl/v3.2/spacer_6.2mm.png b/stl/v3.2/spacer_6.2mm.png new file mode 100644 index 00000000..b631e5bc Binary files /dev/null and b/stl/v3.2/spacer_6.2mm.png differ diff --git a/stl/v3.2/spacer_6.2mm.stl b/stl/v3.2/spacer_6.2mm.stl new file mode 100644 index 00000000..41c32e00 Binary files /dev/null and b/stl/v3.2/spacer_6.2mm.stl differ diff --git a/stl/v3.3/1mm_spacer_placement.jpg b/stl/v3.3/1mm_spacer_placement.jpg new file mode 100644 index 00000000..6199adb4 Binary files /dev/null and b/stl/v3.3/1mm_spacer_placement.jpg differ diff --git a/stl/v3.3/case_a.png b/stl/v3.3/case_a.png new file mode 100644 index 00000000..65c313cd Binary files /dev/null and b/stl/v3.3/case_a.png differ diff --git a/stl/v3.3/case_a.stl b/stl/v3.3/case_a.stl new file mode 100644 index 00000000..e7996d91 Binary files /dev/null and b/stl/v3.3/case_a.stl differ diff --git a/stl/v3.3/case_a_no_oled.png b/stl/v3.3/case_a_no_oled.png new file mode 100644 index 00000000..5972cfe8 Binary files /dev/null and b/stl/v3.3/case_a_no_oled.png differ diff --git a/stl/v3.3/case_a_no_oled.stl b/stl/v3.3/case_a_no_oled.stl new file mode 100644 index 00000000..9c258e26 Binary files /dev/null and b/stl/v3.3/case_a_no_oled.stl differ diff --git a/stl/v3.3/case_b.png b/stl/v3.3/case_b.png new file mode 100644 index 00000000..d5dfd4ca Binary files /dev/null and b/stl/v3.3/case_b.png differ diff --git a/stl/v3.3/case_b.stl b/stl/v3.3/case_b.stl new file mode 100644 index 00000000..78b53456 Binary files /dev/null and b/stl/v3.3/case_b.stl differ diff --git a/stl/v3.3/fan_placement.jpg b/stl/v3.3/fan_placement.jpg new file mode 100644 index 00000000..25dc6149 Binary files /dev/null and b/stl/v3.3/fan_placement.jpg differ diff --git a/stl/v3.3/index.html b/stl/v3.3/index.html new file mode 100644 index 00000000..88b22821 --- /dev/null +++ b/stl/v3.3/index.html @@ -0,0 +1,2827 @@ + + + + + + + + + + + + + + + + + + + + + + PiKVM v3.3 Plastic Case for 3D printing - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

PiKVM v3.3 Plastic Case for 3D printing

+

When printing the case, you can choose the following options:

+
    +
  • The presence or absence of an OLED screen (used to display the IP address and other information).
  • +
+

Also take a look at the PCI bracket for ATX adapter board and great unofficial case mod for Noctua fans

+

Buy options

+ +

Parts

+

The front part

+

Choose ONE of them.

+ + + + + + + + + + + + + + + + + +
VariantDescription
The front part of the case WITHOUT a hole for the OLED
The front part of the case with a hole for installing the OLED
+

The back part

+ + + + + + + + + + + + + +
VariantDescription
The back part of the case
+

Spacers

+ + + + + + + + + + + + + + + + + + + + + +
TypeDescription
6.2mm spacer, required TWO pieces
1mm spacer required TWO pieces
Low spacer required ONE piece
+

Fasteners (screws)

+

The official PiKVM v3.3 hat came with eight M2.5 x 12mm screws for countersunk holes. You can use these with the case.

+

Assembly

+

+

Note: the spacers slide over the (short) hexagonal standoffs included in the official v3.3 hat:

+

+

To assemble:

+
    +
  1. Ensure the hexagonal standoffs are all attached to the top side of the v3.3 hat. Tip: if you need to remove the case in the future, you don't want these hexagonal standoffs spinning while you loosen the screws - be sure to tighten the standoffs more than you tighten the screws in step 17. You could even use some thread-locking fluid on the standoffs now.
  2. +
  3. Ensure the bottom side of the Pi has no screws present
  4. +
  5. Ensure you have eight M2.5 x 12mm screws free for later use.
  6. +
  7. Slide the two short spacers over the two standoffs on the side of the hat which contains the ATX, keyboard/mouse emulation, and HDMI connector. See Figure 1.
  8. +
+ + + + + + + + + + + +
Figure 1: 1mm spacer placement
+
    +
  1. Slide the two long spacers over the two standoffs on the opposite side of the HAT - near the LEDs, power input, and console-over-ethernet connector. See Figure 2.
  2. +
+ + + + + + + + + + + +
Figure 2: Placement of 6.2mm spacers.
+
    +
  1. Attach the fan to the two headers labeled "fan" located next to the CSI ribbon cable and large capacitor.
  2. +
  3. Slide the fan into the slot on the front part of the case. The fan should move fan from outside to inside the case. For the fan in Figure 3, this means mounting with the label facing the inside of the case and the black lead connected to the negative (-) terminal on the PCB. Ensure the fan leads don't bind as you slide the fan in. See Figure 3.
  4. +
+ + + + + + + + + + + +
Figure 3: Fan placement
+
    +
  1. If you still have foam covering the GPI pins on the top side of the hat, now is a good time to remove them. Leaving this in place will restrict airflow.
  2. +
  3. Flip the PiKVM over and set the low spacer bracket you printed on the bottomside of the Pi with the straight edge facing away from the SD card. See Figure 4.
  4. +
+ + + + + + + + + + + +
Figure 4: Low spacer placement
+
    +
  1. While allowing the low spacer to continue resting on the Pi, gently slide the PiKVM into the front part of the case. Ensure the spacers clear the top of the case (likely facing away from you) and that the fan leads don't bind on anything. The low spacer should remain mostly in place thanks to the solder joints on the Pi.
  2. +
  3. If successful, the low spacer should be fairly close to aligning with the holes in the case. Use a small screwdriver or tweezers to fix the alignment. You may need to insert the screwdriver into the case along the inner face to push the low spacer towards the holes. See video for reference.
  4. +
  5. Insert 4 screws into the holes of the case and tighten enough so things don't fall out, but leave plenty of slack - you might need to push the electronics around slightly to align the holes in the next steps.
  6. +
  7. Now is a good time to power on the PiKVM and ensure the fan spins. It should come on automatically unless you explicitly disabled it yourself.
  8. +
  9. Slide the back part over the PiKVM and align with the front part you assembled in previous steps.
  10. +
  11. Ensure the case seats properly around the connectors.
  12. +
  13. Insert the remaining four screws into the case and tighten. If the holes don't line up, you can hold the case while pushing on some of the PiKVM connectors to shift the electronics inside the case.
  14. +
  15. Tighten all screws.
  16. +
  17. Tip your bartender.
  18. +
+ + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/stl/v3.3/low_spacer.png b/stl/v3.3/low_spacer.png new file mode 100644 index 00000000..4a94893f Binary files /dev/null and b/stl/v3.3/low_spacer.png differ diff --git a/stl/v3.3/low_spacer.stl b/stl/v3.3/low_spacer.stl new file mode 100644 index 00000000..a3ba5b08 Binary files /dev/null and b/stl/v3.3/low_spacer.stl differ diff --git a/stl/v3.3/low_spacer_placement.jpg b/stl/v3.3/low_spacer_placement.jpg new file mode 100644 index 00000000..865f67ac Binary files /dev/null and b/stl/v3.3/low_spacer_placement.jpg differ diff --git a/stl/v3.3/spacer_1mm.png b/stl/v3.3/spacer_1mm.png new file mode 100644 index 00000000..2f77de35 Binary files /dev/null and b/stl/v3.3/spacer_1mm.png differ diff --git a/stl/v3.3/spacer_1mm.stl b/stl/v3.3/spacer_1mm.stl new file mode 100644 index 00000000..f9f4b6a1 Binary files /dev/null and b/stl/v3.3/spacer_1mm.stl differ diff --git a/stl/v3.3/spacer_6.2mm.png b/stl/v3.3/spacer_6.2mm.png new file mode 100644 index 00000000..b631e5bc Binary files /dev/null and b/stl/v3.3/spacer_6.2mm.png differ diff --git a/stl/v3.3/spacer_6.2mm.stl b/stl/v3.3/spacer_6.2mm.stl new file mode 100644 index 00000000..467b5463 Binary files /dev/null and b/stl/v3.3/spacer_6.2mm.stl differ diff --git a/stl/v3.3/spacers.jpg b/stl/v3.3/spacers.jpg new file mode 100644 index 00000000..f12ff99f Binary files /dev/null and b/stl/v3.3/spacers.jpg differ diff --git a/stl/v3.3/spacers_placement.jpg b/stl/v3.3/spacers_placement.jpg new file mode 100644 index 00000000..e944ae7d Binary files /dev/null and b/stl/v3.3/spacers_placement.jpg differ diff --git a/switch/conn_kvm_to_switch.png b/switch/conn_kvm_to_switch.png new file mode 100644 index 00000000..4ea5d8ea Binary files /dev/null and b/switch/conn_kvm_to_switch.png differ diff --git a/switch/conn_kvm_to_switch.xcf b/switch/conn_kvm_to_switch.xcf new file mode 100644 index 00000000..b9bc4d5c Binary files /dev/null and b/switch/conn_kvm_to_switch.xcf differ diff --git a/switch/conn_switch_to_switch.png b/switch/conn_switch_to_switch.png new file mode 100644 index 00000000..f205af82 Binary files /dev/null and b/switch/conn_switch_to_switch.png differ diff --git a/switch/conn_switch_to_switch.xcf b/switch/conn_switch_to_switch.xcf new file mode 100644 index 00000000..e670b825 Binary files /dev/null and b/switch/conn_switch_to_switch.xcf differ diff --git a/switch/index.html b/switch/index.html new file mode 100644 index 00000000..0921f472 --- /dev/null +++ b/switch/index.html @@ -0,0 +1,3040 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + PiKVM Switch Multiport Extender Quickstart Guide - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

PiKVM Switch Multiport Extender

+
+

Where to buy?

+ +
+

PiKVM Switch

+

PiKVM Switch Datasheet (PDF)

+

The PiKVM Switch Multiport Extender enables one PiKVM device to view and control multiple target +computers connected to each port. Target computers are viewed using HDMI video capture and then +controlled via USB and ATX connections. Up to five Switch Multiport Extenders can be daisy-chained +for a total of 20 ports. This is the maximum number of target computers that can be controlled by +each supported PiKVM device.

+

Thanks to the modularity of PiKVM and the new Switch, you can build up your infrastructure gradually, +adding new Switches as needed, without replacing the KVM entirely.

+

One target system at a time can be selected for HDMI video capture and USB control. ATX statuses +and controls are available for all connected targets simultaneously. Video inputs include dedicated +EDID (HDMI information and display parameters) and full control of the video connection state of +each port.

+

The PiKVM Switch is fully plug-and-play.

+

It is compatible with PiKVM V4 Plus, PiKVM V3, DIY V2 and DIY V1 devices.

+

Please note that it's not compatible with PiKVM V4 Mini and DIY devices based on Raspberry Pi Zero boards +because of the lack of available USB host ports.

+
+

Installation requirements

+
    +
  • +

    Head device: PiKVM V4 Plus (recommended) or any other PiKVM except V4 Mini and Zero-based DIY.

    +
  • +
  • +

    The PiKVM Switch box includes:

    +
      +
    • Switch device
    • +
    • Power supply unit
    • +
    • DC Barrel Jack Cable
    • +
    • HDMI 2.0 Cable
    • +
    • USB-A Male To USB-C Female Adapter
    • +
    • 2x USB Cable, USB-C Male
    • +
    • 4x ATX kit with brackets and wires
    • +
    +
  • +
  • +

    Some cables are not included in the kit, but are required to connect each target host port:

    +
      +
    • HDMI 2.0 cable (no shorter than 30 centimeters).
    • +
    • USB-A to USB-C cable
    • +
    • Straight Ethernet cable for ATX connection.
    • +
    +
  • +
+
+

Setup

+
    +
  1. +

    Turn off the head PiKVM device.

    +
  2. +
  3. +

    Unpack the box. Turn Switch in your hands and study the purpose of the ports. + Lovingly pat the top cover to show it that you want to be friends.

    +
      +
    • The numbered ports on the front can be used to connect to the target hosts.
    • +
    • UPLINK ports should be connected to PiKVM or to the superior chained Switch.
    • +
    • DOWNLINK ports should be connected to a lower-level Switch.
    • +
    +
  4. +
  5. +

    Connect Switch to PiKVM according to the following diagram. + Example connections with PiKVM V4 Plus are shown, + but similar connections can be made for any supported model.

    +

    +
      +
    • (1) OTG connection for USB emulation (using Type-C cable).
    • +
    • (2) Video (using HDMI cable).
    • +
    • (3) USB control connection (using Type-C cable and included C-to-A adapter).
    • +
    • (4) Optional power chaining. If you're using PiKVM V4 Plus, + both PiKVM and Switch can be powered from a single 12V power supply. + Use the supplied two-way power cable to connect the PiKVM and Switch.
    • +
    • (5) Connect the supplied 12V power supply here.
    • +
    +
    +

    Double power supply is not allowed

    +
      +
    • +

      When power chaining (4), never use your own 5V power port on the PiKVM V4.

      +
    • +
    • +

      The two 12V connectors on the Switch are designed for chaining only. Never connect two power supplies to your Switch.

      +
    • +
    +
    +

    If you want to connect multiple Switches in a chain, use the following diagram. +Two connected units can be considered as a single device, and the left group of UPLINK ports areused +in a similar way: either connect it to a PiKVM as in the previous step, or connect to another Switch to.

    +

    +
    +

    Chaining limit

    +

    A maximum of 5 Switch units can be connected in a chain.

    +
    +
  6. +
  7. +

    Connect the target hosts to the numbered ports on the front panel of Switch.

    +
      +
    • HDMI for a video (don't use a cable shorter than 50 centimeters).
    • +
    • USB-C for USB emulation.
    • +
    • Optional ATX for power management of the host.
    • +
    +
  8. +
  9. +

    PiKVM Switch is a Plug-n-Play device, so you don't need to write any complex configs. + All you need is a fresh PiKVM OS and drivers that can be obtained by updating.

    +
    +

    Check the OS image

    +

    To store the settings, Switch uses the Persistent Storage feature, +which is presented in images older than 2022.06.20. To check if your +PiKVM OS supports this, use the following command:

    +
    [root@pikvm ~]# mount | grep '\<pst\>'
    +/dev/mmcblk0p2 on /var/lib/kvmd/pst type ext4 (ro,nosuid,nodev,noexec,relatime,errors=remount-ro)
    +
    +

    If the output is similar to the above (/var/lib/kvmd/pst), then everything is fine. +Otherwise on empty output, you need to reflash the OS.

    +
    +

    Do the update anyway (even if you did reflashing):

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
  10. +
  11. +

    It's done! PiKVM will automatically configure all your Switches.

    +
  12. +
+
+

Working with the Switch

+

All the functions of the Switch are available through the menu, which you will see in the PiKVM interface. +The attached example uses two Switches, and switching between their ports works transparently.

+

+
    +
  • +

    The menu title shows the current active port (1.4) in unit.port format, + and the status of the ATX power and HDD LEDs for its host.

    +
  • +
  • +

    (1) The Settings button shows the common chain settings window (see below).

    +
  • +
  • +

    (2) The ports are grouped by physical units, the sub-header of the table shows + the unit 1 and the ports following it: 1.1, 1.2, 1.3 and 1.4.

    +
  • +
  • +

    (3) Beacon activation buttons for the UPLINK and DOWNLINK ports on the back of the Switch unit 1. + When activated, the corresponding multifunction LED on the back of the Switch will start flashing + to make it easier to find its connectors. This is especially useful if you have several Switches in a chain.

    +
  • +
  • +

    (4) The port switching button. The green color indicates the current active port.

    +
  • +
  • +

    (5) A button for configuring individual port parameters such as name, EDID, and more.

    +
  • +
  • +

    (6) The beacon activation button for the selected port activates the flashing LED + on the numbered group of connectors on the front of the Switch unit.

    +

    There are four indicators to the right: host video detected, USB detected, +ATX power and HDD LEDs. Next, three ATX action buttons.

    +
  • +
  • +

    (7) The title of the sub-table of the Switch unit 2. The units are numbered according to the closeness + to PiKVM device: Switch number 1 is connected directly to PiKVM, unit 2 is connected to downlink of unit 1.

    +
  • +
+

In the settings menu, you can access the EDIDs Collection and customize the color scheme of the Switch LEDs.

+

Chain settings

+

In the settings menu, you can access the EDIDs Collection and customize the color scheme of the Switch LEDs.

+

Each port can use its own EDID which must be preloaded into the Collection, otherwise it will use +the default EDID (taken from PiKVM). Binary and text EDID in HEX format are supported.

+ + + + + + + + + + + + + +
EDIDs CollectionColor scheme
+

Port settings

+

+

In the port settings, you can set the display name (can be used for the name of the connected host) +and the individual EDID from the Collection.

+

Other parameters relate to the ATX intervals for pressing the power and reset buttons of the target host.

+
+

Firmware updating

+

Sometimes we release firmware updates for the Switch, which are distributed along with PiKVM OS updates. +When the software detects that your switch has an old firmware, it will inform you about it via +the web interface. After that, you will be able update the Switch.

+

If you have several switches in the chain, then all devices will be updated: first, PiKVM uploads the update +to the first switch, then it updates the next one, and so on. +This is very convenient because you don't have to perform complex manual manipulations to maintain your equipment. +The Switches are intelligent and save you time.

+
+

Warning

+

We recommend updating the firmware only if you have physical access to the hardware.

+

Switches are extremely difficult to brick, but if there is a power failure during updating, +you will need physical access to restore the device. So don't worry, it can't be bricked forever.

+

It is also recommended to perform all the operations described below via SSH, and not via a web terminal.

+
+

Performing update

+

Just run these commands via SSH under root:

+
[root@pikvm ~]# cd /usr/share/kvmd/switch
+[root@pikvm switch]# systemctl stop kvmd   # This will stop the KVM web service
+[root@pikvm switch]# make install          # Flash the first switch
+[root@pikvm switch]# systemctl start kvmd  # Start it again
+
+

The switches will show the progress of the update on the front LEDs and will gradually return to service.

+
+

Known issues

+
+A DIY PiKVM device based on HDMI-CSI board does not receive a video through the Switch +

Some HDMI-CSI boards does not follow the HDMI specification correctly. +We have provided a special compatibility mode for them, +which should be enabled using the following configuration:

+
    +
  1. +

    Switch filesystem to RW-mode:

    +
    [root@pikvm ~]# rw
    +
    +
  2. +
  3. +

    Add some lines to /etc/kvmd/override.yaml:

    +
    kvmd:
    +    switch:
    +        ignore_hpd_on_top: true
    +
    +
  4. +
  5. +

    Restart KVMD:

    +
    [root@pikvm ~]# systemctl restart kvmd
    +
    +
  6. +
  7. +

    Switch filesystem back to RO-mode:

    +
    [root@pikvm ~]# ro
    +
    +
  8. +
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/switch/switch.png b/switch/switch.png new file mode 100644 index 00000000..3b838ccd Binary files /dev/null and b/switch/switch.png differ diff --git a/switch/switch_back.jpg b/switch/switch_back.jpg new file mode 100644 index 00000000..1844188f Binary files /dev/null and b/switch/switch_back.jpg differ diff --git a/switch/switch_back_blank.jpg b/switch/switch_back_blank.jpg new file mode 100644 index 00000000..c94e8e27 Binary files /dev/null and b/switch/switch_back_blank.jpg differ diff --git a/switch/switch_datasheet.pdf b/switch/switch_datasheet.pdf new file mode 100644 index 00000000..98434dbb Binary files /dev/null and b/switch/switch_datasheet.pdf differ diff --git a/switch/switch_front.jpg b/switch/switch_front.jpg new file mode 100644 index 00000000..f621564d Binary files /dev/null and b/switch/switch_front.jpg differ diff --git a/switch/switch_front_blank.jpg b/switch/switch_front_blank.jpg new file mode 100644 index 00000000..eda750e7 Binary files /dev/null and b/switch/switch_front_blank.jpg differ diff --git a/switch/ui_menu.png b/switch/ui_menu.png new file mode 100644 index 00000000..66d58762 Binary files /dev/null and b/switch/ui_menu.png differ diff --git a/switch/ui_port.png b/switch/ui_port.png new file mode 100644 index 00000000..1ee743aa Binary files /dev/null and b/switch/ui_port.png differ diff --git a/switch/ui_settings_colors.png b/switch/ui_settings_colors.png new file mode 100644 index 00000000..948999ff Binary files /dev/null and b/switch/ui_settings_colors.png differ diff --git a/switch/ui_settings_edid.png b/switch/ui_settings_edid.png new file mode 100644 index 00000000..829e8857 Binary files /dev/null and b/switch/ui_settings_edid.png differ diff --git a/switch/v4plus_back.jpg b/switch/v4plus_back.jpg new file mode 100644 index 00000000..a166d2a5 Binary files /dev/null and b/switch/v4plus_back.jpg differ diff --git a/switch/v4plus_front.jpg b/switch/v4plus_front.jpg new file mode 100644 index 00000000..5c1e4c31 Binary files /dev/null and b/switch/v4plus_front.jpg differ diff --git a/tailscale/index.html b/tailscale/index.html new file mode 100644 index 00000000..701f488a --- /dev/null +++ b/tailscale/index.html @@ -0,0 +1,3049 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Tailscale VPN - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

Tailscale VPN

+ +

The Tailscale VPN can be used to access PiKVM +from the Internet if configuring port forwarding +is not possible or more security is desired. Tailscale is a convenient +and free (for private use) tool for organizing a small VPN network.

+

The basic Tailscale configuration commands are shown below. For detailed +instructions, refer to Tailscale +support.

+
+

Configuring the PiKVM

+
    +
  1. +

    Update OS:

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
  2. +
  3. +

    Install the Tailscale client, run tailscaled service and register it in the network:

    +
    [root@pikvm ~]# rw
    +# If you were afraid to pikvm-update above first run pacman -Syy
    +[root@pikvm ~]# pacman -S tailscale-pikvm
    +[root@pikvm ~]# systemctl enable --now tailscaled
    +[root@pikvm ~]# tailscale up
    +
    +
  4. +
  5. +

    Follow the link to authorize this installation. + You likely want to disable key expiry!

    +
  6. +
  7. +

    After authorization success, reboot to make sure that everything works correctly:

    +
    [root@pikvm ~]# reboot
    +
    +
  8. +
  9. +

    Now, you can view the IP address of the Tailscale network interface:

    +
    [root@pikvm ~]# ip addr show tailscale0
    +
    +
  10. +
+

If everything is successful, PiKVM will become a member of your VPN network.

+
+

Do not update Tailscale if you don't have access to PiKVM without VPN

+

Unfortunately, sometimes, updating the Tailscale client can cause problems due to +breaking changes. These are compatibility issues on the Tailscale side. +Remember this when updating.

+
+
+

Configuring a client device

+
    +
  • Download and install the Tailscale client + to the system you are using (not to the system you want to control).
  • +
  • Check the Tailscale admin page to view your VPN network.
  • +
  • Follow the URL in the web browser: https://<tailscale_kvm_ip> and you will see the PiKVM web interface.
  • +
+
+

Using Tailscale Certificates

+

PiKVM uses self-signed SSL certificates out of the box. You can also use +Tailscale certificates in place of the default one.

+
+

Warning

+

Tailscale certificates are provided by Let's Encrypt and has a default +expiry of 90 days. +There is currently no mechanism available to auto-renew Tailscale +certificate. You may put the commands below in a script to simplify +process.

+
+
    +
  1. +

    Switch filesystem to RW if in ReadOnly mode and delete existing PiKVM certificates for nginx and vnc.

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# rm -v /etc/kvmd/{nginx,vnc}/ssl/*.{crt,key}
    +
    +
  2. +
  3. +

    Provision new certificates using tailscale cert + command. Optionally you may create a directory to store the certificates.

    +
    [root@pikvm ~]# mkdir .cert
    +[root@pikvm ~]# cd .cert
    +[root@pikvm .cert]# tailscale cert <tailscale_hostname>
    +
    +
  4. +
  5. +

    Copy the certificates to nginx's and vnc's ssl directories.

    +
    [root@pikvm ~]# cp /root/.cert/<tailscale_hostname>.key /etc/kvmd/nginx/ssl/server.key
    +[root@pikvm ~]# cp /root/.cert/<tailscale_hostname>.crt /etc/kvmd/nginx/ssl/server.crt
    +
    +

    Repeat the same steps for vnc if you have configured it.

    +
    [root@pikvm ~]# cp /root/.cert/<tailscale_hostname>.key /etc/kvmd/vnc/ssl/server.key
    +[root@pikvm ~]# cp /root/.cert/<tailscale_hostname>.crt /etc/kvmd/vnc/ssl/server.crt
    +
    +
  6. +
  7. +

    Grant file ownership to nginx and vnc services. Switch filesystem to ReadOnly again

    +
    [root@pikvm ~]# chown :kvmd-nginx /etc/kvmd/nginx/ssl/*
    +[root@pikvm ~]# chown :kvmd-vnc /etc/kvmd/vnc/ssl/*
    +[root@pikvm ~]# ro
    +
    +
  8. +
  9. +

    Restart nginx and vnc services

    +
    [root@pikvm ~]# systemctl restart kvmd-nginx
    +[root@pikvm ~]# systemctl restart kvmd-vnc
    +
    +
  10. +
+
+

Automated Ephemeral Tailscale Certificates Renewal

+

Tailscale has a nice option of running an HTTPS on your behalf within your tailnet: tailscale serve. It is using Let's Encrypt certificates and renews them every 90 days. The issue is that PiKVM’s filesystem is read-only. While tailscale will diligently request new certificates, it will fail to write it on the disk and hence will try to request new certificates next time you access your web server. Let's Encrypt has a limit of 5 certificates for the server per week, so you will end up with an inoperable server and rate-limited by Let's Encrypt for a day or so.

+

Here's the command that allows you to seamlessly run HTTPS proxy for your PiKVM: +

[root@pikvm ~]# tailscale serve --bg https+insecure://localhost:443
+
+And if you want to stop tailscale from serving HTTPS, you can do this by running: +
[root@pikvm ~]# tailscale serve --https=443 off
+````
+
+### Root cause
+Tailscale needs to refresh TLS certificates and write state under `/var/lib/tailscale`.  
+On PiKVM, the root filesystem is read-only, so direct writes fail.  
+
+We can fix this by mounting an **ephemeral overlay filesystem (tmpfs) in RAM** for `/var/lib/tailscale`, backed by a persistent lowerdir (`/root/tailscale-state`).
+
+This ensures that certificate rotation and state writes work without breaking PiKVM’s read-only state.
+
+!!! warning
+    The **caveat** is that renewed certificates exist only in RAM. After a reboot, Tailscale falls back to the older certificates on disk, requests fresh ones, and stores them in RAM again.
+    If you reboot PiKVM too frequently, this can trigger Let's Encrypt's rate limits.
+
+### Solution
+
+Core idea:
+- Mount a **tmpfs** over Tailscale's state folder stored in root's home: /root/tailscale-state. 
+- Mount the resulting *merged* layer onto the actual Tailscale state folder at /var/lib/tailscale.
+- An **overlayfs** will transparently present this folder to Tailscale, while changes are kept in the RAM-based overlay layer.
+
+**Note**: Overlayfs requires that the upperdir and workdir exist before creating the overlay.
+Since these directories live in RAM, they disappear after every reboot.
+This means we cannot use fstab to declare the mount points.
+Instead, we implement this with a systemd service that runs a setup script during boot, before tailscaled starts.
+
+1. Switch filesystem to RW and copy Tailscale state:
+
+```console
+[root@pikvm ~]# rw
+[root@pikvm ~]# cp -a /var/lib/tailscale /root/tailscale-state
+````
+
+2. Create a helper script, save as `/usr/local/bin/setup-tailscale-overlay.sh`:
+
+```bash
+#!/bin/bash
+set -e
+
+# Make tmpfs for tailscale overlay
+mkdir -p /tmp/tailscale-tmpfs
+mountpoint -q /tmp/tailscale-tmpfs || mount -t tmpfs tmpfs /tmp/tailscale-tmpfs
+
+# Prepare overlay dirs
+mkdir -p /tmp/tailscale-tmpfs/upper
+mkdir -p /tmp/tailscale-tmpfs/work
+mkdir -p /tmp/tailscale-merged
+
+# Mount overlay (lowerdir = persistent readonly state in /root)
+mountpoint -q /tmp/tailscale-merged || mount -t overlay overlay \
+  -o lowerdir=/root/tailscale-state,upperdir=/tmp/tailscale-tmpfs/upper,workdir=/tmp/tailscale-tmpfs/work \
+  /tmp/tailscale-merged
+
+# Bind merged to /var/lib/tailscale
+mountpoint -q /var/lib/tailscale && umount /var/lib/tailscale || true
+mount --bind /tmp/tailscale-merged /var/lib/tailscale
+
+

Make it executable:

+
[root@pikvm ~]# chmod +x /usr/local/bin/setup-tailscale-overlay.sh
+
+
    +
  1. Create a systemd unit
  2. +
+

We need to run the overlay setup after /tmp is mounted but before tailscaled.service.

+

Save as /etc/systemd/system/tailscale-overlay.service:

+
[Unit]
+Description=Setup overlayfs for Tailscale
+After=local-fs.target tmp.mount
+Before=tailscaled.service
+
+[Service]
+Type=oneshot
+ExecStart=/usr/local/bin/setup-tailscale-overlay.sh
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
+
+

Notes:

+
    +
  • local-fs.target ensures all local filesystems (including /tmp tmpfs from fstab) are mounted.
  • +
  • tmp.mount is added explicitly in case your system defines it.
  • +
  • +

    Overlay is mounted and bound before tailscaled starts.

    +
  • +
  • +

    Enable and reload

    +
  • +
+
[root@pikvm ~]# systemctl daemon-reload
+[root@pikvm ~]# systemctl enable tailscale-overlay.service
+[root@pikvm ~]# ro
+
+
+

Boot sequence recap:

+
    +
  1. tmpfs is mounted at /tmp/tailscale-tmpfs
  2. +
  3. upper + work dirs are recreated inside tmpfs
  4. +
  5. overlay is mounted with /root/tailscale-state as lowerdir
  6. +
  7. overlay bind-mounted to /var/lib/tailscale
  8. +
  9. tailscaled.service starts with writable state
  10. +
+
+

Troubleshooting

+
    +
  • +

    If something does not work, the usual advice is to completely remove Tailscale from PiKVM and perform a clean installation:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Rscnd tailscale
    +[root@pikvm ~]# rm -rf /var/lib/tailscale /var/cache/tailscale
    +[root@pikvm ~]# reboot
    +
    +
  • +
+

Now, follow the instructions from the beginning to re-install Tailscale.

+
    +
  • +

    In case of certificate issues you can try the following steps to debug and fix.

    +
  • +
  • +

    Check if the services are running. If not please start them. For example, + web UI service can be checked using:

    +
    [root@pikvm ~]# systemctl status kvmd-nginx
    +
    +

    For VNC:

    +
    [root@pikvm ~]# systemctl status kvmd-vnc
    +
    +
  • +
  • +

    If the services are running but not accessible or showing a warning, check + the respective logs. For web UI:

    +
    [root@pikvm ~]# journalctl -xeu kvmd-nginx
    +
    +
  • +
  • +

    If the logs shows TLS/certificate/permissions errors, the issue may be with + file ownership. The services must have at least the group ownership of the + certificates. The ownership should look similar to this:

    +
    [root@pikvm ~]# ls -l /etc/kvmd/{nginx,vnc}/ssl
    +/etc/kvmd/nginx/ssl:
    +total 8
    +-r--r--r-- 1 root kvmd-nginx 2872 Jan  3 16:07 server.crt
    +-r--r----- 1 root kvmd-nginx  227 Jan  3 16:07 server.key
    +
    +/etc/kvmd/vnc/ssl:
    +total 8
    +-r--r--r-- 1 root kvmd-vnc 2872 Jan  3 16:07 server.crt
    +-r--r----- 1 root kvmd-vnc  227 Jan  3 16:07 server.key
    +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tesmart/index.html b/tesmart/index.html new file mode 100644 index 00000000..81f4d747 --- /dev/null +++ b/tesmart/index.html @@ -0,0 +1,2753 @@ + + + + + + + + + + + + + + + + + + + + + + TESMART managed multiport KVM switch - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

TESMART managed multiport KVM switch

+ +

The TESMART managed switch can be controlled by PiKVM to allow it to +connect to multiple hosts. A typical scenario is a single PiKVM device +which can control and switch between multiple hosts or servers using the +TESMART switch. UI elements can be added to the GPIO dropdown +to allow switching between hosts from the PiKVM webpage.

+

The instructions here were tested with the TESMART HKS1601A10 HDMI 16x1 +switch. This should work with +any of the other TESMART variants which have a LAN port - there is both +a 8x1 and 4x1 variant. This was tested with an RPI4, but as this is +executed over a network protocol, this should with almost anything.

+

Connections

+

From a high level, the TESMART switch uses standard connections to the host machines (USB-A to USB-B and HDMI). The Raspberry Pi OTG connector (the one coming from the USB-C port on a Pi 4 via the custom splitter cable or device) should be connected to one of the USB 2 output ports on the TESMART switch (not the keyboard/mouse port). Based on your specific devices, and to get boot images to mount, you may need to connect this through a USB 2 hub.

+
    +
  1. +

    Connect the USB-A cable from the Raspberry Pi OTG port to one of the TESMART switch USB 2 output ports on the back of the switch (not the keyboard/mouse ports).

    +
  2. +
  3. +

    Connect the HDMI out from the TESMART switch to the Raspberry Pi CSI-2 to HMDI input.

    +
  4. +
  5. +

    Connect the LAN port on the front of the switch using standard ethernet cable into one of your network switches.

    +
  6. +
  7. +

    Connect host USB and HDMI cables from the TESMART switch to the machines to be managed per the switch instructions.

    +
  8. +
+
+

Warning

+

There is a limitation in the underlying PiKVM software related to plugging video cables from a host which is already powered and connected to a monitor to a Raspberry Pi CSI2-HDMI encoder. These limitations apply equally when using the TESMART KVM switch. If video is not present in PiKVM, try keeping all host machines off and connecting them directly to the TESMART switch before powering the hosts on.

+
+

Setting the IP Address of the TESMART switch

+

In some ways, this is the most complex part of this. The default IP address of the TESMART switch is 192.168.1.10. If that happens to work with your IP addressing scheme and current set of addresses, then you may be all set. This IP address is not configurable via DHCP or other standard mechanisms. The only way to change it is with a Windows utility available on the TESMART Downloads Page.

+

If you need to change it, you will first need to connect to the switch with a Windows machine, most easily directly through an ethernet cord, with your Windows laptop (or VM) up and assigned to a fixed IP address, such as 192.168.1.5. Once you've launched the utility you will see this screen:

+

Configuration screen for TESMART Windows controller utility

+

On this screen, ensure you are on the "General" tab. Click the radio button for "Network control". Change the IP address to the default for the switch (may already be this -- 192.168.1.10). Press the "Connect" button. Should make the status light go green, as well as the selected port. If you do not get a connection here, you cannot proceed to change the IP address. To change the IP address, change to the "Settings" tab at the top. You will then see this screen:

+

Configuration screen for TESMART Windows controller utility

+

On this screen, change to your desired IP address, gateway, mask, and port. Then press apply. Watch the box on the right to see if it applied OK. Press Query again to double-check. The actual IP address will not be changed until you power off/power on the switch. Make sure you have these settings correct, because if you get them wrong you would have to connect over RS232/serial and not the network.

+

There may be alternatives other than changing the IP address in this manner if you don't have access to a Windows machine or if this address doesn't work for you. See this README for other options (Images and concepts from the bash file were borrowed for creation of this plugin). This also contains a summary of the protocol, which is also available on the TESMART downloads page.

+

Adding UI elements to control the KVM switch

+

The UI can be updated to add buttons to switch between KVM inputs and indicators for which input is currently selected. The instructions below will make these available in the PiKVM UI after clicking the "Switches" menu button in the KVM view.

+
    +
  1. +

    Enable read-write mode on the SD card via rw

    +
  2. +
  3. +

    Edit the /etc/kvmd/override.yaml file and include the following:

    +
    kvmd:
    +    gpio:
    +        drivers:
    +            tes:
    +                type: tesmart
    +                host: 10.10.1.10
    +                port: 5000
    +        scheme:
    +            server0_led:
    +                driver: tes
    +                pin: 0
    +                mode: input
    +            server0_switch:
    +                driver: tes
    +                pin: 0
    +                mode: output
    +                switch: false    
    +            server1_led:
    +                driver: tes
    +                pin: 1
    +                mode: input
    +            server1_switch:
    +                driver: tes
    +                pin: 1
    +                mode: output
    +                switch: false    
    +            server2_led:
    +                driver: tes
    +                pin: 2
    +                mode: input
    +            server2_switch:
    +                driver: tes
    +                pin: 2
    +                mode: output
    +                switch: false    
    +            server3_led:
    +                driver: tes
    +                pin: 3
    +                mode: input
    +            server3_switch:
    +                driver: tes
    +                pin: 3
    +                mode: output
    +                switch: false    
    +        view:
    +            table:
    +                - ["TESMART Switch"]
    +                - []
    +                - ["#Server 1", server0_led, server0_switch|Switch]
    +                - ["#Server 2", server1_led, server1_switch|Switch]
    +                - ["#Server 3", server2_led, server2_switch|Switch]
    +                - ["#Server 4", server3_led, server3_switch|Switch]
    +
    +
  4. +
  5. +

    Return to read-only mode for the sd card via ro

    +
  6. +
  7. +

    Restart the kvmd service: systemctl restart kvmd

    +
  8. +
+

Switching between hosts in the UI

+

To switch between hosts, enter the KVM UI and click the "Switches" menu. You should see your inputs, one of which will have a green circle indicating it is currently selected. Click the other inputs to change the selected host.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tesmart/tesmart_controller_1.png b/tesmart/tesmart_controller_1.png new file mode 100644 index 00000000..772f6a45 Binary files /dev/null and b/tesmart/tesmart_controller_1.png differ diff --git a/tesmart/tesmart_controller_2.png b/tesmart/tesmart_controller_2.png new file mode 100644 index 00000000..6ddd6947 Binary files /dev/null and b/tesmart/tesmart_controller_2.png differ diff --git a/usb/index.html b/usb/index.html new file mode 100644 index 00000000..ecb7ae5b --- /dev/null +++ b/usb/index.html @@ -0,0 +1,2945 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + USB configuration - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

USB configuration

+ +

PiKVM V2+ emulates a small set of USB devices to ensure normal +operation: a keyboard, mouse and mass storage +drive. However, the possibilities are not limited to this. +Optionally, you can add a USB ethernet, serial +port, or (exclusive to PiKVM V3 and V4 +Mini/Plus) a microphone to support two-way audio.

+

In rare cases, the target host's BIOS/UEFI may not understand such a +large number of emulated devices on single USB port, and some of them +may need to be disabled.

+

A complete USB configuration changing (adding or removing devices) +requires a reboot, but it is possible to temporarily disable and then +re-enable existing emulated devices in preset.

+
+

Basics

+

Each emulated USB device consumes a limited hardware resource called endpoints.

+

Depending on the device, the number of required endpoints varies:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
DeviceEndpoints
Keyboard, mouse1 for each
Mass Storage Drive2 for each
USB Microphone2
USB Ethernet, USB Serial3 for each
+

In total, PiKVM provides 9 endpoints for USB emulation, some of which are used by default:

+
    +
  • +

    PiKVM V2-V3 emulates one absolute mouse and one mass storage and uses 4 of 9 endpoints.

    +
  • +
  • +

    PiKVM V4 Mini/Plus also adds a relative mouse by default so it uses 5 of 9 endpoints.

    +
  • +
+

You can add other devices remaining endpoints, disable existing ones +at all to free some endpoints, or do this only temporarily.

+

Moreover, you can configure the preset with a large number of devices +(more than PiKVM allows by endpoints), and then dynamically enable only +the necessary ones.

+

If you have configured too many devices that consume more than +9 endpoints in total, the least important of them will be inactive. +You can enable them using dynamic configuration.

+

To configure additional devices, please refer to the corresponding pages:

+
    +
  • +

    USB Microphone - Two-way audio communication for voice + applications on the target host. Exclusive to PiKVM V3 and V4 Mini/Plus.

    +
  • +
  • +

    Absolute and relative mouse - The most convenient type + of mouse is an absolute mouse, but some BIOSes may not understand it. + In this case, the relative one will help you.

    +
  • +
  • +

    USB Ethernet - An FTP or Samba server on PiKVM + can be configured, and the target host will see this over the network. + It is also possible that PiKVM can work as a router to connect a host + to a big network.

    +
  • +
  • +

    USB Serial Port - It can be used for terminal access + from the target host to the PiKVM, or for any other purpose that + requires a serial connection.

    +
  • +
+

For information on how emulated devices are represented on the target host and how to change it, read here.

+
+

Default preset

+

Device setup includes two stages: adding to config and starting.

+

When you add a device as described on the pages above, it automatically +turns on after PiKVM reboot and becomes available on the target device. +This behaviour can be changed: the device will be created, but not +active until you turn it on dynamically.

+

The /etc/kvmd/override.yaml file is used for such changes. In the following example, +there are USB Serial Port and Microphone enabled, +but the serial port is not started by default:

+
otg:
+    devices:
+        serial:
+            enabled: true
+            start: false
+        audio:
+            enabled: true
+
+

The start parameter is also available for all USB devices, see kvmd -m for the entire configuration tree.

+

Dynamic configuration

+

Command-line utility

+

The kvmd-otgconf utility allows you to view and modify the USB configuration on the fly.

+

It will also inform you about the number of endpoints used.

+

Changing requires root permissions.

+

Let's take a look at the configuration:

+
[root@pikvm ~]# kvmd-otgconf 
+# Endpoints used: 5 of 9
+# Endpoints free: 4
++ hid.usb0  # [1]  Keyboard  # otg/devices/hid/keyboard/start
++ hid.usb1  # [1]  Absolute Mouse  # otg/devices/hid/mouse/start
++ hid.usb2  # [1]  Relative Mouse  # otg/devices/hid/mouse_alt/start
++ mass_storage.usb0  # [2]  Mass Storage Drive  # otg/devices/msd/start
+
+

Each line represents an emulated device, left to right:

+
    +
  • Plus or minus sign: the state (enabled or not).
  • +
  • The device name (e.g., hid.usb0).
  • +
  • The number of required endpoints (e.g., [2]).
  • +
  • The description (e.g., Absolute mouse).
  • +
  • Path to the relevant configuration parameter (e.g., otg/devices/hid/mouse/start) you can use to boot or not boot a service when kvmd launches.
  • +
+

Sometimes it's impossible to get into the UEFI/BIOS due to their bugs +in USB support, and you need to boot from the PiKVM mass storage.

+

In this case, you can disable all devices except keyboard and relative +mouse, and enter the BIOS:

+
[root@pikvm ~]# kvmd-otgconf -d mass_storage.usb0 uac2.usb0 hid.usb1
+# Endpoints used: 2 of 9
+# Endpoints free: 7
++ hid.usb0  # [1]  Keyboard  # otg/devices/hid/keyboard/start
+- hid.usb1  # [1]  Absolute Mouse  # otg/devices/hid/mouse/start
++ hid.usb2  # [1]  Relative Mouse  # otg/devices/hid/mouse_alt/start
+- mass_storage.usb0  # [2]  Mass Storage Drive  # otg/devices/msd/start
+
+

Then change the boot order in the BIOS by setting the USB sticks +as first priority.

+

Exit the BIOS, and turn on mass storage again. Use it as usual to boot +the image from PiKVM mass storage:

+
[root@pikvm ~]# kvmd-otgconf -e mass_storage.usb0
+# Endpoints used: 4 of 9
+# Endpoints free: 5
++ hid.usb0  # [1]  Keyboard  # otg/devices/hid/keyboard/start
+- hid.usb1  # [1]  Absolute Mouse  # otg/devices/hid/mouse/start
++ hid.usb2  # [1]  Relative Mouse  # otg/devices/hid/mouse_alt/start
++ mass_storage.usb0  # [2]  Mass Storage Drive  # otg/devices/msd/start
+
+

You can also enable uac2.usb0 and hid.usb1 again.

+

Web UI menu

+

Using the pseudo-GPIO driver, you can USB control devices via the menu in the web interface. +Read about GPIO basics here.

+

To setup the menu, use kvmd-otgconf --make-gpio-config to generate the configuration, and merge it +with your existing one in /etc/kvmd/override.yaml in a usual way.

+
+The example of kvmd-otgconf --make-gpio-config output +
# kvmd-otgconf --make-gpio-config
+kvmd:
+    gpio:
+        drivers:
+            otgconf:
+                type: otgconf
+        scheme:
+            hid.usb0:
+                driver: otgconf
+                mode: output
+                pin: hid.usb0
+                pulse: false
+            hid.usb1:
+                driver: otgconf
+                mode: output
+                pin: hid.usb1
+                pulse: false
+            hid.usb2:
+                driver: otgconf
+                mode: output
+                pin: hid.usb2
+                pulse: false
+            mass_storage.usb0:
+                driver: otgconf
+                mode: output
+                pin: mass_storage.usb0
+                pulse: false
+        view:
+            table:
+                - ["#Keyboard", "#hid.usb0", hid.usb0]
+                - ["#Absolute Mouse", "#hid.usb1", hid.usb1]
+                - ["#Relative Mouse", "#hid.usb2", hid.usb2]
+                - ["#Mass Storage Drive", "#mass_storage.usb0", mass_storage.usb0]
+
+
+

Please note that this menu is not dynamically generated, you need +to update the configuration if you added or deleted devices.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/usb_dynamic/index.html b/usb_dynamic/index.html new file mode 100644 index 00000000..55315c6d --- /dev/null +++ b/usb_dynamic/index.html @@ -0,0 +1,14 @@ + + + + + + Redirecting... + + + + + +You're being redirected to a new destination. + + diff --git a/usb_ethernet/index.html b/usb_ethernet/index.html new file mode 100644 index 00000000..958faf44 --- /dev/null +++ b/usb_ethernet/index.html @@ -0,0 +1,2967 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Ethernet-over-USB network - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Ethernet-over-USB

+ +

Specifically to PiKVM V2+. When combined with configuring a DNS server, FTP, or SMB (for example), this is a powerful way to extend the capabilities of PiKVM.

+
+

Basic configuration

+
+

USB limitations

+

Each emulated USB device consumes a limited hardware resource called endpoints.

+

Short info: by default, you can add only one additional USB device.

+

To get more information about the endpoints, add more devices, and flexibly manage the configuration on the fly, see here.

+
+
+

Info

+

Before exploring this page, we recommend to read the PiKVM configuration guide +so that you understand the terminology and how exactly the parameters described below change.

+
+
    +
  1. +

    Edit /etc/kvmd/override.yaml and add these lines:

    +
    otg:
    +    devices:
    +        ethernet:
    +            enabled: true
    +            driver: ecm
    +            host_mac: 48:6f:73:74:50:43
    +            kvm_mac: 42:61:64:55:53:42
    +
    +

    The enable: true option was used for activation the USB network. The values of the remaining options are described in the tables.

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    ParameterDefaultDescription
    host_mac<random>The MAC address of the host's network interface.
    kvm_mac<random>The MAC address of the network interface on the PiKVM side called usb0.
    driverecmProtocol driver of the USB network. Different drivers are required for different OS. See below.
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    DriverCompatibility with Operating Systems
    ecmLinux; Mac OS
    eemLinux
    rndis5Windows XP...7 1; Linux > 2.6.13
    rndisWindows >= 7 2; Linux > 2.6.13
    ncmWindows >= 10; Linux > 2.6.37; Mac OS
    +

    1: Manual driver installation is required. Download RNDIS 5 Windows
    +2: Automatic driver installation since KVMD 3.53.

    +
  2. +
  3. +

    To automatically configure the USB network on the host recommended using the service kvmd-otgnet. + It configures the firewall, assigns an address to the local PiKVM interface usb0 and starts DHCP so the target host can get the IPv4 address.

    +

    By default, the address 172.30.30.1/24 to interface usb0 will be assigned. +One of the other addresses from the network 172.30.30.0/24 will be assigned to the host when it requests it via DHCP.

    +

    For security reasons, all incoming connections from the host to the PiKVM side are blocked (except for ICMP and UDP port 67 which is used for DHCP). +If you want to allow access from the host to the PiKVM interface, you will need to add ports 80 and 443 to the whitelist using /etc/kvmd/override.yaml +file like this:

    +
    otgnet:
    +    firewall:
    +        allow_tcp: [80, 443]
    +
    +

    Other useful firewall options are listed here:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ParameterDefaultDescription
    allow_icmptrueOptional ICMP allowed to PiKVM.
    allow_tcp[]List of allowed TCP connections from the host to PiKVM.
    allow_udp[]List of allowed UDP connections from the host to PiKVM.
    forward_iface<none>Default gateway interface on PiKVM for network forwarding (see below).
    +

    See other parameters and command hooks in kvmd -m.

    +
  4. +
  5. +

    To enable the service, use the command systemctl enable kvmd-otgnet.

    +
  6. +
  7. +

    Perform reboot.

    +
  8. +
+

Routing via PiKVM

+

By default, kvmd-otgnet will configure network connection between PiKVM and the host only. +The target host controlled by PiKVM will not be able to reach other hosts beyond PiKVM. +If the full network access is required from the host through the USB-Ethernet feature (access all hosts PiKVM can access), +additional settings are needed in /etc/kvmd/override.yaml.

+
    +
  1. +

    Add network interface to forward requests to (default gateway) by adding a line forward_iface: <interface name> under the firewall section. + Typically it would be eth0 if the built-in ethernet port is used::

    +
    otgnet:
    +    firewall:
    +        forward_iface: eth0
    +
    +
  2. +
  3. +

    Add DNS server to provide host name resolution service. + For example, adding 8.8.8.8 as DNS server requires addition of dnsmasq dhcp options. + This can be done by adding following lines:

    +
    otgnet:
    +    commands:
    +        post_start_cmd_append:
    +        - "--dhcp-option=6,8.8.8.8"
    +
    +
  4. +
  5. +

    Combining above two together::

    +
    otgnet:
    +    firewall:
    +        forward_iface: eth0
    +    commands:
    +        post_start_cmd_append:
    +        - "--dhcp-option=6,8.8.8.8"
    +
    +
  6. +
  7. +

    To enable internet access for the target host, add the following to the otgnet configuration::

    +
     otgnet:
    +    iface:
    +        net: 10.65.0.0/28
    +
    +

    The 'net' parameter defines the network address range of the usb0 network. +The host will automatically receive an IP address within this network including the DNS servers defined under 'post_start_cmd_append'. +Note: This network should not be same as the network PiKVM is connected to.

    +

    See other parameters and command hooks in kvmd -m.

    +
  8. +
  9. +

    Don't forget to reboot.

    +
  10. +
+
+An example of what the config would look like for a host that can access PiKVM and has internet access: +
otgnet:
+    firewall:
+        allow_tcp: [80, 443]
+        forward_iface: wlan0
+    commands:
+        post_start_cmd_append:
+            - "--dhcp-option=6,1.1.1.1,1.0.0.1"
+    iface:
+        ip_cmd:
+            - /usr/bin/ip
+        net: 10.65.0.0/28
+
+
+

Working with Windows Computers

+

This has been proven to work with Windows:

+
    +
  1. +

    Set the driver type to rndis (see above).

    +
  2. +
  3. +

    Download this driver on the Windows machine and unzip it somewhere.

    +
  4. +
  5. +

    Open the devices manager:
    + grafik

    +
  6. +
  7. +

    Select Properties of the Composite KVM Device:
    + grafik

    +
  8. +
  9. +

    Select the RNDIS Device and click properties:
    + grafik

    +
  10. +
  11. +

    Switch to the Driver tab and then click Update driver.

    +
  12. +
  13. +

    Click Browse my computer for driver software:
    + grafik

    +
  14. +
  15. +

    Click Let me pick from a list of available drivers on my Computer:
    + grafik

    +
  16. +
  17. +

    From the list of available hardware types, scroll down and select Network adapters, then click Next:
    + grafik

    +
  18. +
  19. +

    Click Have disk:
    + grafik

    +
  20. +
  21. +

    Click Browse, navigate to the folder where you've stored the driver and select the RNDIS.inf, press Open and then OK:
    + grafik

    +
  22. +
  23. +

    Select Acer Netchip RNDIS/Ethernet Gadget and click Next:
    + grafik

    +
  24. +
  25. +

    Dismiss the warning about non-compatible drivers by clicking Yes:
    + grafik

    +
  26. +
  27. +

    You're done - the device should now be recognized:
    + grafik

    +
  28. +
  29. +

    Verify the card is working by pinging your PiKVM in a console: ping 172.30.30.1:
    + grafik

    +
  30. +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/usb_pass/index.html b/usb_pass/index.html new file mode 100644 index 00000000..b9194f6e --- /dev/null +++ b/usb_pass/index.html @@ -0,0 +1,2761 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + USB Passthrough - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

USB Passthrough

+

For USB keyboards and mice connected to PiKVM directly, USB passthrough allows forwarding their input to the host system. This feature is available for all versions of PiKVM except the v4 Mini (no available USB ports) or a DIY version based on Pi Zero/Pi Zero 2 (using a USB hub prevents utilizing the OTG which the passthru expects to be available). It works best with HDMI passthrough available on PiKVM V4 Plus.

+

Let's consider this setup:

+
    +
  • PiKVM V4 Plus connected to PiKVM switch;
  • +
  • A keyboard and a mouse connected to USB A ports on the PiKVM;
  • +
  • An external display connected to the PiKVM directly using HDMI out.
  • +
+

Example setup

+

With both HDMI passthrough and USB passthrough enabled, you would be able to do this:

+
    +
  • Switch between Computer 1 and Computer 2 connected to PiKVM Switch;
  • +
  • Control them directly from this single keyboard/mouse pair (in addition to remote control);
  • +
  • See the video output from the selected host on the local display.
  • +
+
+

Enabling USB passthrough

+

Follow these steps to enable USB passthrough on your PiKVM:

+
    +
  1. +

    Log into your PiKVM as root, either via SSH, web console, or USB serial connection.

    +
  2. +
  3. +

    You need KVMD 4.74+ to be able to use this feature. Update the PiKVM OS as root:

    +
    [root@pikvm ~]# pikvm-update
    +
    +
  4. +
  5. +

    PiKVM will reboot, log in as root again.

    +
  6. +
  7. +

    Run the following command to change acces to read-write, enable USB passthrough, and change acces to read-only again:

    +
    [root@pikvm ~]# rw; systemctl enable --now kvmd-localhid; ro
    +
    +
  8. +
+

Once you've done that, you should be able to use your USB keyboard and mouse connected directly to your PiKVM to control the host.

+
+

Toggling USB passthrough

+

Every once in a while you may want using keyboard/mouse to control your PiKVM instead of controlling a host. Once USB passthrough is enabled in the system, you can switch it on and off with shortcuts:

+
    +
  • +

    LeftAlt, LeftAlt, K (mnemonic KVM) disables keyboard/mouse grabbing and allows using the input devices with PiKVM locally, for example, for the console operating.

    +
  • +
  • +

    LeftAlt, LeftAlt, H (mnemonic Host) switches back to the passthrough mode and passes keyboard-mouse events to the host.

    +
  • +
+

Press these keys immediately one after another: LeftAlt, then LeftAlt again, then the mnemonic key.

+
+

Switching the PiKVM Switch channels

+

If you have one or two PiKVM Switches, you can use LeftAlt, LeftAlt, 1 (1-8) to switch between up to 8 channels.

+

For three or more PiKVM Switches, you need to use double numbers, e.g., LeftAlt, LeftAlt, 3, 2 (unit 3, channel 2).

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/usb_pass/usb-passthrough.png b/usb_pass/usb-passthrough.png new file mode 100644 index 00000000..fe467acf Binary files /dev/null and b/usb_pass/usb-passthrough.png differ diff --git a/usb_serial/index.html b/usb_serial/index.html new file mode 100644 index 00000000..41e1d30f --- /dev/null +++ b/usb_serial/index.html @@ -0,0 +1,2646 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Serial-over-USB connection - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Serial-over-USB

+ +

Specifically to V2+. This can be used for terminal access from the target host to the PiKVM, or for any other purpose that requires a serial connection. In the last case, you only need to perform step 1 and reboot.

+
+

USB limitations

+

Each emulated USB device consumes a limited hardware resource called endpoints.

+

Short info: by default, you can add only one additional USB device.

+

To get more information about the endpoints, add more devices, and flexibly manage the configuration on the fly, see here.

+
+
    +
  1. +

    Edit /etc/kvmd/override.yaml and add these lines:

    +
    otg:
    +    devices:
    +        serial:
    +            enabled: true
    +
    +
  2. +
  3. +

    Run the following command:

    +
    # echo ttyGS0 >> /etc/securetty
    +
    +
  4. +
  5. +

    Create the directory /etc/systemd/system/getty@ttyGS0.service.d and add a file file named override.conf into it. Afterwards edit the file and copy this into it:

    +
    [Service]
    +TTYReset=no
    +TTYVHangup=no
    +TTYVTDisallocate=no
    +
    +
  6. +
  7. +

    Run these comands:

    +
    # systemctl enable getty@ttyGS0.service
    +# reboot
    +
    +
  8. +
  9. +

    Once PiKVM is rebooted you will have access to a virtual serial port on the server that the USB is connected to. Use mingetty, screen, putty, or something like this to access the kvm from the server. The port is called /dev/ttyAMA0.

    +
  10. +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v1/index.html b/v1/index.html new file mode 100644 index 00000000..64960bea --- /dev/null +++ b/v1/index.html @@ -0,0 +1,3415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + DIY PiKVM V1 quickstart guide - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

DIY PiKVM V1 quickstart guide

+
+

So many choices!

+

There are many different options with sub-items, so you can choose what will suit you.
+However, we marked the recommended way by sign ✮ ✮ ✮

+
+
+

Required parts

+
    +
  1. +

    MicroSD card minimum 8Gb class 10.

    +
  2. +
  3. +

    Official USB-Micro Power Supply.

    +
  4. +
  5. +

    Raspberry Pi board:

    + +
  6. +
  7. +

    Video capture device:

    +
      +
    • ✮ ✮ ✮ HDMI-CSI bridge based on TC358743 chip.
      + Supports H.264 video encoding on Raspberry Pi 3, automatic resolution selection and the lowest possible latency.
    • +
    • ... or HDMI-USB dongle.
      + Only heavy MJPEG video, no resolution detection, big latency compared to HDMI-CSI. + Some users report hardware problems: the dongle may not work in the BIOS or simply stop working after a while. + It's a black box, and no one knows what's inside it. If you have problems with it, it will not be possible to fix them.
    • +
    +
  8. +
  9. +

    The Pico HID Keyboard & mouse emulator:

    +
      +
    • +

      x1 Raspberry Pi Pico board with soldered pins. Pico 2 is not supported right now.

      +
    • +
    • +

      x1 USB-A to Micro-USB cable.

      +
    • +
    • +

      x10 dupont wires female-female.

      +
    • +
    • +

      x1 1N5819 diode. It's optional but strongly recommended. Any similar one will do.

      +
      +

      Warning

      +

      The diode is needed to provide power to the Pico HID regardless of the target host state, +which prevents the backpowering problem. It will allow you to keep the keyboard buttons pressed +during the target host power cycle, which is, for example, important for MacOS to get into the boot menu.

      +

      Do not connect the red wire (the VSYS (Pico) -> 5V (Pi) line) without a diode. +If you can't find a diode, don't connect this wire at all.

      +
      +
    • +
    +
  10. +
  11. +

    Board-specific parts:

    +
    +

    ✮ ✮ ✮ "Nothing special for Raspberry Pi 2 or 3

    +
    +
    +Raspberry Pi Zero 2 W +
    +✮ ✮ ✮ HDMI-CSI bridge + +
    +
    +... or HDMI-USB dongle +
      +
    • x1 USB-A socket to USB-Micro adapter (female-male).
    • +
    +
    +
    +
  12. +
  13. +

    Optional features:

    +
    +✮ ✮ ✮ ATX controller to manage the target host's power +

    With this part, you will be able to remotely turn on, turn off and restart your computer!

    +
      +
    • x4 optocouplers + TLP241BF(F + or PC817X2NSZ9F (the input polarity must be observed) + or OMRON G3VM-61A1 + or OMRON G3VM-61AY1
      + Don't use random relay modules or random optocouplers! Some of these may not be sensitive enough + for the Raspberry Pi, some others may be low-level controlled. Either use relays that are activated by a high logic level, + or follow the design provided. See details here.
    • +
    • x4 390 Ohm resistors (see here for alternatives).
    • +
    • 2x 4.7 kOhm resistors.
    • +
    • x10+ dupont wires male-male.
    • +
    • x1 a breadboard.
    • +
    • various wires for the breadboard.
    • +
    +

    This can be partially replaced by using Wake-on-LAN in the software, but it will not allow +to reboot a hung system, and it is not as reliable as an ATX controller. Sometimes the Wake-on-LAN +on the host just stops working, for its own or network reasons.

    +
    +
    +PS/2 Keyboard & mouse +

    The use of PS/2 is intended for advanced users. Check out the additional list of details in advance +in the corresponding paragraph of the Pico HID manual.

    +
    +
    +VGA video capture +

    If you want to capture VGA from your server instead of HDMI, +buy the VGA-to-HDMI converter. +Some converters have issues with not supporting all resolutions and refresh rates.

    +
    +
  14. +
+
+

Setting up the hardware

+
    +
  1. +

    Video capture device:

    +
    +✮ ✮ ✮ HDMI-CSI bridge +

    Insert the flexible flat cable of the HDMI-CSI bridge into the narrow white connector on the Raspberry Pi +(the closest one to big USB sockets). It is labeled CAMERA. To insert you need to open the connector first. +On the Raspberry Pi side you can gently lift the black part up and a little bit sideways:

    + + + + + + + + + + + +
    Opening the MIPI CSI slot on the Raspberry Pi
    +

    For the HDMI-CSI bridge this operation depends on the version you bought. +Either pull it gently up as on the Raspberry or push it sideways. +Make sure that the cable is inserted on the correct side and until it stops, and then push the black latch back. +Avoid using force when pushing the cable in, as the slots bond to the PCB is quite fragile. +Never connect or disconnect the flat cable from a powered device. This is not Plug-and-Play, and you can damage it. +Also use only the cable that was included with the device package, or make sure that the third-party cable has the correct pinout.

    + + + + + + + + + + + +
    HDMI-CSI bridge connected to Raspberry Pi 4
    + + + + + + + + + + + +
    HDMI-CSI bridge connected to Raspberry Pi 2 W (using the adapter cable)
    +
    +
    +... or HDMI-USB dongle +
    +Raspberry Pi 2 & 3 +

    Connect USB dongle to exactly this port. It is bound in the software so the OS does not confuse the video device with something else.

    + + + + + + + + + + + + + +
    Raspberry Pi 2 and 3Raspberry Pi 4
    +

    There are many revisions of the Raspberry Pi boards and you may come across one that we haven't tested. +If the binding fails, the device will be available for all ports. +Everything will work, but if you use a webcam and Linux mistakes it for a dongle, +write to us and we will fix it.

    +
    +
    +Raspberry Pi Zero 2 W +

    Connect the USB dongle to USB-to-Micro adapter, and connect it to the USB port marked as USB (not PWR) +on the Pi Zero board:

    +

    +
    +
    +
  2. +
  3. +

    The Pico HID and ATX controller:

    +

    Connect all the parts according to this scheme:

    +
    +✮ ✮ ✮ With ATX controller +
    +Simple wiring diagram +

    +
    +
    +Electrical schematic diagram for advanced users +

    +
    +
    +
    +... or without ATX controller +
    +Simple wiring diagram +

    +
    +
    +Electrical schematic diagram for advanced users +

    +
    +
    +
  4. +
  5. +

    Flash firmware to the Pico HID.

    +
  6. +
  7. +

    Flash the memory card with PiKVM OS and insert it to Raspberry Pi.

    +
  8. +
+
+

Wiring

+
+

Warning

+

Double check that the circuit is assembled correctly to avoid any damage of the hardware.

+
+

PiKVM V1 requires several items available separately:

+
    +
  • +

    Ethernet cable (Raspberry Pi 2 and 3 only)

    +
  • +
  • +

    HDMI cable

    +
  • +
+

Let's connect all the wires before you power up the device.

+
    +
  1. +

    Connect the HDMI video capture device to the video output port on the target host.

    +
  2. +
  3. +

    Connect the Pico HID to the USB port on the target host.

    +
  4. +
  5. +

    Raspberry Pi 2/3: connect Ethernet to the network, e.g., to the Wi-Fi router.

    +
  6. +
  7. +
    +Connect the ATX controller if you built it +

    To control the power, two display LEDs (power and HDD activity) and two buttons (power and reset) are provided +on the front panel of the computer case. They are connected by wires to pins on the motherboard.

    +

    +

    All you have to do is connect the PiKVM ATX controller to their wires by making a parallel connection. +Please note that the pinout differs on different motherboards, so before you continue, +check the documentation on your motherboard for correct pinout.

    +

    The following illustration shows how the connection between the power LED and the power button should be performed:

    +

    +

    On the left are the wires from the PiKVM ATX controller, the pad in the middle indicates the pins on the motherboard, +and on the right are the LED and button of the target host. The implementation of this scheme is left to your discretion +and can be performed, for example, by cutting wires and performing twisting, followed by insulation with duct tape.

    +

    Be careful and respect the polarity of the LEDs. The polarity of the button does not matter (they have no polarity at all). +The connection of HDD LED and reset switch is performed in the same way.

    +
    +
  8. +
+
+

Power up

+

If everything is assembled correctly, attach the power supply to the Raspberry Pi.

+

After turning on the power, PiKVM OS generates unique SSH keys and certificates and performs all necessary operations on the memory card. It takes a few minutes.

+

Do not turn off the device until it's fully booted for the first time.

+
+

Configure the display

+

The operating system on your remote computer will treat PiKVM as an additional display and use it in the Extend mode by default. That's why you will see an empty desktop when you first connect.

+

To avoid that, go to the display settings in your remote computer's operating system and enable the mirror mode for the external screen that you operating system identifies as PiKVM. Refer to your operating system's documentation on that.

+
+

Access PiKVM

+

You need to know PiKVM's IP address in the network to be able to access it. Unlike PiKVM V3 and V4, PiKVM V1 doesn't have an OLED to display the IP address it receives automatically. You need to discover it manually. There are several ways to do that.

+
    +
  • Common way: Open the web interface of your router and find the list of issued IP addresses there.
  • +
  • Linux-only: Use the arp-scan --localnet command.
  • +
  • Linux, MacOS, Windows: Download and run Angry IP Scanner.
  • +
  • Windows PowerShell: Use the arp -a command.
  • +
+

Let's assume that PiKVM has received the address 192.168.0.26 and has also been assigned a hostname pikvm.

+

Type the URL in the browser's address bar and press Enter: https://192.168.0.26/ or https://pikvm/.

+

Login screen

+

Submit the default credentials and click Login:

+
    +
  • Username: admin
  • +
  • Password: admin
  • +
  • 2FA Code: disabled by default, skip this field
  • +
+

You will see the initial dashboard screen of the PiKVM where you can access the remote host, connect to the PiKVM command line, or log out:

+

Initial UI

+

Change the default passwords

+

For security's sake, it's best to change the default passwords immediately after running PiKVM for the first time.

+
+

Passwords are important!

+

Please ensure that you change both passwords: for Web UI access and for the Linux superuser (root).

+
+

To do that:

+
    +
  1. +

    On the initial dashboard screen, click the Terminal button to open the web terminal. You will see this command line interface:

    +

    PiKVM WebTerm

    +
  2. +
  3. +

    Gain Linux superuser privileges:

    +
    $ su -
    +
    +

    When prompted for password, use root.

    +
  4. +
  5. +

    Run rw to change the access to the SD card to the write mode:

    +
    [root@pikvm ~]# rw
    +
    +
  6. +
  7. +

    Change the password for the Linux superuser:

    +
    [root@pikvm ~]# passwd root
    +
    +

    Submit the new password, retype it the second time to confirm, press Enter, and you should see this:

    +
    passwd: password updated successfully
    +
    +
  8. +
  9. +

    Change the password for web access:

    +
    [root@pikvm ~]# kvmd-htpasswd set admin
    +
    +

    Submit the new password, retype it the second time to confirm, and press Enter.

    +
  10. +
  11. +

    Run ro to change the access to the SD card back to the read-only mode:

    +
    [root@pikvm ~]# ro
    +
    +
  12. +
  13. +

    Press Ctrl+D or type "exit" and press Enter to drop the root privileges.

    +
  14. +
  15. +

    Go back one page in the browser. You should be back to the initial dashboard screen.

    +
  16. +
+

Access the remote system

+
    +
  1. +

    On the initial dashboard screen, click the KVM button to access the remote host.

    +
  2. +
  3. +

    You should now see the host system's display and interact with it remotely using a keyboard and a mouse.

    +

    Work remotely

    +
  4. +
+
+

Important next steps

+
    +
  • +

    We strongly recommend to update the PiKVM OS after the first launch:

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
  • +
  • +

    Learn about basics of PiKVM OS Configuration: where to find configs, how to edit the, etc.

    +
    +Configuring PiKVM OS +
    +

    Need more info? We have it!

    +

    The following is a brief guide to configuring PiKVM. +For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), +please refer to this page.

    +
    +

    Most of the PiKVM configuration files are located in the /etc/kvmd directory.

    +

    The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. +To redefine system parameters use the file /etc/kvmd/override.yaml. +All other files that are also not recommended for editing have read-only permissions.

    +

    You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory +to split your customization into logical parts. +The override.yaml file definitions takes precedence over the override.d directory.

    +

    A complete list of all parameters can be viewed using the kvmd -m command.

    +

    Files with the *.yaml suffix uses the YAML syntax +and describes a parameter tree with key-value pairs of different types. +To define the parameters within one section, an indent of 4 spaces is used. +Comments starts with the # symbol.

    +
    +

    Only 4 spaces should be used for indentation

    +

    Be careful when editing YAML and follow this rule. +Invalid indentation or tabs instead of spaces will cause an error when starting the services.

    +
    +

    Sections under the same keys should be merged:

    +
      +
    • +

      Wrong:

      +
      kvmd:
      +    gpio:
      +        drivers: ...
      +kvmd:
      +    gpio:
      +        scheme: ...
      +
      +
    • +
    • +

      Correct:

      +
      kvmd:
      +    gpio:
      +        drivers: ...
      +        scheme: ...
      +
      +
    • +
    +

    In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

    +
    +
  • +
  • +

    Get to know PiKVM Web UI: read this help section to better understand all the possibilities of the web user interface.

    +
  • +
  • +

    Tune the HDMI dongle capture device if you're using it:

    +
    +Persistent HDMI cable connection with USB dongle +

    Many USB video capture devices tell the server's video card that the HDMI cable is supposedly disconnected. +This may lead to the fact that if you boot the server without an active stream, the server will not detect +your capture card. This is easy to fix:

    +
      +
    • +

      Switch filesystem to RW-mode: +

      [root@pikvm ~]# rw
      +
      +
    • +
    • +

      Edit file /etc/kvmd/override.yaml and add these lines: +

      kvmd:
      +    streamer:
      +        forever: true
      +        cmd_append: [--slowdown]
      +
      +
    • +
    • +

      Finish: +

      [root@pikvm ~]# ro
      +[root@pikvm ~]# systemctl restart kvmd
      +
      +
    • +
    • +

      Check that everything is working.

      +
    • +
    +
    +
  • +
+
+

Further recommendations

+ +
+

Known issues and limitations

+
    +
  • Max resolution.
    PiKVM V1 with CSI bridge can only handle the maximum resolution 1920x1080@50Hz, 60Hz is not supported due hardware limitation. You can use any other resolution less than the specified one, for example 1280x720@60Hz. If you have any problems with video on CSI bridge, follow this guide.
  • +
+
+

Basic troubleshooting

+
    +
  • +

    Ensure that you are using the right OS image for your platform + by running the following command: pacman -Q | grep kvmd-platform.

    +
  • +
  • +

    If you are not getting a display, run the two following commands:

    +
      +
    • dmesg | egrep 'tc35|1-1.4|uvc'
    • +
    • systemctl status kvmd-tc358743
    • +
    +

    If you see a failed message on that output, be sure verify the orientation of the CSI cable or try reseating it.

    +

    Note that this is not a hotplug device, and you must first turn off the power.

    +
  • +
+
+

Getting user support

+

If something doesn't work, check out our FAQ. Otherwise, head straight to our Support.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v1/v1_breadboard.png b/v1/v1_breadboard.png new file mode 100644 index 00000000..b4cbaeed Binary files /dev/null and b/v1/v1_breadboard.png differ diff --git a/v1/v1_scheme.png b/v1/v1_scheme.png new file mode 100644 index 00000000..6da9130f Binary files /dev/null and b/v1/v1_scheme.png differ diff --git a/v2/index.html b/v2/index.html new file mode 100644 index 00000000..36876a74 --- /dev/null +++ b/v2/index.html @@ -0,0 +1,3417 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + DIY PiKVM V2 quickstart guide - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

DIY PiKVM V2 quickstart guide

+
+

So many choices!

+

There are many different options with sub-items, so you can choose what will suit you.
+However, we marked the recommended way by sign ✮ ✮ ✮

+
+
+

Required parts

+
    +
  1. +

    MicroSD card minimum 16Gb class 10.

    +
  2. +
  3. +

    Raspberry Pi board:

    +
      +
    • ✮ ✮ ✮ Raspberry Pi 4 2Gb.
      + It makes no sense to buy a Pi 4 with more memory than 2Gb, since PiKVM software uses very few resources.
    • +
    • ... or Raspberry Pi Zero 2 W.
      + Compact and cheap, but not so reliable solution because of lack of the wired Ethernet.
    • +
    • ... Raspberry Pi 5 is not supported right now. It doesn't have GPU video encoders, therefore, + there is no point in using it for PiKVM, it will not give any performance boost for this case. + The Pi 5 is a great device, just not suitable for PiKVM.
    • +
    +
  4. +
  5. +

    Video capture device:

    +
      +
    • ✮ ✮ ✮ HDMI-CSI bridge based on TC358743 chip.
      +
      Supports H.264 video encoding, automatic resolution selection and the lowest possible latency.
    • +
    • ... or HDMI-USB dongle (not available for Pi Zero 2).
      + Only heavy MJPEG video, no resolution detection, big latency compared to HDMI-CSI. + Some users report hardware problems: the dongle may not work in the BIOS or simply stop working after a while. + It's a black box, and no one knows what's inside it. If you have problems with it, it will not be possible to fix them.
    • +
    +
  6. +
  7. +

    Board-specific: Power supply, USB connectivity, etc.

    +
    +✮ ✮ ✮ Raspberry Pi 4 +

    On a Raspberry Pi 4 only the USB-C port that receives power is capable of acting as a USB Device. +The other USB ports are capable only of acting as USB Hosts. +Therefore a special cable must be used on the USB power port that it can simultaneously act as USB Device +for the target host and receive external power from an power supply.

    +
    +✮ ✮ ✮ Variant #1: Power supply + ready-made Y-splitter module +
      +
    • x1 USB-C/Power Splitter Module (US/UK/CA).
    • +
    • x1 USB-C to USB-C cable (male-male) for connecting the Raspberry Pi to the splitter.
    • +
    • x1 USB-A to USB-C cable (male-male) for connecting the target host to the splitter.
    • +
    • x1 Official USB-C Power Supply.
    • +
    +
    +
    +... or Variant #2: Power supply + Y-splitter based on power blocker + +
    +
    +... or Variant #3: Power supply + DIY Y-splitter for soldering +
      +
    • x1 USB-A to USB-C cable (male-male).
    • +
    • x1 Another cable USB-A to any (male-any).
    • +
    • x1 Any 5V 3A power supply with USB-A socket.
    • +
    +
    +
    +
    +... or Raspberry Pi Zero 2 W + +
    +
  8. +
  9. +

    Optional features:

    +
    +✮ ✮ ✮ ATX controller to manage the target host's power +

    With this part, you will be able to remotely turn on, turn off and restart your computer!

    +
      +
    • x4 optocouplers + TLP241BF(F + or PC817X2NSZ9F (the input polarity must be observed) + or OMRON G3VM-61A1 + or OMRON G3VM-61AY1
      + Don't use random relay modules or random optocouplers! Some of these may not be sensitive enough + for the Raspberry Pi, some others may be low-level controlled. Either use relays that are activated by a high logic level, + or follow the design provided. See details here.
    • +
    • x4 390 Ohm resistors (see here for alternatives).
    • +
    • 2x 4.7 kOhm resistors.
    • +
    • x10+ dupont wires male-male.
    • +
    • x1 a breadboard.
    • +
    • various wires for the breadboard.
    • +
    +

    This can be partially replaced by using Wake-on-LAN in the software, but it will not allow +to reboot a hung system, and it is not as reliable as an ATX controller. Sometimes the Wake-on-LAN +on the host just stops working, for its own or network reasons.

    +
    +
    +VGA video capture +

    If you want to capture VGA from your server instead of HDMI, +buy the VGA-to-HDMI converter. +Some converters have issues with not supporting all resolutions and refresh rates.

    +
    +
  10. +
+

Kit parts suitable for assembly are also on sale in Poland.

+
+

Setting up the hardware

+
    +
  1. +

    Video capture device:

    +
    +✮ ✮ ✮ HDMI-CSI bridge +

    Insert the flexible flat cable of the HDMI-CSI bridge into the narrow white connector on the Raspberry Pi +(the closest one to big USB sockets). It is labeled CAMERA. To insert you need to open the connector first. +On the Raspberry Pi side you can gently lift the black part up and a little bit sideways:

    + + + + + + + + + + + +
    Opening the MIPI CSI slot on the Raspberry Pi
    +

    For the HDMI-CSI bridge this operation depends on the version you bought. +Either pull it gently up as on the Raspberry or push it sideways. +Make sure that the cable is inserted on the correct side and until it stops, and then push the black latch back. +Avoid using force when pushing the cable in, as the slots bond to the PCB is quite fragile. +Never connect or disconnect the flat cable from a powered device. This is not Plug-and-Play, and you can damage it. +Also use only the cable that was included with the device package, or make sure that the third-party cable has the correct pinout.

    + + + + + + + + + + + +
    HDMI-CSI bridge connected to Raspberry Pi 4
    + + + + + + + + + + + +
    HDMI-CSI bridge connected to Raspberry Pi 2 W (using the adapter cable)
    +
    +
    +... or HDMI-USB dongle +

    Connect USB dongle to exactly this port. It is bound in the software so the OS does not confuse the video device with something else.

    + + + + + + + + + + + + + +
    Raspberry Pi 2 and 3Raspberry Pi 4
    +

    There are many revisions of the Raspberry Pi boards and you may come across one that we haven't tested. +If the binding fails, the device will be available for all ports. +Everything will work, but if you use a webcam and Linux mistakes it for a dongle, +write to us and we will fix it.

    +
    +
  2. +
  3. +

    USB cable and power supply

    +
    +✮ ✮ ✮ Raspberry Pi 4 +
    +✮ ✮ ✮ Variant #1: Power supply + ready-made Y-splitter module +

    +
    +
    +... or Variant #2: Power supply + Y-splitter based on power blocker +

    +
    +
    +... or Variant #3: Power supply + DIY Y-splitter for soldering +

    It is assumed that if you have followed this path, you know how to handle a soldering iron and a multimeter.

    +

    The Y-splitter can be soldered from two suitable USB cables. Check the attached diagram. +The appropriate USB pinout(s) can easily be found on Google.

    +

    Please note that if you make a Y-cable from two no-name cables, the colors of the wires may not match those shown. +Use a multimeter to make sure the connections are correct.

    +

    +

    Video How-To: Making a USB Y-splitter cable

    +
    +
    +
    +... or Raspberry Pi Zero 2 W +

    This board has two USB micro connectors: one for power supply (marked as PWR) and the second for emulating +a USB gadget (marked as USB). Both connectors have a common power line, so to prevent Raspberry power from entering +the USB port of the target host, it is required to make a special USB A-to-Micro cable without power line.

    +

    One way is to physically cut the power wire inside the USB cable.

    +

    An easier way is to stick a piece of duct tape, as shown in this picture:

    +

    +

    Connect the power supply to the PWR, and your magic cable to the USB. The magic cable will be used +to connect the device to the target host.

    +
    +
  4. +
  5. +

    ✮ ✮ ✮ Optional feature: ATX controller

    +

    Connect all the parts according to this scheme:

    +
    +Simple wiring diagram +

    +
    +
    +Electrical schematic diagram for advanced users +

    +
    +
  6. +
  7. +

    Flash the memory card with PiKVM OS and insert it to Raspberry Pi.

    +
  8. +
+
+

Wiring

+
+

Warning

+

Double check that the circuit is assembled correctly to avoid any damage of the hardware.

+
+

PiKVM V2 requires several items available separately:

+
    +
  • Ethernet cable (Raspberry Pi 4 only)
  • +
  • HDMI cable
  • +
+

Let's connect all the wires before you power up the device.

+
    +
  1. +

    Connect the HDMI video capture device to the video output port on the target host.

    +
  2. +
  3. +

    Using the Y-cable, connect the Pi's OTG port to the USB on the target host.

    +
  4. +
  5. +

    Raspberry Pi 4: connect Ethernet to the network, e.g., to the WiFI router.

    +
  6. +
  7. +
    +Connect the ATX controller if you built it +

    To control the power, two display LEDs (power and HDD activity) and two buttons (power and reset) are provided +on the front panel of the computer case. They are connected by wires to pins on the motherboard.

    +

    +

    All you have to do is connect the PiKVM ATX controller to their wires by making a parallel connection. +Please note that the pinout differs on different motherboards, so before you continue, +check the documentation on your motherboard for correct pinout.

    +

    The following illustration shows how the connection between the power LED and the power button should be performed:

    +

    +

    On the left are the wires from the PiKVM ATX controller, the pad in the middle indicates the pins on the motherboard, +and on the right are the LED and button of the target host. The implementation of this scheme is left to your discretion +and can be performed, for example, by cutting wires and performing twisting, followed by insulation with duct tape.

    +

    Be careful and respect the polarity of the LEDs. The polarity of the button does not matter (they have no polarity at all). +The connection of HDD LED and reset switch is performed in the same way.

    +
    +
  8. +
+
+

Power up

+

If everything is assembled correctly, attach the power supply to the Raspberry Pi.

+

After turning on the power, PiKVM OS generates unique SSH keys and certificates and performs all necessary operations on the memory card. It takes a few minutes.

+

Do not turn off the device until it's fully booted for the first time.

+
+

Configure the display

+

The operating system on your remote computer will treat PiKVM as an additional display and use it in the Extend mode by default. That's why you will see an empty desktop when you first connect.

+

To avoid that, go to the display settings in your remote computer's operating system and enable the mirror mode for the external screen that you operating system identifies as PiKVM. Refer to your operating system's documentation on that.

+
+

Access PiKVM

+

You need to know PiKVM's IP address in the network to be able to access it. Unlike V3 and V4, PiKVM V2 doesn't have an OLED to display the IP address it receives automatically. You need to discover it manually. There are several ways to do that.

+
    +
  • Common way: Open the web interface of your router and find the list of issued IP addresses there.
  • +
  • Linux-only: Use the arp-scan --localnet command.
  • +
  • Linux, MacOS, Windows: Download and run Angry IP Scanner.
  • +
  • Windows PowerShell: Use the arp -a command.
  • +
+

Let's assume that PiKVM has received the address 192.168.0.26 and has also been assigned a hostname pikvm.

+

Type the URL in the browser's address bar and press Enter: https://192.168.0.26/ or https://pikvm/.

+

Login screen

+

Submit the default credentials and click Login:

+
    +
  • Username: admin
  • +
  • Password: admin
  • +
  • 2FA Code: disabled by default, skip this field
  • +
+

You will see the initial dashboard screen of the PiKVM where you can access the remote host, connect to the PiKVM command line, or log out:

+

Initial UI

+

Change the default passwords

+

For security's sake, it's best to change the default passwords immediately after running PiKVM for the first time.

+
+

Passwords are important!

+

Please ensure that you change both passwords: for Web UI access and for the Linux superuser (root).

+
+

To do that:

+
    +
  1. +

    On the initial dashboard screen, click the Terminal button to open the web terminal. You will see this command line interface:

    +

    PiKVM WebTerm

    +
  2. +
  3. +

    Gain Linux superuser privileges:

    +
    $ su -
    +
    +

    When prompted for password, use root.

    +
  4. +
  5. +

    Run rw to change the access to the SD card to the write mode:

    +
    [root@pikvm ~]# rw
    +
    +
  6. +
  7. +

    Change the password for the Linux superuser:

    +
    [root@pikvm ~]# passwd root
    +
    +

    Submit the new password, retype it the second time to confirm, press Enter, and you should see this:

    +
    passwd: password updated successfully
    +
    +
  8. +
  9. +

    Change the password for web access:

    +
    [root@pikvm ~]# kvmd-htpasswd set admin
    +
    +

    Submit the new password, retype it the second time to confirm, and press Enter.

    +
  10. +
  11. +

    Run ro to change the access to the SD card back to the read-only mode:

    +
    [root@pikvm ~]# ro
    +
    +
  12. +
  13. +

    Press Ctrl+D or type "exit" and press Enter to drop the root privileges.

    +
  14. +
  15. +

    Go back one page in the browser. You should be back to the initial dashboard screen.

    +
  16. +
+

Access the remote system

+
    +
  1. +

    On the initial dashboard screen, click the KVM button to access the remote host.

    +
  2. +
  3. +

    You should now see the host system's display and interact with it remotely using a keyboard and a mouse.

    +

    Work remotely

    +
  4. +
+
+

Important next steps

+
    +
  • +

    We strongly recommend to update the PiKVM OS after the first launch:

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
  • +
  • +

    Learn about basics of PiKVM OS Configuration: where to find configs, how to edit the, etc.

    +
    +Configuring PiKVM OS +
    +

    Need more info? We have it!

    +

    The following is a brief guide to configuring PiKVM. +For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), +please refer to this page.

    +
    +

    Most of the PiKVM configuration files are located in the /etc/kvmd directory.

    +

    The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. +To redefine system parameters use the file /etc/kvmd/override.yaml. +All other files that are also not recommended for editing have read-only permissions.

    +

    You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory +to split your customization into logical parts. +The override.yaml file definitions takes precedence over the override.d directory.

    +

    A complete list of all parameters can be viewed using the kvmd -m command.

    +

    Files with the *.yaml suffix uses the YAML syntax +and describes a parameter tree with key-value pairs of different types. +To define the parameters within one section, an indent of 4 spaces is used. +Comments starts with the # symbol.

    +
    +

    Only 4 spaces should be used for indentation

    +

    Be careful when editing YAML and follow this rule. +Invalid indentation or tabs instead of spaces will cause an error when starting the services.

    +
    +

    Sections under the same keys should be merged:

    +
      +
    • +

      Wrong:

      +
      kvmd:
      +    gpio:
      +        drivers: ...
      +kvmd:
      +    gpio:
      +        scheme: ...
      +
      +
    • +
    • +

      Correct:

      +
      kvmd:
      +    gpio:
      +        drivers: ...
      +        scheme: ...
      +
      +
    • +
    +

    In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

    +
    +
  • +
  • +

    Get to know PiKVM Web UI: read this help section to better understand all the possibilities of the web user interface.

    +
  • +
  • +

    Tune the HDMI dongle capture device if you're using it:

    +
    +Persistent HDMI cable connection with USB dongle +

    Many USB video capture devices tell the server's video card that the HDMI cable is supposedly disconnected. +This may lead to the fact that if you boot the server without an active stream, the server will not detect +your capture card. This is easy to fix:

    +
      +
    • +

      Switch filesystem to RW-mode: +

      [root@pikvm ~]# rw
      +
      +
    • +
    • +

      Edit file /etc/kvmd/override.yaml and add these lines: +

      kvmd:
      +    streamer:
      +        forever: true
      +        cmd_append: [--slowdown]
      +
      +
    • +
    • +

      Finish: +

      [root@pikvm ~]# ro
      +[root@pikvm ~]# systemctl restart kvmd
      +
      +
    • +
    • +

      Check that everything is working.

      +
    • +
    +
    +
  • +
+
+

Further recommendations

+ +
+

Known issues and limitations

+
    +
  • +

    Max resolution.
    PiKVM V2 with CSI bridge can only handle the maximum resolution 1920x1080@50Hz, 60Hz is not supported due hardware limitation. You can use any other resolution less than the specified one, for example 1280x720@60Hz. If you have any problems with video on CSI bridge, follow this guide.

    +
  • +
  • +

    Motherboards compatibility.
    There may be compatibility issues with some motherboards, such as HP or DELL. If there is no image from the BIOS, you can fine-tune the HDMI settings, but it is possible that the mass storage devices will not be available in the BIOS. In the latter case, USB dynamic configuration will solve the problem.

    +
  • +
+
+

Basic troubleshooting

+
    +
  • +

    Ensure that you are using the right OS image for your platform + by running the following command: pacman -Q | grep kvmd-platform.

    +
  • +
  • +

    If you are not getting a display, run the two following commands:

    +
      +
    • dmesg | egrep 'tc35|1-1.4|uvc'
    • +
    • systemctl status kvmd-tc358743
    • +
    +

    If you see a failed message on that output, be sure verify the orientation of the CSI cable or try reseating it.

    +

    Note that this is not a hotplug device, and you must first turn off the power.

    +
  • +
+
+

Getting user support

+

If something doesn't work, check out our FAQ. Otherwise, head straight to our Support.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v2/v2_atx_breadboard.png b/v2/v2_atx_breadboard.png new file mode 100644 index 00000000..9c757252 Binary files /dev/null and b/v2/v2_atx_breadboard.png differ diff --git a/v2/v2_atx_scheme.png b/v2/v2_atx_scheme.png new file mode 100644 index 00000000..f3234987 Binary files /dev/null and b/v2/v2_atx_scheme.png differ diff --git a/v2/v2_example.jpg b/v2/v2_example.jpg new file mode 100644 index 00000000..4564a3c9 Binary files /dev/null and b/v2/v2_example.jpg differ diff --git a/v2/v2_splitter_cable.jpg b/v2/v2_splitter_cable.jpg new file mode 100644 index 00000000..04374f8d Binary files /dev/null and b/v2/v2_splitter_cable.jpg differ diff --git a/v2/v2_splitter_module.jpg b/v2/v2_splitter_module.jpg new file mode 100644 index 00000000..3da41424 Binary files /dev/null and b/v2/v2_splitter_module.jpg differ diff --git a/v2/v2_splitter_soldering.png b/v2/v2_splitter_soldering.png new file mode 100644 index 00000000..43d3ed57 Binary files /dev/null and b/v2/v2_splitter_soldering.png differ diff --git a/v2/v2_tape_off.jpg b/v2/v2_tape_off.jpg new file mode 100644 index 00000000..275b8f4b Binary files /dev/null and b/v2/v2_tape_off.jpg differ diff --git a/v3/assembled.jpg b/v3/assembled.jpg new file mode 100644 index 00000000..535f3e4a Binary files /dev/null and b/v3/assembled.jpg differ diff --git a/v3/basic_back.jpg b/v3/basic_back.jpg new file mode 100644 index 00000000..8447f290 Binary files /dev/null and b/v3/basic_back.jpg differ diff --git a/v3/basic_front.jpg b/v3/basic_front.jpg new file mode 100644 index 00000000..6d9a6c46 Binary files /dev/null and b/v3/basic_front.jpg differ diff --git a/v3/index.html b/v3/index.html new file mode 100644 index 00000000..2d24d01e --- /dev/null +++ b/v3/index.html @@ -0,0 +1,3424 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + PiKVM V3 HAT & pre-assembled quickstart guide - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

PiKVM V3 HAT & pre-assembled quickstart guide

+

PiKVM V3 HAT

+

PiKVM is a feature-rich, production-grade, open-source, Raspberry Pi based KVM-over-IP device. It allows you to turn your computer on or off, restart it, configure the UEFI/BIOS, and even reinstall the OS using the Virtual CD-ROM or flash drive.

+

PiKVM uses your remote keyboard and mouse to simulate a local keyboard, mouse, and monitor, which are then presented in a web browser as if you were working on a remote system directly.

+

PiKVM V3 is available in two version:

+
    +
  • An assembly kit (HAT).
  • +
  • A pre-assembled unit in a metallic box.
  • +
+

The two versions have the same ports and functionality.

+
+

What's in the box

+
+
+
+
    +
  • The PiKVM V3 HAT for Raspberry Pi 4
  • +
  • USB-C bridge board
  • +
  • ATX adapter board with mounting brackets and motherboard interface wiring
  • +
  • 2x Flat CSI-2 cables
  • +
  • 7x jumpers
  • +
  • 8x brass standoffs
  • +
  • 8x screws
  • +
+
+
+
    +
  • PiKVM V3.3 pre-assembled
  • +
  • ATX adapter board with mounting brackets and motherboard interface wiring
  • +
  • A 32 GB MicroSD card pre-imaged with the PiKVM OS
  • +
+
+
+
+
+

HAT setup

+

If you have an assembly kit without a metal case, you can use our free 3D printing case drawing:

+
    +
  • V3.2 is the pre-release model.
  • +
  • V3.3 is the Kickstarter/Store model.
  • +
+

Once you have that, do the following:

+
    +
  1. +

    Flash the memory card. Please use the V3 image, V2 image is not compatible.

    +
  2. +
  3. +

    Build PiKVM according to the illustrated instructions.

    +
  4. +
+
+

Interface

+
+
+
+

PiKVM V3 Front view

+
    +
  1. 2x USB 2.0
  2. +
  3. 2x USB 3.0
  4. +
  5. RJ45 1Gb Ethernet port
  6. +
  7. RJ45 Serial console port
  8. +
  9. Serial console active LED / Beacon LED (Green)
  10. +
  11. USB 2.0 Serial console port
  12. +
  13. Activity LED (Red)
  14. +
  15. Power LED (Green)
  16. +
  17. Power Input 5.1V 3A
  18. +
+
+
+

PiKVM V3 Rear view

+
    +
  1. Micro SD card slot
  2. +
  3. HDMI video input port
  4. +
  5. USB 2.0 OTG connector
  6. +
  7. RJ45 ATX control port
  8. +
+
+
+

PiKVM V3 Left view

+
    +
  1. Mini-HDMI output port
  2. +
+
+
+

PiKVM V3 Top view

+
    +
  1. Display
  2. +
+
+
+
+
+

Flashing the OS

+

Most of the time, this step is not necessary. However, if there is a possibility that your device had a previous owner (e.g. "Used - Like New" on Amazon), we recommend reflashing the OS to ensure a clean start. Please follow this guide.

+
+

Wiring

+

Both the HAT and the pre-assembled V3 require several items available separately:

+
    +
  • Ethernet cable
  • +
  • RJ-45 cable for ATX (optional)
  • +
  • USB-C cable
  • +
  • HDMI cable
  • +
  • 5V USB power adapter
  • +
+

Let's connect all the wires before you power up the device.

+

Network

+

Ethernet wiring

+

Connect Ethernet (bottom right on the front side) to the network, e.g., to the WiFI router.

+

HDMI and USB-C

+

HDMI and USB-C wiring

+

HDMI input (the top right on the rear side) and OTG port (USB emulation) should be connected to the computer.

+

Optionally, the ATX port can be connected to control the power. There should be no USB hub between PiKVM and the computer, as some UEFI/BIOS cannot detect them at the boot stage.

+
+

Power up

+

Power supply wiring

+

V3 comes has a USB-C 5V power supply. Attach the appropriate connector on the front side (top left). Do not block the ventilation holes on the sides of the device.

+

After turning on the power, PiKVM OS generates unique SSH keys and certificates and performs all necessary operations on the memory card. It takes a few minutes. Do not turn off the device until it's fully booted for the first time. Once it's done, the PiKVM will show a greeting on the built-in display.

+
+

Connect and set up

+

Configure the display

+

The operating system on your remote computer will treat PiKVM as an additional display and use it in the Extend mode by default. That's why you will see an empty desktop when you first connect.

+

To avoid that, go to the display settings in your remote computer's operating system and enable the mirror mode for the external screen that you operating system identifies as PiKVM. Refer to your operating system's documentation on that.

+

Access PiKVM

+

By default, PiKVM receives a dynamic IP address via DHCP and shows it in the top row of the OLED display:

+
192.168.0.26
+(|) iface: eth0
+cpu: 1% mem: 13%
+
+

Let's assume that PiKVM has received the address 192.168.0.26 and has also been assigned a hostname pikvm.

+

Type the URL in the browser's address bar and press Enter: https://192.168.0.26/ or https://pikvm/.

+

Login screen

+

Submit the default credentials and click Login:

+
    +
  • Username: admin
  • +
  • Password: admin
  • +
  • 2FA Code: disabled by default, skip this field
  • +
+

You will see the initial dashboard screen of the PiKVM where you can access the remote host, connect to the PiKVM command line, or log out:

+

Initial UI

+

Change the default passwords

+

For security's sake, it's best to change the default passwords immediately after running PiKVM for the first time.

+
+

Passwords are important!

+

Please ensure that you change both passwords: for Web UI access and for the Linux superuser (root).

+
+

To do that:

+
    +
  1. +

    On the initial dashboard screen, click the Terminal button to open the web terminal. You will see this command line interface:

    +

    PiKVM WebTerm

    +
  2. +
  3. +

    Gain Linux superuser privileges:

    +
    $ su -
    +
    +

    When prompted for password, use root.

    +
  4. +
  5. +

    Run rw to change the access to the SD card to the write mode:

    +
    [root@pikvm ~]# rw
    +
    +
  6. +
  7. +

    Change the password for the Linux superuser:

    +
    [root@pikvm ~]# passwd root
    +
    +

    Submit the new password, retype it the second time to confirm, press Enter, and you should see this:

    +
    passwd: password updated successfully
    +
    +
  8. +
  9. +

    Change the password for web access:

    +
    [root@pikvm ~]# kvmd-htpasswd set admin
    +
    +

    Submit the new password, retype it the second time to confirm, and press Enter.

    +
  10. +
  11. +

    Run ro to change the access to the SD card back to the read-only mode:

    +
    [root@pikvm ~]# ro
    +
    +
  12. +
  13. +

    Press Ctrl+D or type "exit" and press Enter to drop the root privileges.

    +
  14. +
  15. +

    Go back one page in the browser. You should be back to the initial dashboard screen.

    +
  16. +
+

Access the remote system

+
    +
  1. +

    On the initial dashboard screen, click the KVM button to access the remote host.

    +
  2. +
  3. +

    You should now see the host system's display and interact with it remotely using a keyboard and a mouse.

    +

    Work remotely

    +
  4. +
+
+

Important next steps

+
    +
  • +

    We strongly recommend to update the PiKVM OS after the first launch:

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
  • +
  • +

    Learn about basics of PiKVM OS Configuration: where to find configs, how to edit the, etc.

    +
    +Configuring PiKVM OS +
    +

    Need more info? We have it!

    +

    The following is a brief guide to configuring PiKVM. +For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), +please refer to this page.

    +
    +

    Most of the PiKVM configuration files are located in the /etc/kvmd directory.

    +

    The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. +To redefine system parameters use the file /etc/kvmd/override.yaml. +All other files that are also not recommended for editing have read-only permissions.

    +

    You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory +to split your customization into logical parts. +The override.yaml file definitions takes precedence over the override.d directory.

    +

    A complete list of all parameters can be viewed using the kvmd -m command.

    +

    Files with the *.yaml suffix uses the YAML syntax +and describes a parameter tree with key-value pairs of different types. +To define the parameters within one section, an indent of 4 spaces is used. +Comments starts with the # symbol.

    +
    +

    Only 4 spaces should be used for indentation

    +

    Be careful when editing YAML and follow this rule. +Invalid indentation or tabs instead of spaces will cause an error when starting the services.

    +
    +

    Sections under the same keys should be merged:

    +
      +
    • +

      Wrong:

      +
      kvmd:
      +    gpio:
      +        drivers: ...
      +kvmd:
      +    gpio:
      +        scheme: ...
      +
      +
    • +
    • +

      Correct:

      +
      kvmd:
      +    gpio:
      +        drivers: ...
      +        scheme: ...
      +
      +
    • +
    +

    In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

    +
    +
  • +
  • +

    Get to know PiKVM Web UI: read this help section to better understand all the possibilities of the web user interface.

    +
  • +
  • +

    Set up ATX connection if you need to control the power of the remote system.

    +
  • +
+
+

Further recommendations

+
    +
  1. +

    Customize the system:

    + +
  2. +
  3. +

    Configure hardware:

    +
      +
    • +

      If you bought V3 HAT Assembly Kit and it includes the OLED display and/or the fan, you'll need to turn them on. Note this is only needed for the older V3 image for the HAT, in the box image everything is enabled by default:

      +
      +Enabling the OLED and the fan +

      Log in to PiKVM and run these commands:

      +
      [root@pikvm ~]# rw
      +[root@pikvm ~]# systemctl enable --now kvmd-oled kvmd-oled-reboot kvmd-oled-shutdown
      +[root@pikvm ~]# systemctl enable --now kvmd-fan
      +[root@pikvm ~]# ro
      +
      +
      +
    • +
    • +

      Choose Fahrenheit over Celsius to display on the OLED:

      +
      +How to set up Fahrenheit on the OLED +

      Create a directory for a configuration file:

      +
      [root@pikvm ~]# mkdir -p /etc/systemd/system/kvmd-oled.service.d
      +
      +

      Create file /etc/systemd/system/kvmd-oled.service.d/override.conf:

      +
      [Service]
      +ExecStart=
      +ExecStart=/usr/bin/kvmd-oled --clear-on-exit --fahrenheit
      +
      +
      +
    • +
    +
  4. +
+
+

Known issues and limitations

+
    +
  • +

    Max resolution.
    PiKVM V3 supports maximum resolution 1920x1080@50Hz, 60Hz will not work. You can use any other resolution less than the specified one, for example: 1600x1200@60Hz, 1280x720@60Hz, etc. If you have problems with the video, follow this guide.

    +
  • +
  • +

    Motherboards compatibility.
    There may be compatibility issues with some motherboards, such as HP or DELL. If there is no image from the BIOS, you can fine-tune the HDMI settings, but it is possible that the mass storage devices will not be available in the BIOS. In the latter case, USB dynamic configuration will solve the problem.

    +
  • +
  • +

    HDMI backpowering.
    Under specific circumstances, PiKVM may hang during the boot. Turn off the PiKVM, disconnect all cables from it, take a close look at the diagram of its ports and jumpers below, and remove jumper #14 (it is to the right of the CSI connector, not available on the V3.2 board). Then you can connect and power up PiKVM again. (Technical background s described here.)

    +
  • +
  • +

    IO ports.
    Before using GPIO pins to control a relay, KVM switch, or anything else, be sure to check the HAT pinout below. Many ports are busy with internal functions. Before using them for your own use, you must disable them, otherwise you may damage the PiKVM WebTerm

    +
  • +
+
+The ports and jumpers diagram +

+
    +
  1. ATX controller interface (power on/off, reboot control, PWR and HDD ACT LEDs).
  2. +
  3. HDMI reset jumper. Connects GPIO 17 and RESET pin to HDMI capture chip. Currently not used, don't touch it.
  4. +
  5. SPI and GPIO for the custom extension boards.
  6. +
  7. Audio capture jumpers. Connects I2S pins 18, 19, 20 to HDMI capture chip.
  8. +
  9. UART access jumpers. Connects GPIO 14 and 15 to the RJ-45 and USB console ports.
  10. +
  11. Serial console port (default: /dev/ttyAMA0, RS232 input, outputs +6V/-6V, for the Raspberry Pi or server console access, use the Cisco/Mikrotik-style cable).
  12. +
  13. USB-C console port (shared with #6 above, takes priority over RJ45).
  14. +
  15. Power and activity LEDs. On the left of the LEDs the watchdog jumper is located. Don't touch it.
  16. +
  17. USB-C power input.
  18. +
  19. I2C display connector.
  20. +
  21. Alternate +5V power input/output header pins.
  22. +
  23. RTC clock supercapacitor (rechargeable).
  24. +
  25. FAN connector - PWM controlled.
  26. +
  27. CSI-2 interface and HDMI backpowering jumper, see Step 9 of the Basic Setup. Open: (jumper removed) diode will stop current from HDMI input (backpower will be fixed), closed: (jumper connected to both pins) will allow current from HDMI device.
  28. +
  29. Built-in power splitter port.
  30. +
  31. HDMI capture port (max 1080p @ 50Hz) with sound capture support.
  32. +
  33. USB emulation pins for alternative access.
  34. +
  35. USB-C emulation port - this port is doing the emulation of a USB keyboard, mouse, Virtual CD-ROM or USB Flash Drive, USB-Ethernet, USB-Serial port and a lot of other Linux-supported features.
  36. +
  37. 1-Wire & Neo-pixel interface (under, advanced user feature).
  38. +
+
+
+The GPIO pinout +
+

Warning

+

Before proceeding, make sure that the mb you are using has normal ATX headers

+
+
    +
  • ATX control
  • +
  • power led = GPIO 24 - Used for reading the host power state.
  • +
  • hdd led = 22 - Same for the HDD activity.
  • +
  • power switch = 23 - Used for pressing the power button of the host.
  • +
  • reset switch = 27 - Same for the reset button.
  • +
+

These pins can't be used for any other purposes even if ATX function is disabled.

+
    +
  • +

    I2C bus - GPIO 2, 3 - Can be used as I2C ONLY (OLED/RTC).

    +
  • +
  • +

    1-Wire [19] - GPIO 4 - Also available under ATX RJ-45 port (point [19] on the above) as bi-directional buffered open-drain 5V for regular 1-Wire usage.

    +
  • +
  • +

    UART - GPIO 14, 15 - Can be used as UART only for the serial console. When jumpers [5] are removed, you can connect to pins 14 and 15 directly using GPIO header. Also you can remove jumper [5] and disable UART console in the /boot/config.txt and /boot/cmdline.txt to use this pins for any purpose. But it's not recommended.

    +
  • +
  • +

    Red activity led on the front [8] - GPIO 13 - Can be disabled in /boot/config.txt and available on the Neo-pixel port [19].

    +
  • +
  • +

    PWM fan controller - GPIO 12. Can be used for custom purposes if the fan disconnected and kvmd-fan service is stopped.

    +
  • +
  • +

    I2S HDMI sound - GPIO 18, 19, 20, 21. Can be used for custom purposes if the tc358743-audio overlay in /boot/config.txt is disabled AND jumpers [4] are removed.

    +
  • +
  • +

    USB breaker - GPIO 5 - Can't be used for any other purposes.

    +
  • +
+
+

The standard Raspberry Pi HDMI output (marked as VIDEO OUT on the PiKVM case) displays its own PiKVM OS console.

+
+

Basic troubleshooting

+
    +
  • +

    Ensure that you are using the right OS image for your platform + by running the following command: pacman -Q | grep kvmd-platform.

    +
  • +
  • +

    If you are not getting a display, run the two following commands:

    +
      +
    • dmesg | egrep 'tc35|1-1.4|uvc'
    • +
    • systemctl status kvmd-tc358743
    • +
    +
  • +
+
+

Getting user support

+

If something doesn't work, check out our FAQ. Otherwise, head straight to our Support.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/v3-ethernet-wiring.svg b/v3/v3-ethernet-wiring.svg new file mode 100644 index 00000000..dc18649a --- /dev/null +++ b/v3/v3-ethernet-wiring.svg @@ -0,0 +1,160 @@ + + + + + PIKVM V3 Line Drawings + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v3/v3-front-view-numbered.svg b/v3/v3-front-view-numbered.svg new file mode 100644 index 00000000..af642b1d --- /dev/null +++ b/v3/v3-front-view-numbered.svg @@ -0,0 +1,282 @@ + + + + + PIKVM V3 Line Drawings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v3/v3-hdmi-usb-wiring.svg b/v3/v3-hdmi-usb-wiring.svg new file mode 100644 index 00000000..952046ca --- /dev/null +++ b/v3/v3-hdmi-usb-wiring.svg @@ -0,0 +1,161 @@ + + + + + PIKVM V3 Line Drawings + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v3/v3-left-view-numbered.svg b/v3/v3-left-view-numbered.svg new file mode 100644 index 00000000..1f0ffd6e --- /dev/null +++ b/v3/v3-left-view-numbered.svg @@ -0,0 +1,148 @@ + + + + + PIKVM V3 Line Drawings + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v3/v3-power-supply-wiring.svg b/v3/v3-power-supply-wiring.svg new file mode 100644 index 00000000..aa460ec3 --- /dev/null +++ b/v3/v3-power-supply-wiring.svg @@ -0,0 +1,163 @@ + + + + + PIKVM V3 Line Drawings + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v3/v3-rear-view-numbered.svg b/v3/v3-rear-view-numbered.svg new file mode 100644 index 00000000..7fae61a5 --- /dev/null +++ b/v3/v3-rear-view-numbered.svg @@ -0,0 +1,199 @@ + + + + + PIKVM V3 Line Drawings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v3/v3-top-view-numbered.svg b/v3/v3-top-view-numbered.svg new file mode 100644 index 00000000..e71568fe --- /dev/null +++ b/v3/v3-top-view-numbered.svg @@ -0,0 +1,144 @@ + + + + + PIKVM V3 Line Drawings + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v3/v3_features.jpg b/v3/v3_features.jpg new file mode 100644 index 00000000..fbe8d67c Binary files /dev/null and b/v3/v3_features.jpg differ diff --git a/v3_illustrated_install_instructions/FCC_HAT_Ribbon_Cable_install.jpg b/v3_illustrated_install_instructions/FCC_HAT_Ribbon_Cable_install.jpg new file mode 100644 index 00000000..4541698c Binary files /dev/null and b/v3_illustrated_install_instructions/FCC_HAT_Ribbon_Cable_install.jpg differ diff --git a/v3_illustrated_install_instructions/HAT2_insert_into_case.jpg b/v3_illustrated_install_instructions/HAT2_insert_into_case.jpg new file mode 100644 index 00000000..4e518111 Binary files /dev/null and b/v3_illustrated_install_instructions/HAT2_insert_into_case.jpg differ diff --git a/v3_illustrated_install_instructions/HAT2_insert_top_part_of_case.jpg b/v3_illustrated_install_instructions/HAT2_insert_top_part_of_case.jpg new file mode 100644 index 00000000..1fcccb85 Binary files /dev/null and b/v3_illustrated_install_instructions/HAT2_insert_top_part_of_case.jpg differ diff --git a/v3_illustrated_install_instructions/HAT_insert_into_case.jpg b/v3_illustrated_install_instructions/HAT_insert_into_case.jpg new file mode 100644 index 00000000..1c696321 Binary files /dev/null and b/v3_illustrated_install_instructions/HAT_insert_into_case.jpg differ diff --git a/v3_illustrated_install_instructions/HAT_install_OLED_holder.jpg b/v3_illustrated_install_instructions/HAT_install_OLED_holder.jpg new file mode 100644 index 00000000..8fd02651 Binary files /dev/null and b/v3_illustrated_install_instructions/HAT_install_OLED_holder.jpg differ diff --git a/v3_illustrated_install_instructions/HAT_install_OLED_into_holder.jpg b/v3_illustrated_install_instructions/HAT_install_OLED_into_holder.jpg new file mode 100644 index 00000000..ff62defb Binary files /dev/null and b/v3_illustrated_install_instructions/HAT_install_OLED_into_holder.jpg differ diff --git a/v3_illustrated_install_instructions/HAT_install_fan_to_HAT_board.jpg b/v3_illustrated_install_instructions/HAT_install_fan_to_HAT_board.jpg new file mode 100644 index 00000000..fac7fcce Binary files /dev/null and b/v3_illustrated_install_instructions/HAT_install_fan_to_HAT_board.jpg differ diff --git a/v3_illustrated_install_instructions/HAT_install_fan_to_top.jpg b/v3_illustrated_install_instructions/HAT_install_fan_to_top.jpg new file mode 100644 index 00000000..b83d7d6f Binary files /dev/null and b/v3_illustrated_install_instructions/HAT_install_fan_to_top.jpg differ diff --git a/v3_illustrated_install_instructions/HAT_install_plastic spacer.jpg b/v3_illustrated_install_instructions/HAT_install_plastic spacer.jpg new file mode 100644 index 00000000..2314226a Binary files /dev/null and b/v3_illustrated_install_instructions/HAT_install_plastic spacer.jpg differ diff --git a/v3_illustrated_install_instructions/HAT_install_plastic_risers_bottom.jpg b/v3_illustrated_install_instructions/HAT_install_plastic_risers_bottom.jpg new file mode 100644 index 00000000..e91a146e Binary files /dev/null and b/v3_illustrated_install_instructions/HAT_install_plastic_risers_bottom.jpg differ diff --git a/v3_illustrated_install_instructions/HAT_install_usbc_bridge.jpg b/v3_illustrated_install_instructions/HAT_install_usbc_bridge.jpg new file mode 100644 index 00000000..aeb018f2 Binary files /dev/null and b/v3_illustrated_install_instructions/HAT_install_usbc_bridge.jpg differ diff --git a/v3_illustrated_install_instructions/PiKVM_ATX_Packaging.png b/v3_illustrated_install_instructions/PiKVM_ATX_Packaging.png new file mode 100644 index 00000000..f5502ba9 Binary files /dev/null and b/v3_illustrated_install_instructions/PiKVM_ATX_Packaging.png differ diff --git a/v3_illustrated_install_instructions/RPI4_insert_into_case.jpg b/v3_illustrated_install_instructions/RPI4_insert_into_case.jpg new file mode 100644 index 00000000..7710a70d Binary files /dev/null and b/v3_illustrated_install_instructions/RPI4_insert_into_case.jpg differ diff --git a/v3_illustrated_install_instructions/index.html b/v3_illustrated_install_instructions/index.html new file mode 100644 index 00000000..1b9add5b --- /dev/null +++ b/v3_illustrated_install_instructions/index.html @@ -0,0 +1,2845 @@ + + + + + + + + + + + + + + + + + + + + + + Assembling PiKVM V3 HAT - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Assembling PiKVM V3 HAT

+

PiKVM V3 HAT is an assembly kit. You can build it without any case whatsoever, order a metallic case separately, or 3D-print a case yourself. These videos cover all those use cases.

+
+Video guide: Assembly with a metal case +

NOTE: OLED will not light up till step 5 is performed, video was performed after it was already configured, heat sinks NOT included. +

+
+
+Video guide: Assembly with or without a 3D-printed case +

+
+

Step 1

+

Get the parts that are not in the assembly kit:

+
    +
  • Raspberry Pi 4 with 1Gb RAM or more
  • +
  • Heat sinks (Optional)
  • +
  • MicroSD card (at least 16Gb, class 10 recommended)
  • +
  • USB-C to USB-A cable
  • +
  • HDMI cable
  • +
  • Straight Ethernet cable
  • +
  • Power supply unit (5.1V 3A USB-C, recommended by the Raspberry Pi)
  • +
+
+

Tip

+
    +
  • Please review the back of the box. All parts are required before the HAT is fully functional.
  • +
  • The USB-C bridge is located in with the ATX end which includes a pink foam spacer.
  • +
  • Please assemble the HAT onto the RPi and test all of the parts before installing in the case, it's easier to install in the case than to dissasemble it.
  • +
  • If going from a V2 to a V3, the splitter is no longer needed.
  • +
+
+

Step 2

+

Remove contents from assembly kit box:

+
    +
  • 8x M.2 5x12mm screws for the case
  • +
  • 4x M.2 5x12mm screws for the fan
  • +
  • 4x bolts for the fan
  • +
  • 1x fan (30x30x7mm 5v)
  • +
  • 1x case top
  • +
  • 1x case bottom
  • +
  • 1x OLED display (0.91 IIC 128x32 LCD)
  • +
  • 2x bottom plastic risers
  • +
  • 1x plastic top riser
  • +
  • 1x plastic OLED holder that is also a front riser
  • +
  • 2x small FCC ribbon cables
  • +
  • 1x small rubber square that break out to 4x small rubber feet
  • +
+
+

OLED is sensitive to pressure, do NOT push down on the very thin glass as it will crack and become non-functional

+
+

Step 3

+

Take bottom part of the case, insert the RPI4 into the bottom case at an angle, you will need to flex the other side ever so slightly to get it to slot in.

+

+
+IF you bought heatsink's (sold seperatly), it's advised to install them now before installing the HAT +
+

Step 4

+

Insert HAT at the same angle, take care to line up the pins on the Rpi with the HAT pin sleeve, the trick to this is to push the Rpi all of the way to the left then all of the way to the right for proper alignment, do NOT force till the pins are aligned. If properly aligned the pins will match up without issue.

+

+

+
+ALTERNATIVE: As an alternative to the above, you can pre assemble the hat+fcc cable onto the RPI4, then insert them into the bottom portion of the case however you will need to flex the sides more whereby creating a bigger gap when fully assembled. +
+

Step 5

+

There are 2 ways to insert the FCC cable, you can add it when you insert the RPI in Step 2 OR wait till you also have the HAT installed and slide it into the slot.

+

+
+The blue stripes on the ends of the cable will ALWAYS face the side that will be used to tighten the FCC to the camera port or have it positioned towards the power - Ignore the smaller FCC cable that plugs into the USB, was phased out during the KS campaign. This image was used as a means of illustrating FCC placement and orientation +
+

Step 6

+

Install the USB-C bridge.

+
+This is packaged with the ATX board +
+

+

+
+If you do not install this bridge, mouse/kb will not work +
+
+HAT will still power on without this bridge installed +
+

Step 7

+

Turn the bottom of the case upside down, install the 2 bottom plastic risers, it's best to install in a wing formation. Top first by inserting the top screws then slide the bottom part aligning the plastic to the holes then inserting the screws. At this point its OK to tighten the bottom screws. There is no need to use force, just tighten enough to prohibit movement.

+

+

Step 8

+

Take the plastic OLED holder, turn the OLED over where the back side is facing you and insert at an angle so as to create a space between the OLED and holder arm, take a flat head screwdriver (medium normal) and twist it enough so you can clear the electronics on the bottom of the OLED and continue to gently slide in the remaining OLED till its fully inserted.

+

+
+

Be careful on handling this display, slight pressure will damage the OLED, however in the event that this does happen, replacements are cheap and can be found in most electronic stores or Amazon, look for any IIC (I2C) .91 inch display for Arduino

+
+

Step 9

+

Insert the OLED holder with the OLED display into the plug by gently rocking it back and forth till it's fully inserted.

+

+

Step 10

+

Install plastic spacer.

+

+

Step 11

+

Install the screws and bolts to secure the fan, it does not matter the orientation of the fan, push or pulling air will result in the same behavior, its personal preference.

+

+

Step 12

+

Insert the fan leads and align Red with positive and Black with negative.

+

+
+

You can damage the fan if installed incorrectly

+
+

Step 13

+

Install the top of the case to the bottom, use the 4 remaining screws to secure the top.

+

+

Step 14

+

Please follow the V3 quick start guide to activate your PiKVM.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3_illustrated_install_instructions/v3_feet.jpg b/v3_illustrated_install_instructions/v3_feet.jpg new file mode 100644 index 00000000..10ef575d Binary files /dev/null and b/v3_illustrated_install_instructions/v3_feet.jpg differ diff --git a/v4/in-the-box.jpg b/v4/in-the-box.jpg new file mode 100644 index 00000000..e14f8e92 Binary files /dev/null and b/v4/in-the-box.jpg differ diff --git a/v4/index.html b/v4/index.html new file mode 100644 index 00000000..79b84d60 --- /dev/null +++ b/v4/index.html @@ -0,0 +1,3366 @@ + + + + + + + + + + + + + + + + + + + + + + + + PiKVM V4 Mini & Plus quickstart guide - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

PiKVM V4 Mini & Plus quickstart guide

+

PiKVM V4 Mini & Plus

+

PiKVM is a feature-rich, production-grade, open-source, Raspberry Pi based KVM-over-IP device. It allows you to turn your computer on or off, restart it, configure the UEFI/BIOS, and even reinstall the OS using the Virtual CD-ROM or flash drive.

+

PiKVM uses your remote keyboard and mouse to simulate a local keyboard, mouse, and monitor, which are then presented in a web browser as if you were working on a remote system directly.

+

Datasheets:

+

PiKVM V4 Mini PiKVM V4 Plus

+
+

What's in the box

+
    +
  • PiKVM V4 Mini or Plus device
  • +
  • Micro SD card with pre-imaged PiKVM software
  • +
  • ATX control board
  • +
  • ATX connection cables
  • +
  • ATX installation brackets
  • +
  • 1 x Ethernet cable
  • +
  • 1 x ATX cable
  • +
  • 1 x USB C to USB A cable
  • +
  • 12V 2A Power Supply (international adapters)
  • +
+
+

Interface

+
+
+
+

V4 front view

+
    +
  1. Power LED (Green)
  2. +
  3. Power Input 5.1V 3A
  4. +
  5. Activity LED (Red)
  6. +
  7. Micro SD card slot
  8. +
  9. USB 2.0 Serial console port
  10. +
  11. Serial console active LED / Beacon LED (Green)
  12. +
  13. RJ45 1Gb Ethernet port
  14. +
  15. RJ45 Serial console port (V4 Plus only)
  16. +
  17. USB 3.0 port 1 (V4 Plus only)
  18. +
  19. Power Input 12V 2A (V4 Plus only)
  20. +
+
+
+

V4 rear view

+
    +
  1. RJ45 ATX control port
  2. +
  3. USB 2.0 OTG connector
  4. +
  5. Beacon LED
  6. +
  7. Video source ready status LED
  8. +
  9. HDMI video input port
  10. +
  11. Video capture ready status LED
  12. +
  13. Optional antenna mounting hole (only one in V4 Mini)
  14. +
  15. HDMI video output port 2 (V4 Plus only)
  16. +
  17. HDMI video output port 1 (V4 Plus only)
  18. +
  19. USB 3.0 port 2 (V4 Plus only)
  20. +
  21. Optional antenna mounting hole (only one in V4 Mini)
  22. +
+
+
+

V4 right view

+
    +
  1. Service switches
  2. +
  3. Kensington Security Slot
  4. +
+
+
+

V4 top view

+
    +
  1. Display
  2. +
+
+
+
+
+

Flashing the OS

+

Most of the time, this step is not necessary. However, if there is a possibility that your device had a previous owner (e.g. "Used - Like New" on Amazon), we recommend reflashing the OS to ensure a clean start. Please follow this guide.

+
+

Wiring

+

Let's connect all the wires before you power up the device.

+

Network

+

Ethernet wiring

+

Connect Ethernet (bottom right on the front side) to the network using the cable from the kit. The kit includes two Ethernet cables of different colors: one for the network, the second for ATX. Use whichever one you like best.

+

HDMI and USB-C

+

HDMI and USB-C wiring

+

HDMI input (the bottom right on the rear side) and OTG port (USB emulation) should be connected to the computer.

+

Optionally, the ATX port can be connected to control the power. There should be no USB hub between PiKVM and the computer, as some UEFI/BIOS cannot detect them at the boot stage.

+
+

Power up

+

Power supply wiring

+

V4 Mini and V4 Plus have different power supplies:

+
    +
  • The Mini comes with USB-C 5V power supply
  • +
  • The Plus comes with with Barrel 12V
  • +
+

The Plus can also work from 5V. In that case, avoid creating a significant power load on USB (external flash sticks, cameras, and so on).

+

Attach the appropriate connector on the front side. Do not block the ventilation holes on the sides of the device.

+

After turning on the power, PiKVM OS generates unique SSH keys and certificates and performs all necessary operations on the memory card. It takes a few minutes. Do not turn off the device until it's fully booted for the first time. Once it's done, the PiKVM will show a greeting on the built-in display.

+
+

Connect and set up

+

Configure the display

+

The operating system on your remote computer will treat PiKVM as an additional display and use it in the Extend mode by default. That's why you will see an empty desktop when you first connect.

+

To avoid that, go to the display settings in your remote computer's operating system and enable the mirror mode for the external screen that your operating system identifies as PiKVM. Refer to your operating system's documentation on that.

+

Access PiKVM

+

By default, PiKVM receives a dynamic IP address via DHCP and shows it in the top row of the OLED display:

+
192.168.0.26
+(|) iface: eth0
+cpu: 1% mem: 13%
+
+

Let's assume that PiKVM has received the address 192.168.0.26 and has also been assigned a hostname pikvm.

+

Type the URL in the browser's address bar and press Enter: https://192.168.0.26/ or https://pikvm/.

+

Login screen

+

Submit the default credentials and click Login:

+
    +
  • Username: admin
  • +
  • Password: admin
  • +
  • 2FA Code: disabled by default, skip this field
  • +
+

You will see the initial dashboard screen of the PiKVM, where you can access the remote host, connect to the PiKVM command line, or log out:

+

Initial UI

+

Change the default passwords

+

For security's sake, it's best to change the default passwords immediately after running PiKVM for the first time.

+
+

Passwords are important!

+

Please ensure that you change both passwords: for Web UI access and for the Linux superuser (root).

+
+

To do that:

+
    +
  1. +

    On the initial dashboard screen, click the Terminal button to open the web terminal. You will see this command line interface:

    +

    MISSING SCREENSHOT

    +
  2. +
  3. +

    Gain superuser privileges:

    +
    $ su -
    +
    +

    When prompted for a password, use root.

    +
  4. +
  5. +

    Run rw to change the access to the SD card to the write mode:

    +
    [root@pikvm ~]# rw
    +
    +
  6. +
  7. +

    Change the password for the superuser:

    +
    [root@pikvm ~]# passwd root
    +
    +

    Submit the new password, retype it the second time to confirm, press Enter, and you should see this:

    +
    passwd: password updated successfully
    +
    +
  8. +
  9. +

    Change the password for web access:

    +
    [root@pikvm ~]# kvmd-htpasswd set admin
    +
    +

    Submit the new password, retype it the second time to confirm, and press Enter.

    +
  10. +
  11. +

    Run ro to change the access to the SD card back to the read-only mode:

    +
    [root@pikvm ~]# ro
    +
    +
  12. +
  13. +

    Press Ctrl+D or type "exit" and press Enter to drop the root privileges.

    +
  14. +
  15. +

    Go back one page in the browser. You should be back to the initial dashboard screen.

    +
  16. +
+

Access the remote system

+
    +
  1. +

    On the initial dashboard screen, click the KVM button to access the remote host.

    +
  2. +
  3. +

    You should now see the host system's display and interact with it remotely using a keyboard and a mouse.

    +

    Work remotely

    +
  4. +
+
+

Important next steps

+
    +
  • +

    We strongly recommend updating the PiKVM OS after the first launch:

    +
    +Updating PiKVM OS +

    To update, run following commands under the root user:

    +
    [root@pikvm ~]# pikvm-update
    +
    +

    If you encounter an error like:

    +
    [root@pikvm ~]# pikvm-update
    +bash: pikvm-update: command not found
    +
    +

    It's most likely you have an old OS release. You can update the OS as follows:

    +
    [root@pikvm ~]# rw
    +[root@pikvm ~]# pacman -Syy
    +[root@pikvm ~]# pacman -S pikvm-os-updater
    +[root@pikvm ~]# pikvm-update
    +
    +

    Next time you will be able to use the usual method with pikvm-update.

    +
    +
  • +
  • +

    Learn the basics of PiKVM OS Configuration: where to find configs, how to edit the, etc.

    +
    +Configuring PiKVM OS +
    +

    Need more info? We have it!

    +

    The following is a brief guide to configuring PiKVM. +For more information (including the basics of YAML syntax and how to use a text editor in the Linux console), +please refer to this page.

    +
    +

    Most of the PiKVM configuration files are located in the /etc/kvmd directory.

    +

    The /usr/lib/kvmd/main.yaml file defines the platform configuration, and you should never edit it. +To redefine system parameters use the file /etc/kvmd/override.yaml. +All other files that are also not recommended for editing have read-only permissions.

    +

    You can also create several files with the .*yaml suffix and put then into /etc/kvmd/override.d directory +to split your customization into logical parts. +The override.yaml file definitions takes precedence over the override.d directory.

    +

    A complete list of all parameters can be viewed using the kvmd -m command.

    +

    Files with the *.yaml suffix uses the YAML syntax +and describes a parameter tree with key-value pairs of different types. +To define the parameters within one section, an indent of 4 spaces is used. +Comments starts with the # symbol.

    +
    +

    Only 4 spaces should be used for indentation

    +

    Be careful when editing YAML and follow this rule. +Invalid indentation or tabs instead of spaces will cause an error when starting the services.

    +
    +

    Sections under the same keys should be merged:

    +
      +
    • +

      Wrong:

      +
      kvmd:
      +    gpio:
      +        drivers: ...
      +kvmd:
      +    gpio:
      +        scheme: ...
      +
      +
    • +
    • +

      Correct:

      +
      kvmd:
      +    gpio:
      +        drivers: ...
      +        scheme: ...
      +
      +
    • +
    +

    In the /etc/kvmd/meta.yaml file you can specify some information regarding this PiKVM installation in an almost free YAML format.

    +
    +
  • +
  • +

    Get to know PiKVM Web UI: read this help section to better understand all the possibilities of the web user interface.

    +
  • +
  • +

    Set up an ATX connection if you need to control the power of the remote system.

    +
  • +
+
+

Further recommendations

+
    +
  1. +

    Customize the system:

    + +
  2. +
  3. +

    Configure hardware:

    +
      +
    • +

      Install and set up the Wi-Fi antenna:

      +
      +Quick WiFi antenna how-to +

      The PiKVM V4 has a robust metal case that protects your device from physical damage and electromagnetic interference. This also means that an external antenna must be used for Wi-Fi. We recommend the official Antenna Kit for Raspberry Pi.

      +

      To install the antenna, fix it in the round hole in the back side of the PiKVM, and connect the wire to the connector on the Compute Module 4, as described in the instructions.

      +

      Next, to activate the antenna, add line dtparam=ant2 to the /boot/config.txt file on PiKVM.

      +

      Here is a video:

      +

      +

      Follow this guide to configure Wi-Fi in PiKVM OS.

      +
      +
    • +
    • +

      Install and set up LTE/5G modem (only for PiKVM V4 Plus).

      +
    • +
    • +

      Set up internal USB port for USB 3.0 (only for PiKVM V4 Plus):

      +
      +Enable USB 3.0 on the internal port +

      PiKVM V4 Plus has an internal USB port. It supports USB 3.0, but only works with USB 2.0 devices by default to minimize the power consumption. You need to flash the USB controller to enable USB 3.0. To do so, follow these steps:

      +
        +
      1. +

        Open a terminal window and log into the PiKVM via SSH:

        +
        $ ssh user@host
        +
        +
      2. +
      3. +

        Flash the USB controller using the built-in flashrom utility. Choose usb3 for USB 3.0 support:

        +
        [root@pikvm ~]# flashrom-vl805 usb3
        +
        +

        If you need to disable USB 3.0 support at any time later, run the same command, but use default instead:

        +
        [root@pikvm ~]# flashrom-vl805 default
        +
        +
      4. +
      5. +

        Perform the soft reboot:

        +
        [root@pikvm ~]# reboot
        +
        +
      6. +
      7. +

        After the soft reboot, perform the reboot by power: unplug and plug again the power cable.

        +
      8. +
      +
      +
    • +
    • +

      Learn about DIP switches:

      +
      +DIP switches purpose +
      +
      The left switch [1]:
      +
      When pulled down (ON state), the advanced backpower protection is used. On the default state is OFF (up), "diode protection" is used. This is required for debugging at the request of technical support. Under normal conditions, it is not necessary to change the mode.
      +
      The right switch [2]:
      +
      When pulled down (ON state), the Power Delivery chip is activated on the USB OTG port. The default state is OFF (up).
      +
      +

      To change the position of switches:

      +
        +
      1. Turn the PiKVM off.
      2. +
      3. Change the position of the switched.
      4. +
      5. Turn the PiKVM on.
      6. +
      +
      +

      Warning

      +

      Do not do that change the state of the DIP switched while the device is turned on. This may cause irreparable damage.

      +
      +
      +
    • +
    • +

      Choose Fahrenheit over Celsius to display on the OLED:

      +
      +How to set up Fahrenheit on the OLED +

      Create a directory for a configuration file:

      +
      [root@pikvm ~]# mkdir -p /etc/systemd/system/kvmd-oled.service.d
      +
      +

      Create file /etc/systemd/system/kvmd-oled.service.d/override.conf:

      +
      [Service]
      +ExecStart=
      +ExecStart=/usr/bin/kvmd-oled --clear-on-exit --fahrenheit
      +
      +
      +
    • +
    +
  4. +
+
+

Known issues and limitations

+
    +
  • +

    There may be compatibility issues with certain motherboards, such as HP or DELL. If there is no image from the BIOS, you can fine-tune the HDMI settings, but it is possible that mass storage devices may not be available in the BIOS. In the latter case, USB dynamic configuration will solve the problem.

    +
  • +
  • +

    While the V4 Plus features a Mini-PCIe slot, it was only designed for LTE modems. An NVME card will not work.

    +
  • +
+
+

Basic troubleshooting

+
    +
  • +

    Ensure that you are using the right OS image for your platform + by running the following command: pacman -Q | grep kvmd-platform.

    +
  • +
  • +

    If you are not getting a display, run the two following commands:

    +
      +
    • dmesg | egrep 'tc35|1-1.4|uvc'
    • +
    • systemctl status kvmd-tc358743
    • +
    +
  • +
+
+

Getting user support

+

If something doesn't work, check out our FAQ. Otherwise, head straight to our Support.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v4/initial-ui.png b/v4/initial-ui.png new file mode 100644 index 00000000..d32ef931 Binary files /dev/null and b/v4/initial-ui.png differ diff --git a/v4/login-prompt.png b/v4/login-prompt.png new file mode 100644 index 00000000..d8de4c19 Binary files /dev/null and b/v4/login-prompt.png differ diff --git a/v4/overview.jpg b/v4/overview.jpg new file mode 100644 index 00000000..e1fcfee6 Binary files /dev/null and b/v4/overview.jpg differ diff --git a/v4/pikvm-web-terminal-start.png b/v4/pikvm-web-terminal-start.png new file mode 100644 index 00000000..5af392b6 Binary files /dev/null and b/v4/pikvm-web-terminal-start.png differ diff --git a/v4/plus_back.jpg b/v4/plus_back.jpg new file mode 100644 index 00000000..ebb4630f Binary files /dev/null and b/v4/plus_back.jpg differ diff --git a/v4/plus_front.jpg b/v4/plus_front.jpg new file mode 100644 index 00000000..2112b784 Binary files /dev/null and b/v4/plus_front.jpg differ diff --git a/v4/plus_right.jpg b/v4/plus_right.jpg new file mode 100644 index 00000000..652abb6b Binary files /dev/null and b/v4/plus_right.jpg differ diff --git a/v4/remote-screen.png b/v4/remote-screen.png new file mode 100644 index 00000000..1842f368 Binary files /dev/null and b/v4/remote-screen.png differ diff --git a/v4/v4-ethernet-wiring.svg b/v4/v4-ethernet-wiring.svg new file mode 100644 index 00000000..66254e60 --- /dev/null +++ b/v4/v4-ethernet-wiring.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/v4/v4-front-view-numbered.svg b/v4/v4-front-view-numbered.svg new file mode 100644 index 00000000..cbcebab7 --- /dev/null +++ b/v4/v4-front-view-numbered.svg @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v4/v4-hdmi-usb-wiring.svg b/v4/v4-hdmi-usb-wiring.svg new file mode 100644 index 00000000..e845c0bb --- /dev/null +++ b/v4/v4-hdmi-usb-wiring.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v4/v4-plus-front-view.svg b/v4/v4-plus-front-view.svg new file mode 100644 index 00000000..7601dfa8 --- /dev/null +++ b/v4/v4-plus-front-view.svg @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + 1 + + + + 3 + + + + 2 + + diff --git a/v4/v4-power-supply-wiring.svg b/v4/v4-power-supply-wiring.svg new file mode 100644 index 00000000..d971c0e4 --- /dev/null +++ b/v4/v4-power-supply-wiring.svg @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v4/v4-rear-view-numbered.svg b/v4/v4-rear-view-numbered.svg new file mode 100644 index 00000000..ffe826bd --- /dev/null +++ b/v4/v4-rear-view-numbered.svg @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v4/v4-right-view-numbered.svg b/v4/v4-right-view-numbered.svg new file mode 100644 index 00000000..d25767a7 --- /dev/null +++ b/v4/v4-right-view-numbered.svg @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + diff --git a/v4/v4-top-view-numbered.svg b/v4/v4-top-view-numbered.svg new file mode 100644 index 00000000..ef0f3751 --- /dev/null +++ b/v4/v4-top-view-numbered.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/v4/v4_dip_switches.png b/v4/v4_dip_switches.png new file mode 100644 index 00000000..1a4cf0a7 Binary files /dev/null and b/v4/v4_dip_switches.png differ diff --git a/v4/v4mini_datasheet.pdf b/v4/v4mini_datasheet.pdf new file mode 100644 index 00000000..42456f55 Binary files /dev/null and b/v4/v4mini_datasheet.pdf differ diff --git a/v4/v4plus_datasheet.pdf b/v4/v4plus_datasheet.pdf new file mode 100644 index 00000000..0f6af100 Binary files /dev/null and b/v4/v4plus_datasheet.pdf differ diff --git a/video/index.html b/video/index.html new file mode 100644 index 00000000..3912da0d --- /dev/null +++ b/video/index.html @@ -0,0 +1,2935 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Video modes - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

Video modes

+

PiKVM V3, V4 Plus/Mini and all DIY devices based on +HDMI-CSI bridge provides three video streaming modes. This page explains +the key differences between them and helps you to achieve optimal video +performance.

+

The video mode can be switched in the System menu in the Web UI. If +you don't see the switch, probably your browser does not support H.264 +video.

+

+
+

Quick tips

+
    +
  • +

    Good network: use WebRTC or Direct mode, set H.264 gop = 0.

    +
  • +
  • +

    Bad network and WebRTC mode: Set H.264 gop = 30.

    +
  • +
  • +

    Bad network and Direct mode: Set H.264 gop = 0.

    +
  • +
  • +

    If the WebRTC mode is not working, try the Direct.

    +
  • +
  • +

    The Direct mode doesn't support audio yet. If you need audio, but WebRTC is not working, follow this guide.

    +
  • +
+
+
+

Settings

+
    +
  • +

    H.264 kbps (Bitrate) - with a large value, the video quality will be better, but the network traffic will increase.

    +
  • +
  • +

    H.264 gop (Group of Pictures) - the number of frames between which a reference frame must be forcibly added. + The recommended values are described above.

    +
  • +
+
+

WebRTC H.264 mode

+

This is the default mode. It'is using the efficient H.264 encoding to +save traffic. The video is streamed over WebRTC protocol which you may +have encountered when you used video calls in Discord or Google Chat. +Since WebRTC does not use HTTP for video, establishing a connection is +quite tricky (but PiKVM automates 99% of cases). If you have problems +with the WebRTC mode, please check this guide.

+
+

Advantages / Disadvantages

+
    +
  • +

    ✅ Supported by all modern browsers.

    +
  • +
  • +

    ✅ Provides two-way audio on PikVM V3 and V4 Plus/Mini.

    +
  • +
  • +

    ❌ The video may be lost due to a poor connection (like mobile internet, bad Wi-Fi, etc.), + or because of the router settings, when WebRTC is given low priority.

    +
  • +
  • +

    ❌ It may be blocked at all in some networks.

    +
  • +
  • +

    ❌ Sometimes the latency may increase slightly due to the peculiarities of WebRTC processing in all browsers.

    +
  • +
+
+
+

Direct H.264 mode

+

The new experimental mode for real-time streaming, introduced by PiKVM. +It also uses H.264 encoding, but streams the video over regular HTTP (WebSocket).

+
+

Advantages / Disadvantages

+
    +
  • +

    ✅ Very stable on poor networks, better than WebRTC (based on our tests and user reviews).

    +
  • +
  • +

    ✅ It is not blocked by firewalls because it appears to be regular HTTPS traffic.

    +
  • +
  • +

    ✅ The latency is low and stable too.

    +
  • +
  • +

    ❌ No audio support right now (but it will).

    +
  • +
  • +

    ❌ Some older browsers doesn't have the WebCodes support needed for this mode.

    +
  • +
+
+
+

Legacy MJPEG mode

+

Good old Motion JPEG. This is the way IP cameras have been streaming videos to browsers since ancient times. +The stream is just infinite queue of JPEGs that replace each other in <img> HTML tag. +There is no point in using it now if one of the previous modes is working.

+
+

Advantages / Disadvantages

+
    +
  • +

    ✅ Sometimes the H.264 is disabled in a browser by OS license limitations (for example, in Red Had Linux or Debian). + But MJPEG is working always.

    +
  • +
  • +

    ✅ It is not blocked by firewalls because it appears to be regular HTTPS traffic.

    +
  • +
  • +

    ✅ Low latency if you have a good network.

    +
  • +
  • +

    ❌ No audio support.

    +
  • +
  • +

    ❌❌❌ Consumes a HUGE amount of traffic. No Wi-Fi, no mobile, nothing but cable connection will work.

    +
  • +
+
+
+

What if H.264 is not supported by browser at all

+

There are some Linux distro's that require more work to be able to use H.264, +this may include any RedHat or Debian variant. Here some examples:

+
    +
  • +

    In case of Chromium on Fedora, you can connect the RPM Fusion repo + and then install the chromium-freeworld package instead of chromium.

    +
  • +
  • +

    On Debian GNU/Linux and Firefox, make sure the OpenH264 Plugin both exists and is enabled. + Press Ctrl+Shift+A to open the Add-on Manager, then press Plugins. There you should see + OpenH264 Video Codec provided by Cisco Systems, Inc. + Make sure it is enabled by pressing the "more options" button (tree dots), then pressing Always Activate.

    +
  • +
+
+

Video recording

+

At the moment, it is not possible to record videos in a convenient way from the Web UI, +but a small trick in the console can be used to record videos without sound. +It's only available on all PiKVM models which support H.264 video.

+

Available since KVMD 4.110

+
+Recording video from terminal on Linux or Mac OS +
    +
  1. +

    Install ffmpeg and websocat.

    +
  2. +
  3. +

    Let's assume that your PiKVM is located on https://pikvm and uses a self-signed certificate. + Request the stream from it from the first opened console on your PC (not PiKVM):

    +
    [user@host ~]$ websocat -k wss://pikvm/api/ws?stream=1 -H X-KVMD-User:admin -H X-KVMD-Passwd:admin
    +
    +
  4. +
  5. +

    Keeping the previous command running, open a new terminal and run the video recording process:

    +
    [user@host ~]$ websocat -b -B 10000000 -k wss://pikvm/api/media/ws?video=h264 -H X-KVMD-User:admin -H X-KVMD-Passwd:admin | ffmpeg -use_wallclock_as_timestamps 1 -i pipe: -c:v copy my_captured_video.mp4
    +
    +
  6. +
  7. +

    Same can be done on PiKVM itself, locally.

    +
  8. +
  9. +

    Press Ctrl+C to stop the recording.

    +
  10. +
+
+
+Take a screenshot from terminal on PiKVM +

To take a screenshot, switch filesystem to RW-mode like in previous example and run the stream.

+

Next, take a screenshot:

+
[root@pikvm ~]# curl --unix-socket /run/kvmd/ustreamer.sock http://localhost/snapshot -o /tmp/screen.jpg
+
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/video/menu.png b/video/menu.png new file mode 100644 index 00000000..f0a0def8 Binary files /dev/null and b/video/menu.png differ diff --git a/vnc/index.html b/vnc/index.html new file mode 100644 index 00000000..8c97307b --- /dev/null +++ b/vnc/index.html @@ -0,0 +1,2857 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + VNC - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

VNC

+

As an alternative to the Web UI, a regular VNC client can be used to +access to the PiKVM.

+

The main advantage of VNC over the browser is the ability to expand the +image to the full screen, as well as complete interception of all +keyboard shortcuts. In some cases, VNC will be more responsive than the +browser, especially on weak client computers.

+
+

Warning

+

Don't use VNC without X.509 or TLS encryption on untrusted networks! +Otherwise your password will be transmitted over the network in plain text. +Unfortunately, this is the reality of the VNC protocol.

+
+
+

Note

+

The performance of VNC on PiKVM does not make sense to compare with regular VNC servers +or a similar remote access tool at the OS level. +PiKVM will run a little slower due to the fact that access is done at the hardware level.

+

A typical video processing chain looks like this:

+
    +
  • Regular VNC/RDP/TeamViewer/Etc: OS -> Remote access server -> Network -> Client.
  • +
  • PiKVM: OS -> Video card -> PiKVM video capture -> PiKVM server -> Network -> Client.
  • +
+
+
+

Enabling VNC on the PiKVM side

+
    +
  1. +

    The recommended client is TigerVNC.

    +
  2. +
  3. +

    Switch the PiKVM filesystem to read-write mode using command rw.

    +
  4. +
  5. +
    +Optional for non-TigerVNC clients: Change the keybobard layout for non-US keyboard +

    This step is nessessory if you're using a client that does not support +the direct keyboard access.

    +

    In this case you can force the client layout in /etc/kvmd/override.yaml:

    +
    vnc:
    +    keymap: /usr/share/kvmd/keymaps/ru
    +
    +

    All available keymaps are located in /usr/share/kvmd/keymaps:

    +

    +
    +
  6. +
  7. +
    +Optional for non-TigerVNC and NOT RECOMMENDED: Enable VNCAuth method +

    This step is nessessory if you're using a client that does not support the user/password +auth method like TightVNC (don't confuse it with TigerVNC).

    +

    In this case you can enable VNCAuth passphrases mode in /etc/kvmd/override.yaml:

    +
    vnc:
    +    auth:
    +        vncauth:
    +            enabled: true
    +
    +

    To set passphrases edit the file /etc/kvmd/vncpasswd.

    +

    But once again: THIS IS AN UNSAFE AUTHORIZATION METHOD and it is better to use TigerVNC.

    +
    +
  8. +
  9. +

    Enable kvmd-vnc daemon. VNC will be available on the port 5900: systemctl enable --now kvmd-vnc.

    +
  10. +
  11. +

    Switch filesystem back to read-only: ro.

    +
  12. +
+
+

Note

+

With enabled 2FA, you will need to append the one-time code +to the password without spaces. That is, if the password is foobar and the code is 123456, +then the string foobar123456 should be used as a password.

+
+
+

Configuring the client

+

We recommend TigerVNC for a better experience on a desktop.

+

If you're using PiKVM V3+ or DIY based on CSI bridge, you can try +the latest version (>= 1.13.0) of TigerVNC with H.264 support. +It will improve performance and save traffic.

+

H.264 video mode is available in binary builds for Windows, for other OS it needs to be compiled manually +(ffmpeg libraries required to build).

+

Here are our recommended settings for TigerVNC:

+ + + + + + + + + + + + + + + + + +
Compression tabSecurity tab
If your client does not support H.264, choose Tight
+

For iOS and Android the recommended application is bVNC:

+ +
+

Hotkeys

+

Inside a VNC session, you can use several hotkeys related to PiKVM, independent of the VNC client. +Hotkeys are triggered by quickly pressing and releasing each key sequentially (that is, you don't need to hold them down like Ctrl+Alt+Del).

+
    +
  • +

    LeftAlt, LeftAlt, P - Paste text from the clipboard.
    + PiKVM does not have access to the clipboard, so pasting works as if you had typed this text. ASCII always works, layout switching is not supported. To type text in a different language, you need the layout on the host to match the one you are using (and keymap is also configured as described above for some VNC clients)

    +
  • +
  • +

    LeftAlt, LeftAlt, 1 (1-8) - Switch to channel 1 with PiKVM Switch, when you have one or two switches.

    +
  • +
  • +

    LeftAlt, LeftAlt, 3, 2 - Switch to unit 3, channel 2 of PiKVM Switch chain, when you have more than two switches.
    + Single-key port numbers do not work if there are more than two candles.

    +
  • +
+
+

Unsupported clients

+
    +
  • RealVNC - Does not support most widely used open VNC protocol extensions.
  • +
  • Remmina - Slightly imperfect algorithms for matching settings with the server, we are working on it.
  • +
  • Guacamole - Incorrectly implements vencrypt, no JPEG compression.
  • +
  • Vinagre - Incorrectly implements vencrypt, dead.
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vnc/keymaps.png b/vnc/keymaps.png new file mode 100644 index 00000000..fb9d51e3 Binary files /dev/null and b/vnc/keymaps.png differ diff --git a/vnc/tigervnc_compression.png b/vnc/tigervnc_compression.png new file mode 100644 index 00000000..0562cf86 Binary files /dev/null and b/vnc/tigervnc_compression.png differ diff --git a/vnc/tigervnc_security.png b/vnc/tigervnc_security.png new file mode 100644 index 00000000..2ce11685 Binary files /dev/null and b/vnc/tigervnc_security.png differ diff --git a/webrtc/index.html b/webrtc/index.html new file mode 100644 index 00000000..e0f56a2c --- /dev/null +++ b/webrtc/index.html @@ -0,0 +1,14 @@ + + + + + + Redirecting... + + + + + +You're being redirected to a new destination. + + diff --git a/webrtc_config/index.html b/webrtc_config/index.html new file mode 100644 index 00000000..13998dc6 --- /dev/null +++ b/webrtc_config/index.html @@ -0,0 +1,2778 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + WebRTC H.264 - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

WebRTC H.264

+

This is the default mode. It'is using the efficient H.264 encoding to save traffic. +The video is streamed over WebRTC protocol which you may have encountered when you used video calls in Discord or Google Chat.

+

It is available on PiKVM V3, V4 Plus/Mini and all DIYdevices based on HDMI-CSI bridge.

+

The video mode can be switched in the System menu in the Web UI. +If you don't see the switch, probably your browser does not support H.264 video.

+
+

How it's working

+

The Direct H.264 or MJPEG video is streaming video using the +similar HTTP connection like to get the Web UI. This means that for +remote access, you just need to forward only ports +80 and 443 on your router it has public external IP address.

+

In contrast, WebRTC is a completely different way of transmitting video. +It uses a P2P connection and UDP. This reduces network load, but makes +it difficult to connect—the PiKVM needs to know your network +configuration in order to use it correctly: public IP, NAT type and so +on.

+

To achieve this, the PiKVM checks which of the network interfaces is +used for the default gateway, and tries to find out your external IP +address using the Google STUN +server.

+
+

Tip

+

Google STUN servers was choosen for reliability reasons.

+

If you don't want to use it, you can choose any other public STUN server you like, or set up your own.

+

To change the STUN server, edit /etc/kvmd/override.yaml (an example):

+
janus:
+    stun:
+        host: stun.stunprotocol.org
+        port: 3478
+
+

... and restart kvmd-janus service using systemctl restart kvmd-janus.

+
+
+

Custom Janus config

+

Janus is a WebRTC gateway that is +used to transmit the video from PiKVM +uStreamer. PiKVM has a special +service named kvmd-janus which is a wrapper for Janus that monitors +the network configuration and applies changes.

+

However, if your PiKVM is not connected to the Internet and/or you want +to use a custom Janus configuration, you should run the +kvmd-janus-static service instead.

+

The configuration is located in /etc/kvmd/janus/janus.jcfg. You can +change all you need according to the Janus +Documentation, stop +the kvmd-janus and start the kvmd-janus-static service:

+
[root@pikvm ~]# systemctl disable --now kvmd-janus
+[root@pikvm ~]# systemctl enable --now kvmd-janus-static
+
+
+

Troubleshooting

+

In some cases, WebRTC may not work. Here some common tips:

+
    +
  • +

    Clear the browser cache.

    +
  • +
  • +

    Try any other browser, incognito or private window without any extensions.

    +
  • +
  • +

    Tricky IPv6 configuration on the network can be a problem. IPv6 support for WebRTC in PiKVM is still in its infancy, so if your network has IPv4, it will be easiest to disable IPv6 on PiKVM. To do this, switch the file system to write mode using rw command, add option ipv6.disable_ipv6=1 to /boot/cmdline.txt and perform reboot. Also see here.

    +
  • +
  • +

    A paranoid firewall can interfere too when you try to connect to the PiKVM by forwarding port 443 to the Internet from the internal network. WebRTC is not enough of this, it uses UDP on ports 20000-40000 for a P2P connection. Make sure that the Firewall does not block them.

    +
  • +
  • +

    If nothing helps, open the browser's JavaScript console, look at the log and contact our Support. Developers and/or experienced users will definitely help you.

    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/webui/ATX.jpg b/webui/ATX.jpg new file mode 100644 index 00000000..3e781361 Binary files /dev/null and b/webui/ATX.jpg differ diff --git a/webui/Drive.jpg b/webui/Drive.jpg new file mode 100644 index 00000000..bbbb8f33 Binary files /dev/null and b/webui/Drive.jpg differ diff --git a/webui/Login.jpg b/webui/Login.jpg new file mode 100644 index 00000000..7a9340b9 Binary files /dev/null and b/webui/Login.jpg differ diff --git a/webui/Macro.jpg b/webui/Macro.jpg new file mode 100644 index 00000000..dec998d7 Binary files /dev/null and b/webui/Macro.jpg differ diff --git a/webui/Page1.jpg b/webui/Page1.jpg new file mode 100644 index 00000000..c571d99c Binary files /dev/null and b/webui/Page1.jpg differ diff --git a/webui/Page2.jpg b/webui/Page2.jpg new file mode 100644 index 00000000..eec693f9 Binary files /dev/null and b/webui/Page2.jpg differ diff --git a/webui/Portal.jpg b/webui/Portal.jpg new file mode 100644 index 00000000..4f5466f3 Binary files /dev/null and b/webui/Portal.jpg differ diff --git a/webui/Shortcuts.jpg b/webui/Shortcuts.jpg new file mode 100644 index 00000000..247fcba0 Binary files /dev/null and b/webui/Shortcuts.jpg differ diff --git a/webui/System.jpg b/webui/System.jpg new file mode 100644 index 00000000..ea8006d0 Binary files /dev/null and b/webui/System.jpg differ diff --git a/webui/Text.jpg b/webui/Text.jpg new file mode 100644 index 00000000..d47b48fd Binary files /dev/null and b/webui/Text.jpg differ diff --git a/webui/Toolbar.jpg b/webui/Toolbar.jpg new file mode 100644 index 00000000..91dd8e13 Binary files /dev/null and b/webui/Toolbar.jpg differ diff --git a/webui/index.html b/webui/index.html new file mode 100644 index 00000000..f212cef9 --- /dev/null +++ b/webui/index.html @@ -0,0 +1,2911 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Getting to know the web UI - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

Web UI Overview

+ +

Logging in

+

After following the first steps document on setup, you will be presented with the following pages (Chrome is being used in the following examples)

+

+

Click Advanced

+

+

Click Proceed

+
+

Credentials are found in the first steps document that is located to the left

+
+

+

This is where you fill in the login credentials, please be sure to +review the first steps document first. This is also where you configure +the 2FA token.

+

Initial screen

+

+
+Please expand to see what each number represents +
    +
  1. This is where your PiKVM name will go - Please reference the first steps document on how to change this
  2. +
  3. This is where you can access the display for the Target system
  4. +
  5. You can open a web terminal and put in commands that you will find within these documents
  6. +
  7. By default this will not show up till its activated, this will tell you the VNC address you need to use
  8. +
  9. This is so you can logout of your PiKVM
  10. +
  11. Please read carefully
  12. +
  13. These are links to the PiKVM project, current documentation and support
  14. +
  15. NOT SHOWN, in the lower left of the KVM screen is some information that when you mouse over, will let you know what they are for
  16. +
+
+

Web UI toolbar

+

+
+Please expand to see what each number represents +
    +
  1. This is the system setting, more details will be shown below
  2. +
  3. This is the interface to controlling the ATX, will ONLY work if wired up correctly
  4. +
  5. This is part of the MSD and will show you what images/iso's are available
  6. +
  7. This is where you can program in a Macro (Ex. Hitting F2 to get into the bios, setting Infinite loop playback to on and doing other tasks)
  8. +
  9. This is where you can SEND text to the Target or using OCR, you can copy FROM the target, be mindful that OCR can make mistakes, please review before finalizing
  10. +
  11. This is where you can find most Shortcuts (Windows only, for now) (Not editable)
  12. +
  13. This is placed here to give you an idea what you can achieve if you make your own menu item
  14. +
+
+

The System menu

+

+
+

The following is self explanatory but will highlight the important parts

+
+
+Please expand to see what each number represents +
    +
  1. +

    System Icons

    +

    ETH Icon = PiKVM network connectivity

    +

    Monitor Icon = Shows if the target is sending an active signal

    +

    KeyBoard Icon = Shows if data for the KB is active, will likely show Orange/Green as data is passed and goes idle

    +

    Mouse Icon = Same as above

    +
  2. +
  3. +

    These are additional buttons for important acitivies

    +

    Term = Can launch a quick Web Terminal along with the active KVM

    +

    About = Shows everything About your PiKVM, including PiKVM Hardware and version

    +

    Log = Shows the current log from your PiKVM

    +
  4. +
  5. +

    ONLY for MJPEG mode

    +
  6. +
  7. ONLY for H.264 (WebRTC) mode
  8. +
+
+

The ATX menu

+

+

This ONLY works if you have the hardware connected to the MB, otherwise will not work

+

The Drive menu

+

+

This is where you can select the IMG or ISO's that are stored

+

The Macro menu

+

+
    +
  1. Please read and understand this section
  2. +
  3. This is where you can upload or download your scripts
  4. +
+

The Text menu

+

+
+

Note

+

This is not like VNC/AnyDesk/TeamViewer as these are software solutions, this is a hardware solution therefor cannot change the behavior of the target system. +This does not act like a clipboard

+
+
    +
  1. +

    This will allow you to paste text to the target system—be mindful whats being pasted to the target and how.

    +
  2. +
  3. +

    This will allow you to ONLY copy text from the target—be mindful that OCR will do its best to recognize text but may fail at it.

    +
  4. +
+

The Shortcuts menu

+

+

This is an expanded view and shows the shortcuts mostly for Windows.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/webui/kvm window.jpg b/webui/kvm window.jpg new file mode 100644 index 00000000..55a446d1 Binary files /dev/null and b/webui/kvm window.jpg differ diff --git a/wifi/index.html b/wifi/index.html new file mode 100644 index 00000000..e4d63107 --- /dev/null +++ b/wifi/index.html @@ -0,0 +1,2839 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Setting up Wi-Fi - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Setting up Wi-Fi

+ +
+

Tip

+
    +
  • There is nothing more reliable than wired Ethernet, so it's better to use it. Wi-Fi with the steel case (on PiKVM V3 and V4) results in poor performance. But who are we to stop you... :)
  • +
  • Devices based on Raspberry Pi Zero 2 W does not support 5GHz Wi-Fi.
  • +
+
+

The following describes how to setup a Wi-Fi connection. We recommend to +do this while having a display and keyboard or a serial console +connected directly to the Raspberry Pi as you will loose network +connectivity once you connect to a Wi-Fi. Alternatively you can connect +to the PiKVM via SSH. The built-in Web Terminal (available through the +browser) should also work.

+
+

Take a look at the easiest way

+

This guide describes how to manually set up a Wi-Fi. An easier way is to use On-boot config. +It is also mandatory for Zero 2 W board.

+
+
+

Setting up Wi-Fi manually

+
    +
  1. +

    Make filesystem writable using the rw command.

    +
  2. +
  3. +

    Create the Wi-Fi settings file /etc/systemd/network/wlan0.network with the following content:

    +
    [Match]
    +Name=wlan0
    +
    +[Network]
    +DHCP=yes
    +DNSSEC=no
    +
    +[DHCP]
    +ClientIdentifier=mac
    +RouteMetric=50
    +
    +
  4. +
  5. +

    Set network ESSID and password:

    +
    [root@pikvm ~]# wpa_passphrase 'MyNetwork' 'P@assw0rd' > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
    +[root@pikvm ~]# chmod 640 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
    +
    +
    +

    WPA2 and WPA3 support

    +

    Add options key_mgmt=WPA-PSK-SHA256 WPA-PSK and ieee80211w=1 to /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

    +
    +
    +

    Using Wi-Fi with hidden ESSID

    +

    Add option scan_ssid=1 to /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

    +
    +
    +

    Using 5GHz Wi-Fi in the USA

    +

    Add option country=US to /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

    +
    +
    +

    Block 2ghz or 5ghz

    +

    Add option bssid=xx:xx:xx:xx:xx:xx to /etc/wpa_supplicant/wpa_supplicant-wlan0.conf within the network={ block

    +
    +
  6. +
  7. +

    Enable WPA-supplicant service:

    +
  8. +
+
[root@pikvm ~]# systemctl enable wpa_supplicant@wlan0.service
+
+
    +
  1. Make filesystem read-only again using ro command
  2. +
+
+

Multiple Wi-Fi networks

+

You can configure PiKVM to connect to one of several known Wi-Fi networks. +To do this, just simply add the configuration of these networks. +Pay attention to the symbol >>, it is used to append at the end of configuration, +while a single > will overwrite the entire configuration.

+
    +
  1. +

    Make the filesystem writeble with rw command.

    +
  2. +
  3. +

    Add some new networks:

    +
    [root@pikvm ~]# wpa_passphrase 'Wifi1' 'P@assw0rd' >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
    +[root@pikvm ~]# wpa_passphrase 'Wifi2' 'P@assw0rd' >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
    +[root@pikvm ~]# wpa_passphrase 'Wifi3' 'P@assw0rd' >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
    +
    +
  4. +
  5. +

    Restart the service: systemctl restart wpa_supplicant@wlan0.service.

    +
  6. +
  7. +

    Make the filesystem read-only again using ro command

    +
  8. +
+
+

Useful console commands

+
    +
  • iwconfig - Manipulate the basic wireless parameters.
  • +
  • iwlist - Allow's you to initiate scanning and list frequencies, bit-rates, encryption keys, etc.
  • +
  • iwspy - Displays per node link quality.
  • +
  • iwpriv - Allow's you to manipulate the Wireless Extensions specific to a driver (private).
  • +
+
+Some examples +

[root@pikvm ~]# iw dev wlan0 scan | egrep "signal:|SSID:" | sed -e "s/\tsignal: //" -e "s/\tSSID: //" | awk '{ORS = (NR % 2 == 0)? "\n" : " "; print}' | sort
+
+
[root@pikvm ~]# iwlist wlan0 scan | egrep "Cell|ESSID|Signal|Rates"
+
+
[root@pikvm ~]# iwlist wlan0 scan
+
+
[root@pikvm ~]# iw wlan0 info
+
+
+
+

Additional resources

+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/wiring_examples/csi_wiring.jpg b/wiring_examples/csi_wiring.jpg new file mode 100644 index 00000000..04374f8d Binary files /dev/null and b/wiring_examples/csi_wiring.jpg differ diff --git a/wiring_examples/csi_wiring_w_pcb_splitter.jpg b/wiring_examples/csi_wiring_w_pcb_splitter.jpg new file mode 100644 index 00000000..747bab66 Binary files /dev/null and b/wiring_examples/csi_wiring_w_pcb_splitter.jpg differ diff --git a/wiring_examples/direct_connect_to_target.jpg b/wiring_examples/direct_connect_to_target.jpg new file mode 100644 index 00000000..fbaddaf2 Binary files /dev/null and b/wiring_examples/direct_connect_to_target.jpg differ diff --git a/wiring_examples/ezcoo_wiring.jpg b/wiring_examples/ezcoo_wiring.jpg new file mode 100644 index 00000000..77da5d17 Binary files /dev/null and b/wiring_examples/ezcoo_wiring.jpg differ diff --git a/wiring_examples/index.html b/wiring_examples/index.html new file mode 100644 index 00000000..baf8bf15 --- /dev/null +++ b/wiring_examples/index.html @@ -0,0 +1,2678 @@ + + + + + + + + + + + + + + + + + + + + + + Some example wiring setups - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ + + + + +

Some example wiring setups

+ +

HDMI-CSI

+

drawing

+

List of items: (WARNING! Links may dissappear or no longer work, this just gives you an idea)

+ +

Another CSI example using the PCB splitter

+

drawing

+

HDMI-USB

+

drawing

+

Direct connect to target

+

drawing

+

Explanation of pic +- USB-C from PI to USB-A onto target which also powers the PI

+

Use case: +- Trying to determine if the data cable is truly a data cable and not just a power cable +- Testing to see if the splitter or cable is defective +- Basic troubleshooting

+

EZCOO wiring example

+

drawing

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/wiring_examples/usb_capture_wiring.jpg b/wiring_examples/usb_capture_wiring.jpg new file mode 100644 index 00000000..d3c9b326 Binary files /dev/null and b/wiring_examples/usb_capture_wiring.jpg differ diff --git a/wol/index.html b/wol/index.html new file mode 100644 index 00000000..6b61632c --- /dev/null +++ b/wol/index.html @@ -0,0 +1,2707 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Wake-on-LAN - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Wake-on-LAN

+

Simplified method (one host)

+

To use Wake-on-LAN with your server you must define some options such as the server's MAC address and (optionally) IP address. Use /etc/kvmd/override.yaml. The format is:

+
kvmd:
+    wol:
+        mac: ff:ff:ff:ff:ff:ff
+
+

Replace ff:ff:ff:ff:ff:ff with the MAC of your server. By default, a packet is sent via a broadcast request to the entire IPv4 network (255.255.255.255, port 9), but you can address it to a specific static address:

+
kvmd:
+    wol:
+        mac: ff:ff:ff:ff:ff:ff
+        ip: 192.168.0.100
+        # port: 9  # By default
+
+

... then restart kvmd using systemctl restart kvmd. It will now show up in the system button in the upper right corner.

+

GPIO method (multiple hosts)

+

Follow the manual for building the GPIO menu and use the wol driver to build a menu with many buttons tied to different hosts.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xh_hk4401/ft232_config.png b/xh_hk4401/ft232_config.png new file mode 100644 index 00000000..e41ecccd Binary files /dev/null and b/xh_hk4401/ft232_config.png differ diff --git a/xh_hk4401/index.html b/xh_hk4401/index.html new file mode 100644 index 00000000..033c8cbb --- /dev/null +++ b/xh_hk4401/index.html @@ -0,0 +1,3083 @@ + + + + + + + + + + + + + + + + + + + + + + XH-HK4401 4-port HDMI USB KVM Switch - PiKVM Handbook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + +

XH-HK4401 4-port HDMI USB KVM Switch

+
+

This document was supplied by a community member, thus it is not officially endorsed or supported.

+
+
+

PiKVM + Multiport Switches compatibility

+

Please note that this switch requires a USB port for control. The following devices can provide this:

+
    +
  • PiKVM V3 & V4 Plus.
  • +
  • DIY devices based on Raspberry Pi 2, 3 and 4.
  • +
+

The following devices are not compatible:

+
    +
  • PiKVM V4 Mini - it doesn't have a USB host port and cannot control switches, it's a single-host device.
  • +
  • DIY based on Raspberry Pi Zero 2 W - it doesn't have USB host port too.
  • +
+
+

drawing

+

This KVM is sold under many names, and comes in two versions. +The only way these two versions differ is that one has one of its USB ports replaced with a PS/2 port. The +identifying feature is that they come with a small external control unit with 4 buttons. This controller is +connected to the main KVM via a micro USB cable, however this is NOT as USB connection.

+
+

Warning

+

Audio was not tested, it is assumed to be non-functional

+
+

Connections

+
    +
  1. +

    Connect the USB-A cable from the Raspberry Pi OTG port to to any of the USB ports on the XH-HK4401 switch. All 3/4 USB ports work exactly the same, internally they are just connected to a USB HUB.

    +
  2. +
  3. +

    Connect the HDMI out from the XH-HK4401 switch to the Raspberry Pi CSI-2 to HDMI input.

    +
  4. +
  5. +

    Connect host USB and HDMI cables from the XH-HK4401 switch to the machines to be managed per the switch instructions.

    +
  6. +
  7. +

    Finally see below for details about connecting to the control micro USB port. This it not a normal USB micro port.

    +
  8. +
+
+

Warning

+

There is a limitation in the underlying PiKVM software related to plugging video cables from a host which is already powered and connected to a monitor to a Raspberry Pi HDMI-CSI bridge. These limitations apply equally when using the XH-HK4401 KVM switch. If video is not present in PiKVM, try keeping all host machines off and connecting them directly to the XH-HK4401 switch before powering the hosts on.

+
+

RS-232 control cable

+

The control unit communicates to the KVM using the RS-232 protocol (at 5v) not USB, and one of the following +solutions must be used.

+

Inverting USB UART adapter (FT-232) - The easy way

+

Some USB UART adapters have the rare feature to invert the logic level of the RX/TX signals. For example the FTDI FT232 can +be configured via the FTDI configuration GUI to do this. With such an adapter, the circuit above is not required. All you +need is to connect it to a micro-USB connector.

+
+

Warning

+

These options will only work on UART adapters with genuine FTDI chips. There are a lot of cheap fakes on the +market that either lack this option, or will prevent you from changing the settings. To avoid getting a fake +ensure you always purchase from a reputable store and brand (Adafruit, Sparkfun, etc.), Amazon is not a +reputable store.

+
+

Linux Instructions

+
+References I used to get my FTDIs working: + +
+
+

Warning

+

Steps were performed on Debian-like installation (Pop!_OS 21.10)

+
+

This workflow has worked for a self-described NON-genuine FTDI FT232RL chip. The other MAY be genuine, but it is also working.

+

Neither of the following FTDI UART adapters are recommended. Purchasing both chips was an error (only 1 intended). However, having two (potentially non-genuine) FTDI UART adapters helped to create these instructions.

+ +
+

Warning

+

The HiLetGo UART adapter comes with a USB MINI female connector and necessitates another adapter/cable for interfacing with the Pi.

+
+
    +
  1. +
    +Get info from FTDI +
      +
    • Plug the FTDI into a USB port on your Linux device and run lsusb to verify that the device is found +
      lsusb
      +
    • +
    • Ensure the device is recognized as FTDI +
      sudo lshw | grep -B 10 ftdi
      +
    • +
    • Record hardware information (not sure if needed, but was saved to prevent overwriting critical data in the EEPROM)
    • +
    +
    +
  2. +
  3. +
    +Blacklist ftdi_sio kernel module +
      +
    • The kernel module ==ftdi_sio== is currently enabled (and how you saw the device in the previous step). We need to disable this module to read/write to the EEPROM.
    • +
    • The following command creates a file to blacklist the ==ftdi_sio== module. +
      echo "blacklist ftdi_sio" | sudo tee /etc/modprobe.d/bl-ftdi.conf > /dev/null
      +
    • +
    +
    +
  4. +
  5. +
    +Reboot machine +
      +
    • We need to reboot into an environment without ftdi_sio active. +
      shutdown -r 0
      +
    • +
    +
    +
  6. +
  7. +
    +Install ftdi_eeprom if not already installed +
      +
    • Install ==ftdi_eeprom== with the following command. +
      sudo apt install ftdi_eeprom
      +
    • +
    +
    +
  8. +
  9. +
    +Make a folder to work from and change it to our working directory +
    mkdir ./ftdi_config
    +cd ./ftdi_config
    +
    +
    +
  10. +
  11. +
    +Create a valid FTDI configuration file for ftdi_eeprom consumption +
      +
    • The below command (copy/paste all lines) will create a valid configuration file. Change parameters as required. +
      tee ./ftdi.conf > /dev/null <<EOF
      +filename=eeprom.bin
      +vendor_id=0x0403
      +product_id=0x6001
      +manufacturer="FTDI"
      +product="FT232 Serial (UART)"
      +serial="SERIAL"
      +use_serial=true
      +max_power=500
      +self_powered=false
      +invert_txd=true
      +invert_rxd=true
      +cha_type="UART"
      +EOF
      +
    • +
    • This configuration is trimmed from the example due to size of the EEPROM on the FTDIs used.
    • +
    • The example configuration at ==/usr/share/doc/ftdi-eeprom/example.conf== describes possible configuration options for the FTDI and is well-documented.
    • +
    • The above configuration worked for the mentioned devices. The ==filename==, ==vendor_id==, ==product_id==, ==invert_txd==, and ==invert_rxd== variables are required. The others might not be, but seemed applicable.
    • +
    • If you're using a different FTDI chip than used here, please update that in the above configuration. Ensure that vendor_id and product_id are what was obtained from the output of the initial lsusb command.
    • +
    • ==max_power==, ==serial==, and ==product== were updated to reflect the output of the initial lshw. These updates may not be required and were done to avoid overwriting anything important. ==cha_type== was updated to ==UART== where both of the devices were originally designated as FIFO.
    • +
    +
    +
  12. +
  13. +
    +Test the configuration and read the eeprom initially before flashing +
      +
    • Read the EEPROM with the following command +
      sudo ftdi_eeprom --read-eeprom ./ftdi.conf
      +
    • +
    • If you get an error here, there's something wrong with your configuration. Check that the device is properly identified and try again.
    • +
    +
    +
  14. +
  15. +
    +Rename/preserve and review the contents of the binary read from the EEPROM +
      +
    • First, rename the output binary file so we don't overwrite it when we flash (flashing writes the flashed binary to the ==filename== path) +
      mv ./eeprom.bin ./original_eeprom.bin
      +
    • +
    • Then, display the outputs of the binary +
      hexdump -C original_eeprom.bin
      +
    • +
    • You can rename the binary in the configuration file by editing the ==filename== variable. If you can't be bothered to edit the file, rename it as detailed above.
    • +
    +
    +
  16. +
  17. +
    +Flash the configuration +
      +
    • Run the following command to flash the EEPROM of the FTDI +
      sudo ftdi_eeprom --flash-eeprom ./ftdi.conf
      +
    • +
    • Optional: compare the flashed configuration to the initial configuration with the below command. If there is no output, the files are the same. You will likely need to re-flash. +
      diff <(xxd original_eeprom.bin) <(xxd eeprom.bin)
      +
    • +
    • Alternatively, you can manually compare the files by running hexdump -C original_eeprom.bin and hexdump -C eeprom.bin
    • +
    +
    +
  18. +
  19. +
    +Your FTDI should be flashed and working to control the KVM! +
      +
    • Plug it into one of the Pi's USB slots (if not already), and it's good to go.
    • +
    • The KVM will sink power from the FTDI (Pi) if Vcc is connected. If Vcc is disconnected, ensure that grounds between the Pi and KVM are tied.
    • +
    +
    +
  20. +
  21. +
    +Clean up the ftdi blacklist to reenable the ftdi_sio module +
      +
    • Comment out the line but leave the file with the following command: +
      sudo sed -i 's/blacklist ftdi_sio/#blacklist ftdi_sio/g' /etc/modprobe.d/bl-ftdi.conf
      +
    • +
    • If you'd need to read/flash FTDI EEPROM in the future, you can use the following command (followed by a reboot) to blacklist the ==ftdi_sio== module again. +
      sudo sed -i 's/#blacklist ftdi_sio/blacklist ftdi_sio/g' /etc/modprobe.d/bl-ftdi.conf
      +
    • +
    • If you want to wash your hands of FTDI flashing, then delete the blacklist file with the following command: +
      sudo rm /etc/modprobe.d/bl-ftdi.conf
      +
    • +
    +
    +
  22. +
  23. +
    +Reboot the machine to reset to initial state (with ftdi_sio loaded) +
      +
    • ==ftdi_sio== should reload as the driver, and the FTDI should be able to be seen with lshw / dmesg once again. If you tried to run either command while ==ftdi_sio== was blacklisted, you probably would have come up empty.
    • +
    +
    +
  24. +
+

Windows Instructions

+

In order to invert the RX/TX signals, you can use ft_prog and set the +following settings:

+

+

Once the UART is configured, please fully disconnect it and connect it back to the computer. Relaunch ft_prog and ensure the settings are still set. If they are not, you have a fake FTDI chip.

+

FTDI Terminal Configuration

+

Finally, you will need to connect it to the micro USB port (This it not a normal USB micro port.) +like so:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SignalColourFT232 Pin
VbusRed5v (if you want to power the KVM from the Pi's USB)
D-WhiteRX
D+GreenTX
GndBlackGND
+

An inverter circuit - The cheap way

+

For this you will need:

+
    +
  • 1x 74HC14
  • +
  • 1x USB A socket, or sacrificial micro USB cable
  • +
  • Optional 1x Diode - If you want to power the KVM from the Raspberry Pi
  • +
  • 1x 5-pin header
  • +
  • 5x Female - Female jumper cables
  • +
+

+
+

Note

+

Please search online for USB pinouts to ensure you connect it properly.

+
+

Adding UI elements to control the KVM switch

+

The UI can be updated to add buttons to switch between KVM inputs and indicators for which input is currently selected. The instructions below will make these available in the PiKVM UI after clicking the "GPIO" menu button in the KVM view.

+
    +
  1. +

    SSH into PiKVM

    +
  2. +
  3. +

    Enable read-write mode on the sd card via rw

    +
  4. +
  5. +

    Edit the /etc/kvmd/override.yaml file and include the following.

    +
  6. +
+ + + + + + + + + + + + + + + + + +
MethodDevice
FT-232/dev/ttyUSB0
Inverter/dev/ttyAMA0
+
kvmd:
+    gpio:
+        drivers:
+            hk:
+                type: xh_hk4401
+                device: /dev/ttyUSB0
+        scheme:
+            ch0_led:
+                driver: hk
+                pin: 0
+                mode: input
+            ch1_led:
+                driver: hk
+                pin: 1
+                mode: input
+            ch2_led:
+                driver: hk
+                pin: 2
+                mode: input
+            ch3_led:
+                driver: hk
+                pin: 3
+                mode: input
+            ch0_button:
+                driver: hk
+                pin: 0
+                mode: output
+                switch: false
+            ch1_button:
+                driver: hk
+                pin: 1
+                mode: output
+                switch: false
+            ch2_button:
+                driver: hk
+                pin: 2
+                mode: output
+                switch: false
+            ch3_button:
+                driver: hk
+                pin: 3
+                mode: output
+                switch: false
+        view:
+            table:
+                - ["#Input 1", ch0_led, ch0_button]
+                - ["#Input 2", ch1_led, ch1_button]
+                - ["#Input 3", ch2_led, ch2_button]
+                - ["#Input 4", ch3_led, ch3_button]
+
+
    +
  1. +

    Return to read-only mode for the sd card via ro

    +
  2. +
  3. +

    Restart the kvmd service: systemctl restart kvmd

    +
  4. +
+

Switching between hosts in the UI

+

To switch between hosts, enter the KVM UI and click the "GPIO" menu. You should see 4 inputs, one of which will have a green circle indicating it is currently selected. Click the other inputs to change the selected host.

+

Please review this latest issue for an update to the existing instructions

+ + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xh_hk4401/xh-hk4401.jpg b/xh_hk4401/xh-hk4401.jpg new file mode 100644 index 00000000..0da85155 Binary files /dev/null and b/xh_hk4401/xh-hk4401.jpg differ diff --git a/xh_hk4401/xh-hk4401_circuit.png b/xh_hk4401/xh-hk4401_circuit.png new file mode 100644 index 00000000..607e31c9 Binary files /dev/null and b/xh_hk4401/xh-hk4401_circuit.png differ