<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Hung Vu</title>
    <description>The latest articles on Forem by Hung Vu (@hunghvu).</description>
    <link>https://forem.com/hunghvu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F807797%2Fb11838ae-c033-44ae-9052-275f91dfa16d.png</url>
      <title>Forem: Hung Vu</title>
      <link>https://forem.com/hunghvu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hunghvu"/>
    <language>en</language>
    <item>
      <title>Guide: Update NVM firmware on Intel i226 and Intel i225 Ethernet controllers</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Sun, 01 Feb 2026 17:20:35 +0000</pubDate>
      <link>https://forem.com/hunghvu/guide-update-nvm-firmware-on-intel-i226-and-intel-i225-ethernet-controllers-o2m</link>
      <guid>https://forem.com/hunghvu/guide-update-nvm-firmware-on-intel-i226-and-intel-i225-ethernet-controllers-o2m</guid>
      <description>&lt;p&gt;The Intel i225 and i226 Ethernet controllers and their variants are widely known for their unreliable performance, namely random network disconnections, packet loss, and power saving incompatibility. Since the release back in Q4 of 2019, Intel unfortunately has not been able to fully resolve these various issues as far as I know. Some say the hardware itself is flawed, some says it is the firmware (non volatile memory - NVM) that needs to be updated, and some says it is the driver issue. In reality, it is probably a combination of all these factors.&lt;/p&gt;

&lt;p&gt;In this article, I want to talk about the NVM firmware part. As of early 2026, the Intel i225 and i226 controllers are still widely used in many consumer devices, but Intel opted to not release the Intel i226 NVM firmware update tool for public download on their official website, while the Intel i225 counterpart is available. Instead, they only provide the firmware update tool to OEMs and system integrators. With that said, most users are stuck with the outdated NVM firmware that came with their devices. Still, there is a way to update the NVM firmware for these controllers, and I will show you how.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DISCLAIMER&lt;/strong&gt;: Performing NVM firmware update carries inherent risks, including the possibility of bricking your device. &lt;em&gt;Proceed with caution and at your own risk&lt;/em&gt;. Ensure you have a backup of important data and configurations before proceeding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we begin, make sure you have the following prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A computer with an Intel i225-V or i226-V Lan on Motherboard (LOM) or PCIe Network Interface Card (NIC). &lt;strong&gt;Note&lt;/strong&gt;, only the &lt;em&gt;V&lt;/em&gt; variants are discussed in this article. Performing the NVM firmware update on non-V variants may brick your device.&lt;/li&gt;
&lt;li&gt;A Windows operatiing system installed on the computer. &lt;strong&gt;Note&lt;/strong&gt;, other operating systems should work too, but this guide focuses on Windows.&lt;/li&gt;
&lt;li&gt;Administrative privileges on the Windows operating system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Steps to update NVM firmware
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Download NVM binary files
&lt;/h3&gt;

&lt;p&gt;Download and extract the NVM firmware binary from &lt;a href="https://github.com/hunghvu/Intel-I226-V-NVM-Firmware" rel="noopener noreferrer"&gt;here&lt;/a&gt; (forked from BillyCurtis repository). As always, be cautious when downloading firmware files from third-party sources. For the purpose of this article, I store the extracted files in &lt;code&gt;~&lt;/code&gt; (your home location).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Download Intel driver and NVM update Tool
&lt;/h3&gt;

&lt;p&gt;Download Intel Driver and NVM Update Tool from &lt;a href="https://www.intel.com/content/www/us/en/download/15084/intel-Ethernet-adapter-complete-driver-pack.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. As of this writing, the package version is 30.6.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This package contains both the Intel Ethernet drivers and the NVM Update Tool. I recommend updating the Ethernet drivers to the latest version before proceeding with the NVM firmware update, unless you have a reason not to. This is to ensure you are not running an outdated driver or OEM customized driver that may interfere with the NVM update process.&lt;/li&gt;
&lt;li&gt;The driver for i225-V and i226-V locates in &lt;code&gt;~\Release_30.6\PRO2500\Winx64\W11&lt;/code&gt; folder inside the downloaded package.&lt;/li&gt;
&lt;li&gt;There is no &lt;code&gt;setup.exe&lt;/code&gt; file in the package, so you will need to manually update the driver via Device Manager.&lt;/li&gt;
&lt;li&gt;To do this, open Device Manager, locate your Intel i225-V or i226-V Ethernet controller under "Network adapters", right-click on it, and select "Update driver". Then, choose "Browse my computer for drivers" and navigate to the folder mentioned above. Follow the prompts to complete the driver update.&lt;/li&gt;
&lt;li&gt;If you have multiple &lt;em&gt;Network Adapters&lt;/em&gt; showing up, make sure to update all of them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Understand NVM update tool structure
&lt;/h3&gt;

&lt;p&gt;Extract the NVM Update Tool from the downloaded package. The tool is located in &lt;code&gt;~\Release_30.6\NVMUpdatePackage&lt;/code&gt; folder.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If you use Intel i225-V&lt;/strong&gt;, navigate to &lt;code&gt;~\I225\I225_NVMUpdatePackage_v1_00_Windows&lt;/code&gt; folder. Intel provide a convenient &lt;code&gt;exe&lt;/code&gt; file to perform the update. Run the file as Administrator and follow the prompts to update the NVM firmware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you use Intel i226-V&lt;/strong&gt;, instead of running an &lt;code&gt;exe&lt;/code&gt; file, you will extract it to find packaged binaries and a command line tool to perform the update. I personally use 7-Zip to extract the &lt;code&gt;exe&lt;/code&gt; file. Continue to the next step.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Confirm Ethernet controller details
&lt;/h3&gt;

&lt;p&gt;Open Command Prompt as Administrator. To do this, search for "cmd" in the Start menu, right-click on "Command Prompt", and select "Run as administrator". Then, navigate to the &lt;code&gt;~\Release_30.6\NVMUpdatePackage\I225\I225_NVMUpdatePackage_v1_00_Windows\I225_NVMUpdatePackage_v1_00_Windows\I225\Winx64&lt;/code&gt; folder. Copy the binaries extracted from step 4 to this folder. I choose &lt;code&gt;I226-V\2.32&lt;/code&gt; binaries because they are the latest as of this writing.&lt;/p&gt;

&lt;p&gt;Let's pause here for a moment and ensure the following before proceeding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have administrative privileges in the Command Prompt.&lt;/li&gt;
&lt;li&gt;You have navigated to the correct folder containing the NVM Update Tool. Either via &lt;code&gt;cd&lt;/code&gt; command or by openning Command Prompt directly in that folder.&lt;/li&gt;
&lt;li&gt;You have copied the correct NVM firmware binaries to this folder.&lt;/li&gt;
&lt;li&gt;If all is good, continue to the next step.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the following command &lt;code&gt;nvmupdatew64e.exe -i -l inventory.txt&lt;/code&gt; to list specification and status of all Intel Ethernet controllers on your system. This step is to ensure that the NVM Update Tool can detect your Intel i226-V controllers properly. Afterward, you will see an &lt;code&gt;inventory.txt&lt;/code&gt; file generated in the same folder. Open the file to verify the information, which should look similar to the following in structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Detail of each line may vary from device to device, but the structure remains the same.
[00:008:00:00]: Intel(R) Ethernet Controller I226-V
    Vendor                 : 8086
    Device                 : 125C  ===&amp;gt; Intel(R) Ethernet Controller I226-V
    Subvendor              : 8086
    Subdevice              : 0000
    Revision               : 4
    LAN MAC                : FFFFFFFFFFFF
    Alt MAC                : 000000000000
    SAN MAC                : FFFFFFFFFFFF
    ETrackId               : 8000028D ===&amp;gt; ETrack ID for 2MB NVM variant
    SerialNumber           : FFFFFFFFFFFFFFFF
    NVM Version            : 2.20(2.14) ===&amp;gt; 2.14 is the binary version
    PBA                    : FFFFFF-FFF
    VPD status             : Not set
    VPD size               : 0
    NVM update             : No config file entry
      checksum             : Valid
    OROM update            : No config file entry
      CIVD                 : 0.0.0
      EFI                  : 0.1.1, checksum None
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps me confirm the NVM Update Tool is functioning correctly and can communicate with the Ethernet controllers. Also, my NIC is using an outdated version 2.14 firmware, and it is a 2MB variant as indicated by the ETrackId.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Configure NVM update settings
&lt;/h3&gt;

&lt;p&gt;Now, open &lt;code&gt;nvmupdate.cfg&lt;/code&gt; file in a text editor (e.g., Notepad) to configure the NVM update settings. You will need to specify the path to the NVM firmware binary file you extracted in step 4. The configuration file should look similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BEGIN DEVICE
DEVICENAME: FoxPond1_I225_15F2_2MB_1p94_800003BB
VENDOR: 8086
DEVICE: 15F2 ===&amp;gt; Intel(R) Ethernet Controller I225-LM
SUBVENDOR: 8086
SUBDEVICE: 0001
NVM IMAGE: FoxPond1_I225_15F2_2MB_1p94_800003BB.bin ===&amp;gt; Binary within the same directory
EEPID: 800003BB ===&amp;gt; ETrackID
EEPROM MAP: Foxpond_Map_File_v01.txt
RESET TYPE: REBOOT
REPLACES: 80000180 800003BB =&amp;gt; Original ETrackIDs being replaced
END DEVICE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can ignore what is originally included in the file because based on the language, it is unique to Intel i225-LM 2MB variant, and create a new entry at the bottom of the file as follows (remember to remove my comments after the &lt;code&gt;===&amp;gt;&lt;/code&gt; symbols and save the file):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BEGIN DEVICE
DEVICENAME: Intel(R) Ethernet Controller I226-V
VENDOR: 8086
DEVICE: 125C ===&amp;gt; Intel(R) Ethernet Controller I225-LM
SUBVENDOR: 8086
SUBDEVICE: 0000
NVM IMAGE: FXVL_125C_V_2MB_2.32.bin ===&amp;gt; Binary within the same directory
EEPID: 80000422 ===&amp;gt; ETrackId, but for version 2.32, 2MB variant
RESET TYPE: REBOOT
REPLACES: 8000028D ===&amp;gt; Original ETrackID being replaced
END DEVICE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Perform NVM firmware update and verify result
&lt;/h3&gt;

&lt;p&gt;Finally, run the following command to perform the NVM firmware update: &lt;code&gt;nvmupdatew64e.exe -u -f nvmupdate.cfg -l update_log.txt&lt;/code&gt;. This command will initiate the update process using the configuration file you just edited. An &lt;code&gt;update_log.txt&lt;/code&gt; file will be generated to log the update process. Monitor the Command Prompt for any prompts or messages during the update process. If there is no message, check the &lt;code&gt;update_log.txt&lt;/code&gt; file for details. Once the update is complete, you may need to reboot your computer for the changes to take effect. Below is an example of a successful update log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... (truncated for brevity) ...

[00:013:00:00]: Intel(R) Ethernet Controller I226-V
Flash update started.
NVM verification started.
Shadow RAM verification started.
Shadow RAM verification finished.
Flash verification started.
Flash verification finished.
NVM verification finished.
Flash update successful.
Device update successful.

... (truncated for brevity) ...

A reboot is required to complete the update process.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an error occurs during the update process, refer to the &lt;code&gt;update_log.txt&lt;/code&gt; file for troubleshooting information. Common errors may include issues with the NVM firmware binary, incorrect configuration settings, or communication problems with the Ethernet controller. Below are some examples of error messages you may encounter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Config file line 11: File does not exist: 'FXVL_125C_V_2MB_2.32.bin'
Error: Cannot parse CONFIG VERSION parameter due to the mistakes in configuration file.
Error: Flash update failed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After successfully updating the NVM firmware, you can verify the update by running the inventory command again: &lt;code&gt;nvmupdatew64e.exe -i -l inventory_post_update.txt&lt;/code&gt;. Check the &lt;code&gt;inventory_post_update.txt&lt;/code&gt; file to confirm that the NVM Version reflects the updated firmware version (e.g., 2.32).&lt;/p&gt;

&lt;p&gt;That's it! You have successfully updated the NVM firmware for your Intel i225-V or i226-V Ethernet controller. Remember to monitor your network performance to see if the update resolves any issues you were experiencing. If problems persist, consider exploring other factors such as driver updates or hardware compatibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  How was my experience after updating NVM firmware?
&lt;/h2&gt;

&lt;p&gt;Well, hard to tell, but in a sense it got worse. Back in 2024, I was testing the Intel i226-V quad port NIC on my OpenWRT x86 setup. This means my NIC was using NVM version 2.14 at the time. Below was my observation at the time (copied from my &lt;a href="https://github.com/hunghvu/homelab" rel="noopener noreferrer"&gt;homelab README&lt;/a&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It appears Intel I226-V is buggy with ASPM.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With an Intel I226-V NIC, the system boots really slow, and when ASPM is enforced via &lt;code&gt;powertop&lt;/code&gt;, the system completely freezes because the CPU utilization gradually increase up to 100%. Probably, this is an upstream bug of &lt;code&gt;igc&lt;/code&gt;. There seems to be many report on this matter. Meanwhile, Realtek RTL 8125BG works perfectly.&lt;/li&gt;
&lt;li&gt;Currently, there is no available NVM update for Intel I226-V (only Intel I225 series), so not sure if an NVM update can resolve the problem or not.&lt;/li&gt;
&lt;li&gt;Unrelated note: Normally, &lt;code&gt;ethX&lt;/code&gt; is based on whichever NIC is electrically closet to the CPU. For example, &lt;code&gt;eth0&lt;/code&gt; is an integrated NIC, &lt;code&gt;eth1&lt;/code&gt; is a nic at PCIE slot 1. However, the I226-V nic messes up the order, and making itself the first set of interface, from &lt;code&gt;eth0&lt;/code&gt; to &lt;code&gt;eth3&lt;/code&gt;, other NIC order is also changed too.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsl9luqjbhrc77vtlz29l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsl9luqjbhrc77vtlz29l.png" alt="&amp;lt;br&amp;gt;
Intel i226-V Ethernet controller is buggy under ASPM." width="800" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How about now after updating to NVM version 2.32? Installing the NIC makes my system experience a kernel panic and boot loop. I attached part of the kernel panic log below for reference. Looking at it, it seems the &lt;code&gt;igc&lt;/code&gt; driver crashes. Is it a firmware issue? Driver issue (null pointer reference)? Hardware issue (PCIe Bus)? Not sure yet, but possibly a combination of all these factors again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... (truncated for brevity) ...

[   22.283426] pcieport 0000:00:1c.4: AER: Uncorrectable (Non-Fatal) error message received from 0000:0a:00.0
[   22.2937641] igc 0000:0a:00.0: PCIe Bus Error: severity=Uncorrectable (Non-Fatal), type=Transaction Layer, (Requester ID)
[   22.3051211] igc 0000:0a:00.0: device [8086:125c] error status/mask=00004000/00000000
[   22.421718] genirq: Flags mismatch irq 145. 00200000 (eth2) us. 00200000 (eth2)
[   22.4297171] ------------[ cut here ]------------
[   22.434546] remove_proc_entry: removing non-empty directory 'irq/145', leaking at least 'eth2'
[   22.443341] WARNING: CPU: PID: 128 at

... (truncated for brevity) ...

[   27.347954] CR2: 0000000000000080
[   27.351617] ---[ end trace 0000000000000000 ]---
[   27.356573] RIP: 0010:0xffffffffa0286787 [igc@00000000ae720c49+0x14000]
[   27.363497] Code: 89 f7 c6 07 00 0f 1f 00 8b b3 b8 fe ff ff 31 c9 31 ff 85 f6 7e 5a 49 8b 84 24 a8 00 00 00 48 8b 94 cb c0 fe ff ff a8 04 74 35 &amp;lt;0f&amp;gt; b7 82 80 00 00 00 44 0f b7 82 82 00 00 00 41 89 f9 0f b7 72 44
[   27.382861] RSP: 0018:ffffc90001b23e20 EFLAGS: 00010202
[   27.388426] RAX: 0000000000000007 RBX: ffff888102044b68 RCX: 0000000000000000
[   27.395875] RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000000
[   27.403316] RBP: ffffc90001b23e50 R08: ffff88810235aec0 R09: ffff88810004cac0
[   27.410757] R10: 0000000000000007 R11: 0000000000000000 R12: ffff888102044000
[   27.418208] R13: ffff8881020449c0 R14: ffff888102044bf8 R15: ffff888102044b70
[   27.425640] FS:  0000000000000000(0000) GS:ffff88846f600000(0000) knlGS:0000000000000000
[   27.434021] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   27.440075] CR2: 0000000000000080 CR3: 0000000002230004 CR4: 0000000000370ef0
[   27.447508] Kernel panic - not syncing: Fatal exception
[   27.453116] Kernel Offset: disabled
[   27.456937] Rebooting in 3 seconds..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm using OpenWRT 25.12.0-rc1 at the moment, and my environment has changed a lot since an intital test back in 2024. I have not investigated further nor attempting to reproduce the issue using my 2024 configuration. So for now, I would say the NVM firmware update did not help much in my case. Your mileage may vary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Updating the NVM firmware for Intel i225 and i226 Ethernet controllers can potentially improve performance and resolve certain issues. However, it is essential to proceed with caution due to the inherent risks involved in firmware updates. Always ensure you have a backup of important data and configurations before proceeding with the update process. If you encounter any issues during or after the update, refer to the logs for troubleshooting information and consider exploring other factors such as driver updates or hardware compatibility.&lt;/p&gt;

&lt;p&gt;If you find this article to be helpful, I have some more for you!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.toquantum-fiber-w1700k-teardown-board-view-and-uart-pins"&gt;Quantum Fiber W1700K teardown, board view, and UART pins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tomigration-from-ipv4-to-ipv6-on-aws"&gt;What I learned when migrating hungvu.tech from IPv4 to IPv6 on AWS?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tovirtualize-openwrt-firewall-in-harvester-hci-cluster"&gt;OpenWRT as an x86 virtualized firewall in Harvester HCI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, let's connect!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/hunghvu/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hunghvu" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x.com/hunghvu_dev" rel="noopener noreferrer"&gt;X (formerly Twitter)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>networking</category>
      <category>testing</category>
      <category>learning</category>
    </item>
    <item>
      <title>Eliminate IPv4 tax on AWS, is it that easy?</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Fri, 03 May 2024 15:39:49 +0000</pubDate>
      <link>https://forem.com/hunghvu/eliminate-ipv4-tax-on-aws-is-it-that-easy-ib5</link>
      <guid>https://forem.com/hunghvu/eliminate-ipv4-tax-on-aws-is-it-that-easy-ib5</guid>
      <description>&lt;p&gt;Starting from February 1st, 2024, Amazon Web Services (AWS) starts charging public IPv4 fees at the rate of $0.005 per IP per hour, or $3.6 per IP per month. Not a lot to me, but considering my AWS usage only has been around $6 per month, that is a 60% increase in price. How to cut costs? That was when I looked into public IPv6, which is free on AWS.&lt;/p&gt;

&lt;p&gt;This article is about my experience migrating &lt;a href="https://hungvu.tech"&gt;hungvu.tech&lt;/a&gt; to IPv6 on AWS. Although this is not a tutorial, it can give you some insight into the findings during the migration. For the infrastructure as code, &lt;a href="https://github.com/hunghvu/hungvu.tech/tree/main/infras/iaac/aws"&gt;you can visit my GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which parts of my technology stack are affected by the IPv6 migration?
&lt;/h2&gt;

&lt;p&gt;All of them.&lt;/p&gt;

&lt;p&gt;It was just switching a public IP, how hard could it be? Or so I thought. Unlike IPv4 which is universally supported, IPv6 support is still limited at many levels even though the protocol itself was introduced and standardized years ago. It is not just a software problem but is also an infrastructure issue. I like to loosely conceptualize my findings based on &lt;a href="https://en.wikipedia.org/wiki/OSI_model"&gt;the OSI model&lt;/a&gt;, which includes 7 different layers of abstractions in a network stack. I simplified the abstraction quite a bit though, from 7 layers to just "hardware, network" and "software". The below is how I associate my technology stack.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;AWS (hardware, network, software)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;My homelab (hardware, network)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next.js, Payload CMS (Express), Node.js (software)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Caddy via &lt;a href="https://github.com/lucaslorentz/caddy-docker-proxy"&gt;Caddy Docker Proxy&lt;/a&gt; (network).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mongo DB Atlas, ghcr.io, and GitHub (network).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloudflare (network, and software).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Is my homelab network IPv6 compatible?
&lt;/h2&gt;

&lt;p&gt;Because my AWS infrastructure will soon utilize a public IPv6 address, I must be able to connect to AWS from my homelab. Technically, everything is accessible via web GUI, but that is only useful for an administration purpose. I also need to test and monitor my website from the lab, so without proper IPv6 support, that will not be possible. Luckily, my ISP (CenturyLink) does support IPv6, and with the help of an x86 OpenWRT router/firewall, my homelab infrastructure is dual-stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does AWS support IPv6 across the services that I utilize?
&lt;/h2&gt;

&lt;p&gt;I needed to check whether the AWS services I utilized supported IPv6 or not. It was funny to think about this I must say, like, have I ever needed to check whether a service supports IPv4 before?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;EC2:&lt;/strong&gt; I looked into &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html"&gt;AWS specifications&lt;/a&gt;. My instance is t4g.micro and it supports IPv6. In any case, it seems all instance types support IPv6 at the time of writing, so it should not be a problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;VPC:&lt;/strong&gt; It supports IPv6 in my region (US West - Oregon). AWS also offers a /56 CIDR block for IPv6, which will be helpful down the road because a smaller subnet can complicate the setup. I heard some other cloud providers offer a CIDR smaller than /100, which becomes an issue down the road when segmenting network and routing traffic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;EC2 Instance Connect:&lt;/strong&gt; There are 2 different options, either an SSH connection via public IP, or an internal VPC network. At the time of writing, Instance Connect via public IP only supports IPv4. I think that is also the case for internal VPC network connections. However, my VPC still offers a private IPv4 address, so Instance Connect via the internal VPC network is usable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API for IaaC:&lt;/strong&gt; At least for Pulumi, it appears not all IPv6 settings are configurable. For example, I could not retrieve IPv6 automatically in the same way as IPv4 via Elastic IP, or I could not configure ICMPv6 ACL (&lt;a href="https://github.com/hashicorp/terraform-provider-aws/issues/35526"&gt;a similar issue is reported in the Terraform repository&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are interested in how I implemented AWS IaaC via Pulumi, &lt;a href="https://github.com/hunghvu/hungvu.tech/tree/main/infras/iaac/aws"&gt;check out the hungvu.tech's repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do Next.js, Payload CMS (Express.js), and Node.js offer IPv6 support?
&lt;/h2&gt;

&lt;p&gt;I host both Next.js and Payload CMS (with Express.js underneath) on the same EC2 instance. They both support IPv6 out of the box. This means their server will listen and bind to an IPv6 address and its port. I am not too familiar with low-level networking programming, but I guess it is thanks to Node.js, which has supported IPv6 since the very beginning. Starting from Node.js v17 (released in 2021), IPv6 is even preferred in a dual-stack host, so I can say IPv6 is a first-class citizen here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can Caddy via Caddy Docker Proxy route IPv6 traffic?
&lt;/h2&gt;

&lt;p&gt;Caddy as a reverse proxy works with IPv6 because the service simply binds to all interfaces by default, nothing to complain about here, but here comes the unexpected. Out of the box, Caddy automatically provisions TLS certificates from either Zero SSL (primary public ACME CA), or Let's Encrypt (fall-back public ACME CA). However, &lt;em&gt;Zero SSL does not support IPv6 so all requests will fail.&lt;/em&gt; Technically, this is not an issue, because Let's Encrypt supports IPv6. However, somehow my deployment bugged out so it did not fall back to Let's Encrypt. It took a while for me to figure out what went wrong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## AAAA records 
https://acme.zerossl.com/v2/DV90: Not found
https://acme-v02.api.letsencrypt.org/: 2606:4700:60:0:f53d:5624:85c7:3a2c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TLS provisioning issue aside, it appears Caddy Docker Proxy does not support IPv6 &lt;code&gt;upstream&lt;/code&gt; out of the box. With the use of &lt;code&gt;upstream&lt;/code&gt;, the Caddy Docker Proxy container will automatically detect the IP of containers in the same network (masquerade or not). However, I was not able to make it detect my services' IPv6 addresses. Eventually, I decided to just assign static IPv6 to each of my services and set up &lt;code&gt;reverse_proxy&lt;/code&gt; accordingly. &lt;a href="https://github.com/hunghvu/hungvu.tech/blob/main/infras/containers/docker-compose/aws/docker-compose-ipv6.yaml#L21"&gt;The &lt;code&gt;docker-compose.yml&lt;/code&gt; implementation is available at hungvu.tech's GitHub repository.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How about MongoDB Atlas, ghcr.io, and GitHub?
&lt;/h2&gt;

&lt;p&gt;In case you do not know, MongoDB Atlas is a managed MongoDB service, while ghcr.io is GitHub's container registry service. Guess what?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Atlas does not support connectivity via IPv6 addresses at this time. "- &lt;a href="https://www.mongodb.com/community/forums/t/does-mongodb-atlas-support-ipv6-only-client-for-m2-instance/276117"&gt;MongoDB Atlas support's response to my question&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;They all do not support IPv6&lt;/em&gt;. For my MongoDB cluster, I chose AWS &lt;code&gt;us-west&lt;/code&gt; (the same as my other services), so clearly, the infrastructure is IPv6 compatible. This means the lack of IPv6 support is on the MongoDB Atlas side. Meanwhile, GitHub is the largest code collaboration platform as of 2024, and IPv6 is still not there yet... But hey, &lt;a href="https://www.githubstatus.com/incidents/5y8b8lsqbbyq"&gt;GitHub is working on IPv6 enablement now&lt;/a&gt;, so maybe it will be ready by the end of this year.&lt;/p&gt;

&lt;p&gt;I do not want to move away from MongoDB Atlas right now, so I self-hosted the database solution instead. For the container registry though, I simply modified my GitHub Actions workflow and pointed the publish to Docker Hub, &lt;a href="https://www.docker.com/blog/docker-hub-registry-ipv6-support-now-generally-available/"&gt;which also just generally supported IPv6 in August 2023&lt;/a&gt; (better late than never).&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloudflare is not a bulletproof solution to migrate from IPv4 to IPv6
&lt;/h2&gt;

&lt;p&gt;My journey started with this article from Cloudflare: &lt;a href="https://blog.cloudflare.com/amazon-2bn-ipv4-tax-how-avoid-paying"&gt;Amazon’s $2bn IPv4 tax — and how you can avoid paying it&lt;/a&gt;. It is a great article to have me explore the IPv6 side of Cloudflare, but it does not give a full picture of how the IPv4 to IPv6 migration happens from start to finish, and how complicated the process can be.&lt;/p&gt;

&lt;p&gt;Putting their article aside, Cloudflare has offered IPv6 support since 2011, so their IPv6 service and portfolio are way more than enough for my use case. Without their IPv6 compatibility service, it would potentially take more time for me to configure an equivalent NAT64 and further complicate the network stack. Most end users are still on IPv4 after all, and without proper IPv6 configuration on their end, they will not be able to access my website. Considering the IPv6 on the end-user side is out of my control, so it is better to leave Cloudflare, the perimeter, to do the hard labor here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Did the IPv6 migration work out?
&lt;/h2&gt;

&lt;p&gt;In the end, I was able to fully migrate &lt;a href="https://hungvu.tech"&gt;hungvu.tech&lt;/a&gt; from IPv4 to IPv6. It took me more or less 2 days though, so do remember to carefully plan for your production migration. Unfortunately, I was not able to bear the fruit of this migration, because my EC2 instance does not have enough resources to self-host MongoDB. At the time of writing, my website is hosted on the homelab. Technically speaking, utilizing homelab is a win-win situation for me, but I digress, that is a story for another day.&lt;/p&gt;

&lt;p&gt;Spending time learning more about IPv6 infrastructure and migration was a worthwhile experience for me, and I would suggest you try that out too!&lt;/p&gt;

&lt;p&gt;If you find this article to be helpful, I have some more for you!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/considerations-for-a-production-ready-website"&gt;My checklist for bringing a website to production.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/compare-pci-and-gpu-passthrough-in-harvester-hci-with-proxmox"&gt;PCI and GPU passthrough in Harvester HCI vs. Proxmox.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/is-harvester-a-good-hypervisor-for-a-beginner-my-hands-on-experience"&gt;Harvester HCI as a hypervisor, the new choice for homelab experiments.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/lab/openwrt-table-of-hardware"&gt;A new way to search for OpenWRT-supported devices (modernize table of hardware).&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, let's connect!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.linkedin.com/in/hunghvu/"&gt;&lt;strong&gt;LinkedIn&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/hunghvu"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/hunghvu_dev"&gt;&lt;strong&gt;X (formerly Twitter)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>aws</category>
      <category>networking</category>
      <category>docker</category>
    </item>
    <item>
      <title>Expand Promox storage with external enclosures in a homelab environment</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Wed, 03 Apr 2024 04:00:11 +0000</pubDate>
      <link>https://forem.com/hunghvu/expand-promox-storage-with-external-enclosures-in-a-homelab-environment-13kn</link>
      <guid>https://forem.com/hunghvu/expand-promox-storage-with-external-enclosures-in-a-homelab-environment-13kn</guid>
      <description>&lt;p&gt;This article was originally published at &lt;a href="https://hungvu.tech/can-i-use-external-ssd-enclosures-for-proxmox-disks"&gt;hungvu.tech - Can I use external SSD enclosures for Proxmox disks?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While experimenting with the storage configuration of my Proxmox node in my homelab, I wondered what the experience would be if I utilized my spare SSD-to-USB enclosures to expand storage. Normally, hypervisor products are appliances so the underlying OS is relatively locked down. Using external USB storage might not be possible with these appliances at all. However, Proxmox allows free root access to its Debian distro underneath, so I expect the drives to be mountable without any issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part list
&lt;/h2&gt;

&lt;p&gt;For internal storage, drives connect to the CPU through a SATA/SAS controller, motherboard chipset, or direct PCIe lanes. However, for external SSD-to-USB enclosures, the drives connect to the SATA/NVMe-to-USB controller within the SSD enclosure, and then to the USB hub controller of the server. Regardless of which SSD enclosure you purchase, its SATA/NVMe-to-USB controller likely comes from either ASMedia or Realtek. Therefore, I decided it would be interesting to test out both. For this experiment, I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alxum AX-S207A: An NVMe SSD enclosure with an ASMedia ASM2362 NVMe-to-USB controller (10 Gbps).&lt;/li&gt;
&lt;li&gt;Orico AM2-C3-2N: An NVMe SSD enclosure with a Realtek RTL9210 NVMe-to-USB controller (10 Gbps). There is no suffix, indicating that it is neither RTL9210A nor RTL9210B on paper; the controller is simply RTL9210.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These SSD enclosures were directly attached to the back of my MSI B660M Mortar Wifi DDR4 motherboard (with an Intel I7 13700k CPU installed). The MSI motherboard features 5 Gbps, 10 Gbps, and 20 Gbps USB ports, but I only tested the 10 Gbps and 20 Gbps ports (or USB 3.2 Gen 2 and USB 3.2 Gen 2x2, according to these USB-IF naming conventions).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The three 10 Gbps USB ports are powered by the Genesys GL3590 USB hub controller and all share a single 10 Gbps uplink.&lt;/li&gt;
&lt;li&gt;The one 20 Gbps port is powered by the B660 chipset, offering a full 20 Gbps uplink.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Last but not least, the SSDs I utilized were four Intel Optane P1600x 118 GB. Why? There was no specific reason; they were simply spare parts I had available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardware Configuration
&lt;/h2&gt;

&lt;p&gt;In my opinion, the controller (or the internals) is more important than the enclosure model, unless the vendor has somehow compromised the implementation. For technical clarity, I will refer to the enclosures by their associated controllers. Among the four Intel Optane SSDs, two were installed directly on the motherboard: one had access to the direct-to-CPU PCIe lane, and the other was routed via the B660 chipset. The remaining two SSDs were installed in SSD enclosures, providing a variety of configurations to test.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Configuration 1&lt;/strong&gt;: Two Intel Optane P1600x 118 GB drives in ASM2362 enclosures, both using 10 Gbps USB ports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration 2&lt;/strong&gt;: Similar to Configuration 1, but one enclosure connects to a 10 Gbps port and the other to a 20 Gbps port.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration 3&lt;/strong&gt;: One Intel Optane drive in an ASM2362 enclosure and the other in an RTL9210 enclosure, both using 10 Gbps ports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration 4&lt;/strong&gt;: Similar to Configuration 3, but the ASM2362 enclosure connects to a 10 Gbps port and the RTL9210 to a 20 Gbps port.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration 5&lt;/strong&gt;: Similar to Configuration 3, but the ASM2362 enclosure connects to a 20 Gbps port and the RTL9210 to a 10 Gbps port.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration 6&lt;/strong&gt;: Two Intel Optane P1600x 118 GB drives in RTL9210 enclosures, both using 10 Gbps ports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration 7&lt;/strong&gt;: Similar to Configuration 6, but one enclosure connects to a 10 Gbps port and the other to a 20 Gbps port.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why so many test cases? Hardware can exhibit unique behaviors when interfaced with specific components. While protocols are standardized, eliminating most issues, there are anecdotes of hardware, like GPUs, exhibiting bugs when plugged into certain PCIe slots. Hence, I explored every possible combination in this experiment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Software Configuration
&lt;/h2&gt;

&lt;p&gt;The experiment was conducted on Proxmox v8.1.3. With four drives (two internal and two external), I opted to create a ZFS pool with one VDEV in RaidZ1. I chose RaidZ1, the least safe configuration, to observe behavior in potentially the worst-case scenario.&lt;/p&gt;

&lt;p&gt;The point of failure would have been the external drives. These could fail at any moment, necessitating a time-consuming reconfiguration. Had I selected RaidZ2, which tolerates up to two failed drives within a VDEV, even if the external drives all failed, my pool would remain intact. Although this redundancy is theoretically advantageous, it could obscure minor errors that I aimed to explore in this experiment.&lt;/p&gt;

&lt;p&gt;Previously, on a different system, I utilized two ASM2362 enclosures as a mirrored metadata VDEV in a TrueNAS Scale experiment, which proceeded without noticeable trivial bugs or performance degradation. Given that TrueNAS Scale is also Debian-based, like Proxmox, I surmised that Proxmox could similarly manage the external enclosures. Well, to some extent...&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;Let's go over my observations.&lt;/p&gt;

&lt;h3&gt;
  
  
  ASMedia ASM2362 enclosures always error out and were not usable even after ASMedia firmware changes
&lt;/h3&gt;

&lt;p&gt;This outcome was surprising to me, especially since these specific enclosures worked fine on a TrueNAS Scale system I had mentioned earlier. However, this discrepancy is understandable given that everything about the two experiments was different. My TrueNAS Scale experiment was conducted on a bare metal AMD system &lt;a href="https://hungvu.tech/virtualize-truenas-with-harvester-and-kubevirt"&gt;the same one discussed in virtualizing TrueNAS system&lt;/a&gt;, while the Proxmox experiment was carried out on an Intel system. Regardless, the error rendered the Disks page of Proxmox inaccessible, displaying a permanent spinning circle, and sometimes it even caused the PVE dashboard to crash or made the node fail to shut down, reboot, or boot (particularly at the initramfs stage).&lt;/p&gt;

&lt;p&gt;If relevant, I also have a handy Windows To Go installation, which is only functional with the RTL9210 enclosure on the Intel system. Although the ASM236 enclosure is operational, the latency is extremely high—for example, it takes more than 10 minutes to boot and similarly over 10 minutes to reach the login screen. This behavior may be related to the USB errors observed in Proxmox, though I'm not certain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xskl3Ayr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/USB-enumaration-power-cycle-address-acceptance-and-timeout-errors-code-62-71.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xskl3Ayr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/USB-enumaration-power-cycle-address-acceptance-and-timeout-errors-code-62-71.png" alt="USB enumaration, power cycle, address acceptance, and timeout errors (code -62, -71)." width="676" height="211"&gt;&lt;/a&gt;&lt;br&gt;
USB enumeration, power cycle, address acceptance, and timeout errors (code -62, -71).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UYuBSD68--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/unable-to-read-config-index-0-descriptor-start-code-61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UYuBSD68--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/unable-to-read-config-index-0-descriptor-start-code-61.png" alt="Unable to read config index 0 descriptor/start: -61 error." width="499" height="292"&gt;&lt;/a&gt;&lt;br&gt;
Unable to read config index 0 descriptor/start: -61 error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Realtek RTL9210 enclosures were buggy but worked fine after a firmware change
&lt;/h2&gt;

&lt;p&gt;Initially, my RTL9210 enclosures were operating on firmware version 4.30.23, built on 2022-07-19. Unfortunately, they did not perform well with Proxmox. Sometimes, the devices would disappear after a reboot, and at other times, they would generate numerous errors in &lt;code&gt;dmesg&lt;/code&gt;. After conducting some research and coming across the Station-Driver forum discussion, I concluded that a firmware upgrade might resolve these issues. Consequently, I upgraded to version 1.32.87 (build date: 2023-08-29), specifically for the Realtek RTL9210B – note the suffix 'B'. This upgrade eliminated all the previously encountered buggy behaviors.&lt;/p&gt;

&lt;p&gt;In the future, I may write an article about the firmware upgrade process, as it took me an hour or two to sift through Station-Driver forum discussions to grasp the procedure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zW2zkUgV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/error-5-type-2-with-RTL9210-controller-pre-firmware-upgrade.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zW2zkUgV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/error-5-type-2-with-RTL9210-controller-pre-firmware-upgrade.png" alt="Error 5, type 2 with RTL9210 controller pre-firmware upgrade." width="800" height="380"&gt;&lt;/a&gt;&lt;br&gt;
Error 5, type 2 with RTL9210 controller pre-firmware upgrade.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P_MEnzRW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/rtl-9210-enclosures-experienced-over-current-condition-error-on-firmware-v4.30.23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P_MEnzRW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/rtl-9210-enclosures-experienced-over-current-condition-error-on-firmware-v4.30.23.png" alt="RTL 9210 enclosures experienced an over-current condition error on firmware v4.30.23." width="459" height="248"&gt;&lt;/a&gt;&lt;br&gt;
RTL 9210 enclosures experienced an over-current condition error on firmware v4.30.23.&lt;/p&gt;

&lt;h2&gt;
  
  
  Genesys GL3590 USB hub controller (10 Gbps port) cannot handle any two external enclosures at once.
&lt;/h2&gt;

&lt;p&gt;When using two RTL9210 enclosures, having one plugged into a 10 Gbps port and the other into a 20 Gbps port allowed my ZFS pool to remain operational. This setup enabled my Windows 11 VM to achieve more than 30 days of uptime. However, attempting to connect both enclosures to two 10 Gbps ports led to issues. It appeared that the Genesys GL3590 USB hub controller struggled with this configuration, resulting in connection errors.&lt;/p&gt;

&lt;p&gt;Regarding the Windows To Go installation previously mentioned, performance was significantly better when using the 20 Gbps port. This port benefits from a dedicated PCIe lane that facilitates direct communication with the CPU. In contrast, disk performance is severely degraded when utilizing the 10 Gbps port. While it's unclear whether this is a hardware or software issue, I think it is a hardware limitation, correlating with my observation in the Proxmox environment. The following are some of the errors observed when connecting two RTL9210 enclosures to the 10 Gbps ports.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1XM2ctzD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/connect-debounced-failed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1XM2ctzD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/connect-debounced-failed.png" alt="Connect-debounced failed error on the Genesys GL3590 USB hub controller." width="612" height="429"&gt;&lt;/a&gt;&lt;br&gt;
Connect-debounced failed error on the Genesys GL3590 USB hub controller.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hS2rqBPm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/various-types-of-device-io-buffer-timeout-error-on-genesys-gl-3590-usb-hub-controller.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hS2rqBPm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/various-types-of-device-io-buffer-timeout-error-on-genesys-gl-3590-usb-hub-controller.png" alt="Various types of device, I/O, buffer, timeout errors when using two 10 Gbps port at the same time." width="665" height="557"&gt;&lt;/a&gt;&lt;br&gt;
Various types of device, I/O, buffer, timeout errors when using two 10 Gbps ports at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  If one external enclosure fails, it is best to have the failure happen on the 10 Gbps port
&lt;/h2&gt;

&lt;p&gt;ZFS RaidZ1 can tolerate up to one drive failure. If a failure occurs, it is most likely to be in the external enclosures. However, more common than hardware issues are connection issues, such as loose USB connections. Therefore, I simulated a failure by simply unplugging one external enclosure. As a reminder, only the scenario in which one RTL9210 enclosure is plugged into a 10 Gbps port and the other into a 20 Gbps port worked. With that in mind, I noticed that if the failure occurs on a 10 Gbps USB port, my ZFS pool continues to perform as expected. Conversely, if the failure occurs on a 20 Gbps USB port, then random issues may arise.&lt;/p&gt;

&lt;p&gt;The issues varied, but they resembled what was shown in other sections of this article. Interestingly, the likelihood of experiencing random issues when the enclosure is not plugged into the 20 Gbps port varies. If the enclosure is unplugged before booting, or during the shutdown/reboot process, the pool is likely to fail, leading to a system stuck in the shutdown/reboot/boot sequence. However, if the system is running and the enclosure is unplugged, sometimes my ZFS pool continues to operate, and sometimes it degrades immediately.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D-7tQNzw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/failed-to-start-and-import-zfs-pool-due-to-drive-failure.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D-7tQNzw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/failed-to-start-and-import-zfs-pool-due-to-drive-failure.png" alt="Failed to start and import ZFS pool due to drive failure." width="800" height="310"&gt;&lt;/a&gt;&lt;br&gt;
Failed to start and import ZFS pool due to drive failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance-wise, there was an inconsistency
&lt;/h2&gt;

&lt;p&gt;Delving into storage performance is beyond my expertise, so drawing any definitive conclusions was challenging. From what I understand, virtualized storage performance can be influenced by multiple factors due to the various layers of abstraction and configuration inherent in virtualization. One observation I made was that performance fluctuated when the OS drive was under heavy use.&lt;/p&gt;

&lt;p&gt;My OS drive offers around of usable space. When conducting tests with CrystalDiskMark at smaller test sizes (below 16 GB per run), performance appeared relatively stable. This stability is likely because Proxmox and ZFS were able to cache all the data, resulting in speeds of around 20 GB/s. However, when I increased the test size to 32 GB with 9 runs, performance inconsistencies began to emerge, occasionally causing the Windows 11 VM to freeze until the tests concluded. I believe these inconsistencies were due to a combination of factors, including hardware limitations (like the data access patterns to USB and bottlenecks) and software configurations (like storage tuning). Below are some images highlighting the observed inconsistencies. These runs were not consecutive, so will see differences in usable storage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1rUo3KFz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/high-performance-with-small-test-size.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1rUo3KFz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/high-performance-with-small-test-size.png" alt="High performance with small test size." width="800" height="419"&gt;&lt;/a&gt;&lt;br&gt;
High performance with small test size.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bkdMulAz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/storage-performance-inconsistencies-starts-showing-up-at-32gb-9-runs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bkdMulAz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/storage-performance-inconsistencies-starts-showing-up-at-32gb-9-runs.png" alt="Storage performance inconsistencies starts showing up at 32gb, 9 runs." width="531" height="390"&gt;&lt;/a&gt;&lt;br&gt;
Storage performance inconsistencies starts showing up at 32gb, 9 runs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tM3Snfqj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/low-measured-performance-possibly-due-to-cache-saturation-and-external-enclosures-access.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tM3Snfqj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://payload.hungvu.tech/media/low-measured-performance-possibly-due-to-cache-saturation-and-external-enclosures-access.png" alt="Low measured performance, possibly due to cache saturation and external SSD enclosures access, leading to OS freeze during the run." width="717" height="534"&gt;&lt;/a&gt;&lt;br&gt;
Low measured performance, possibly due to cache saturation and external SSD enclosures access, leading to OS freeze during the run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Following this experiment, my conclusion is that utilizing external storage for a ZFS pool in Proxmox is indeed feasible. Would I recommend it? Not particularly for valuable data or in a production environment. However, in the context of a homelab—where the expectation is that things might break down eventually—it was an enjoyable experience to explore the possibility of expanding Proxmox storage with external SSD enclosures. I did not delve into and troubleshoot the underlying causes of errors, as my goal was merely to observe behaviors in this experiment. Perhaps I'll conduct a more thorough investigation in a future article. Until next time!&lt;/p&gt;

&lt;p&gt;If you find this article to be helpful, I have some more for you!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hungvu.tech/considerations-for-a-production-ready-website"&gt;What to consider for a production-ready blog website?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hungvu.tech/virtualize-openwrt-firewall-in-harvester-hci-cluster"&gt;OpenWRT as an x86 virtualized firewall in Harvester HCI.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hungvu.tech/is-harvester-a-good-hypervisor-for-a-beginner-my-hands-on-experience"&gt;Harvester HCI as a hypervisor, the new choice for homelab experiments.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, let's connect!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/hunghvu/"&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hunghvu"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/hunghvu_dev"&gt;X (formerly Twitter)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>learning</category>
      <category>testing</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>My checklist for a production-ready website</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Sun, 31 Dec 2023 18:21:29 +0000</pubDate>
      <link>https://forem.com/hunghvu/my-checklist-for-a-production-ready-website-3lm7</link>
      <guid>https://forem.com/hunghvu/my-checklist-for-a-production-ready-website-3lm7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article was originally published at: &lt;a href="https://hungvu.tech/considerations-for-a-production-ready-website" rel="noopener noreferrer"&gt;My checklist for bringing a website to production - hungvu.tech&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The article below is my personal note on what to consider before putting a website into production. It is certainly applicable to this website, &lt;a href="https://hungvu.tech" rel="noopener noreferrer"&gt;hungvu.tech&lt;/a&gt;, but your mileage may vary depending on the requirements of your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the "production checklist" of the chosen technology stack documentation
&lt;/h2&gt;

&lt;p&gt;Most likely, the documentation of the technology you use has a "production checklist" somewhere. Reading documentation is a very good starting point. Let's have a real example, the core technologies behind my website are Next.js, Payload CMS, MongoDB, Cloudflare, AWS, Docker, and Caddy. There are specific points to look out for.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What is the interaction between technologies if I combine them? For example,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What do I need to consider when hosting Next.js using a Docker container?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens when I put the Payload CMS backend behind a layer 7 reverse proxy like Caddy?&lt;/li&gt;
&lt;li&gt;Do I need to connect Payload CMS to MongoDB in a specific way?&lt;/li&gt;
&lt;li&gt;What happens when running Caddy on an EC2 instance, with traffic proxied through Cloudflare?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;What is the security consideration, considering that the application is facing the public Internet now?&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;What is the performance consideration? For example, hardware specification, traffic behavior, and more.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;As you can see, these points are very high level, and as I think more about them, a lot more questions showed up and led me to some corners on GitHub discussion, community-specific platforms (like Payload CMS Discord server), and so on.&lt;/p&gt;

&lt;p&gt;Now, let's review my personal checklist, in no particular order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Metadata
&lt;/h2&gt;

&lt;p&gt;Thinking about the word "front end", I mean it for both "front of the front end", and "front of the back end".&lt;/p&gt;

&lt;p&gt;This blog is built with Next.js, which is capable of both delivering HTML/CSS/JS content and operating its own API routes. In this context, I say the HTML/CSS/JS part is the front end of API "front-end" routes, hence "front of the front end". Meanwhile, my back end, which Payload CMS powers, has its admin dashboard. I call this admin dashboard "front of the back end".&lt;/p&gt;

&lt;p&gt;Every front end has its metadata information. Overall, they are used to support crawlers, and clients in understanding what the website is about. For a blog site, I need 4 types of metadata.&lt;/p&gt;

&lt;p&gt;The first is represented by &lt;code&gt;meta tags.&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Charset&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Viewport&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Theme color&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Google site verification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open graph (og)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Twitter&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second is other important tags inside the &lt;code&gt;head&lt;/code&gt; element.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Title&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Canonical link&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Favicon&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The third one is &lt;a href="https://hungvu.tech" rel="noopener noreferrer"&gt;Schema.org&lt;/a&gt; JSON-LD. I actually question the usefulness of this feature, but if it is relatively easy to implement without a glaring downside, just give it a shot I guess? In Next.js, there is &lt;a href="https://github.com/garmeeh/next-seo" rel="noopener noreferrer"&gt;next-seo&lt;/a&gt; package that greatly simplifies the implementation of &lt;a href="https://hungvu.tech" rel="noopener noreferrer"&gt;Schema.org&lt;/a&gt; JSON-LD.&lt;/p&gt;

&lt;p&gt;The last one is not an HTML element, instead, it consists of special files that affect how the web crawlers see your page.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Robots.txt&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sitemap.xml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RSS.xml (my website currently does not have this, but may in the future)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Caching
&lt;/h2&gt;

&lt;h3&gt;
  
  
  In Next.js
&lt;/h3&gt;

&lt;p&gt;The modern version of Next.js supports caching fetch requests, so that raises a few questions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Which request should be cached?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What should be the cache duration?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Should the cache be ephemeral or persistent?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep in mind, as of Next.js v14.0.4, the cached response size limit per request is 2 MB. Exceeding the limit will error out the fetch request, hence making this feature useless (or at least, not intended for) large responses. Caching larger responses, in combination with Next.js images, is resource-intensive. At the moment, I cannot say if this is an error from my implementation or not, but I can say the caching mechanism did hammer down my CPU, RAM, and bottleneck IO throughput of my EC2 instance.&lt;/p&gt;

&lt;p&gt;Besides, I make my Next.js cache ephemeral so that every time I update the web service image, the stale cache is purged when creating a new container, ensuring my website is always up to date.&lt;/p&gt;

&lt;h3&gt;
  
  
  In Cloudflare
&lt;/h3&gt;

&lt;p&gt;There are many layers of caching in web development. Aside from the Next.js system, &lt;a href="https://hungvu.tech" rel="noopener noreferrer"&gt;hungvu.tech&lt;/a&gt; uses Cloudflare (a content delivery network) as a second cache layer. This brings up certain questions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Is Cloudflare caching at the moment? This can be confirmed by monitoring Cloudflare statistics or observing the cache header of the response. I recently noticed the cache hit rate of my blog suddenly dropped and am investigating the issue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If an issue is observed in production, is it due to the Cloudflare cache? The issues are variable, from cross-origin resource sharing, and no response request, to broken layout (due to Cloudflare "optimization" like Rocket loader, auto minify), and more. In my experience, purging the cache does not always make the website up to date, it is better to enable &lt;strong&gt;Development Mode&lt;/strong&gt; to completely bypass the Cloudflare cache layer to troubleshoot the issue in real-time.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;p&gt;I'm not a security expert by any means, so I do not want to pretend I know the ins and outs of the items mentioned below. There are plenty of deep-dive articles out there such as those from Mozilla documentation, so this list is, well, just a checklist. It is best to search these keywords below in your technology stacks documentation, I bet they do have a section regarding reference implementation somewhere.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Access control list (ACL):&lt;/strong&gt; This goes without saying. ACL exists at multiple layers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Software-wise, some notable ones are navigation route protection, API rules, identity-aware proxy, and identity access management.&lt;/li&gt;
&lt;li&gt;Hardware-wise, there are physical, network (North-South and East-West traffic), and host protection. Really, defense in depth is a very specialized topic and I am still learning more about it over time.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content Security Policy (CSP):&lt;/strong&gt; This helps the front end mitigate certain types of security issues.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross-origin resource request (CORS), same-origin policy (SOP), and cross-site request forgery (CSRF):&lt;/strong&gt; Similar to CSP, these are presented to mitigate common attack vectors. These concepts are not the same though, but in my experience, they often belong to the same section in a documentation.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Rate limit, IP blocking&lt;/strong&gt;, &lt;strong&gt;and CAPTCHA:&lt;/strong&gt; These exist to mitigate bot traffic and API abuse issues. There are good bots like search engine bots, but the majority are bad bots that exist to exploit websites. Rate limit, IP blocking, and CAPTCHA are prominent ways to fight against bad bots. There are some things to consider though.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rate limit and IP block can be applied at different layers. In my case, Cloudflare, Caddy, and Payload CMS (with Express underneath) do have their own implementation for rate limit and IP blocking.&lt;/li&gt;
&lt;li&gt;IP block may not behave as expected when traffic is proxied through multiple layers such as Cloudflare and Caddy at &lt;a href="https://hungvu.tech" rel="noopener noreferrer"&gt;hungvu.tech&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;CAPTCHA may affect real user experience and their privacy, so use it at your judgment. At the time of writing, my blog does not have CAPTCHA implemented.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Trust proxy&lt;/strong&gt;: This in Express.js, and equivalent features in other frameworks, is used to specify configuration when the web server is behind a reverse proxy. The setting itself can have security implications.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Secure Socket Layer (SSL) and Transport Layer Security (TLS) for Hypertext Transfer Protocol Secure (HTTPS):&lt;/strong&gt; SSL was deprecated about 2 decades ago, and its successor is TLS. That said, people still use both terms interchangeably nowadays, even in the Cloudflare dashboard, hence the confusion. Just keep in mind that even though they all use the keyword "SSL", products on the market right now are pretty much TLS only. Anyway, simple TLS and HTTPS are the main reasons why I use Caddy in the first place. There is one thing to consider.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does the encryption tunnel look like in a full round trip? In my case, a high-level view of traffic order is as follows: Client browser, then Cloudflare, then origin server (Caddy on port 443), then Next.js server, then Payload CMS server, and back. With my website, the priority is to have traffic between the client browser, Cloudflare, and the origin server fully encrypted. Internal traffic on the server is a different story though.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Caching itself should belong under this performance section, but I consider it important enough to be in a dedicated section. Now, performance is a measurable metric, and there are various aspects of an application that can be optimized using the said benchmark. The list below is just agnostic items that help improve performance &lt;em&gt;on paper&lt;/em&gt;. Are they really useful? It is unknown until there is a benchmark.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HTTP/3 and QUIC&lt;/strong&gt;: The third major version of the HTTP protocol, and is said to greatly improve performance along with many other improvements compared to HTTP/2. This is another reason why I use Caddy as a reverse proxy, as it supports HTTP/3 and QUIC protocols with just a little configuration. But, like SSL/TLS/HTTPS, there are a few things to consider.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does the request look like in a full round trip?&lt;/li&gt;
&lt;li&gt;What happens when one part of the chain is not HTTP/3 and QUIC supported? For encryption, I can say if a chain is broken, then that specific part is unencrypted and comes with security implications. For network protocol though, a benchmark will be helpful here.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhungvu.tech%2F_next%2Fimage%3Furl%3Dhttps%253A%252F%252Fpayload.hungvu.tech%252Fmedia%252FAIVjas12.webp%26w%3D3840%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhungvu.tech%2F_next%2Fimage%3Furl%3Dhttps%253A%252F%252Fpayload.hungvu.tech%252Fmedia%252FAIVjas12.webp%26w%3D3840%26q%3D75" alt="My website 7-day netowkr statistics, monitored in Cloudflare dashboard."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My website 7-day netowkr statistics, monitored in Cloudflare dashboard.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Compression&lt;/strong&gt;: I use the term compression loosely here, and below is what I mean&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Request/response compression&lt;/em&gt;: This category includes gzip, ztsd, and Brottli. They have reduced the size of the response, but I also need to consider how the compression is applied when there are many layers in-between (as discussed with HTTPS, and HTTP3). Besides, compression means increasing server load, so if not configured properly, the compression can slow down response time.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Image optimization&lt;/em&gt;: Broadly said, this is static asset optimization, but when coming to images specifically, the two widely used compressed formats are AVIF and WebP.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Request and response size&lt;/strong&gt;: This is an issue when the application overfetches. It may not be a glaring issue in a local development environment, but in production where applications are deployed to cloud services (or on-prem servers), it is a real deal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bandwidth costs money, and latency can heavily affect performance.&lt;/li&gt;
&lt;li&gt;By default, applications and anywhere that requests and responses go through, have a limitation on request and response sizes. For example, Next.js fetch cache limit, and Payload CMS max allowed JSON body size are default to 2 MB. Without proper configuration to lift the limits, it can cause unexpected behaviors or outright crash the applications.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Frequency of requests and responses&lt;/strong&gt;: In addition to the size mentioned above, frequency is also a factor.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frequent requests and responses mean increasing bandwidth usage.&lt;/li&gt;
&lt;li&gt;This can create an increased load on the host, leading to unexpected side effects. For example, the Payload CMS editor has an autosave feature and defaults at 800 milliseconds. The default is fine in the local development environment but breaks down in production. I changed the frequency to 15 seconds and issues are resolved.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Host machine architecture and specification&lt;/strong&gt;: This is less of an issue for containerized applications as they can run on different CPU architectures. From my research, AWS's general purpose offer on ARM is more performant than x86 alternatives. Anyway, &lt;a href="https://hungvu.tech" rel="noopener noreferrer"&gt;hungvu.tech&lt;/a&gt; is containerized on an EC2 t4g.micro instance (as nano lacks memory), which is an ARM platform powered by AWS Graviton2 processors. There are some required steps to create an ARM image though, but it is greatly simplified using Docker GitHub Actions.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Potential bugs in compiler/transpiler and bundler
&lt;/h2&gt;

&lt;p&gt;Here is a thing, to make the application production-ready, the source code must go through a compilation process of some sort. In Next.js with TypeScript, the bundling and transpiling process are required. Going through the process means the source code is transformed and optimized by the framework bundler and transpiller. If you can fully control the process, great. In reality, these processes are abstracted away to improve developer experience, and that by itself is a double-edged sword.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What if the bundler and compiler/transpiler are "stealthily" broken?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What if the bundler and compiler/transpiler conflict with your code base?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Considering the criticality of these components, they are mostly stable, but there is always an exception. For example, the Next.js production build can potentially mess up the front-end layout due to unexpected CSS ordering. This has been an ongoing issue since 2020 and is not fixed as of the latest version (Next.js v14.0.4). References are as below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/vercel/next.js/issues/13092" rel="noopener noreferrer"&gt;Next.js issue #13092.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/vercel/next.js/issues/16630" rel="noopener noreferrer"&gt;Next.js issue #16630.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;So, the list above is what I consider before bringing the application to production. The items, I suppose are all over the place, from software layer to infrastructure consideration. That's why I created the article to consolidate my thoughts for future reference. Is it the best and most accurate list? Certainly not, because each project has its own goal and looks at matters differently, so the points above are mostly personal to me. I hope it is useful to you, but remember to treat the list with a grain of salt.&lt;/p&gt;

&lt;p&gt;If you find this article to be helpful, I have some more for you!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/virtualize-truenas-with-harvester-and-kubevirt" rel="noopener noreferrer"&gt;Virtualize TrueNAS with Harvester (and Kubevirt for VM management)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/virtualize-openwrt-firewall-in-harvester-hci-cluster" rel="noopener noreferrer"&gt;Deploy a virtualized OpenWRT firewall in Harvester, how did it go?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/is-harvester-a-good-hypervisor-for-a-beginner-my-hands-on-experience" rel="noopener noreferrer"&gt;Is Harvester a good hypervisor for a beginner? My hands-on experience&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, let's connect!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.linkedin.com/in/hunghvu/" rel="noopener noreferrer"&gt;&lt;strong&gt;LinkedIn&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/hunghvu" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/hunghvu_dev" rel="noopener noreferrer"&gt;&lt;strong&gt;X (formerly Twitter)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>security</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>TrueNAS virtualization using Harvester and Kubevirt</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Wed, 05 Jul 2023 15:42:02 +0000</pubDate>
      <link>https://forem.com/hunghvu/truenas-virtualization-using-harvester-and-kubevirt-5fok</link>
      <guid>https://forem.com/hunghvu/truenas-virtualization-using-harvester-and-kubevirt-5fok</guid>
      <description>&lt;p&gt;Virtualizing TrueNAS has been a common theme in the homelab world for a long time. However, there are not many discussions on this topic with Harvester as a hypervisor, so I would like to go over my experience doing so in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual machine configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Planning
&lt;/h3&gt;

&lt;p&gt;Harvester uses Kubevirt for its virtualization management, so the virtual machines are configured using a Kubevirt YAML template. Before creating a virtual machine, let's sketch out the configuration beforehand.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CPU&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A general recommendation is to start with 2 vCPUs and scale them according to your workload and CPU model. In my case, I only use TrueNAS for archiving records, so 2 vCPUs of Ryzen 5 5600G are enough for me.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RAM&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
TrueNAS recommends 16 GB at minimum, and besides, ZFS loves RAM. I am not a ZFS expert by any means, but on experimenting with an 8 GB to 128 GB setup, I see no visible difference to my use case after 16 GB. I can technically run at 16 GB, but I decided to use 24 GB instead to give the machine some leeway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Boot drives&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Modern versions of TrueNAS (both Scale and Core) require more than 8 GB for a boot drive, 16 GB is a good starting point. For my installation, I use a 32 GB boot drive to give the OS some overhead, and also, create a second virtual disk to later form a mirror boot drive during TrueNAS installation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Installer drive&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
TrueNAS ISO ranges about 2 GB or less depending on the version, 5 GB is a good starting point for an installer drive. Make this one as &lt;code&gt;bootOrder: 1&lt;/code&gt;&lt;br&gt;&lt;br&gt;
so the virtual machine can boot into that right away. It actually does not need to be the first boot, but from my experience, sometimes this makes the virtual not able to detect the installer drive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For my use case, I bridge the virtual machine with a &lt;code&gt;L2VlanNetwork&lt;/code&gt; so it can communicate with my infrastructure. TrueNAS works well with VirtIO, so use it to maximize the performance (usually 3 to 5 times better in throughput compared to emulation).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bind the virtual machine to a specific node&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
TrueNAS, or more likely ZFS, does not like virtual IO (if at all). Therefore, PCI passthrough is required for all data drives. Enabling PCI passthrough in Harvester means your machine cannot perform a live migration, so you have to schedule the VM on a specific Harvester node.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Side note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;There might be a strategy for falling back or migration between multiple virtual machines if you have identical nodes with PCI passthrough enabled, I am not certain how that work at the moment.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Boot loader mode&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
TrueNAS installation supports both Legacy BIOS and UEFI boot modes. By default, Harvester creates a virtual machine with Legacy BIOS with Secure Boot disabled. UEFI boot is an option but from what in my use case, it makes no difference, so use the Legacy BIOS option. Make sure to choose the correct installation type, or else, you will be greeted with &lt;code&gt;Booting to hard disk&lt;/code&gt; stuck indefinitely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lv0VyAZK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688449173532/adc10a43-56b7-437c-8bac-846719c30065.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lv0VyAZK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688449173532/adc10a43-56b7-437c-8bac-846719c30065.png" alt="TrueNAS boot loader mode selection (Legacy BIOS vs. UEFI)" width="800" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kI7jYmA5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688449603493/3ad33199-3970-499c-8e94-dfad1f437f37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kI7jYmA5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688449603493/3ad33199-3970-499c-8e94-dfad1f437f37.png" alt="A legacy BIOS virtual machine cannot boot if an OS installation is of type UEFI." width="742" height="94"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  YAML configuration
&lt;/h3&gt;

&lt;p&gt;Configure the virtual machine via the Harvester web interface based on this specification, and the final result will resemble the following template.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Side note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;This is from&lt;/em&gt; &lt;code&gt;Edit YAML&lt;/code&gt;, not &lt;code&gt;Edit Config &amp;gt; Edit as YAML&lt;/code&gt;&lt;em&gt;. I am not certain about the relationship between those two but changes in one might not reflect in the other, even if they look almost identical.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;affinity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nodeAffinity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;requiredDuringSchedulingIgnoredDuringExecution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;nodeSelectorTerms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;matchExpressions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;network.harvesterhci.io/mgmt&lt;/span&gt;
                &lt;span class="na"&gt;operator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;In&lt;/span&gt;
                &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;true'&lt;/span&gt;
  &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cores&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
      &lt;span class="na"&gt;sockets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="na"&gt;threads&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;disks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;bootOrder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
          &lt;span class="na"&gt;disk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;bus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;virtio&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-2&lt;/span&gt;
          &lt;span class="c1"&gt;# Note: serial number is defined&lt;/span&gt;
          &lt;span class="na"&gt;serial&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dae05b93-c3c4-4a3e-9ec0-5403f9e70494&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;bootOrder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
          &lt;span class="na"&gt;disk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;bus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;virtio&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-1&lt;/span&gt;
          &lt;span class="na"&gt;serial&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ec0082c0-b2ec-4104-96d9-dec3562a6d06&lt;/span&gt;
        &lt;span class="c1"&gt;# Note: cloudinit is missing here&lt;/span&gt;
      &lt;span class="na"&gt;hostDevices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Note: PCI devices are passed through&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;amd.com/500_SERIES_CHIPSET_USB_3_1_XHCI_CONTROLLER&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;htpc-000016000&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;amd.com/500_SERIES_CHIPSET_SATA_CONTROLLER&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;htpc-000016001&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;asmedia.com/1064&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;htpc-000026000&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;bus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;usb&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tablet&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tablet&lt;/span&gt;
      &lt;span class="na"&gt;interfaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;bridge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
          &lt;span class="na"&gt;macAddress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;f6:28:ac:32:c2:3a&lt;/span&gt;
          &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;virtio&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;br-vlan1-lan&lt;/span&gt;
    &lt;span class="na"&gt;features&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;acpi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;q35&lt;/span&gt;
    &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;guest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;24476Mi&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2'&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;24Gi&lt;/span&gt;
      &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;125m&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;16Gi&lt;/span&gt;
  &lt;span class="na"&gt;evictionStrategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LiveMigrate&lt;/span&gt;
  &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="s"&gt;nas-core&lt;/span&gt;
  &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;multus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;networkName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default/vlan1-lan&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;br-vlan1-lan&lt;/span&gt;
  &lt;span class="na"&gt;nodeSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kubernetes.io/hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;htpc&lt;/span&gt;
  &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-2&lt;/span&gt;
      &lt;span class="na"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;claimName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;zfs-truenas-core-2&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-1&lt;/span&gt;
      &lt;span class="na"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;claimName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;zfs-truenas-core-1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actually, this template is after I finish setting up TrueNAS, so it is a bit different than your brand new YAML template. Let's talk about the differences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Missing&lt;/strong&gt; &lt;code&gt;installer&lt;/code&gt; &lt;strong&gt;, and&lt;/strong&gt; &lt;code&gt;cloudinit&lt;/code&gt; &lt;strong&gt;disks&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When the TrueNAS installer runs, you will see 3 different disks: &lt;code&gt;vtbd1&lt;/code&gt;, &lt;code&gt;vtbd2&lt;/code&gt;, &lt;code&gt;vtbd3&lt;/code&gt;. Aside from the installer, there should only be 2 drives for boot, which are &lt;code&gt;vtbd1: zfs-truenas-core-1&lt;/code&gt;, and &lt;code&gt;vtbd2: zfs-truenas-core-2&lt;/code&gt;. Meanwhile, the &lt;code&gt;vtbd3: cloudinit&lt;/code&gt;, is hidden from Harvester web GUI but is visible in the YAML config. It is responsible for managing and applying a configuration in the first boot of the virtual machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Go-_Jdfv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688449084216/fbaed78f-63fa-4d11-b84b-7598fb40de6d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Go-_Jdfv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688449084216/fbaed78f-63fa-4d11-b84b-7598fb40de6d.png" alt="TrueNAS installer shows 3 different disks." width="329" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After using &lt;code&gt;vtbd1&lt;/code&gt;, and &lt;code&gt;vtbd2&lt;/code&gt; as boot drives, &lt;code&gt;installer&lt;/code&gt; and &lt;code&gt;cloudinit&lt;/code&gt; becomes redundant and can cause certain issues, so they are removed just in cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drives have serial numbers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The boot drives are virtual, so by default, they do not have associated serial numbers. TrueNAS uses serial numbers as a way to keep track of drives, so without the identifier, certain operations such as creating a new pool are not possible (at least via the web GUI), even if your pool does not consist of the unidentified drive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QzbYIaCg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688450104425/03a27cce-bd3c-4ec4-9343-5316d75a94f7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QzbYIaCg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688450104425/03a27cce-bd3c-4ec4-9343-5316d75a94f7.png" alt="cloudinit drive does not have serial number and limits TrueNAS operation." width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;vtbd2&lt;/code&gt; here is the &lt;code&gt;cloudinit&lt;/code&gt; (number changes due to different boot environments). Before it is unmounted, a warning is shown in TrueNAS and that prevents pool creation. The same applies to the boot drives. Even though they do not appear in the warning if they do not have a unique serial number, no operation can be completed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IuDuHLWq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688450334370/48da4678-4758-4dd0-8736-b03de9846abc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IuDuHLWq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688450334370/48da4678-4758-4dd0-8736-b03de9846abc.png" alt="The boot drives do not have unique serial numbers." width="800" height="93"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Harvester does not expose a mechanism to set a serial number for drives via web GUI, so I manually adjust the Kubevirt YAML config and add the &lt;code&gt;serial&lt;/code&gt; property (with UUID). TrueNAS is perfectly happy with that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;disks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;bootOrder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="na"&gt;disk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;bus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;virtio&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-2&lt;/span&gt;
    &lt;span class="c1"&gt;# Note: serial number is defined&lt;/span&gt;
    &lt;span class="na"&gt;serial&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dae05b93-c3c4-4a3e-9ec0-5403f9e70494&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;bootOrder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="na"&gt;disk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;bus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;virtio&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-1&lt;/span&gt;
    &lt;span class="na"&gt;serial&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ec0082c0-b2ec-4104-96d9-dec3562a6d06&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bDpa9PT8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688450619234/891c864b-d3bb-4e68-9714-59aded8676d4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bDpa9PT8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688450619234/891c864b-d3bb-4e68-9714-59aded8676d4.png" alt="Serial number of TrueNAS virtual boot drives are defined." width="800" height="56"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PCI device devices are passed through.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Depending on your hardware, the PCI passthrough experience might differ. I did go over this a bit in &lt;a href="https://hungvu.tech/virtualize-openwrt-firewall-in-harvester-hci-cluster#heading-pcie-passthrough-is-straightforward-but-with-caveats"&gt;my previous article on deploying an OpenWRT firewall in Harvester&lt;/a&gt;. For my motherboard, which is MSI PRO B550M-VC WIFI, let's have a look at the block diagram below (from the motherboard manual).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s8QNtENr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688493325004/7ecfa6c9-8b92-472c-853c-89b4ee2a4eda.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s8QNtENr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688493325004/7ecfa6c9-8b92-472c-853c-89b4ee2a4eda.png" alt="MSI PRO B550M-VC WIFI PCIE block diagram." width="800" height="857"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have to pass through the section circled in green so TrueNAS can see the drives. There are some rules when passing through PCI devices.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;All devices in an IOMMU group must be passed through. Their group can be determined by looking at the device address. Generally, devices in the same &lt;code&gt;domain:bus&lt;/code&gt; are in a group. However, it is best to look at &lt;code&gt;/sys/kernel/iommu_groups/&lt;/code&gt; (F12 to access Harvester's node console), to see which device belongs to which group. Many times, devices with different &lt;code&gt;domain:bus&lt;/code&gt; addresses can be in the same group too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is not necessary to make all passed-through devices available to the virtual machine. Instead, some will even prevent the virtual machine to boot or causes random errors or behaviors. In extreme cases, a node failure may happen. I guess the extreme cases happen because an errored device overwhelms the logging and I/O of the node, hence node failure. Just make what is needed available by cherry-picking them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All devices in the same &lt;code&gt;domain:bus&lt;/code&gt; must be made available to the virtual machine, or else it cannot boot.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So with that, I choose the following devices (all in IOMMU group 12).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JOFhxGPJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688494255543/86c04c9e-a62c-48d7-ba0b-6dcb8f73237f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JOFhxGPJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688494255543/86c04c9e-a62c-48d7-ba0b-6dcb8f73237f.png" alt="IOMMU group 12 of MSI PRO B550M-VC WIFI are passed through to TrueNAS." width="800" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But only make 3 of them available to the virtual machine, because the other two PCI devices can make my node fail. The failure causes all sorts of issues like management address becoming unavailable, node not responding, and having to reboot, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;hostDevices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;amd.com/500_SERIES_CHIPSET_USB_3_1_XHCI_CONTROLLER&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;htpc-000016000&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;amd.com/500_SERIES_CHIPSET_SATA_CONTROLLER&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;htpc-000016001&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;asmedia.com/1064&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;htpc-000026000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may have been easier if I use my IBM M5110/LSI 9207-8i (SAS 2308, IT mode), but it makes no difference in the end for me. My disks eventually look like this, and the performance at default is very reasonable considering the overhead of virtualization. I guess it can still be further improved.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9pxS94pt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688495997376/a7583443-7fe1-4317-bbaf-4a8e963cb71e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9pxS94pt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688495997376/a7583443-7fe1-4317-bbaf-4a8e963cb71e.png" alt="TrueNAS disks setup after PCI passthrough." width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xo_Pijp4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688495525333/628b9839-ca17-404a-9b32-c6a04d01e6e4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xo_Pijp4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688495525333/628b9839-ca17-404a-9b32-c6a04d01e6e4.png" alt="TrueNAS VirtIO NIC performance is close to 10 Gbe." width="550" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Side note&lt;/em&gt;&lt;/strong&gt;*: The test runs only a few seconds, hence the skewness in its statistics. That said, the max throughput can reach close to 9 Gbps at one point on a 5 x 2 TB SSD pool, RAID-Z2.*&lt;/p&gt;

&lt;h2&gt;
  
  
  Miscellaneous details about TrueNAS installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Standard first-boot procedure
&lt;/h3&gt;

&lt;p&gt;When I first log in to TrueNAS installation, there is a standard procedure I use to set the machine up.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Set static IP, DNS, and default gateway (required for Internet access).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install the latest update.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a client account to access a network share.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move system dataset to boot pool.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable 2FA.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the SMART tests, schedule a weekly LONG test, and a daily SHORT test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For snapshots, schedule a daily task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For scrubbing, schedule a weekly task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a pool, data set, set user permission (OPEN template), enable SMB service, and create a share.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The below are optional, because they are not critical in a homelab environment, but are generally a must in production.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Disable the root account and use an admin account instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If using SSH, harden SSH authentication by disabling password login and enabling the public key requirement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up an encrypted email notification.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Granularly configure alert settings.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configured a verified SSL connection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Schedule a replication task for a different system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Schedule a cloud sync task for an off-site backup (3-2-1 strategy at minimum).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify ACL for granular access permission.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  "This system does not support virtualization" error
&lt;/h3&gt;

&lt;p&gt;At Harvester v1.1.2, it seems virtual machines on some AMD platforms cannot detect nested virtualization. This might relate to &lt;a href="https://github.com/harvester/harvester/issues/3900"&gt;Harvester issue #3900&lt;/a&gt;, but that issue is categorized as a user interface bug only. Besides, I can run virtual machines on my Ryzen 5600G node normally (with SVM, IOMMU, and SR-IOV enabled, while &lt;code&gt;/sys/module/kvm_amd/parameters/nested&lt;/code&gt; returns &lt;code&gt;1&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Up to this point in the article, I have been generalizing the TrueNAS version because both Core and Scale should be relatively the same. In fact, my first try is to migrate my bare metal TrueNAS Scale instance. It has some virtual machines and apps, but the migration to Harvester virtual machine is not without an issue. After the migration, TrueNAS Scale virtual machines are now nested virtualization, and they simply break the web GUI operations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r8HRWYkD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/62678592/250414760-080b8c69-7cf9-4b7f-ba14-e04ce0757d80.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r8HRWYkD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/62678592/250414760-080b8c69-7cf9-4b7f-ba14-e04ce0757d80.png" alt="This system does not support virtualization." width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essentially, TrueNAS Scale virtual machines cannot work in my nested environment. When I want to do any operation via the web GUI, such as creating a new pool, or new data set, this error shows up and interrupts the operation. However, operations via shell are not affected, nor are any other underlying features. For example, I import the pool via shell, and network sharing performs without a hassle. Apps also start automatically and are accessible via LAN connection, but are not modifiable via TrueNAS Scale web GUI.&lt;/p&gt;

&lt;p&gt;As now I use Harvester as a hypervisor type 1, I figure TrueNAS Scale is not the most optimal choice considering its bleeding edge nature. Therefore, I go back to TrueNAS Core, which has been battle-tested in the last decade and is widely considered a feature completed by this point. The TrueNAS Scale is only my playground, so there is no issue for me to completely wipe it off and move to the Core. I suppose a similar issue might raise again if I decide to enable virtualization on the current TrueNAS Core installation, so I leave it untouched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Originally, I dedicate the whole Ryzen 5600G node to a TrueNAS Scale bare metal installation. It has no issue but is certainly not a good utilization of the hardware. The current configuration makes no difference, and besides, it helps me learn a lot more about configuring virtual environments.&lt;/p&gt;

&lt;p&gt;This labwork also makes me recognize one important thing: "Searching for Harvester information is not always the way to go". This is because Harvester consists of many different components, such as the underlying Linux OS, Kubernetes, Kubevirt, Longhorn, and so on. When I face issues with virtual machines, it is better to search for the answer in Kubervirt context, like: "XYZ error in Kubevirt", not "XYZ error in Harvester".&lt;/p&gt;

&lt;p&gt;That's all for now. I wonder what would be a fun topic to learn about next!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KNrWcSm2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688516283329/29d66e6a-5fcd-42ec-8cca-e4c10ee9500f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KNrWcSm2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688516283329/29d66e6a-5fcd-42ec-8cca-e4c10ee9500f.png" alt="My current homelab has 5 virtual machines: Home Assistant, Omada controller, OpenWRT, TrueNAS Core, and OPNSense." width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;This article was originally published at &lt;a href="https://hungvu.tech/virtualize-truenas-with-harvester-and-kubevirt"&gt;Virtualize TrueNAS with Harvester (and Kubevirt for VM management)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find this article to be helpful, I have some more for you!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/is-harvester-a-good-hypervisor-for-a-beginner-my-hands-on-experience"&gt;Is Harvester a good hypervisor for a beginner? My hands-on experience&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/virtualize-openwrt-firewall-in-harvester-hci-cluster"&gt;Deploy a virtualized OpenWRT firewall in Harvester, how did it go?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/is-amd-gpu-better-than-nvidia-on-linux"&gt;Is AMD GPU better than Nvidia on Linux? It depends 🐞&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, let's connect!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.linkedin.com/in/hunghvu/"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/hunghvu"&gt;GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/hunghvu_dev"&gt;Twitter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>opensource</category>
      <category>linux</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>I virtualize OpenWRT in Harvester HCI, and it was a long story...</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Mon, 19 Jun 2023 12:00:00 +0000</pubDate>
      <link>https://forem.com/hunghvu/i-virtualize-openwrt-in-harvester-hci-and-it-was-a-long-story-56nb</link>
      <guid>https://forem.com/hunghvu/i-virtualize-openwrt-in-harvester-hci-and-it-was-a-long-story-56nb</guid>
      <description>&lt;p&gt;In my previous article, &lt;a href="https://hungvu.tech/is-harvester-a-good-hypervisor-for-a-beginner-my-hands-on-experience"&gt;Is Harvester a good hypervisor for a beginner? My hands-on experience&lt;/a&gt;, I tried out Harvester as a virtualization platform for my multi-node homelab. The experience was not flawless, but that is to be expected in a homelab environment. In this article, I will go over my experience setting up an OpenWRT firewall for my 1-gigabit fiber connection in a virtual machine (VM) in Harvester. There are some guides for configuring OpenWRT, but they are not full-on tutorials (many details were omitted). In a sense, this is more about my findings on working with Harvester.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenWRT, on an x86 machine?
&lt;/h2&gt;

&lt;p&gt;Talking about firewalls with routing capabilities in the homelab scene, pfSense, and OPNSense are the usual recommendations. They are great products, and I also use pfSense in a production environment. That said, networking is not my specialty, nor the focus of my homelab. I only need a few features such as VLAN and QoS, pfSense, and OPNSense are practically overkill for me.&lt;/p&gt;

&lt;p&gt;I had been using off-the-shelf OpenWRT-flashed routers for years. If the solution can put up a decent performance while maintaining up-to-date security guards, that is more than enough for me. OpenWRT fits the bill, and it is Linux-based, which I am more familiar with. Therefore, I looked into the idea of using OpenWRT on an x86 platform, and surprisingly, it is possible. The OpenWRT team also has a dedicated page for the x86 platform, which for some reason, I have not been aware of up till now. For the VM, I used &lt;code&gt;openwrt-22.03.5-x86-64-generic-ext4-combined-efi.img&lt;/code&gt;, the latest version at the time of writing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring a VM for the firewall, a long story...
&lt;/h2&gt;

&lt;p&gt;The YAML snippet below is my configs. Unnecessary information is removed to make it more concise&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubevirt.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;VirtualMachine&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;spec&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;affinity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
      &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;cores&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
          &lt;span class="na"&gt;sockets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
          &lt;span class="na"&gt;threads&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;disks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;bootOrder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
              &lt;span class="na"&gt;disk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;bus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;virtio&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-0&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;disk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;bus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;virtio&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cloudinitdisk&lt;/span&gt;
          &lt;span class="na"&gt;hostDevices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;intel.com/ETHERNET_CONNECTION_5_I219LM&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;harvester-ha2-0000001f6&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;intel.com/200_SERIES_Z370_CHIPSET_FAMILY_SMBUS_CONTROLLER&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;harvester-ha2-0000001f4&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;intel.com/200_SERIES_PCH_LPC_CONTROLLER_Q270&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;harvester-ha2-0000001f0&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;realtek.com/RTL8125_2_5GBE_CONTROLLER&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;harvester-ha2-000001000&lt;/span&gt;
          &lt;span class="s"&gt;...&lt;/span&gt;
          &lt;span class="na"&gt;interfaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;macAddress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;52:54:00:de:03:c1&lt;/span&gt;
              &lt;span class="na"&gt;masquerade&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
              &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;virtio&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
          &lt;span class="s"&gt;...&lt;/span&gt;
        &lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;q35&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;guest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;924Mi&lt;/span&gt;
        &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2'&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1Gi&lt;/span&gt;
          &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;125m&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;682Mi&lt;/span&gt;
      &lt;span class="na"&gt;evictionStrategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LiveMigrate&lt;/span&gt;
      &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openwrt&lt;/span&gt;
      &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
          &lt;span class="na"&gt;pod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
      &lt;span class="na"&gt;nodeSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kubernetes.io/hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;harvester-ha2&lt;/span&gt;
      &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-0&lt;/span&gt;
          &lt;span class="na"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;claimName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openwrt-disk-0-e9h90&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cloudInitNoCloud&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;networkDataSecretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openwrt-hilki&lt;/span&gt;
            &lt;span class="na"&gt;secretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openwrt-hilki&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cloudinitdisk&lt;/span&gt;
&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;conditions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;- lastProbeTime&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="no"&gt;null&lt;/span&gt;
      &lt;span class="s"&gt;lastTransitionTime&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="no"&gt;null&lt;/span&gt;
      &lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;VMI uses a PCI host devices&lt;/span&gt;
      &lt;span class="s"&gt;reason&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HostDeviceNotLiveMigratable&lt;/span&gt;
      &lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;False'&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LiveMigratable&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Virtual hardware specification
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Which node to run on?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My Harvester cluster consists of 3 nodes, in which the second node is a medium form factor computer with 3 network interface controllers (NIC), while the other nodes only have 1 NIC each. Technically, it is possible to set up OpenWRT with only 1 virtual NIC, shared between host and guest OS, and utilize the high availability (fallback) feature of a Harvester cluster, but I decided not to do so for now. Because this VM is for a firewall, it sorts of creates a chicken-and-egg issue, so using only 1 NIC will complicate the setup quite a bit since it involves configuring VLAN and virtual NIC for the VM. I may try that out down the road, but for now, running on the second node with PCIe passthrough is my choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CPU&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For this OpenWRT VM, I decided to go with 2 virtual cores. Actually, I tried out with only 1 virtual core, but that made the LAN to WAN performance inconsistent. With 1 core, fresh installation, and no additional service enabled (e.g., AdBlock, QoS), the LAN to WAN throughput ranged from 400 Mbps to 900 Mbps inbound and outbound. With 2 cores enabled, the performance has been consistent at around 800 - 900 Mbps with many additional services enabled. One thing to keep in mind, my second node has an Intel i5-6500 CPU, which is not a powerhouse by any means, so the performance is strictly applied to this CPU only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenWRT has a very small memory footprint and only consumes under 120 MB at fresh installation. That is understandable because OpenWRT is designed for consumer all-in-one devices with minimal hardware, it just so happens that the OS is compilable to x86 so here we are. Therefore, 1 GB of memory is more than enough for my use case. I probably will never consume over half of that though&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disk size&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Depending on your use case, you may require more drive space than me (e.g., for logging). Generally, the same story as memory applies here. OpenWRT installation consumes around 128 MB, so 1 GB for the installation is overkill. By default, OpenWRT does not even use all available drive space, and users must expand the root partition manually. Not that I need all available space though, so I tried to create an under-1 GB volume, but Harvester does not allow that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 1 GB is the minimum disk size you can choose.&lt;/span&gt;
&lt;span class="c1"&gt;# Chossing a smaller value (e.g., 0.256 GB) causes the following error.&lt;/span&gt;
&lt;span class="na"&gt;disk-0&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Exceed maximum size 999999999 GiB!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NIC&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The second node has 3 NICs: Intel I219-LM, Realtek RTL8125 (only 8125, neither rev. A nor B), and Intel X710 DA-2. The X710 is a management NIC, so I passed through the I219-LM and RTL8125. The x86 image supports both of these ethernet controllers out-of-the-box, separate driver installation is not necessary. It is also possible to utilize VLANs to set up WAN and LAN on 1 NIC, but that is a story for another day.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# RTL8125 uses kmod-r8169, and I219-LM uses kmod-e1000.&lt;/span&gt;
&lt;span class="c1"&gt;# The below are drivers bundled in the OpenWRT x86 image.&lt;/span&gt;
&lt;span class="c1"&gt;# Source: https://github.com/openwrt/openwrt/blob/3556455f040341099a6563968a6e9e8c22c0847e/target/linux/x86/image/64.mk#L6&lt;/span&gt;

&lt;span class="s"&gt;DEVICE_PACKAGES += \&lt;/span&gt;
    &lt;span class="s"&gt;kmod-amazon-ena kmod-amd-xgbe kmod-bnx2 kmod-e1000e kmod-e1000 \&lt;/span&gt;
    &lt;span class="s"&gt;kmod-forcedeth kmod-fs-vfat kmod-igb kmod-igc kmod-ixgbe kmod-r8169 \&lt;/span&gt;
    &lt;span class="s"&gt;kmod-tg3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although there are stories of people having terrible experiences using these NICs in OpenWRT (e.g., packet drop, kernel panic, etc.), they had been working fine on bare metal for me, so virtualization should be the same, right? Well, I did hope for that..., but I eventually decided to swap the roles of X710 and RTL8125. Let's talk more about it below.&lt;/p&gt;

&lt;h3&gt;
  
  
  PCIe passthrough is straightforward but with caveats
&lt;/h3&gt;

&lt;p&gt;Harvester offers PCIe passthrough out-of-the-box, but at the time of writing, &lt;em&gt;this feature is still experimental&lt;/em&gt;. PCIe passthrough is accessible via &lt;strong&gt;Virtual machine config &amp;gt; PCI Devices&lt;/strong&gt; web GUI, and the feature just takes a few clicks to enable (assuming your hardware supports that, e.g., VT-d, IOMMU, etc.) There is a technical difference between PCI and PCIe terminologies, but I will use the term PCIe devices in the following sections.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GOstnGtw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687047494008/5f255b20-a060-4465-80fb-116f883f95ef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GOstnGtw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687047494008/5f255b20-a060-4465-80fb-116f883f95ef.png" alt="Harvester PCIe passthrough web GUI is very intuitive." width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, I went ahead and passed through my NICs without any issues, or at least, not yet...&lt;/p&gt;

&lt;h3&gt;
  
  
  RTL 8125 does not like being passed through in Harvester
&lt;/h3&gt;

&lt;p&gt;At first sight, the RTL8125 NIC could be passed through easily, and indeed, it was. I could fully utilize it in my OpenWRT VM without any performance drop, hangs, or equivalent issues. Well, until I decided to reboot my VM.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In virtual machine events&lt;/p&gt;

&lt;p&gt;Reason: Sync Failed&lt;/p&gt;

&lt;p&gt;Resource: VirtualMachineInstance openwrt - Server error.command SyncVMI failed: "LibvirtError(Code=1, Domain=0, Message="internal error: Unknown PCI header type '127' for device '0000:01:00.0")"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A very cryptic error message, but in short, the VM was not bootable. This &lt;em&gt;usually&lt;/em&gt; happens whenever I reboot the VM by any means (e.g., via OpenWRT GUI, power off and start in Harvester GUI, etc.) Alongside, there were all sorts of random problems when this error message appeared such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;VM became unresponsive to actions (via web GUI) like power off, restart, delete, edit-config, and so on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;VM was indefinitely stuck at &lt;em&gt;Starting&lt;/em&gt; state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node became unresponsive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was not able to reliably reproduce the issue, and still do not know the reasons behind that. From the research I made, all I can say is it has something to do with the virtual machine type (q35), its virtual BIOS, and the NIC itself is stuck in a certain state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# dmesg on the second node.&lt;/span&gt;
&lt;span class="s"&gt;vfio-pci 0000:01:00.0: Refused to change power state, currently in D3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rebooting and unplugging the node (to discharge) a few times can resolve this. Technically, it is not a big deal if the VM stays online for a long period. However, I was in the tinkering phase, so the issue got on my nerves due to its random nature. That is why, I eventually turned RTL8125 into a management NIC, while dedicating the X710 to my VM. I had to reinstall Harvester, but at least, I have not faced the same problem since then.&lt;/p&gt;

&lt;h3&gt;
  
  
  But ... it did not stop there
&lt;/h3&gt;

&lt;p&gt;I think if you have extensive knowledge of K8s, the following error messages tell something. To a newcomer like me, they are more or less comparable to reading an AES-256 encrypted message. I did spend a good amount of time searching for these error messages but yielded no results. I guess that is because these messages are somewhat specific to Harvester's usage of K8s. Considering there are not many online resources about the platform at the moment (relative to equivalent solutions like VM Ware or Proxmox), probably I need to dig even deeper to find out the answers.&lt;/p&gt;

&lt;p&gt;Here are some generic errors that I faced when enabling PCIe passthrough. The same as the RTL8125 story mentioned above, the following errors randomly appear. Essentially, they prevent the VM from completing an action, such as starting, or stopping. They may go away after some time, or get stuck there indefinitely and require a node reboot. The error messages are notified via several ways, such as pop up, VM events, statuses, etc. I do not use a coding textbox below because they are very long messages, and I am not sure if it consists of many different ones. Harvester does not give any new lines though.&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;0/3 nodes are available: 3 node(s) didn't match Pod's node affinity/selector.preemtion: 0/3 nodes are available: 3 Preemtion is not helpful for scheduling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error: Stop virtual machine default/openwrt failed, Operation cannot be fulfilled on virtualmachine.kubevirt.io "openwrt": Halted does not support manual stop requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FailedAttachVolume: Pod virt-launcher-openwrt AttachVolume.Attach failed for volume "...": rpc error: code = Internal desc = Bad response statusCode[500]. Status [500 Internal Server Error]. Body: [code=Server Error, detail=, message=unable to attach volume ... to harvester-ha2: node harvester-ha2 is not ready, couldn't attach volume ... from [&lt;a href="http://longhorn-backend:9500/v1/volumes/...?action=attach%5C"&gt;http://longhorn-backend:9500/v1/volumes/...?action=attach\&lt;/a&gt;]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;0/3 nodes are available: 1 Insufficient devices.kubevirt.io/kvm, 1 Insufficient devices.kubevirt.io/tun, 1 Insufficient devices.kubevirt.io/vhost-net, 1 insufficient intel.com/200_SERIES_PCH_LPC_CONTROLLER_Q270, 1 Insufficient intel.com/200_SERIES_Z370_CHIPSET_FAMILY_SMBUS_CONTROLLER, 1 Insufficient intel.com/ETHERNET_CONNECTION_5_I219LM, 1 Insufficient realtek.com/RTL8125_2_5GBE_CONTROLLER, 2 node(s) didn't match Pod's node affinity/selector.preemption: 0/3 nodes are available: 1 No preemption victims found for incoming pod, 2 Preemption is not helpful for scheduling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;0/3 nodes are available: 1 Insufficient CPU&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unable to retrieve container logs for containerd://...&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  All devices in the same IOMMU group must be passed through
&lt;/h3&gt;

&lt;p&gt;This is not an issue with Harvester but is more about how the platform handles it. When passing through a PCIe device, all in the same IOMMU group must be passed through unless Access Control Service is enabled (which I do not have). It is not necessary to activate all passed-through devices though. In Harvester, there is no clear indicator for which IOMMU group a PCIe device belongs, but it can be determined using the &lt;strong&gt;Address&lt;/strong&gt; column on the &lt;strong&gt;PCI Devices&lt;/strong&gt; page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q57fwWbG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687066560414/237dea90-2a31-4b9d-bf33-33cc1cb4eb86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q57fwWbG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687066560414/237dea90-2a31-4b9d-bf33-33cc1cb4eb86.png" alt="PCIe device addresses." width="176" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The addresses follow a Bus, Device, Function (BDF notation) for PCI Domain, which consists of 3 parts: Domain (0000), Bus (00), Device (02), and Function (0). All devices that have the same &lt;code&gt;Domain:Bus:Device&lt;/code&gt; sections, they are in the same IOMMU group. Another way to check is to look at a device name because Harvester by default uses a format of &lt;code&gt;node name-address&lt;/code&gt; as a convention. For example, in the picture below, I passed through all devices in the group&lt;code&gt;0000:00:1f&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--07-6CWUn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687067248172/4232ee8e-2d4e-4984-a6ae-5259edffae1c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--07-6CWUn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687067248172/4232ee8e-2d4e-4984-a6ae-5259edffae1c.png" alt="All devices in the same IOMMU group must be passed through to the VM." width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a thing, when a device is not passed through probably, there is no indicator. I faced three different scenarios that are related to this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Devices stuck in &lt;em&gt;In Progress&lt;/em&gt; state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Devices are shown as &lt;em&gt;Enabled&lt;/em&gt;, but in fact, are not visible in the VM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And I simply forgot to pass through one device.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In these cases, the VM could not boot up, or bootable but stuck in &lt;em&gt;Starting&lt;/em&gt; state and became unresponsive. There were no indicators, no logs, nothing. Admittedly, I only used web GUI, so maybe something could be seen if using the terminal. This is not a good user experience in my opinion.&lt;/p&gt;

&lt;p&gt;On a side note, although I passed through 5 devices in this IOMMU group as shown in the picture, I must not activate the &lt;em&gt;Power Management Controller (0000:00:1f.2).&lt;/em&gt; Activating that device always makes my VM not bootable and throws the following error message.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;1. 0/4 nodes are available: 1 Insufficient intel.com/200_SERIES_Z370_CHIPSET_FAMILY_POWER_MANAGEMENT_CONTROLLER, 3 node(s) didn't match Pod's node affinity/selector.preemption: 0/4 nodes are available: 1 No preemption victims found for incoming pod, 3 Preemption is not helpful for scheduling&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setting up OpenWRT for the gigabit network
&lt;/h2&gt;

&lt;p&gt;Alright, I have been focusing on Harvester up to this point, let's briefly shift the focus to my experience on configuring the OpenWRT for my 1-gigabit line. To do so, I accessed the VM via Harvester serial console and modify the network config file, then ran the command &lt;code&gt;service network restart&lt;/code&gt; to apply changes. Note, it was &lt;code&gt;restart&lt;/code&gt; in my case, as &lt;code&gt;reload&lt;/code&gt; did not work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# vim /etc/config/network&lt;/span&gt;

&lt;span class="c1"&gt;# These are default OpenWRT config, no need to modify&lt;/span&gt;
&lt;span class="s"&gt;config interface 'loopback'&lt;/span&gt;
        &lt;span class="s"&gt;option device 'lo'&lt;/span&gt;
        &lt;span class="s"&gt;option proto 'static'&lt;/span&gt;
        &lt;span class="s"&gt;option ipaddr '127.0.0.1'&lt;/span&gt;
        &lt;span class="s"&gt;option netmask '255.0.0.0'&lt;/span&gt;

&lt;span class="s"&gt;config globals 'globals'&lt;/span&gt;
        &lt;span class="s"&gt;option ula_prefix 'fd6c:3930:3b2c::/48'&lt;/span&gt;

&lt;span class="c1"&gt;# Add your customize configs down below&lt;/span&gt;
&lt;span class="s"&gt;config device&lt;/span&gt;
        &lt;span class="s"&gt;option name 'br-lan'&lt;/span&gt;
        &lt;span class="s"&gt;option type 'bridge'&lt;/span&gt;
        &lt;span class="s"&gt;list ports 'br-vlan.1'&lt;/span&gt;

&lt;span class="c1"&gt;# I could add eth3 to use as a backup NIC&lt;/span&gt;
&lt;span class="c1"&gt;# but I just did not do so&lt;/span&gt;
&lt;span class="s"&gt;config device&lt;/span&gt;
        &lt;span class="s"&gt;option type 'bridge'&lt;/span&gt;
        &lt;span class="s"&gt;option name 'br-vlan'&lt;/span&gt;
        &lt;span class="s"&gt;list ports 'eth2'&lt;/span&gt;
        &lt;span class="s"&gt;option bridge_empty '1'&lt;/span&gt;

&lt;span class="s"&gt;config bridge-vlan&lt;/span&gt;
        &lt;span class="s"&gt;option device 'br-vlan'&lt;/span&gt;
        &lt;span class="s"&gt;option vlan '1'&lt;/span&gt;
        &lt;span class="s"&gt;list ports 'eth2:u*'&lt;/span&gt;

&lt;span class="s"&gt;config interface 'lan'&lt;/span&gt;
        &lt;span class="s"&gt;option device 'br-lan'&lt;/span&gt;
        &lt;span class="s"&gt;option proto 'static'&lt;/span&gt;
        &lt;span class="s"&gt;option ipaddr '10.10.10.1'&lt;/span&gt;
        &lt;span class="s"&gt;option netmask '255.255.255.0'&lt;/span&gt;
        &lt;span class="s"&gt;option ip6assign '60'&lt;/span&gt;

&lt;span class="s"&gt;config interface 'wan'&lt;/span&gt;
        &lt;span class="s"&gt;option type 'bridge'&lt;/span&gt;
        &lt;span class="s"&gt;option proto 'pppoe'&lt;/span&gt;
        &lt;span class="s"&gt;option username 'your-username'&lt;/span&gt;
        &lt;span class="s"&gt;option password 'your-password'&lt;/span&gt;
        &lt;span class="s"&gt;option device 'eth1.201'&lt;/span&gt;
        &lt;span class="s"&gt;option ipv6 'auto'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what led me to perform these changes in the first place?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;OpenWRT uses a classic unpredictable naming scheme (eth0, 1, 2, etc.) From my understanding, whichever is closer to the CPU goes first. With an educated guess, &lt;code&gt;eth0&lt;/code&gt; is a virtual NIC from Harvester, &lt;code&gt;eth1&lt;/code&gt; is an onboard NIC Intel I219-LM and &lt;code&gt;eth2&lt;/code&gt;, &lt;code&gt;eth3&lt;/code&gt; is for X710-DA2. I used the I219-LM for WAN and one port of X710 for LAN.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You may wonder why I did not use two NICs of X710-DA2 for WAN and LAN. It is because I do not have a compatible SFP+ to multi-gig RJ45 NIC for the X710.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# X710-DA2 driver and firmware (NVM) blocks unbranded SFP modules.&lt;/span&gt;
&lt;span class="c1"&gt;# You will not see this issue before installing X710 driver though.&lt;/span&gt;
&lt;span class="na"&gt;kern.err kernel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;  &lt;span class="nv"&gt;415.070583&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="s"&gt;i40e 0000:02:00.0: Rx/Tx is disabled on this device because an unsupported SFP module type was detected.&lt;/span&gt;
&lt;span class="na"&gt;kern.err kernel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;  &lt;span class="nv"&gt;415.070831&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="s"&gt;i40e 0000:02:00.0: Refer to the Intel(R) Ethernet Adapters and Devices User Guide for a list of supported modules.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, my WAN was up and the OpenWRT instance had access to the Internet, but that was just the start. I ran the following commands right after.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Retrieve package list from OpenWRT.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# The less packages (and size), the better&lt;/span&gt;
&lt;span class="c1"&gt;# because that reduce attack surface.&lt;/span&gt;
&lt;span class="s"&gt;opkg update&lt;/span&gt;

&lt;span class="c1"&gt;# Install driver for x710-DA2.&lt;/span&gt;
&lt;span class="c1"&gt;# This allows eth2 and eth3 to appear.&lt;/span&gt;
&lt;span class="s"&gt;opkg install kmod-i40e&lt;/span&gt;

&lt;span class="c1"&gt;# This package contains several security patches.&lt;/span&gt;
&lt;span class="c1"&gt;# E.g., Meltdown, Spectre, etc.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# There is an equivalent package for different platforms too.&lt;/span&gt;
&lt;span class="s"&gt;opkg install intel-microcode&lt;/span&gt;

&lt;span class="c1"&gt;# This is for DNS logging, and can be substitue with tcpdump-mini.&lt;/span&gt;
&lt;span class="s"&gt;opkg install tcpdump&lt;/span&gt;

&lt;span class="c1"&gt;# Network-wide adblocker, this utilize tcpdump.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# If a package name is prepended with luci-app&lt;/span&gt;
&lt;span class="c1"&gt;# it provides a web GUI.&lt;/span&gt;
&lt;span class="s"&gt;opkg install luci-app-adblock&lt;/span&gt;

&lt;span class="c1"&gt;# OpenWRT on x86 does not have a firmware flash feature.&lt;/span&gt;
&lt;span class="c1"&gt;# In other words, an upgrade is a complete reinstallation&lt;/span&gt;
&lt;span class="c1"&gt;# of the OpenWRT image.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# The package below allows an in-place upgrade for OpenWRT&lt;/span&gt;
&lt;span class="c1"&gt;# while preserving packages and settings.&lt;/span&gt;
&lt;span class="s"&gt;opkg install luci-app-attendedsysupgrade&lt;/span&gt;

&lt;span class="c1"&gt;# Network-wide DNS enforcer.&lt;/span&gt;
&lt;span class="c1"&gt;# Test config at: https://www.dnsleaktest.com/&lt;/span&gt;
&lt;span class="s"&gt;opkg install luci-app-https-dns-proxy&lt;/span&gt;

&lt;span class="c1"&gt;# Mitigate bufferbloat.&lt;/span&gt;
&lt;span class="c1"&gt;# Test config at: https://www.waveform.com/tools/bufferbloat (or DSL report)&lt;/span&gt;
&lt;span class="s"&gt;opkg install luci-app-sqm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These packages can be configured either via serial console, or via the web GUI, but I will skip over the tutorials for that. To be frank, I am more of a power user with basic domain-specific knowledge in this regard, meaning I am aware of which toggle to turn on, and which number to put in. However, I do not have a deep networking background to explain those options, hence my explanation might not be the best. If you want to learn more, the OpenWRT documentation is a good starting point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is a saying, a picture says a thousand words. Here are some tests I performed on the OpenWRT VM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web GUI, notice the system information?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yMHTxilQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687129248597/8c07aa2b-83fd-462b-8de1-b0fa88f20e78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yMHTxilQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687129248597/8c07aa2b-83fd-462b-8de1-b0fa88f20e78.png" alt="Virtual OpenWRT web GUI." width="800" height="692"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Waveform bufferbloat test result.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KHh4JLtk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687125869246/ae35321a-beb8-4874-b1f6-ae4bd66ed99e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KHh4JLtk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687125869246/ae35321a-beb8-4874-b1f6-ae4bd66ed99e.png" alt="A perfect bufferfloat score on Waveform test." width="800" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudflare network test result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xGu2BzKX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687126605787/edb00d39-41b5-4293-afcb-5e2dfffc1f1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xGu2BzKX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687126605787/edb00d39-41b5-4293-afcb-5e2dfffc1f1f.png" alt="Cloudflare network test shows no sign of issue." width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ss8cljSN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687126616638/83de4325-da0a-4005-b650-93787d25aae9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ss8cljSN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687126616638/83de4325-da0a-4005-b650-93787d25aae9.png" alt="Every metric in Cloudflare network test reflects a good connection." width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YPKVYe8M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687130110082/39b3c22d-2257-4e6e-9f89-a7936163b461.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YPKVYe8M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687130110082/39b3c22d-2257-4e6e-9f89-a7936163b461.png" alt="Resource consumption during bufferbloat stress test." width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iperf3 from client to OpenWRT result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r3Q11yNA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687130417102/b75adb96-4608-41f8-8701-0ddd7ac4a91b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r3Q11yNA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687130417102/b75adb96-4608-41f8-8701-0ddd7ac4a91b.png" alt="iperf3 from client to OpenWRT result and resource consumption." width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iperf3 loopback result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I7539vIW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687130675108/670136a2-e5b8-40ce-b772-71e5620dda76.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I7539vIW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687130675108/670136a2-e5b8-40ce-b772-71e5620dda76.png" alt="iperf3 loop back result on virtualized Intel I5-6500 reaches 50 Gbit/s." width="800" height="916"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;It was a wild ride but at last, I have been able to use this VM firewall full-time. When it runs, the performance is miles ahead compared to off-the-shelf routers, the only hiccups that I still occasionally face are random errors when rebooting the machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G33Kpe3o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687131133313/2c4c1b1d-2aa7-4dca-ac3d-29a1b67f1e62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G33Kpe3o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687131133313/2c4c1b1d-2aa7-4dca-ac3d-29a1b67f1e62.png" alt="I have been using OpenWRT VM for more than a month." width="136" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, this is not a huge deal breaker to me as I do not play around with networking that much in my homelab. Considering there is no measurable difference between a virtualized firewall with bare metal installation, it is certainly worth a try. Theoretically, there are security implications when virtualizing the firewall though, but I suppose I am not the best person to discuss that.&lt;/p&gt;

&lt;p&gt;I am currently working on virtualizing TrueNAS and deploying websites on my Harvester cluster, they might be good ones to talk about in my future articles.&lt;/p&gt;




&lt;p&gt;This article was originally published at: &lt;a href="https://hungvu.tech/virtualize-openwrt-firewall-in-harvester-hci-cluster"&gt;Deploy a virtualized OpenWRT firewall in Harvester, how did it go?&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find this article to be helpful, I have some more for you!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/is-harvester-a-good-hypervisor-for-a-beginner-my-hands-on-experience"&gt;Is Harvester a good hypervisor for a beginner? My hands-on experience&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/amplication-vs-supabase-vs-appwrite-baas-comparison"&gt;Amplication vs Supabase vs Appwrite, for an effortless back end&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/bootstrap-a-simple-back-end-with-a-user-notification-feature-using-novu-and-amplication"&gt;Bootstrap a simple back end with a user notification feature using Novu and Amplication&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, let's connect!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.linkedin.com/in/hunghvu/"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/hunghvu"&gt;GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/hunghvu_dev"&gt;Twitter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>devops</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🦕 How to build a simple back end PoC with user notification using Novu, Amplication, and Discord?</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Sun, 11 Jun 2023 18:37:17 +0000</pubDate>
      <link>https://forem.com/hunghvu/how-to-build-a-simple-back-end-poc-with-user-notification-using-novu-amplication-and-discord-4h14</link>
      <guid>https://forem.com/hunghvu/how-to-build-a-simple-back-end-poc-with-user-notification-using-novu-amplication-and-discord-4h14</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;In this project, I’ll be showing you some unique ways to integrate Novu with Amplification, a BaaS platform. With it, I’ll show you some interesting ways to leverage Novu’s open-source notification platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Amping It Up to Eleven
&lt;/h2&gt;

&lt;p&gt;Building the complex software of today’s world is no easy task. A recent trend to help developers create these new applications is low-code and no-code, tools that can generate code automatically.&lt;/p&gt;

&lt;p&gt;Not only can these tools help non-developers create applications, they can also massively boost the productivity of a developer. These tools can help rapidly set up and create applications without needing to hand-code every aspect of an application.&lt;/p&gt;

&lt;p&gt;In this article, I’ll be showing you how to leverage one of these tools, Amplification, alongside a powerful open-source notification platform in Novu.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at: &lt;a href="https://hungvu.tech/bootstrap-a-simple-back-end-with-a-user-notification-feature-using-novu-and-amplication" rel="noopener noreferrer"&gt;Bootstrap a simple back end with a user notification feature using Novu and Amplication&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Tech
&lt;/h2&gt;

&lt;p&gt;If you already know what Novu and Amplication are, that's great! For those who don't, let me introduce you to the tip of the low-code solution iceberg.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Novu?
&lt;/h3&gt;

&lt;p&gt;Novu is an MIT-licensed open-source notification infrastructure that empowers developers to send and manage notifications seamlessly across various channels and platforms. Its unified interface simplifies the process of delivering notifications through email, SMS, push notifications, and other channels.&lt;/p&gt;

&lt;p&gt;Developed using cutting-edge technologies like Node.js, MongoDB, and Redis, Novu boasts exceptional scalability and reliability. With features such as notification templates and scheduled notifications that can be defined via the graphical user interface, Novu provides an exceptional developer experience even in a fast pace environment.&lt;/p&gt;

&lt;p&gt;Using Novu can save developers considerable time and effort that would otherwise be spent building and managing a notification infrastructure. When your project scales and contains dozens of SDKs only for the messaging module, it can create unnecessary complexity in management. Without the use of Novu, you have to develop integration and interaction between different channels on your own.&lt;/p&gt;

&lt;p&gt;On the theme of trying to speed up the development process while still maintaining the quality of your final product, backend-as-a-service (BaaS) is also a concept you must know about.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is backend-as-a-service (BaaS)?
&lt;/h3&gt;

&lt;p&gt;Backend-as-a-Service (BaaS) is a model that provides developers with a pre-built backend infrastructure to create multi-platform applications. Pre-built infrastructure is one thing, but you can also define your architecture on several aspects such as databases, and API access control lists via a friendly graphical user interface. By abstracting away the complexities of managing server-side infrastructure, BaaS platforms empower developers to focus on crafting exceptional user experiences on the front end.&lt;/p&gt;

&lt;p&gt;BaaS providers offer an array of backend services such as user authentication, database management, file storage, ... and the list goes on. Whatever tasks are usually done on the backend, then a BaaS can achieve that in a low-code manner. These services can be easily integrated into an application using APIs or software development kits (SDKs).&lt;/p&gt;

&lt;p&gt;BaaS is particularly valuable for startups and small businesses with limited resources that seek to develop applications quickly and efficiently. It eliminates the need for building and maintaining their backend infrastructure, which can be both costly and time-consuming.&lt;/p&gt;

&lt;p&gt;Nevertheless, BaaS generally has some drawbacks, mainly flexibility and control of your codebase (e.g., for performance optimization). BaaS is an abstraction for barebone back-end development, so it is a trade-off. Also, using a BaaS platform could increase dependency on third-party services as most are cloud-based, meaning availability and low-level security control are not in your hand.&lt;/p&gt;

&lt;p&gt;However, no need to be disappointed, because Amplication is here to resolve those drawbacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Amplication?
&lt;/h3&gt;

&lt;p&gt;Amplication is a revolutionary Apache 2.0-licensed open-source platform that simplifies the development process by automating the creation of functional, human-readable, and editable services based on TypeScript and Node.js. By generating the boilerplate code, Amplication allows developers to focus on building their core product, rather than worrying about the underlying infrastructure. Besides, its efficient automation not only saves developers a considerable amount of time and effort but also allows them to make changes quickly and easily. This ensures that developers can respond to evolving needs and requirements promptly and efficiently.&lt;/p&gt;

&lt;p&gt;Like many other BaaS products, Amplication offers features like data modeling, user authentication, and access control, Amplication offers a comprehensive solution for building web, mobile, and desktop applications and APIs. However, what makes Amplication truly exceptional and eliminate common BaaS drawback is its ability to produce code that is not only fully functional but also easily understandable and customizable, making it an excellent tool for developers of all skill levels.&lt;/p&gt;

&lt;p&gt;Typically, most BaaS products are cloud-based, so when you develop software using their services, you are effectively locked in their wall-garden ecosystem and have little control of the underlying mechanism. In a sense, this is to be expected because BaaS is supposed to abstract away the technical parts. However, while Amplication is doing the same, the generated codebase and self-hosted options allow you to keep the whole infrastructure in your hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrate Amplication with Novu
&lt;/h2&gt;

&lt;p&gt;Now, why is Novu needed, you may ask? Amplication is there to generate all of your backend infrastructure. With notification as a common feature in modern applications, it should be a part generated by Amplication, or is it?&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a sample use case of Amplication?
&lt;/h3&gt;

&lt;p&gt;Imagine a startup that specializes in selling sustainable fashion products online. As an e-commerce business, they need a reliable and scalable backend infrastructure to manage their product catalog, customer data, and orders. However, the startup's small team lacks the resources and expertise to build a custom backend infrastructure from scratch.&lt;/p&gt;

&lt;p&gt;That's where Amplication comes in. Using Amplication's visual editor, the startup's development team can quickly generate a custom backend infrastructure that meets their specific needs. They can easily create services for product management, order processing, payment processing, and customer management. The codebase for this service is then generated and can be version controlled and synced to GitHub so the team has a formal commit tree to follow through, thus enabling rolling back the development when breaking bugs happen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680481143504%2Fe7213590-8380-459a-b82c-4343edb3f15f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680481143504%2Fe7213590-8380-459a-b82c-4343edb3f15f.png" alt="Amplication can generate a database for an ecommerce service."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With Amplication, the startup can focus on building its storefront or social media outreach effort, knowing that the backend infrastructure is secure, scalable, and customizable. One thing to note, Amplication can generate most of the core codebase, that said, its scope (at default) is limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Database (e.g., PostgreSQL, MongoDB)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access control&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API (REST, GraphQL)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server (NestJS)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Admin dashboard (front-end for content managers)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Theoretically, the startup can leverage existing APIs (e.g., via plugins) to seamlessly integrate with popular shipping carriers, payment gateways, and inventory management systems. This integration saves the startup's development team time and resources while providing a seamless shopping experience for their customers. The thing is, not many plugins are available at the time of writing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680481977404%2Fae9c57c5-bc59-48f4-b6e1-de8f0638ccba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680481977404%2Fae9c57c5-bc59-48f4-b6e1-de8f0638ccba.png" alt="Amplication has limited selections of plugins at the time of writing."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Considering the open-source nature of Amplication, more community plugins along with first-party solutions will become available over time. The startup needs a notification feature to let their customers know when new items arrive, but there is no notification plugin at the moment. Does it mean the startup has to wait for that specific plugin to come out? Not at all, for now, the startup can take advantage of the generated codebase and build a custom business logic using Novu, an open-source notification infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is custom code (and business logic) in Amplication?
&lt;/h3&gt;

&lt;p&gt;In Amplication, there are two main layers of abstraction to have a separation of concerns.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;One layer is dedicated to code generated by Amplication.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Another layer is dedicated to custom code so developers can customize apps and minimize merge conflicts. Technically said, the conflicts should not happen in the first place as two layers are isolated. However, as Amplication gets updated and breaking changes arrive, merging the code generated from different Amplication versions may require manual intervention.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When your application is generated, the folder structure looks like the below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;// Root
(config files)
prisma
scripts
src
&lt;span class="p"&gt;-&lt;/span&gt; (NestJS project files/folders)
&lt;span class="p"&gt;-&lt;/span&gt; (Entity folders)
&lt;span class="p"&gt;  -&lt;/span&gt; base
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;entity-name&amp;gt;&lt;/span&gt;.controller.ts
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;entity-name&amp;gt;&lt;/span&gt;.module.ts
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;entity-name&amp;gt;&lt;/span&gt;.resolver.ts
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;entity-name&amp;gt;&lt;/span&gt;.service.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One layer of abstraction is in the &lt;code&gt;base&lt;/code&gt; folder, and this is for files that are generated by Amplication. These files are not for customized code and will be overwritten by subsequent commits from Amplication. Meanwhile, the other layer of abstraction consists of files on the same level as the &lt;code&gt;base&lt;/code&gt; folder. This means &lt;code&gt;controller&lt;/code&gt;, &lt;code&gt;module&lt;/code&gt;, &lt;code&gt;resolver&lt;/code&gt;, and &lt;code&gt;service&lt;/code&gt; are customizable and you can add more files or folders to the same directory as needed.&lt;/p&gt;

&lt;p&gt;Being customizable, many categories of code can be implemented, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;em&gt;action&lt;/em&gt; when a request hits an API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;em&gt;query&lt;/em&gt; in a GraphQL resolver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Business logic&lt;/em&gt; in service and responses.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Business logic in this context is an operation performed when a database query is invoked (e.g., send a notification when a new item is added to the database). The following is a generic sample of implementing custom business logic in Amplication, but in the next section, you will dive into the practical usage of this feature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Author: Hung Vu&lt;/span&gt;

&lt;span class="c1"&gt;// &amp;lt;entity-name&amp;gt;.service.ts&lt;/span&gt;
&lt;span class="c1"&gt;// Example of adding business logic to a service&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../prisma/prisma.service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SneakerServiceBase&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./base/sneaker.service.base&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SneakerService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;SneakerServiceBase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PrismaService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Add your custom business logic here&lt;/span&gt;
    &lt;span class="nf"&gt;notifyCustomersOnNewArrivals&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// &amp;lt;entity-name&amp;gt;.controller.ts&lt;/span&gt;
&lt;span class="c1"&gt;// Example of adding business logic to a REST API response&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;common&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;swagger&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nestjs/swagger&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;nestAccessControl&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nest-access-control&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./product.service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductControllerBase&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./base/product.controller.base&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;swagger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ApiTags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;common&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ProductControllerBase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;nestAccessControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;InjectRolesBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;rolesBuilder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nestAccessControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RolesBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rolesBuilder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;HttpCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;yourResponse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Add your custom business logic here&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example: How to implement a Discord notification in Amplication using Novu?
&lt;/h3&gt;

&lt;p&gt;In this section, you will explore the integration between Amplication and Novu via Discord webhooks. This tutorial is not intended to cover the entire process from start to finish, and it assumes a certain knowledge of the initial steps like installation and user interface navigation. Considering the introductory nature of the tutorial, you do not need to be an expert in Amplication, Novu, and Discord. If you have not tried them out, go ahead and spend like 30 minutes reading over the documentation. That should be more than sufficient before getting to this tutorial.&lt;/p&gt;

&lt;h3&gt;
  
  
  Define user story, a hypothetical scenario
&lt;/h3&gt;

&lt;p&gt;Coming back to the mentioned example, let's say you are a fashion store owner. Your store has grown at a very decent rate in the past few years and now, you have a dedicated community on Discord. To increase customer experience, you want to have multi-channel notification features so customers know when new products arrive. Your website is powered by Amplication, and you have just learned about the unified API capabilities of Novu, an open-source notification infrastructure. This seems to be a good combination and with that in mind, your Discord community channel is the first group of customers to receive this update.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Discord channel webhook
&lt;/h3&gt;

&lt;p&gt;There are two main ways to integrate service with Discord: Webhooks and Discord Bots. At the time of writing, Novu only supports a webhook approach. To create a webhook:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Go to your Discord server and choose your targeted announcement channel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hover your mouse over that channel, then go to the &lt;em&gt;Edit channel dashboard.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680496276521%2F025afe09-c7d8-4da2-8feb-5de9a4b4cdc0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680496276521%2F025afe09-c7d8-4da2-8feb-5de9a4b4cdc0.png" alt="Edit Discord channel."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Navigate to &lt;em&gt;Integrations&lt;/em&gt;, then choose &lt;em&gt;Create Webhooks.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680496364438%2F8c3c58dd-9463-48f4-bff7-bdb0ee7c32d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680496364438%2F8c3c58dd-9463-48f4-bff7-bdb0ee7c32d1.png" alt="Discord channel webhook dashboard."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Your first webhook is automatically created, click on that webhook and &lt;em&gt;Copy Webhook URL&lt;/em&gt;. Remember, Discord webhooks do not require authentication, so it is sensitive. Do not share the URL publicly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680496750490%2Fd6b3e27f-aa7e-49b0-a33e-793658fa8587.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680496750490%2Fd6b3e27f-aa7e-49b0-a33e-793658fa8587.png" alt="The webhook is created, and automatically labeled as "&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configure Discord message channel in Novu
&lt;/h3&gt;

&lt;p&gt;Novu offers a variety of integrations in their store, and Discord is one of them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Navigate to the &lt;em&gt;Integration Store&lt;/em&gt; and activate Discord in the &lt;em&gt;Chat&lt;/em&gt; section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680497892103%2F2e5e4a8b-b996-4414-a264-b0db3e4237e6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680497892103%2F2e5e4a8b-b996-4414-a264-b0db3e4237e6.png" alt="Discord can be integrated with Novu via "&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Navigate to the &lt;em&gt;Notifications&lt;/em&gt; tab, and create a new template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;em&gt;Edit Template&lt;/em&gt; dashboard, go to the &lt;em&gt;Workflow&lt;/em&gt; editor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After &lt;em&gt;Trigger&lt;/em&gt;, add the &lt;em&gt;Chat&lt;/em&gt; step. In the &lt;em&gt;Edit Chat Template&lt;/em&gt;, add the following:&lt;code&gt;A new product has just arrived, check it out at&lt;/code&gt; &lt;a href="https://hungvu.tech/" rel="noopener noreferrer"&gt;&lt;code&gt;store.example.com&lt;/code&gt;&lt;/a&gt;&lt;code&gt;!&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680498113822%2F46885dc1-fadb-421d-aefa-902988eb93eb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680498113822%2F46885dc1-fadb-421d-aefa-902988eb93eb.png" alt="Configure the Chat in notification workflow."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Register a service user with Novu
&lt;/h3&gt;

&lt;p&gt;Normally, Novu is integrated using the flow below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a user in your user database (e.g., Amplication database).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upon user creation, create a Novu &lt;em&gt;subscriber&lt;/em&gt; using your user id and contact information. This subscriber acts as a service user for the Discord notification functionality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upon receiving a specific event on your backend, retrieve your targeted user(s) from the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the user id, &lt;em&gt;trigger&lt;/em&gt; &lt;em&gt;notification templates&lt;/em&gt; via Novu unified API. This whole step can be inside a loop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upon receiving a Trigger, Novu will use the provided user information, go over each workflow then send out a message dedicated to that user across different channels.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although Discord is more of a group, non-personalized channel, there still needs an associated user in each &lt;code&gt;trigger&lt;/code&gt; request. This user does not need to be in your store user database, it can be a pre-configured service user that you create in Novu at the beginning. To do so, fire up a temporary Node.js application and call Novu API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Author: Hung Vu&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Novu&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@novu/node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;novu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Novu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NOVU_API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// The second parameter can be ignored as this&lt;/span&gt;
&lt;span class="c1"&gt;// service user is only there to trigger Discord notification.&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;novu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;identify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;discord&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implement a notification business logic in Amplication backend
&lt;/h3&gt;

&lt;p&gt;For demonstration purposes, Amplication provides a sample service for the e-commerce backend and it will be used in the tutorial. To start, navigate to the &lt;code&gt;server&lt;/code&gt; folder and install Novu's SDK using:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install @novu/node&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, navigate to &lt;code&gt;src&lt;/code&gt;, create a &lt;code&gt;global&lt;/code&gt; folder and put the following two files in there: &lt;code&gt;notification.service.ts&lt;/code&gt; and &lt;code&gt;notification.module.ts&lt;/code&gt;. In Nest.js, that is a way to define reusable modules which can then be imported across different services. In this case, we want to define a notification feature once and reuse it in different business logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * notification.service.ts
 *
 * Author: Hung Vu
 *
 * Discord notification service powered by Novu.
 */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ChatProviderIdEnum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Novu&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@novu/node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;novu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Novu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NOVU_API_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;notifyDiscordCommunity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// You may notice there is no credential configuration for Discord webhook in Novu dashboard, so this step is to assign a URL to your service user.&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;novu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NOVU_SERVICE_USER_ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ChatProviderIdEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Discord&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// This is a Discord webhook URL retrieved in a very first step.&lt;/span&gt;
        &lt;span class="na"&gt;webhookUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DISCORD_WEBHOOK&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="c1"&gt;// Send Discord notification via a service user.&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;novu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;discord&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// This is a user ID created in a previous step.&lt;/span&gt;
          &lt;span class="na"&gt;subscriberId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NOVU_SERVICE_USER_ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * notification.module.ts
 *
 * Author: Hung Vu
 *
 * Export the service to use in other modules.
 */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NotificationService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./notification.service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NotificationService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NotificationService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's revisit the project requirement one more time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You want to have multi-channel notification features so customers know when new products arrive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are two parts to this statement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-channel notification&lt;/strong&gt;: This is out of the scope of our tutorial, but with the unified API of Novu, you can continue to scale horizontally with the provided introductory codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Let customers know when new products arrive&lt;/strong&gt;: This means whenever you add a new &lt;code&gt;product&lt;/code&gt; to the database, Novu is triggered and sends out a Discord notification. To implement this, you need to modify &lt;code&gt;product.module.ts&lt;/code&gt; and &lt;code&gt;product.controller.ts&lt;/code&gt;. The controller is only responsible for REST API requests. GraphQL-wise, &lt;code&gt;product.resolver.ts&lt;/code&gt; needs to be modified, but the general concept is the same.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * product.module.ts
 *
 * Author: Hung Vu
 *
 * A central location to configure modules to be used in product endpoint.
 */&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductModuleBase&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./base/product.module.base&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./product.service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductController&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./product.controller&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductResolver&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./product.resolver&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NotificationModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../global/notification.module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// Import the Notification module, so it can be used&lt;/span&gt;
  &lt;span class="c1"&gt;// in the controller.&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ProductModuleBase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NotificationModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ProductController&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ProductService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ProductResolver&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ProductService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * product.controller.ts
 *
 * Author: Hung Vu
 *
 * Controller for product endpoint, that invoke Novu notification workflow
 * when a new product is successfully added to the database.
 */&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;common&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;swagger&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nestjs/swagger&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;nestAccessControl&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nest-access-control&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./product.service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductControllerBase&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./base/product.controller.base&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NotificationService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../global/notification.service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;swagger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ApiTags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;common&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ProductControllerBase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;nestAccessControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;InjectRolesBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;rolesBuilder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nestAccessControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RolesBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Gain access to NotificationService&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NotificationService&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rolesBuilder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// When a new product is successfully added to the database&lt;/span&gt;
  &lt;span class="c1"&gt;// via REST API POST request, HTTP status code 200 is returned&lt;/span&gt;
  &lt;span class="c1"&gt;// and fire a Discord notification workflow in Novu.&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;HttpCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;notifyDiscordCommunity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notifyDiscordCommunity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that is it, you have successfully integrated Amplication with Novu. With this, whenever a new item arrives, your beloved Discord community will be the first one to learn about it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680512993494%2Fd9073c3e-410e-4d8a-bc6d-c99325bc5474.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680512993494%2Fd9073c3e-410e-4d8a-bc6d-c99325bc5474.png" alt="A POST request successfully adds new product to the database, and trigger Discord notification."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Depending on the scope of what you are trying to achieve, developing a production-ready application is not always a straight line to think of. That said, with the introduction of Amplication and Novu, both platforms excel in their own job and provide great solutions to speed up your development process while still maintaining a high-quality and human-readable codebase. All comes at no cost if self-hosted is your choice, but if you prefer delegating the hassle of managing bare metal infrastructure, both Amplication and Novu also provide cloud-based options.&lt;/p&gt;

&lt;p&gt;This article is just the tip of the iceberg, it is highly recommended to take a look at the product documentation and see what they can do in the real world.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.amplication.com/" rel="noopener noreferrer"&gt;Amplication's documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.novu.co/overview/introduction/" rel="noopener noreferrer"&gt;Novu's documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/hunghvu/integrate-amplication-with-novu" rel="noopener noreferrer"&gt;The repository for the codebase of this tutorial&lt;/a&gt; is available on GitHub, and &lt;a href="https://discord.com/invite/novu" rel="noopener noreferrer"&gt;Novu's team is always available in Discord to answer any of your questions&lt;/a&gt;, so check them out!&lt;/p&gt;




&lt;p&gt;If you find this article to be helpful, I have some more for you!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/is-harvester-a-good-hypervisor-for-a-beginner-my-hands-on-experience" rel="noopener noreferrer"&gt;Is Harvester a good hypervisor for a beginner? My hands-on experience&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/amplication-vs-supabase-vs-appwrite-baas-comparison" rel="noopener noreferrer"&gt;Amplication vs Supabase vs Appwrite, for an effortless back end&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/advanced-github-actions-conditional-workflow" rel="noopener noreferrer"&gt;Advanced GitHub Actions - Conditional Workflow ❓&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, let's connect!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.linkedin.com/in/hunghvu/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/hunghvu" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/hunghvu_dev" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>🔧I tried out Harvester HCI for the homelab, and it is an interesting solution</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Thu, 11 May 2023 18:33:19 +0000</pubDate>
      <link>https://forem.com/hunghvu/i-tried-out-harvester-hci-for-the-homelab-and-it-is-an-interesting-solution-3ii1</link>
      <guid>https://forem.com/hunghvu/i-tried-out-harvester-hci-for-the-homelab-and-it-is-an-interesting-solution-3ii1</guid>
      <description>&lt;p&gt;When I notice there are old computers collecting dust in my place, I ask about the possibility of repurposing them. With that in mind, I start building a homelab as a hobby. Each device can host one service, but I decide to virtualize my infrastructure to efficiently utilize every bit of hardware I have. There are popular solutions such as Proxmox, ESXI, and XCP-ng, but to make it more fun, I want to try out a more obscure solution. After looking around, Harvester, an open-source Hyperconverged Infrastructure, is the choice for my setup.&lt;/p&gt;

&lt;p&gt;In this article, I will go over my very first experience with Harvester on a cluster of 3 management nodes. Keep in mind though, this article is more about documenting my experience, rather than being a proper tutorial, so please treat it with a grain of salt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hardware
&lt;/h2&gt;

&lt;p&gt;When using a hypervisor type 1 such as Harvester, users should pay attention to the hardware of their infrastructure, because there are a plethora of compatibility issues that are lurking around, so what I experience may very well be isolated to my setup. Also, these are repurposed computers, so the specifications are nowhere near the recommendation from the Harvester team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node 1, an old laptop:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;CPU: Intel I7-7700HQ&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RAM: 16GB&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NIC: Realtek RTL8111 (management NIC)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Storage: 1 TB NVME SSD (used for both Harvester and VM data)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Node 2, a medium form factor computer:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;CPU: Intel I5-6500&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RAM: 8GB&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NIC 1: Intel I219-LM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NIC 2: Realtek RTL8125 (&lt;a href="https://linuxreviews.org/Realtek_RTL_8125"&gt;not rev. A or B, only 8125&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NIC 3: Intel X710 DA-2 (management NIC)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Storage: 128 GB SATA SSD (used for both Harvester and VM data)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Node 3, a mini computer:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;CPU: Intel I5-6500T&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RAM: 16GB&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NIC: Intel I219-LM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Storage: 256 GN NVME SSD (used for both Harvester and VM data)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Harvester installation experience
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The basic steps
&lt;/h3&gt;

&lt;p&gt;The Harvester team has excellent documentation on initial installation, but being a geek, I decided to initially skip that to have a true first-hand experience. Overall, the installation process is fairly standard, but with some catches, more below.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Download the ISO:&lt;/strong&gt; This confused me a little bit, because the very first "Get Started" on the Harvester website did not lead to an installation, but rather, it is a download button at the bottom of the page. Also, the switch leads to the Harvester GitHub repository, not a direct download.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Ft5x2EB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683510616936/c2f7749c-0e7f-4a9e-a34e-7ad3b77cd5e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Ft5x2EB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683510616936/c2f7749c-0e7f-4a9e-a34e-7ad3b77cd5e2.png" alt="Download Harvester ISO from their GitHub repository." width="355" height="224"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a bootable USB drive using Rufus:&lt;/strong&gt; There is not much about this step, because Rufus can burn the image without any issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install Harvester in the other Node 1 &amp;gt; Node 2 &amp;gt; Node 3:&lt;/strong&gt; Each node takes about 10 minutes to install. Perhaps there is a way to install them all at once (IaC?), if so, it will scale much better.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sR8DytLN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683511217640/d79c7d9d-7d8d-457d-9d30-1d9f292e7930.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sR8DytLN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683511217640/d79c7d9d-7d8d-457d-9d30-1d9f292e7930.png" alt="Harvester displays the installation process." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The weird first-login issue?
&lt;/h3&gt;

&lt;p&gt;Here is a thing, although the image above shows the name, &lt;strong&gt;Rancher&lt;/strong&gt;, I did not notice that, but bear with me and keep that in mind for a bit. When first installing Harvester, one step was to define a static &lt;em&gt;VIP (Virtual IP for management)&lt;/em&gt;. Well, it only shows an acronym and not knowing what that is, I essentially left it at default (DHCP). When the installation finished, I logged into the first node using its static &lt;em&gt;node IP&lt;/em&gt; and was greeted with a login screen ... &lt;strong&gt;from Rancher?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I did not know about Rancher at that point, so here came another confusion. Later on, I also noticed that the branding of that page actually &lt;em&gt;randomly changes between Harvester and Rancher branding when refreshed (F5)&lt;/em&gt;. Also, it asks for a &lt;strong&gt;Bootstrap password&lt;/strong&gt; and that is not the one I chose during the Harvester setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i8KYaLXJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683512282335/dc6442fb-a8d2-4110-9c1d-c8443447147e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i8KYaLXJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683512282335/dc6442fb-a8d2-4110-9c1d-c8443447147e.png" alt="A wrong welcome to Harvester login page." width="451" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this being nowhere documented, I dived into GitHub issues and found &lt;a href="https://github.com/harvester/harvester/issues/1479"&gt;#1479&lt;/a&gt;. I learned the bootstrap password is &lt;code&gt;admin&lt;/code&gt;, which then allowed me to log in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v7SDtMHC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683512401180/e67aad47-26f9-4984-97d7-857801c3ec4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v7SDtMHC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683512401180/e67aad47-26f9-4984-97d7-857801c3ec4b.png" alt="Rancher dashboard." width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And ... here is the &lt;strong&gt;Rancher&lt;/strong&gt; dashboard. The best part is, I was not supposed to be here in the first place. This happened because I did not set up VIP for my cluster, so the Rancher dashboard and this whole weird first login behavior manifested. That said, there is no trivial way to modify management IP after Harvester installation, so I needed to reinstall the whole node. At the time of writing, I have an idea of Rancher's role already (albeit limited), but still, I could not find an explanation for the login behavior.&lt;/p&gt;

&lt;p&gt;After setting up the VIP, I was able to create the first account and sign in to the Harvester dashboard (located at VIP) without an issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Harvester platform experience
&lt;/h2&gt;

&lt;p&gt;Aside from the log-in issue that I mentioned, there were several pain points that I faced when trying out Harvester. Were they really pain points though? I'm not certain, and there is a chance they are intended behaviors. This is my first time trying out the platform after all. Anyway, here are some of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  The failover functionality is clunky
&lt;/h3&gt;

&lt;p&gt;With my setup, I have 3 nodes. Initially, only Node 1 is a management node, but after the other two nodes join the cluster, they were automatically promoted to a management one. Three nodes are required for the promotion to form a high-availability cluster. In a Harvester cluster of three, the fault tolerance is one. Well, the theory is that, but in practice, it is not as "high-availability" as I expected.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If node 1 is down, my cluster is effectively down (VIP - not ready; VMs, dashboard, and remaining nodes are not accessible).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From a power-off state, if only nodes 1 and 3 are turned on, then node 2 is &lt;em&gt;cordoned&lt;/em&gt;. Nothing wrong there, but if I turn on node 2 afterward, then node 3 is &lt;em&gt;cordoned&lt;/em&gt;. I have to reset node 3 so all are &lt;em&gt;ready&lt;/em&gt; again. The same behavior applies when only nodes 1 and 2 are turned on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From the power-off state, the nodes often cannot properly form a cluster after starting up (always &lt;em&gt;not ready&lt;/em&gt;). This can be fixed with a few tries of rebooting the whole cluster (via console, F12).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When the cluster is working, but node 2 or 3 is cordoned, the whole cluster often becomes unstable. It takes ages to access the Harvester dashboard, VMs become unresponsive, and actions are stuck in &lt;em&gt;in-progress&lt;/em&gt;. Resources (capacity) spike sky-high and are more or less stuck there. I guess this has something to do with live migration. If the node is online again, the resources will gradually decrease and the cluster is usable again. To emphasize, this behavior often happens, but not always. The picture below was when one node just came back from being cordoned.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DbwnfQVG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683784941246/85a47752-6dcf-4f16-95ed-ebd1a7f7797e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DbwnfQVG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683784941246/85a47752-6dcf-4f16-95ed-ebd1a7f7797e.png" alt="Harvester CPU is overused during a live migration scenario." width="748" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And compared to after it got settled down.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L31pL6aA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683784987226/1d667623-d842-4b00-9e70-b4c0637fe640.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L31pL6aA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683784987226/1d667623-d842-4b00-9e70-b4c0637fe640.png" alt="Harvester CPU is used normally when all nodes are up." width="742" height="309"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Some essential processes are not trivial in Web UI, for example, the update process
&lt;/h3&gt;

&lt;p&gt;There does not seem to be a &lt;em&gt;Check for Update&lt;/em&gt; button. Only when a new release arrives, a small button appears in the top right corner of the &lt;em&gt;Dashboard&lt;/em&gt; tab that provides the update functionality. The update is also very slow even with my 1 gigabit connection and SSD in the nodes. It took me about 90 minutes to update nodes 1 and 2, but node 3 never got updated. My cluster has been working normally under this condition though (not considering the issues mentioned in this article).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---w5xYSQP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683785789769/86d22b7e-736d-4bfc-b01a-f69afb84047b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---w5xYSQP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683785789769/86d22b7e-736d-4bfc-b01a-f69afb84047b.png" alt="Harvester node 3 could not be upgraded." width="765" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This issue can be generalized as a lack of essential UX components like an official way to power off or reboot the cluster, view SMART data for hosts, and more. They certainly can be done in a headless manner or directly using the node console, but those might not be user-friendliest depending on your preference.&lt;/p&gt;

&lt;h3&gt;
  
  
  System-wide logging capability is rather limited out of the box
&lt;/h3&gt;

&lt;p&gt;When facing problems, my first thought was to look at the logs to troubleshoot. That's when I noticed it does not even exist in the admin dashboard. I mean something equivalent to &lt;code&gt;syslog&lt;/code&gt; or &lt;code&gt;dmesg&lt;/code&gt; to be specific, because Harvester &lt;strong&gt;does have&lt;/strong&gt; monitoring and logging capabilities via Events, Metrics, or Grafana. The first two are rather limited, while Grafana has been hit-or-miss for me. I'm often not able to view data in Grafana for some reasons (as errors shown in the picture below, plus some other random ones).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Some errors that prenvent me from using Grafana. They randomly happens.&lt;/span&gt;
Templating [job]
Error updating options: no elements in sequence

Templating
Templating init failed Couldn't find variable with id:instance

502 Bad Gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gnDf-4Ti--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683817464942/8e1e814f-1694-4e18-ba4a-81f150a45964.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gnDf-4Ti--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683817464942/8e1e814f-1694-4e18-ba4a-81f150a45964.png" alt="Bad Gateway error in Grafana." width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Harvester consumes a lot of resources
&lt;/h3&gt;

&lt;p&gt;This by itself is not necessarily an issue, but when compared to other solutions like Proxmox or XCP-ng, Harvester does require a beefy device to run on. Considering it reserves about 6 cores on a 4-core 8-thread node, I suppose an 8-core 16-thread node is a better starting point, which is in line with the Harvester team recommendation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1M42iEfc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683787173297/11ad4868-2986-4a97-b5a4-e86170b2474f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1M42iEfc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683787173297/11ad4868-2986-4a97-b5a4-e86170b2474f.png" alt="Harvester hosts consume a lot of resources." width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Almost all my nodes are over-committed upon fresh installation (no VMs, or configuration changes), but the cluster is still fairly responsive under this condition. The downside is, it forces my devices to run at full power and inherently increases power consumption and heat dissipation. They are not deal breakers by any means though.&lt;/p&gt;

&lt;h3&gt;
  
  
  The OS is read-only, but still modifiable to a certain extent
&lt;/h3&gt;

&lt;p&gt;Harvester is openSUSE-based, so I thought additional packages can be installed directly on nodes via SSH or direct console. However, Harvester enforces immutability to most locations by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;rancher@harvester:~&amp;gt; sudo zypper install smartmontools
The target filesystem is mounted as read-only. Please make sure the target filesystem is writable.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, there are a few possibilities to overcome this immutability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The installation image can be customized.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using cloud-config to apply boot-time changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Temporarily enable the read-write mode for the system.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have not tried any of them, however, I needed to modify the system for one reason. My node 1 is a laptop, so when the lid is closed, the system will be suspended. I don't want to keep the lid open all day so I had to disable this suspension feature. Luckily, this was not restricted by the immutability of Harvester.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Harvester only has Vim by default.&lt;/span&gt;
&lt;span class="gh"&gt;# This was done via direct console access on the laptop (F12).&lt;/span&gt;

&lt;span class="gh"&gt;# Step 1: Access logind.conf.&lt;/span&gt;
sudo vim /etc/systemd/logind.conf

&lt;span class="gh"&gt;# Step 2: Make sure the following rows use the "ignore" option, and remove the "#" sign.&lt;/span&gt;
HandleLidSwitch=ignore
HandleLidSwitchExternalPower=ignore
HandleLidSwitchDocked=ignore
LidSwitchIgnoreInhibited=no

&lt;span class="gh"&gt;# Step 3: Mask some system options.&lt;/span&gt;
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

&lt;span class="gh"&gt;# Side note: There are many online discussions regarding on making the laptop not suspended when its lid is close. It seems the answer varies based on your device. On my laptop, the above sequence works, but may not be applicable to yours.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;In this article, I went over multiple issues I face when trying out Harvester.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Were they annoying? Kind of.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Were they fun to go through? Yes!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is Harvester a good option for a beginner? I think so.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At default, Harvester is fairly straightforward, but it certainly can become complicated on an established infrastructure. Getting my hands dirty is how I learn things over time, so for homelab purposes, it is a good choice. In the next article, I will go over my experience virtualizing the firewall on Harvester. Spoiler, it can handle my Gigabit connection easily, but with some catches. Stay tuned for that!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U_aNGqtQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683819542756/5ef72a18-82b3-4c09-8394-c1c9d1c8c06a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U_aNGqtQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1683819542756/5ef72a18-82b3-4c09-8394-c1c9d1c8c06a.png" alt="OpenWRT VM on Harvester can handle 1 gigabit connection." width="762" height="161"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;This article was first published at &lt;a href="https://hungvu.tech/is-harvester-a-good-hypervisor-for-a-beginner-my-hands-on-experience"&gt;hungvu.tech: Is Harvester a good hypervisor for a beginner? My hands-on experience&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find this article to be helpful, I have some more for you!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/chromeos-flex-have-i-just-opened-a-can-of-worms"&gt;ChromeOS Flex, have I just opened a can of worms?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/is-amd-gpu-better-than-nvidia-on-linux"&gt;Is AMD GPU better than Nvidia on Linux? It depends&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/amplication-vs-supabase-vs-appwrite-baas-comparison"&gt;Amplication vs Supabase vs Appwrite, for an effortless back end&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, let's connect!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.linkedin.com/in/hunghvu/"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/hunghvu"&gt;GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/hunghvu_dev"&gt;Twitter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>beginners</category>
      <category>linux</category>
      <category>learning</category>
    </item>
    <item>
      <title>🍂Simplify the back end with low code solutions: Amplication, Supabase, and Appwirte overview</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Wed, 19 Apr 2023 15:36:10 +0000</pubDate>
      <link>https://forem.com/hunghvu/simplify-the-back-end-with-low-code-solutions-amplication-supabase-and-appwirte-overview-4ia7</link>
      <guid>https://forem.com/hunghvu/simplify-the-back-end-with-low-code-solutions-amplication-supabase-and-appwirte-overview-4ia7</guid>
      <description>&lt;p&gt;The modern web space is built up on time and resources of uncountable numbers of contributors over decades. There is a high chance that the tasks you are trying to achieve have been done by someone, somewhere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Cioj62o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.explainxkcd.com/wiki/images/d/d7/dependency.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Cioj62o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.explainxkcd.com/wiki/images/d/d7/dependency.png" alt="XKCD: Dependency." width="385" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When talking about websites, people think about the front end and the back end. Each has its own ecosystem and associate frameworks to build up the product, but you, as a developer, still need to tie everything together. This leads to a question, what if there is an existing product that helps you bind everything together out of the box? In the case of the back end, management systems such as headless content management systems, and learning management systems come into play, and back-end-as-a-service comes into play.&lt;/p&gt;

&lt;p&gt;This article focuses on a comparison between back-end-as-a-service and headless content management systems. It is a continuation of the previous two that dived into headless CMS, so if you are not aware of them, go ahead and check them out!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/headless-cms-for-portfolio-and-blogs"&gt;Headless content management introduction&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/strapi-vs-directus-vs-payload-headless-cms-comparison"&gt;Strapi vs Directus vs Payload, Headless content management comparison&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is a headless content management system (headless CMS)?
&lt;/h2&gt;

&lt;p&gt;Imagine you are a creator, and you create content on a daily basis (e.g., similar to the article you are reading), at some points, you are going to have dozens if not hundreds, and more pieces in your pocket. To &lt;strong&gt;centrally&lt;/strong&gt; manage them, you need a management system specifically designed for content in this case, and it is a headless CMS. In this case, the front-end team is responsible for the presentation layer, and they can retrieve information from the headless CMS to display, be it videos, images, text, and more.&lt;/p&gt;

&lt;p&gt;Unlike traditional CMS systems that combine content creation, storage, and delivery into a single software, a headless CMS separates content management from content delivery. In other words, it provides an API for developers to access the content, which can then be delivered through any platform or device, such as websites, mobile apps, or IoT devices. With a single source of truth, developers have no need to manually modify content in their code, and effectively, create a separation of concerns.&lt;/p&gt;

&lt;p&gt;This decoupling of the content management and delivery layers provides more flexibility and freedom to developers and content creators, allowing them to create and manage content independently of any specific presentation layer. It also enables developers to use their preferred front-end technologies and frameworks, giving them more control over the user interface and user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Back-end-as-a-Service (BaaS)?
&lt;/h2&gt;

&lt;p&gt;BaaS is a type of service that provides developers with a complete server-side infrastructure for building and deploying applications across multiple platforms (e.g., desktop apps, websites, and mobile apps). It allows developers to focus on the client-side development of their applications, while the BaaS takes care of the back-end infrastructure. Usually, BaaS is a cloud service, but as time goes on, more self-hosted solutions have appeared on the market.&lt;/p&gt;

&lt;p&gt;A BaaS typically offers a set of pre-built services and features, such as user authentication, access control list, workflow, and most fundamentally, database management and creation. These services can be accessed through a web-based dashboard or an API, which developers can integrate into their applications. If you are familiar with the object-relational mapper, then in a sense, BaaS is a GUI version of that, plus a lot more functionalities to build a full-featured back-end.&lt;/p&gt;

&lt;p&gt;Using BaaS developers to accelerate the development process by reducing the amount of time and resources needed to build and maintain the back-end infrastructure. This can result in faster time-to-market for applications and lower development costs. BaaS also handle the scalability and availability of the back-end infrastructure, ensuring that the applications can handle high traffic and maintain high uptime.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the differences between headless CMS and BaaS?
&lt;/h2&gt;

&lt;p&gt;Both headless CMS and BaaS provide a battle-tested and full-featured back end out of the box. In fact, many of their functionalities overlap, so what makes the difference here?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Focus&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Headless CMS focuses on providing a flexible content management system that can be used to manage content for different channels and platforms. This means their data usually are unstructured like articles, images, and videos. Besides, there is almost always a user-friendly dashboard (e.g., for creators) so it greatly reduces the learning curve for non-technical users.&lt;/p&gt;

&lt;p&gt;BaaS, meanwhile, focuses on providing a GUI approach (little to no code) to build a back end. The data can be unstructured, but more than often, BaaS is used to create a complex structured application data model for tasks such as transactions, user profiles, and so on. These data may not even be used on the front end, instead, the other back end is its user. BaaS targets developers, so end-users usually do not know about BaaS's existence.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Customization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both headless CMS and BaaS are very customizable. However, headless CMS focuses more on content creation-relation functionalities out of the box such as a WYSIWYG editor and content modeling, so other functionalities such as payment processing might need to be manually integrated. That said, many headless CMS has an existing method to integrate, via plugins for example. In contrast, BaaS as a full-featured package usually includes everything out of the box.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both can provide cloud and self-hosted solutions. Usually, a self-hosted solution is only available when the product is open-source. When talking about cloud cost though, CMS, for the most part, follows a subscription per person model (e.g., $5/user/month). Meanwhile, the BaaS pricing model can vary a lot, from subscription, to pay per uptime, per request, and so on. Essentially, it is the same as traditional infrastructure-as-a-service cloud provides.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What are some open-source BaaS solutions?
&lt;/h2&gt;

&lt;p&gt;There are various BaaS providers on the market, but not many are open-source, so let's focus on them today.&lt;/p&gt;

&lt;h3&gt;
  
  
  Amplication
&lt;/h3&gt;

&lt;p&gt;Amplication is a relatively new open-source BaaS provider that aims to simplify the development process by providing a low-code platform for building and deploying applications. In fact, it just reached version 1.0 (production ready) in September 2022.&lt;/p&gt;

&lt;p&gt;Amplication supports PostgreSQL, MySQL, MongoDB, and a variety of integrations, but most notably, &lt;strong&gt;it generates the whole back end with&lt;/strong&gt; a &lt;strong&gt;human-readable NestJS codebase&lt;/strong&gt; for you. You do not run Amplication as a service (or use it as a dependency), instead, you use Amplication to generate codes for you. You own the code, and it can be hosted wherever you prefer. This feature is the one and only in an open-source market (so not counting proprietary products like AWS Amplify).&lt;/p&gt;

&lt;p&gt;Amplication provides both cloud and self-hosted solutions. There are a few points.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The price is fairly steep. Aside from a customized enterprise plan, only two plans Free and Pro exist. Free is slightly feature-limited, and Pro costs $320/month (billed annually) at the time of writing. This indicates that small business may not be their targetted segment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is unclear whether the self-hosted option is feature-limited.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you are a business customer in a regulated sector, there is no public &lt;strong&gt;Compliance&lt;/strong&gt; statement on their website, so you may need to reach out to their customer support first to confirm the clearance.&lt;/p&gt;

&lt;p&gt;However, as a relatively new platform, Amplication is still evolving and may not have all the features and integrations of more established BaaS providers. Still, it has the potential to be a leader in a low-code solution segment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yBUelhZZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1681889583961/a2a25230-9465-479b-9f0b-3edee5ec69ff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yBUelhZZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1681889583961/a2a25230-9465-479b-9f0b-3edee5ec69ff.png" alt="Amplication road map." width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Appwrite
&lt;/h3&gt;

&lt;p&gt;Appwrite is another open-source BaaS provider that offers a range of back-end services for building web and mobile applications. Coincidentally, its first production-ready version, v1.0, was also released back in September 2022. Appwrite provides features such as user authentication, database storage, file storage, serverless functions, and email sending.&lt;/p&gt;

&lt;p&gt;Unlike Amplication, you integrate Appwrite to your back end with SDK. This may sound confusing because BaaS should be responsible for the whole back end in the first place, isn't it? Yes, although it handles all business logic for your application, Appwrite is a dependency of your application that you have to manually initialize and configure. This is another form of BaaS.&lt;/p&gt;

&lt;p&gt;When talking about Appwrite, the product has three strengths. They might not be unique, but many other solutions do not have them all at the same time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Support for multiple platforms and programming languages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Serverless functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real-time data subscription.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That said, Appwrite abstracts the database, meaning it is handled internally and only the NoSQL-like interface is exposed, so you have less flexibility in this regard.&lt;/p&gt;

&lt;p&gt;Appwrite also provides both cloud and on-premise options. However, their cloud service is still in private beta, and there is no official pricing at the moment. The on-premise, or self-hosted, is free and full-featured, but certainly, it costs in the overhead maintenance.&lt;/p&gt;

&lt;p&gt;And the same Amplication, Appwrite does not have any public statement about &lt;strong&gt;Compliance&lt;/strong&gt;, so you may have to reach out to their support for clarification on this matter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V2iY81nz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1681890917972/48eadb82-f10c-4ce3-aee6-cd3ef20a2f92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V2iY81nz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1681890917972/48eadb82-f10c-4ce3-aee6-cd3ef20a2f92.png" alt="Appwrite feature list." width="800" height="701"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Supabase
&lt;/h3&gt;

&lt;p&gt;Founded in 2020, in roughly the same period as Amplication and Appwrite, however, Supabase is arguably the most established open-source solution among the three. In a sense, Supabase is a direct equivalent and close to feature-parity with Appwrite, offering a self-hosted option, plus a mature cloud platform that offers enterprise support and an even greater amount of integrations. However, Supabase only supports PostgreSQL, the opposite of the NoSQL approach in Appwrite.&lt;/p&gt;

&lt;p&gt;Regarding the cloud platform price, Supabase has a Free plan, a Pro plan, and a customized Enterprise plan. There are a few points to mention.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Unlike Amplication, which generates code and you are responsible for the hosting solution, Supabase provides integration and hosting services for you. The Pro plan costs $25 per month per project. That said, this is a different pricing model compared to Amplication, so they are not comparable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;They also have add-ons for the subscription, and the compute instance can be customized to your need. These will change the subscription fee though.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supabase does not seem to have usage caps on their Pro plan, so if you accidentally exceed the limit, prepare your pocket.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the topic of &lt;strong&gt;Compliance&lt;/strong&gt;, Supabase has official support for SOC2 Type 2. There is no mention of other compliances, but they certainly do not support HIPAA and PCI (learned from their ToS and confirmed by a support agent).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--okPUiWbO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1681893508556/9847b1e7-2737-456d-966d-87a5ca7e581a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--okPUiWbO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1681893508556/9847b1e7-2737-456d-966d-87a5ca7e581a.png" alt="Supabase security and compliance statement." width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What are some open-source headless CMS?
&lt;/h2&gt;

&lt;p&gt;The articles below dived deep into 12 different solutions on the market. Do feel free to check them out if you are interested in this topic!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/headless-cms-for-portfolio-and-blogs"&gt;Headless content management introduction&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/strapi-vs-directus-vs-payload-headless-cms-comparison"&gt;Strapi vs Directus vs Payload, Headless content management comparison&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;The article gives you an introduction to the concept of headless CMS, BaaS, the differences between them, and some open-source BaaS solutions on the market. That said, this article is just an introduction to the topic, the tip of the iceberg you can say, so there is a lot more to learn about. If you notice, the three mentioned BaaS all have their trade-off, so make sure to do deeper research before you decide to commit to one solution. Hopefully, this article was able to help you be aware of these fascinating products, and successfully in improving your developer experience and productivity.&lt;/p&gt;




&lt;p&gt;This article was originally published at: &lt;a href="https://hungvu.tech/amplication-vs-supabase-vs-appwrite-baas-comparison"&gt;Amplication vs Supabase vs Appwrite, for an effortless back end&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find this article to be helpful, I have some more for you!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/chromeos-flex-have-i-just-opened-a-can-of-worms"&gt;ChromeOS Flex, have I just opened a can of worms?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/how-to-set-up-bitwarden-enterprise-sso-via-oidc-with-google"&gt;How to set up Bitwarden Enterprise SSO via OIDC with Google?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/cloudflare-turnstile-and-wordfence-2fa-break-wordpress-login-flow-how-to-fix-it"&gt;Cloudflare Turnstile and Wordfence 2FA break WordPress login flow, how to fix it?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/is-amd-gpu-better-than-nvidia-on-linux"&gt;Is AMD GPU better than Nvidia on Linux? It depends&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, let's connect!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.linkedin.com/in/hunghvu/"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/hunghvu"&gt;GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/hunghvu_dev"&gt;Twitter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>🤯Twitter Recommendation Algorithm is now open sourced</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Sat, 01 Apr 2023 13:51:51 +0000</pubDate>
      <link>https://forem.com/hunghvu/twitter-recommendation-algorithm-is-now-open-sourced-3p4m</link>
      <guid>https://forem.com/hunghvu/twitter-recommendation-algorithm-is-now-open-sourced-3p4m</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This requires a recommendation algorithm to distill the roughly 500 million Tweets posted daily down to a handful of top Tweets that ultimately show up on your device’s For You timeline.&lt;/p&gt;

&lt;p&gt;The pipeline above runs approximately 5 billion times per day and completes in under 1.5 seconds on average. A single pipeline execution requires 220 seconds of CPU time, nearly 150x the latency you perceive on the app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Along side with OpenAI, I personally think this is one of an important moment in the computing community as no one would ever guess a global-scale algorithm such as Twitter's Recommendation becomes open-sourced. Based on their engineer blog post, it is not out of reach to say the code base literally costs hundred thousands if not millions a day to run. How do you feel about this moment?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Twitter's engineer blog&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://blog.twitter.com/engineering/en_us/topics/open-source/2023/twitter-recommendation-algorithm" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--sDIEE6jE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.cms-twdigitalassets.com/content/dam/blog-twitter/engineering/en_us/main-template-assets/Eng_EXPLORE_Pink.png.twimg.768.png" height="288" class="m-0" width="768"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://blog.twitter.com/engineering/en_us/topics/open-source/2023/twitter-recommendation-algorithm" rel="noopener noreferrer" class="c-link"&gt;
          Twitter's Recommendation Algorithm
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Twitter Apache Thrift is an open-source, standalone, lightweight, data encoding library. In this blog post, we share the library we built so iOS developers outside Twitter can start using Thrift data.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--OnKLeezV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.twitter.com/etc/designs/blog-twitter/public/img/favicon.ico" width="48" height="48"&gt;
        blog.twitter.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;GitHub repository&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/twitter"&gt;
        twitter
      &lt;/a&gt; / &lt;a href="https://github.com/twitter/the-algorithm"&gt;
        the-algorithm
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Source code for Twitter's Recommendation Algorithm
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Twitter Recommendation Algorithm&lt;/h1&gt;
&lt;p&gt;The Twitter Recommendation Algorithm is a set of services and jobs that are responsible for constructing and serving the
Home Timeline. For an introduction to how the algorithm works, please refer to our &lt;a href="https://blog.twitter.com/engineering/en_us/topics/open-source/2023/twitter-recommendation-algorithm" rel="nofollow"&gt;engineering blog&lt;/a&gt;. The
diagram below illustrates how major services and jobs interconnect.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/twitter/the-algorithmdocs/system-diagram.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---ntOj60T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/twitter/the-algorithmdocs/system-diagram.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;These are the main components of the Recommendation Algorithm included in this repository:&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Feature&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/twitter/the-algorithmsrc/scala/com/twitter/simclusters_v2/README.md"&gt;SimClusters&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Community detection and sparse embeddings into those communities.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/twitter/the-algorithm-ml/blob/main/projects/twhin/README.md"&gt;TwHIN&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Dense knowledge graph embeddings for Users and Tweets.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/twitter/the-algorithmtrust_and_safety_models/README.md"&gt;trust-and-safety-models&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Models for detecting NSFW or abusive content.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/twitter/the-algorithmsrc/scala/com/twitter/interaction_graph/README.md"&gt;real-graph&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Model to predict likelihood of a Twitter User interacting with another User.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;

&lt;td&gt;&lt;a href="https://github.com/twitter/the-algorithmsrc/scala/com/twitter/graph/batch/job/tweepcred/README"&gt;tweepcred&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Page-Rank algorithm for calculating Twitter User reputation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;

&lt;td&gt;&lt;a href="https://github.com/twitter/the-algorithmrecos-injector/README.md"&gt;recos-injector&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Streaming event processor for building input streams for &lt;a href="https://github.com/twitter/GraphJet"&gt;GraphJet&lt;/a&gt; based services.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;

&lt;td&gt;&lt;a href="https://github.com/twitter/the-algorithmgraph-feature-service/README.md"&gt;graph-feature-service&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Serves graph features for a directed pair of Users (e.g. how many of User A's following liked Tweets from User B).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Candidate Source&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/twitter/the-algorithmsrc/java/com/twitter/search/README.md"&gt;search-index&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/twitter/the-algorithm"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>cloud</category>
      <category>discuss</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Moving from classic Linux distro to ChromeOS Flex? Here was what I found &lt;🪲&gt;</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Sun, 12 Mar 2023 21:07:14 +0000</pubDate>
      <link>https://forem.com/hunghvu/moving-from-classic-linux-distro-to-chromeos-flex-here-was-what-i-found--eek</link>
      <guid>https://forem.com/hunghvu/moving-from-classic-linux-distro-to-chromeos-flex-here-was-what-i-found--eek</guid>
      <description>&lt;p&gt;I have never been a Linux guru, but as a casual user, I love playing around with the operating system from time to time. At one point, I decided that Pop!_OS (or PopOS) is a stopping point after a long distro-hopping journey. It's a great all-in-one package with several core features ready to go out of the box: Desktop customization, dedicated GPU supports, Bluetooth codec supports, and whatnot, you name it! I'm satisfied with PopOS, and I still do, but a question eventually arose.&lt;/p&gt;

&lt;p&gt;When coming to laptop usage, 95% of my time spends on the browser. I boot up the laptop, open Firefox, search the web, consume media, and write articles like what you are reading now. For other more intensive tasks like gaming, coding, or so, my PC is responsible for them. Do I need a full-fledged highly customizable operating system for the laptop? Probably not, so ChromeOS came to my mind. In July 2022, Google announced a general availability for ChromeOS Flex (formerly CloudReady), a version that can be installed on non-Chromebook devices (any computer, in other words). In a sense, ChromeOS Flex is bleeding edge so it is expected to be somewhat unstable at the beginning, and I decided to wait until early 2023 to try it out, and here I am.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why did ChromeOS come to my mind?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Minimalism&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
ChromeOS sacrifices lots of customizability but provides a decent set of Google applications out of the box. Chrome is in the name of the OS itself, so that alone covers 95% of my usage. Considering I have been working with different IT systems daily, I suppose having to tweak some Linux configurations outside of work hours is not that desirable. Don't get me wrong, playing around with technology has always been my hobby, but there is a line for when I just need to get things done, and ChromeOS provides that simple and minimalistic experience. That said, Linux on ChromeOS (or Crostini) is there, so I can always fire up the Linux environment if needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lightweight&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The minimalistic approach inherently means no bloatware comes with ChromeOS. It consumes about 20 GB of storage and 1.7 GB of RAM out-of-the-box. Nothing spectacular though, as PopOS is relatively the same. Both ChromeOS and Linux blow Windows 10/11 out of water because Microsoft somehow makes their OS consumes more than 60 GB and storage and around 6 GB of ram with a fresh installation. Technically, this resource consumption is negligible to my laptop specification (AMD Ryzen 7 5825U CPU, Solidigm P41 Plus 2TB SSD, and 64GB of RAM), but it is always better to remove those data-harvesting programs when possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When considering a fresh installation, ChromeOS is arguably more secure than PopOS or other Linux distros. Minimalism greatly reduces the attack surface and ChromeOS was designed with security in mind using sandboxing and limited user write access. I'm by no means an expert on cybersecurity matters, but there are lots of resources online regarding this topic, and &lt;a href="https://chromium.googlesource.com/chromiumos/docs/+/master/security/chromeos_security_whitepaper.md"&gt;Security in Chrome OS&lt;/a&gt; is an example.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  And my first try? Well, it was worse than I expected
&lt;/h2&gt;

&lt;p&gt;Living on the edge is nothing new to me, eventually, things will work out. That is, assuming the fundamentals are satisfied, at least to a certain degree. The stable, beta, and canary versions are 110, 111, and 112 respectively at the time of writing. In my case, I tried out ChromeOS Flex using all those versions on three different laptop models (from Dell, HP, and Asus), and all exhibited breaking bugs in one way or another. What were they then?&lt;/p&gt;

&lt;h3&gt;
  
  
  Network chipset compatibility
&lt;/h3&gt;

&lt;p&gt;At the moment, ChromeOS Flex does not support Intel AX210 and Mediatek MT7921 wireless modules. Unfortunately, two of my laptops have these so I could not even start the OS installation process because ChromeOS Flex requires Internet to set up. That said, these are documented in &lt;em&gt;ChromeOS Flex Help - Known Issues&lt;/em&gt;, so it is acceptable to me. However, being a PC hobbyist, I have a plethora of computer components lying around, so I decided to try other modules which yielded the following results.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Intel AC3168 (unknown revision): Recognized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Intel AC7265 (unknown revision): Bluetooth was recognized, but no Wi-Fi&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Intel AX200 (unknown revision): Recognized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Realtek - wireless module (missing label, unknown model): Unrecognized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Realtek RTL8118 - USB to 1 Gbe ethernet: Rev 3000 was recognized, while rev3100 was a hit or miss (might be due to USB implementation)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are widely used wireless chipset and has long been supported in the Linux mainline kernel. Clearly, ChromeOS Flex needs to address these somehow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other miscellaneous hardware compatibilities
&lt;/h3&gt;

&lt;p&gt;Unlike network chipset which has only a few big players on the market such as Intel, Mediatek, Qualcomm, and Broadcom, other components of the laptops are from more obscure providers and have a lot of variations. Using the PopOS's latest version (kernel v6.1 at the moment), there are still certain compatibility issues, so I suppose it is understandable for ChromeOS Flex to stay behind in this aspect. For example.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The touch function of a laptop screen did not work during an initial OS installation but is fine after getting to the desktop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Touchpad, meanwhile, worked in the OS installation phase but became unusable after getting to the desktop. There were also times the touchpad worked fine from start to finish, but got disabled in a lock screen. Generally said, it was a hit or miss.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Speakers had the same issue as the touchpad.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The fingerprint was completely not supported on the three laptops I tried.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No tablet mode detection when the screen passed a 180 degrees angle (e.g., no rotation, no auto on-screen keyboard).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Somewhat lackluster in user experience
&lt;/h3&gt;

&lt;p&gt;Although using a minimal OS is my goal, ChromeOS Flex is missing certain features that reduce my overall experience. They are not breaking deals though, but worth to be mentioned. For example.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Chrome tabs do not close after the browser exits, and there is no option to decide whether to keep tabs between sessions. Apparently, ChromeOS Flex simply does not support this, and the user must right-click on a browser tab, then choose to &lt;em&gt;close other tabs&lt;/em&gt; before exiting the browser. It is an oversight in my opinion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Website scroll speed is very inconsistent, as in, the acceleration kept jumping around. It seems this was once reported in Chromium Issue 836258, but it is not viewable anymore.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ChromeOS Flex has worse settings than PopOS, such as no main monitor resolution, no time to sleep, no sleep button, and no Bluetooth codec adjustment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No trivial way to enable the tablet mode, which is commonly used when a laptop is a 2-in-1 type. The workaround I found was to enable the ASH shortcut flag in Chrome then press CTRL+ALT+SHIFT+T to enter and exit the tablet mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is a disassociation between mouse action and touch gestures in tablet mode. For example, swiping right means return but it is only doable with a touch gesture, not with a mouse cursor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even inside the tablet mode, the on-screen keyboard does not automatically open when typing and must be manually turned on (and off) in Settings. This creates a blockage when a user switches between desktop and tablet mode frequently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Non-standard way to enable an extra keyboard for special characters. Keyboards in other operating systems tend to reserve SHIFT for capitalization or expand options of one key, and an extra keyboard can be accessed using a special button at the corner. Meanwhile, SHIFT is used to switch keyboard types in ChromeOS Flex.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The list goes on, but again, not that big of a deal. Then, I found a serious issue with ChromeOS Flex which can potentially harm my laptops in the long run, and that was...&lt;/p&gt;

&lt;h3&gt;
  
  
  Completely broken sleep system
&lt;/h3&gt;

&lt;p&gt;Using a laptop, I rarely shut down the machine, rather, sleep is my usual choice. Why? It is simply about convenience, what is better than just opening the lid and all your application is there in their previous state? And yet, Chrome OS completely broke my laptop's sleep functionality. There are three types of breaking bugs.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The laptop cannot wake up from sleep:&lt;/strong&gt; I'm away from the keyboard or close the lid, and the laptop goes to sleep (screen off, keyboard-led off, fan spin down, no battery drain). However, when trying to turn it on, the fan spins, and the keyboard led lights up, but no screen. In this case, the screen is completely off (no backlight), and HDMI output does not provide a display signal. Only forcing the shutdown by pressing the power button can exit this state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The laptop cannot go to the sleep state:&lt;/strong&gt; I'm closing the lid, and the laptop &lt;em&gt;does not&lt;/em&gt; go to sleep (screen off, keyboard-led off, fan either spins down or keeps rotating, battery drains even faster than usual).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The laptop is unresponsive after waking up:&lt;/strong&gt; On one of my laptops that uses HDD, when the laptop goes to sleep (as expected) and wakes up. It is normal in the lock screen, but after singing, the user inputs (keystroke, mouse movement) are delayed for more than 1 minute, which effectively renders the laptop unusable. I have to force shutdown with the power button to exit this state. This persists through HDD replacement, but the problem disappears when using an SSD.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the best part, these problems randomly happen but at a very high frequency, likely more than 80% of the time. I consider them harmful to my system because repetitive behaviors like force shutting down (unsafe shutdown) and battery drain can potentially corrupt OS or even degrade the hardware over time.&lt;/p&gt;

&lt;p&gt;Are these isolated issues that only happen to my laptops? Maybe, but I could not identify the root cause. Here was what I found in the log for type one (wall of text, with my educated guess on their meaning). In this scenario, I opened the laptop and sign in, then let it stay there (not open any program or do anything) until the sleep kicks in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Starting to go sleep.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;13.976131&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Got&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305475&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shill&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305473&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;13.977835&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Got&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305476&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305473&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.37&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;13.977901&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;254&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Notifying&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;observers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;13.978472&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspender.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;739&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Starting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Is this error relevant? Or just a vague message?&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;13.978682&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_configurator.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;deep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/sys/power/mem_sleep:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Invalid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;argument&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;14.054817&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;main.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;408&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Running&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/bin/powerd_setuid_helper --action=suspend --suspend_wakeup_count_valid --suspend_wakeup_count=72"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Sleep for about 8 minutes, then wake up.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.150638&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;960&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd_suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;returned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.152115&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;wakeup_device.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/sys/devices/platform/i8042/serio0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;had&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;event_count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;65&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;before&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;66&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;after&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resume&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.152227&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dark_resume.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;triggered&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wake&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.152250&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspender.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;627&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Finishing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305473&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;successfully&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;after&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;8m42s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.153198&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1157&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Updated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;settings:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;quick_dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;screen_off&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;m30s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;m40s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;quick_lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idle_warn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;m30s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lid_closed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;use_audio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;use_video&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wake_locks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# The laptop is on now, and screen is going to light up.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.153237&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;133&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Undimming&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.153253&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;133&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Turning&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.153319&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_power_setter.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Asking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DisplayService&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;turn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;displays&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# ERROR!!! The screen cannot turn on!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.480391&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;object_proxy.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;622&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;method:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.DisplayServiceInterface.SetPower:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;object_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;/org/chromium/DisplayService:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.freedesktop.DBus.Error.NoReply:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;recipient&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;disconnected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;without&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;replying&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.480475&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;internal_backlight_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;781&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Setting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;brightness&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;95&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;63&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;over&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.488015&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bluetooth_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Writing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"auto"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/sys/devices/pci0000:00/0000:00:08.1/0000:04:00.4/usb3/3-3/power/control&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;succeeded&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Another crypted error.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.488073&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cros_ec_device_event.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/dev/cros_ec:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;such&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.488473&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1662&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Received&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;updated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;external&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;policy:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ac_dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ac_screen_off&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ac_lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ac_idle_warn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ac_idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="n"&gt;m30s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery_dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery_screen_off&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery_lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery_idle_warn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery_idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;m30s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ac_idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery_idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lid_closed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;use_audio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;use_video&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;presentation_factor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_activity_factor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wait_for_initial_user_activity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;force_nonzero_brightness_for_user_activity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Prefs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.488573&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1157&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Updated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;settings:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;quick_dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;screen_off&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;quick_lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idle_warn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;m30s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lid_closed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;use_audio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;use_video&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wake_locks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.489603&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;134&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Unregistering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305476&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;due&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;D-Bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.37&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;going&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;away&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.489659&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;134&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Unregistering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dark&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67338241&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;due&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;D-Bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.37&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;going&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;away&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Battery is at 79% (note, this is a new laptop battery, and performs well in PopOS).&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.490001&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;79&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;81&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.826&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0.456A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calculating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.490444&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;udev.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Removing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/sys/devices/platform/i8042/serio1/input/input5/event11&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.491477&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1753&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Session&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;changed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stopped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.491627&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1157&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Updated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;settings:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;quick_dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;screen_off&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;quick_lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idle_warn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;m30s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lid_closed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;use_audio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;use_video&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wake_locks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.493120&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;wakeup_source_identifier.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;137&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Stopped&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;monitoring&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wakeup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/sys/devices/platform/i8042/serio1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wake&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.493151&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;udev.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Removing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/sys/devices/platform/i8042/serio1/input/input5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.511177&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Unregistering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305477&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pause&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;VMs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspended&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;behalf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.134&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;56.945571&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1197&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;D-Bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.SessionManager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ownership&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;changed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.170&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;57.057971&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;73&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Registering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305478&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;5000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;behalf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.171&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;57.058236&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;73&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Registering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dark&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67338243&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;5000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;behalf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.171&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Pressing the power button again, in an attempt to wake up screen. This parts seems to indicate it. Pay attention to the timestamp.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;57.113615&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1643&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Chrome&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;normal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;57.137056&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;D-Bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.DisplayService&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ownership&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;changed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.171&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;57.137088&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_power_setter.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Asking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DisplayService&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;turn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;displays&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# And the display is still off, while the whole computer is (supposedly running)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.139349&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;WARNING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bus.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;644&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Bus::SendWithReplyAndBlock&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;took&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;5002ms&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;method_call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;/org/chromium/DisplayService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;org.chromium.DisplayServiceInterface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SetPower&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;2023-03-02T05:30:02.139379Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;object_proxy.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;622&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;method:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.DisplayServiceInterface.SetPower:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;object_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;/org/chromium/DisplayService:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.freedesktop.DBus.Error.NoReply:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Did&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;receive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Possible&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;causes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;include:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;did&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;blocked&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;was&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;broken.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.139443&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1204&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;D-Bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.PrivacyScreenService&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ownership&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;changed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.171&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Battery drops after 5 second.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.148549&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;78&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;81&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.822&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2.408A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;3h48m44s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;h45m44s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# These screen-related errors may indicate something.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;05.142901&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;object_proxy.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;622&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;method:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.PrivacyScreenService.GetPrivacyScreenSetting:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;object_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;/org/chromium/PrivacyScreenService:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.freedesktop.DBus.Error.NoReply:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Did&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;receive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Possible&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;causes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;include:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;did&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;blocked&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;was&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;broken.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;05.142930&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1435&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;D-Bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;GetPrivacyScreenSetting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;failed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;21.493067&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;object_proxy.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;622&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;method:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.MlDecisionService.ShouldDeferScreenDim:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;object_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;/org/chromium/MlDecisionService:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.freedesktop.DBus.Error.ServiceUnknown:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.MlDecisionService&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;was&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;provided&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;21.493097&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dim_advisor.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;181&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;D-Bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.MlDecisionService.ShouldDeferScreenDim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;failed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.492176&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;126&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Dimming&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;after&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;30s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.492201&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;internal_backlight_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;781&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Setting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;brightness&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;26&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;35.1246&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;over&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;200&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;32.157441&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;78&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;80&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.804&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2.194A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2h32m9s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;h29m9s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;36.495411&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;126&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Turning&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;off&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;after&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;40s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;36.495438&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;internal_backlight_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;781&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Setting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;brightness&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;over&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;200&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# A screen off request?&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;36.695850&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;display_power_setter.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Asking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DisplayService&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;turn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;displays&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;off&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;41.700939&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;WARNING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bus.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;644&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Bus::SendWithReplyAndBlock&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;took&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;5005ms&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;method_call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;/org/chromium/DisplayService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;org.chromium.DisplayServiceInterface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SetPower&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# It seems the request somehow fails. Note, the screen been off till now while the laptop has been running (fan spins, keyboard lights up).&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;41.700965&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;object_proxy.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;622&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;method:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.DisplayServiceInterface.SetPower:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;object_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;/org/chromium/DisplayService:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.freedesktop.DBus.Error.NoReply:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Did&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;receive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Possible&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;causes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;include:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;did&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;blocked&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;was&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;broken.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;46.496482&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;126&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Locking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;after&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;50s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;46.497000&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;object_proxy.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;622&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;method:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.SessionManagerInterface.LockScreen:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;object_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;/org/chromium/SessionManager:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;org.chromium.SessionManagerInterface.SessionDoesNotExist:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Attempt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lock&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;outside&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;session.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Battery drops again just after 1 minute, this is unusual.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.166440&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;77&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;80&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.786&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2.069A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1h54m48s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;h51m48s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;32.176555&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;77&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;79&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.768&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2.198A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1h30m41s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;h27m41s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;57.360460&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;134&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Unregistering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305478&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;due&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;D-Bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.171&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;going&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;away&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;57.360489&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;134&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Unregistering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dark&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67338243&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;due&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;D-Bus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.171&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;going&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;away&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# The battery drops seems really fast even with screen off, isn't it? This may indicate certain hardware components are underload and drains the battery.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.188245&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;76&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;79&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.751&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1.086A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1h21m1s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;h18m1s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;32.200221&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;76&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;79&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.742&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1.111A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1h32m39s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;h29m39s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.212217&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;76&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;78&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.733&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1.116A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1h45m29s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;h42m29s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;32.224203&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;76&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;78&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.724&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1.097A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2h35s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;h57m35s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.236210&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;75&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;78&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.715&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1.109A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2h23m57s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;h20m57s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;32.248213&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;75&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;77&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.706&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0.953A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2h26m37s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;h23m37s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.260236&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;75&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;77&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.698&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1.095A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2h27m8s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;h24m8s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;32.272206&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;75&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;77&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.689&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1.088A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2h27m26s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;h24m26s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.284024&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1213&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;74&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;77&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.680&lt;/span&gt;&lt;span class="n"&gt;/3.600Ah&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0.955A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2h30m40s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;h27m40s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.496102&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1347&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ready&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;perform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;6m30s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.496195&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspender.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;575&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Starting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305474&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.598662&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bluetooth_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Writing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"on"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/sys/devices/pci0000:00/0000:00:08.1/0000:04:00.4/usb3/3-3/power/control&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;succeeded&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.598754&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;837&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Reading&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wakeup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/sys/power/wakeup_count&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.598856&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;daemon.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;841&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wakeup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;92&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.598880&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;151&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Announcing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305474&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;outstanding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;previous&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.599324&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cros_ec_device_event.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/dev/cros_ec:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;such&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.600370&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Got&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305473&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bluetooth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305474&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.600946&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Got&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305474&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trunksd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305474&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.601620&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Got&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305475&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shill&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;67305474&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;1.8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.601700&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_delay_controller.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;254&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Notifying&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;observers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Request to sleep again, which it should not be at this moment as I keep pressing the keyboards. That said, aside from special keys like power, keyboard backlight adjust, etc. I could not confirm whether my keystroke are registered.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.602362&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspender.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;739&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Starting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# And it fails?&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.602558&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suspend_configurator.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;deep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/sys/power/mem_sleep:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Invalid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;argument&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="nt"&gt;-03-02T05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.630702&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powerd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;main.cc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;408&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Running&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/bin/powerd_setuid_helper --action=suspend --suspend_wakeup_count_valid --suspend_wakeup_count=92"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;ChromeOS Flex, in my opinion, is still very worth a try and I like what it offers at the very early phase like now. Lightweight, security, and minimalism, these aspects can bring your device a new life, be it a powerful machine or one that has been in storage for years. Feature-wise, it is expected to not be comparable to a full fledge operating system such as PopOS, and that is completely fine to me. Without the very broken sleep functionality, I may have continued my journey with ChromeOS Flex and its ecosystem, but for now, I have to postpone the plan. I wonder, a year from now, what will Chrome OS Flex become?&lt;/p&gt;




&lt;p&gt;This article was originally published at &lt;a href="https://hungvu.tech/chromeos-flex-have-i-just-opened-a-can-of-worms"&gt;🪱ChromeOS Flex, have I just opened a can of worms?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find my article to be helpful, I have some more for you!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/how-to-set-up-bitwarden-enterprise-sso-via-oidc-with-google"&gt;How to set up Bitwarden Enterprise SSO via OIDC with Google?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/cloudflare-turnstile-and-wordfence-2fa-break-wordpress-login-flow-how-to-fix-it"&gt;Cloudflare Turnstile and Wordfence 2FA break WordPress login flow, how to fix it?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hungvu.tech/how-to-back-up-microsoft-365-with-synology-active-backup"&gt;How to back up Microsoft 365 with Synology Active Backup?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, let's connect!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.linkedin.com/in/hunghvu/"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/hunghvu"&gt;GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/hunghvu_dev"&gt;Twitter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>testing</category>
      <category>linux</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>🌱Using Forem as an intranet website, yay or nay?</title>
      <dc:creator>Hung Vu</dc:creator>
      <pubDate>Tue, 07 Mar 2023 23:16:33 +0000</pubDate>
      <link>https://forem.com/hunghvu/using-forem-as-an-intranet-website-yay-or-nay-3hdo</link>
      <guid>https://forem.com/hunghvu/using-forem-as-an-intranet-website-yay-or-nay-3hdo</guid>
      <description>&lt;p&gt;&lt;strong&gt;I'm looking into building an intranet website and is researching on available options. There are two solutions that I have at the moment:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DIY the website. This offers customizability but come at the cost of overhead such as development and maintenance time.&lt;/li&gt;
&lt;li&gt;Use an existing open-source forum solutions like Forem, Discourse, NodeBB, etc. This cut down the overhead, but also reduces customizability (no tailored UX?) and might not scale well when requirements evolve.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Which options would you suggest? And what else should I consider? The draft requirements can be seen below:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are 2 main classes of users: Authors, and readers. The authors have right to create contents (articles, videos), while the readers can only consume content. A user can only be one or another.&lt;/li&gt;
&lt;li&gt;More advanced access control list: E.g., only authorized users can see the content.&lt;/li&gt;
&lt;li&gt;Good user experience (navigation, search, organization, etc.) Cloud file-directory based options such as Google Workspace has become an obstacle for non-technical users in this specific environment.&lt;/li&gt;
&lt;li&gt;Targeted audience: Certain type of content can be promoted or pin to dashboard of targeted audience.&lt;/li&gt;
&lt;li&gt;User profile.&lt;/li&gt;
&lt;li&gt;SSO.&lt;/li&gt;
&lt;li&gt;Optional: Scheduling (calendar), and location (map) features.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>discuss</category>
      <category>help</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
