<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>larry &#8211; LarryLai</title>
	<atom:link href="https://larrylai.com/author/larry/feed/" rel="self" type="application/rss+xml" />
	<link>https://larrylai.com</link>
	<description>兼聽則明 偏聽則暗</description>
	<lastBuildDate>Sat, 13 Jun 2026 16:58:00 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://larrylai.com/wp-content/uploads/2017/03/larrylai_com-favicon.png</url>
	<title>larry &#8211; LarryLai</title>
	<link>https://larrylai.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Piwigo Fotorama Conflict w/ Embedded Video</title>
		<link>https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video-2/</link>
					<comments>https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video-2/#respond</comments>
		
		<dc:creator><![CDATA[larry]]></dc:creator>
		<pubDate>Sat, 13 Jun 2026 16:58:00 +0000</pubDate>
				<category><![CDATA[Application]]></category>
		<guid isPermaLink="false">https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video-2/</guid>

					<description><![CDATA[<p>Issue: After installing Fotorama plugin in Piwigo provided that there is Embedded Video installed, the following error message will be shown while clicking the slideshow button on top of the video pages: Notice: Undefined index: selected_derivative in /&#8230;/plugins/Fotorama/main.inc.php on line 54 Fatal error: Call to a member function get_type() on a non-object in /&#8230;/plugins/Fotorama/main.inc.php on [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video-2/">Piwigo Fotorama Conflict w/ Embedded Video</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>Issue:</strong></p>
<p>After installing Fotorama plugin in Piwigo provided that there is Embedded Video installed, the following error message will be shown while clicking the slideshow button on top of the video pages: Notice: Undefined index: selected_derivative in /&#8230;/plugins/Fotorama/main.inc.php on line 54 Fatal error: Call to a member function get_type() on a non-object in /&#8230;/plugins/Fotorama/main.inc.php on line 54 </p>
<p><strong>Solution:</strong></p>
<p>Maybe it is just a workaround for the issue. However, it works so far. Comment out the statements causing the error in main.inc.php of Fotorama plugin as below:</p>
<pre>$type = $current['selected_derivative']-&gt;get_type();
    $defined = ImageStdParams::get_defined_type_map();
    if (!isset($defined[$type]))
    {
      $type = pwg_get_session_var('picture_deriv', $conf['derivative_default_size']);
    }</pre>
<p>and rewrite the following line:</p>
<pre>$type = pwg_get_session_var('picture_deriv', $conf['derivative_default_size']);</pre>
<p><strong>Config:</strong></p>
<ul>
<li>Piwigo          2.6.2</li>
<li>Embedded plugin: 2.6.2</li>
<li>Fotorama plugin:   2.6.h</li>
</ul>
<p>The post <a rel="nofollow" href="https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video-2/">Piwigo Fotorama Conflict w/ Embedded Video</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Piwigo Fotorama Conflict w/ Embedded Video</title>
		<link>https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video/</link>
					<comments>https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video/#respond</comments>
		
		<dc:creator><![CDATA[larry]]></dc:creator>
		<pubDate>Sat, 13 Jun 2026 13:55:35 +0000</pubDate>
				<category><![CDATA[Application]]></category>
		<guid isPermaLink="false">https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video/</guid>

					<description><![CDATA[<p>Issue: After installing Fotorama plugin in Piwigo provided that there is Embedded Video installed, the following error message will be shown while clicking the slideshow button on top of the video pages: Notice: Undefined index: selected_derivative in /&#8230;/plugins/Fotorama/main.inc.php on line 54 Fatal error: Call to a member function get_type() on a non-object in /&#8230;/plugins/Fotorama/main.inc.php on [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video/">Piwigo Fotorama Conflict w/ Embedded Video</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>Issue:</strong></p>
<p>After installing Fotorama plugin in Piwigo provided that there is Embedded Video installed, the following error message will be shown while clicking the slideshow button on top of the video pages: Notice: Undefined index: selected_derivative in /&#8230;/plugins/Fotorama/main.inc.php on line 54 Fatal error: Call to a member function get_type() on a non-object in /&#8230;/plugins/Fotorama/main.inc.php on line 54 </p>
<p><strong>Solution:</strong></p>
<p>Maybe it is just a workaround for the issue. However, it works so far. Comment out the statements causing the error in main.inc.php of Fotorama plugin as below:</p>
<pre>$type = $current['selected_derivative']-&gt;get_type();
    $defined = ImageStdParams::get_defined_type_map();
    if (!isset($defined[$type]))
    {
      $type = pwg_get_session_var('picture_deriv', $conf['derivative_default_size']);
    }</pre>
<p>and rewrite the following line:</p>
<pre>$type = pwg_get_session_var('picture_deriv', $conf['derivative_default_size']);</pre>
<p><strong>Config:</strong></p>
<ul>
<li>Piwigo          2.6.2</li>
<li>Embedded plugin: 2.6.2</li>
<li>Fotorama plugin:   2.6.h</li>
</ul>
<p>The post <a rel="nofollow" href="https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video/">Piwigo Fotorama Conflict w/ Embedded Video</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larrylai.com/piwigo-fotorama-conflict-w-embedded-video/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Fix CentOS VM Client Boot Failure: A Step-by-Step Troubleshooting Guide</title>
		<link>https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide-2/</link>
					<comments>https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide-2/#respond</comments>
		
		<dc:creator><![CDATA[larry]]></dc:creator>
		<pubDate>Tue, 09 Jun 2026 18:40:53 +0000</pubDate>
				<category><![CDATA[Virtualization]]></category>
		<guid isPermaLink="false">https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide-2/</guid>

					<description><![CDATA[<p>Understanding the Boot Failure: Two Failed Services When I tried to spin up my CentOS 7 guest—running on kernel 3.10 within VirtualBox 6.0.10—the boot process didn&#8217;t behave as expected. Instead of reaching a stable login prompt, the system stalled mid-way through the startup sequence. Upon inspecting the console logs, I noticed two critical error messages [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide-2/">How to Fix CentOS VM Client Boot Failure: A Step-by-Step Troubleshooting Guide</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Understanding the Boot Failure: Two Failed Services</h2>
<p>When I tried to spin up my CentOS 7 guest—running on kernel 3.10 within VirtualBox 6.0.10—the boot process didn&#8217;t behave as expected. Instead of reaching a stable login prompt, the system stalled mid-way through the startup sequence.</p>
<p>Upon inspecting the console logs, I noticed two critical error messages that pointed to exactly where things were breaking down: <code>[FAILED] Failed to start Virtual Machine and Container Registration Service</code> and <code>[FAILED] Failed to start Login Service</code>. </p>
<p>At this stage, I wasn&#8217;t entirely certain of the smoking gun. It looked like a potential issue with the SELinux configuration—specifically how it was interacting with the system&#8217;s boot state—but I also had to consider that this might be a known bug within VirtualBox 6 itself. Regardless of the exact culprit, these two service failures were preventing me from accessing my environment.</p>
<h2>Prerequisites for Troubleshooting</h2>
<p>Before diving into the fix, I made sure I had a few things in place—this approach means editing system files during boot, so a little preparation goes a long way:</p>
<ul>
<li><strong>Access to the VirtualBox console.</strong> You need to be at the keyboard when the VM first powers on, ready to catch the GRUB menu before it hands off to the kernel. (My environment was a CentOS 7 guest on VirtualBox 6.0.10.)</li>
<li><strong>A snapshot or backup first.</strong> Since we&#8217;ll be remounting the filesystem and editing <code>/etc/selinux/config</code>, take a VirtualBox snapshot beforehand. If anything goes sideways, you can roll straight back.</li>
<li><strong>Comfort with a terminal editor.</strong> The fix happens in <code>vi</code> inside a minimal rescue shell, so basic <code>vi</code> navigation (insert, save, quit) is all you need.</li>
<li><strong>Knowing your boot entry.</strong> If GRUB lists multiple kernels, be ready to identify your primary CentOS entry—that&#8217;s the one we&#8217;ll edit.</li>
</ul>
<h2>Step 1: Revealing the Hidden Boot Errors (Exit Quiet Boot)</h2>
<p>When I first encountered the boot failure, I was met with nothing but a static progress bar. By default, CentOS 7 uses a &#8220;quiet boot&#8221; setting that hides the technical minutiae of the startup process behind a clean splash screen. While this looks professional, it is incredibly unhelpful when you are troubleshooting a system that refuses to start.</p>
<p>To see what was actually happening under the hood, I needed to reveal the full system logs. As soon as the boot sequence begins, pressing the <strong>Esc</strong> key interrupts the quiet mode and displays the detailed text-based output. By doing this, I was finally able to see the specific <code>[FAILED]</code> messages—such as those regarding the Virtual Machine and Container Registration Service—that provided the first real clue into the system&#8217;s instability.</p>
<h2>Step 2: Booting CentOS into Rescue Mode via GRUB</h2>
<p>Once I realized the standard boot process was hitting a wall, my next move was to use the GRUB menu to bypass the failing services and drop straight into a command-line environment. It&#8217;s important to note that GRUB itself isn&#8217;t corrupt—it is still functioning perfectly as our entry point—we just need to change how it hands off control to the kernel.</p>
<p>Here is exactly how I navigated through the bootloader to enter rescue mode:</p>
<ol>
<li><strong>Select the Entry:</strong> When the VirtualBox window displays the GRUB boot menu, use your arrow keys to highlight your primary CentOS boot entry.</li>
<li><strong>Edit the Boot Parameters:</strong> Press the <code>e</code> key on your keyboard. This opens an editor that allows you to modify the boot instructions before they are actually executed by the system.</li>
<li><strong>Modify the Linux Line:</strong> Scroll down through the text until you find the line starting with <code>linux16</code>. This line contains the kernel-specific arguments and parameters. Navigate to the very end of this line, add a space, and append: <code>systemd.unit=rescue.target</code></li>
<li><strong>Execute the Boot:</strong> Once the parameter is added, press <code>Ctrl+X</code> (or <code>F10</code>) to boot with these new settings.</li>
</ol>
<p>This process forces CentOS to skip the standard multi-user startup sequence—where the failing services are triggered—and instead boots you directly into a minimal, single-user rescue environment where we can address the SELinux configuration issues manually.</p>
<h2>Step 3: Fixing the SELinux Configuration (the Root Cause)</h2>
<p>Once I was settled into the rescue shell, my first task wasn&#8217;t editing files—it was making sure I could actually save them. Depending on how the system lands in rescue mode, the root filesystem can come up read-only, so to be safe I remounted it writable before touching anything:</p>
<p><code>mount -o remount,rw /</code></p>
<p>With write access secured, I turned my attention to the primary suspect: the SELinux configuration. SELinux sits deep in the boot path, and when its policy gets tangled up with the system&#8217;s state—as it can in a quirky VirtualBox guest—it&#8217;s capable of quietly stalling the very services CentOS needs to finish starting.</p>
<p>I opened the configuration file using <code>vi</code>:</p>
<p><code>vi /etc/selinux/config</code></p>
<p>Inside the file, I located the line starting with <code>SELINUX=</code>. Here is the detail that made this issue so hard to pin down: it wasn&#8217;t set to <code>enforcing</code>, as you might assume. It was already on <code>permissive</code>—a mode that is only supposed to <em>log</em> policy violations, not block anything. That&#8217;s precisely why SELinux is such an easy culprit to overlook here; on paper it shouldn&#8217;t have been able to stop those services at all. Yet they still refused to start. So rather than half-measures, I turned SELinux off completely:</p>
<p><code>SELINUX=disabled</code></p>
<p>Setting the mode to <code>disabled</code> takes SELinux fully out of the boot path on the next startup, which is what finally cleared the conflict stalling the Registration and Login services. I saved the file and exited the editor. (If you&#8217;d prefer to keep SELinux active for security, you can switch it back to <code>enforcing</code> once you&#8217;ve confirmed the VM boots reliably—but for getting a stuck machine running again, disabling it is the fastest, most decisive fix.)</p>
<h2>Step 4: Verifying the Fix and Ruling Out the VirtualBox 6 Bug</h2>
<p>After saving my changes in rescue mode, I performed a standard reboot to see if the system would finally reach the login prompt. This time, the boot sequence progressed smoothly; those alarming <code>[FAILED]</code> messages that had been stalling the startup process were nowhere to be seen.</p>
<p>To double-check my work, I ran <code>getenforce</code> once the system was up. The output came back <code>Disabled</code>, confirming SELinux was fully switched off and no longer interfering with the services that had been failing to initialize.</p>
<p>While the VM is now stable, I kept one caveat in mind: the environment involves VirtualBox 6.0.10. There have been documented instances of specific service failures linked to bugs within this particular version of the hypervisor. While correcting the SELinux configuration solved my immediate problem, if you encounter similar boot issues on a different machine even after following these steps, it is worth considering that the issue might reside in the VirtualBox software itself rather than your CentOS configuration.</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide-2/">How to Fix CentOS VM Client Boot Failure: A Step-by-Step Troubleshooting Guide</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Fix CentOS VM Client Boot Failure: A Step-by-Step Troubleshooting Guide</title>
		<link>https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide/</link>
					<comments>https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide/#respond</comments>
		
		<dc:creator><![CDATA[larry]]></dc:creator>
		<pubDate>Tue, 09 Jun 2026 18:03:23 +0000</pubDate>
				<category><![CDATA[Virtualization]]></category>
		<guid isPermaLink="false">https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide/</guid>

					<description><![CDATA[<p>Understanding the Boot Failure: Two Failed Services When I tried to spin up my CentOS 7 guest—running on kernel 3.10 within VirtualBox 6.0.10—the boot process didn&#8217;t behave as expected. Instead of reaching a stable login prompt, the system stalled mid-way through the startup sequence. Upon inspecting the console logs, I noticed two critical error messages [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide/">How to Fix CentOS VM Client Boot Failure: A Step-by-Step Troubleshooting Guide</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Understanding the Boot Failure: Two Failed Services</h2>
<p>When I tried to spin up my CentOS 7 guest—running on kernel 3.10 within VirtualBox 6.0.10—the boot process didn&#8217;t behave as expected. Instead of reaching a stable login prompt, the system stalled mid-way through the startup sequence.</p>
<p>Upon inspecting the console logs, I noticed two critical error messages that pointed to exactly where things were breaking down: <code>[FAILED] Failed to start Virtual Machine and Container Registration Service</code> and <code>[FAILED] Failed to start Login Service</code>. </p>
<p>At this stage, I wasn&#8217;t entirely certain of the smoking gun. It looked like a potential issue with the SELinux configuration—specifically how it was interacting with the system&#8217;s boot state—but I also had to consider that this might be a known bug within VirtualBox 6 itself. Regardless of the exact culprit, these two service failures were preventing me from accessing my environment.</p>
<h2>Prerequisites for Troubleshooting</h2>
<p>Before diving into the fix, I made sure I had a few things in place—this approach means editing system files during boot, so a little preparation goes a long way:</p>
<ul>
<li><strong>Access to the VirtualBox console.</strong> You need to be at the keyboard when the VM first powers on, ready to catch the GRUB menu before it hands off to the kernel. (My environment was a CentOS 7 guest on VirtualBox 6.0.10.)</li>
<li><strong>A snapshot or backup first.</strong> Since we&#8217;ll be remounting the filesystem and editing <code>/etc/selinux/config</code>, take a VirtualBox snapshot beforehand. If anything goes sideways, you can roll straight back.</li>
<li><strong>Comfort with a terminal editor.</strong> The fix happens in <code>vi</code> inside a minimal rescue shell, so basic <code>vi</code> navigation (insert, save, quit) is all you need.</li>
<li><strong>Knowing your boot entry.</strong> If GRUB lists multiple kernels, be ready to identify your primary CentOS entry—that&#8217;s the one we&#8217;ll edit.</li>
</ul>
<h2>Step 1: Revealing the Hidden Boot Errors (Exit Quiet Boot)</h2>
<p>When I first encountered the boot failure, I was met with nothing but a static progress bar. By default, CentOS 7 uses a &#8220;quiet boot&#8221; setting that hides the technical minutiae of the startup process behind a clean splash screen. While this looks professional, it is incredibly unhelpful when you are troubleshooting a system that refuses to start.</p>
<p>To see what was actually happening under the hood, I needed to reveal the full system logs. As soon as the boot sequence begins, pressing the <strong>Esc</strong> key interrupts the quiet mode and displays the detailed text-based output. By doing this, I was finally able to see the specific <code>[FAILED]</code> messages—such as those regarding the Virtual Machine and Container Registration Service—that provided the first real clue into the system&#8217;s instability.</p>
<h2>Step 2: Booting CentOS into Rescue Mode via GRUB</h2>
<p>Once I realized the standard boot process was hitting a wall, my next move was to use the GRUB menu to bypass the failing services and drop straight into a command-line environment. It&#8217;s important to note that GRUB itself isn&#8217;t corrupt—it is still functioning perfectly as our entry point—we just need to change how it hands off control to the kernel.</p>
<p>Here is exactly how I navigated through the bootloader to enter rescue mode:</p>
<ol>
<li><strong>Select the Entry:</strong> When the VirtualBox window displays the GRUB boot menu, use your arrow keys to highlight your primary CentOS boot entry.</li>
<li><strong>Edit the Boot Parameters:</strong> Press the <code>e</code> key on your keyboard. This opens an editor that allows you to modify the boot instructions before they are actually executed by the system.</li>
<li><strong>Modify the Linux Line:</strong> Scroll down through the text until you find the line starting with <code>linux16</code>. This line contains the kernel-specific arguments and parameters. Navigate to the very end of this line, add a space, and append: <code>systemd.unit=rescue.target</code></li>
<li><strong>Execute the Boot:</strong> Once the parameter is added, press <code>Ctrl+X</code> (or <code>F10</code>) to boot with these new settings.</li>
</ol>
<p>This process forces CentOS to skip the standard multi-user startup sequence—where the failing services are triggered—and instead boots you directly into a minimal, single-user rescue environment where we can address the SELinux configuration issues manually.</p>
<h2>Step 3: Fixing the SELinux Configuration (the Root Cause)</h2>
<p>Once I was settled into the rescue shell, my first task wasn&#8217;t editing files—it was making sure I could actually save them. Depending on how the system lands in rescue mode, the root filesystem can come up read-only, so to be safe I remounted it writable before touching anything:</p>
<p><code>mount -o remount,rw /</code></p>
<p>With write access secured, I turned my attention to the primary suspect: the SELinux configuration. SELinux sits deep in the boot path, and when its policy gets tangled up with the system&#8217;s state—as it can in a quirky VirtualBox guest—it&#8217;s capable of quietly stalling the very services CentOS needs to finish starting.</p>
<p>I opened the configuration file using <code>vi</code>:</p>
<p><code>vi /etc/selinux/config</code></p>
<p>Inside the file, I located the line starting with <code>SELINUX=</code>. Here is the detail that made this issue so hard to pin down: it wasn&#8217;t set to <code>enforcing</code>, as you might assume. It was already on <code>permissive</code>—a mode that is only supposed to <em>log</em> policy violations, not block anything. That&#8217;s precisely why SELinux is such an easy culprit to overlook here; on paper it shouldn&#8217;t have been able to stop those services at all. Yet they still refused to start. So rather than half-measures, I turned SELinux off completely:</p>
<p><code>SELINUX=disabled</code></p>
<p>Setting the mode to <code>disabled</code> takes SELinux fully out of the boot path on the next startup, which is what finally cleared the conflict stalling the Registration and Login services. I saved the file and exited the editor. (If you&#8217;d prefer to keep SELinux active for security, you can switch it back to <code>enforcing</code> once you&#8217;ve confirmed the VM boots reliably—but for getting a stuck machine running again, disabling it is the fastest, most decisive fix.)</p>
<h2>Step 4: Verifying the Fix and Ruling Out the VirtualBox 6 Bug</h2>
<p>After saving my changes in rescue mode, I performed a standard reboot to see if the system would finally reach the login prompt. This time, the boot sequence progressed smoothly; those alarming <code>[FAILED]</code> messages that had been stalling the startup process were nowhere to be seen.</p>
<p>To double-check my work, I ran <code>getenforce</code> once the system was up. The output came back <code>Disabled</code>, confirming SELinux was fully switched off and no longer interfering with the services that had been failing to initialize.</p>
<p>While the VM is now stable, I kept one caveat in mind: the environment involves VirtualBox 6.0.10. There have been documented instances of specific service failures linked to bugs within this particular version of the hypervisor. While correcting the SELinux configuration solved my immediate problem, if you encounter similar boot issues on a different machine even after following these steps, it is worth considering that the issue might reside in the VirtualBox software itself rather than your CentOS configuration.</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide/">How to Fix CentOS VM Client Boot Failure: A Step-by-Step Troubleshooting Guide</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larrylai.com/how-to-fix-centos-vm-client-boot-failure-a-step-by-step-troubleshooting-guide/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Hybrid AI Protocol: Orchestrating Cloud and Local AI</title>
		<link>https://larrylai.com/hybrid-ai-protocol-orchestrating-cloud-and-local-ai/</link>
					<comments>https://larrylai.com/hybrid-ai-protocol-orchestrating-cloud-and-local-ai/#respond</comments>
		
		<dc:creator><![CDATA[larry]]></dc:creator>
		<pubDate>Sun, 07 Jun 2026 18:36:59 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://larrylai.com/hybrid-ai-protocol-orchestrating-cloud-and-local-ai/</guid>

					<description><![CDATA[<p>Background I am not going to define or describe what AI agents are, as all of us can easily find relevant information on the web. I would like to share a framework I developed to balance the cognitive power of cloud AI with the cost-efficiency of local execution. While powerful cloud models like Opus 4.x [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/hybrid-ai-protocol-orchestrating-cloud-and-local-ai/">Hybrid AI Protocol: Orchestrating Cloud and Local AI</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>Background</strong><br />
I am not going to define or describe what AI agents are, as all of us can easily find relevant information on the web. I would like to share a framework I developed to balance the cognitive power of cloud AI with the cost-efficiency of local execution.</p>
<p>While powerful cloud models like Opus 4.x can be integrated to manage local files and interact with my computer, running all tasks—no matter if they are complex, basic, or recurring—unnecessarily consumes expensive tokens. Even though there are several pricing tiers of cloud models to choose from, constantly switching between them during rapid implementation cycles is inconvenient. Local open-source models are fantastic for handling basic, repetitive tasks for free, but they are strictly bound by the hardware they run on.</p>
<p><strong>Config</strong><br />
* <strong>Mac hardware:</strong> Mac mini M2 Pro with 32GB Unified Memory.<br />
* <strong>Local Agent:</strong> &#8220;Hermes&#8221; framework running the <code>gemma4:26b-mlx</code> model.<br />
* <strong>Cloud Agent:</strong> Claude running Opus 4.x.</p>
<p><strong>Issue</strong><br />
Due to the hardware limitation of my Mac&#8217;s 32GB of memory (unlike a Mac Studio which can be configured with up to 512GB of unified memory), the relatively small <code>gemma4:26b-mlx</code> model frequently truncated complex Python scripts mid-generation. It would abruptly cut off critical logic right after the <code>import</code> statements and variable declarations.</p>
<p>To be clear, this truncation is due to the physical hardware constraints and the local model size, not a limitation or flaw in the Hermes agent framework itself. However, it meant the local agent could not be trusted to reliably write structural code.</p>
<p><strong>Solution</strong><br />
To solve this, I built the <strong>Hybrid AI Orchestration Protocol</strong>: a directory-isolated, dual-agent &#8220;Walkie-Talkie&#8221; Blackboard architecture. The agents never speak directly; they coordinate via a single <code>state.json</code> file inside a <code>.handover/</code> directory. This file separates <em>liveness</em> from <em>intent</em> (tracking the <code>holder</code> and the <code>purpose</code>).</p>
<p>To prevent file conflicts and token waste, the protocol enforces strict roles:<br />
1. <strong>The Client (Me):</strong> Initiates the Product Requirements Document (PRD), answers questions, and gives final sign-off.<br />
2. <strong>Claude (The Architect &amp; QA):</strong> Handles structural planning, complex coding, and final QA. Claude is also the sole <strong>Version Control Manager</strong>—Hermes is strictly locked out of autonomous Git operations so a truncated script never overwrites the repository.<br />
3. <strong>Hermes (The Executor):</strong> Restricted from structural coding. It reads Claude&#8217;s scripts, checks paths, installs <code>pip</code> dependencies, executes terminal tests, and reports errors back to Claude.</p>
<p><strong>Tricks</strong><br />
What makes this system genuinely robust are three specific guardrails implemented to prevent common multi-agent failure modes:<br />
* <strong>The DRILL-ME Phase:</strong> Before any code is written, Claude must interrogate me about the PRD. Crucially, Claude must ask operational questions <em>on behalf of Hermes</em> (e.g., confirming the exact macOS path for credentials). This ensures the local execution environment is mapped beforehand.<br />
* <strong>Anti-Infinite-Loop:</strong> Agents can easily get stuck in an endless loop of failing a test and rewriting broken code. The state file tracks an <code>attempt_count</code>. If a script fails 5 times, it triggers an <code>ABORTED</code> state, forcing a human review.<br />
* <strong>Append-Only Logs:</strong> During testing, failures are saved as append-only numbered logs (<code>log_001.txt</code>, <code>log_002.txt</code>) instead of overwriting the terminal output. This preserves the complete debugging history for Claude to analyze.</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/hybrid-ai-protocol-orchestrating-cloud-and-local-ai/">Hybrid AI Protocol: Orchestrating Cloud and Local AI</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larrylai.com/hybrid-ai-protocol-orchestrating-cloud-and-local-ai/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Port Forwarding Issue &#8211; Netgear Nighthawk</title>
		<link>https://larrylai.com/port-forwarding-issue-netgear-nighthawk/</link>
					<comments>https://larrylai.com/port-forwarding-issue-netgear-nighthawk/#respond</comments>
		
		<dc:creator><![CDATA[larry]]></dc:creator>
		<pubDate>Wed, 15 Jul 2020 04:40:37 +0000</pubDate>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[netgear]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[port forwarding]]></category>
		<category><![CDATA[router]]></category>
		<guid isPermaLink="false">https://larrylai.com/?p=3913</guid>

					<description><![CDATA[<p>Background This morning when accessing YouTube from TV, there&#8217;s no response. Found that the reason was internet access failure though WiFi connection was fine. Then some other things got wrong due to router issue. Issue All the web hosting sites in local virtual server were down. The problem was port forwarding records all disappeared. I [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/port-forwarding-issue-netgear-nighthawk/">Port Forwarding Issue &#8211; Netgear Nighthawk</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3>Background</h3>
<p>This morning when accessing YouTube from TV, there&#8217;s no response. Found that the reason was internet access failure though WiFi connection was fine.</p>
<p>Then some other things got wrong due to router issue.</p>
<h3>Issue</h3>
<p>All the web hosting sites in local virtual server were down. The problem was port forwarding records all disappeared. I guess that after rebooting the router some configuration was corrupted.</p>
<p>Even worse, once adding back those port forwarding records, there&#8217;s error message about something like IP conflicts.</p>
<h3><strong>Solution</strong></h3>
<p>Restore previous configuration backup</p>
<h3>Tricks</h3>
<p>Sometimes a buggy device is bad. This time there are double bugs. First, configuration settings (port forwarding) unexpectedly corrupted; then the previous port forwarding became zombie configuration records. New addition of settings create conflicts.</p>
<h3>Configuration</h3>
<p>Netgear Nighthawk MR60: firmware ver. 1.0.4.98</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/port-forwarding-issue-netgear-nighthawk/">Port Forwarding Issue &#8211; Netgear Nighthawk</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larrylai.com/port-forwarding-issue-netgear-nighthawk/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Make Phone Calls on Mac</title>
		<link>https://larrylai.com/make-phone-calls-on-mac/</link>
					<comments>https://larrylai.com/make-phone-calls-on-mac/#respond</comments>
		
		<dc:creator><![CDATA[larry]]></dc:creator>
		<pubDate>Mon, 13 Jul 2020 04:15:31 +0000</pubDate>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[iMac]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[phone calls]]></category>
		<guid isPermaLink="false">https://larrylai.com/?p=3899</guid>

					<description><![CDATA[<p>Issue: When trying to use FaceTime on iMac to make phone calls through iPhone, there is an issue to connect the iPhone with the Mac. Even though these 2 devices are on the same WiFi network. There&#8217;s an error message on the iPhone &#8220;Cannot turn on calls on other devices&#8221;. When clicking &#8220;Calls on Other [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/make-phone-calls-on-mac/">Make Phone Calls on Mac</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading">Issue:</h3>



<p>When trying to use FaceTime on iMac to make phone calls through iPhone, there is an issue to connect the iPhone with the Mac. Even though these 2 devices are on the same WiFi network. There&#8217;s an error message on the iPhone &#8220;Cannot turn on calls on other devices&#8221;. When clicking &#8220;Calls on Other Devices&#8221; under &#8220;Settings -&gt; phone&#8221; as suggested by Apple&#8217;s support forum, it doesn&#8217;t work to connect the iPhone with the Mac.</p>



<h3 class="wp-block-heading">Solution:</h3>



<p> In the iPhone, go to Settings, and click &#8220;facetime&#8221;, select something like &#8230; AppleID&#8230; and sign in.</p>



<h3 class="wp-block-heading">Tricks:</h3>



<p>Though the AppleID is signed in probably in my new iPhone, some Apps have to be signed in, I guess, before some of its features are to be enabled.</p>



<h3 class="wp-block-heading">Config:</h3>



<ul class="wp-block-list"><li>iPhone SE 2020: iOS 13.5.1</li><li>iMac (late 2013): macOS 10.15.5 (Catalina)</li></ul>
<p>The post <a rel="nofollow" href="https://larrylai.com/make-phone-calls-on-mac/">Make Phone Calls on Mac</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larrylai.com/make-phone-calls-on-mac/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Google Site Kit All Blank in WP</title>
		<link>https://larrylai.com/google-site-kit-all-blank-in-wp/</link>
					<comments>https://larrylai.com/google-site-kit-all-blank-in-wp/#respond</comments>
		
		<dc:creator><![CDATA[larry]]></dc:creator>
		<pubDate>Tue, 12 May 2020 12:47:06 +0000</pubDate>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[site kit]]></category>
		<guid isPermaLink="false">https://larrylai.com/?p=3877</guid>

					<description><![CDATA[<p>Background: Google Site Kit plugin for WordPress is no doubt a comprehensive site performance plugin delivering promised all-in-one dashboard also with colourful layout. Issue: Using Google Site Kits plugin for a while without problem, suddenly its dashboard, settings, analytics, etc. all go blank. Solution: Disable the plugin – Remove Query Strings by Littlebizzy Tricks: A [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/google-site-kit-all-blank-in-wp/">Google Site Kit All Blank in WP</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading">Background:</h3>



<p>Google Site Kit plugin for WordPress is no doubt a comprehensive site performance plugin delivering promised all-in-one dashboard also with colourful layout. </p>



<h3 class="wp-block-heading">Issue:</h3>



<p>Using Google Site Kits plugin for a while without problem, suddenly its dashboard, settings, analytics, etc. all go blank.</p>



<h3 class="wp-block-heading">Solution:</h3>



<p>Disable the plugin – Remove Query Strings by <a href="https://www.littlebizzy.com/plugins" target="_blank" rel="noopener">Littlebizzy</a> </p>



<h3 class="wp-block-heading">Tricks:</h3>



<ul class="wp-block-list"><li>A common practice to solve this kind of problem is to disable all plugins. However, in some cases with CDN installed like CloudFlare plugin, the DNS of the website is usually switched from domain hosting company to the CDN. Then, once the plugin is disabled, the website address will be disconnected with your web hosting server.</li><li>The &#8216;Remove Query Strings&#8217; plugin is to improve website speed rating. </li></ul>
<p>The post <a rel="nofollow" href="https://larrylai.com/google-site-kit-all-blank-in-wp/">Google Site Kit All Blank in WP</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larrylai.com/google-site-kit-all-blank-in-wp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SSL Key Ownership</title>
		<link>https://larrylai.com/ssl-key-ownership/</link>
					<comments>https://larrylai.com/ssl-key-ownership/#respond</comments>
		
		<dc:creator><![CDATA[larry]]></dc:creator>
		<pubDate>Sun, 09 Feb 2020 07:39:51 +0000</pubDate>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[certbot]]></category>
		<category><![CDATA[Jupiter-notebook]]></category>
		<category><![CDATA[letsencrypt]]></category>
		<category><![CDATA[ssl-key]]></category>
		<guid isPermaLink="false">http://larrylai.com/?p=3775</guid>

					<description><![CDATA[<p>Issue: After receiving renewal notice from Let&#8217;s Encrypt for Jupyter server, go to the virtual machine hosting Jupyter and renew the key successfully. But cannot login to the jupyter notebook from https. Solution Remove the symbolic link of privkey.pem under /etc/letsencrypt/live/[mydomain]/privkey.pem recreate the symbolic link with the dedicated user running Jupyter notebook. Run command as [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/ssl-key-ownership/">SSL Key Ownership</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>Issue:</strong><br />
After receiving renewal notice from Let&#8217;s Encrypt for Jupyter server, go to the virtual machine hosting Jupyter and renew the key successfully. But cannot login to the jupyter notebook from https.</p>
<p><strong>Solution</strong></p>
<ol>
<li style="list-style-type: none;">
<ol>
<li>Remove the symbolic link of privkey.pem under
<pre>/etc/letsencrypt/live/[mydomain]/privkey.pem</pre>
</li>
<li>recreate the symbolic link with the dedicated user running Jupyter notebook.</li>
<li>Run command as root:
<pre>systemctl restart jupyterhub</pre>
</li>
</ol>
</li>
</ol>
<p><strong>Tricks</strong></p>
<ol>
<li style="list-style-type: none;">
<ol>
<li style="list-style-type: none;">
<ul>
<li>As the jupyter server is run by the ownership of a dedicated user, after the renewal, the private key, i.e. privkey.pem must be owned by this user. However, I run the command:
<pre>certbot renew --standalone</pre>
<p>under root.</li>
<li>note that let&#8217;s encrypt command for CentOS 6 is quite different from CentOS7</li>
</ul>
</li>
</ol>
</li>
</ol>
<p><strong>Config</strong></p>
<ol>
<li style="list-style-type: none;">
<ul>
<li>OS: CentOS 7</li>
<li>Jupyter-notebook: 5.7.8</li>
</ul>
</li>
</ol>
<p>The post <a rel="nofollow" href="https://larrylai.com/ssl-key-ownership/">SSL Key Ownership</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larrylai.com/ssl-key-ownership/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CSS List item style a) b)</title>
		<link>https://larrylai.com/css-list-item-style-a-b/</link>
					<comments>https://larrylai.com/css-list-item-style-a-b/#respond</comments>
		
		<dc:creator><![CDATA[larry]]></dc:creator>
		<pubDate>Tue, 07 Jan 2020 07:48:19 +0000</pubDate>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Ordered List Item]]></category>
		<category><![CDATA[Text-indent]]></category>
		<guid isPermaLink="false">http://larrylai.com/?p=3756</guid>

					<description><![CDATA[<p>Issue Default ordered list item style is decimal number, lower/upper alpha, lower/upper roman then followed by a dot. Thought it&#8217;s easy to change the dot to something like &#160; a) This is good 1st item &#160; b) This is good 2nd item. &#160; &#160; &#160; instead of: &#160; a. This is not good 1st item [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://larrylai.com/css-list-item-style-a-b/">CSS List item style a) b)</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>Issue</strong></p>
<p>Default ordered list item style is decimal number, lower/upper alpha, lower/upper roman then followed by a dot. Thought it&#8217;s easy to change the dot to something like<br />
&nbsp; a) This is good 1st item<br />
&nbsp; b) This is good 2nd item.   </p>
<p>&nbsp; &nbsp; &nbsp; instead of:<br />
&nbsp; a. This is not good 1st item<br />
&nbsp; b. This is not good 2nd item</p>
<p>However, there&#8217;s no simple way to change the style of ordered list item and remove the dot after the order number <code>&lt;ol&gt; &lt;li&gt;&lt;/li&gt;&lt;/ol&gt;</code>.<br />
As I got used to markdown&#8217;s convinence of auto numbering for ordered list items, don&#8217;t want to hard code the order into the list.</p>
<p><strong>Solution</strong></p>
<ol>
<li>Removing the default ordering number and using counter by creating counter variable  (say, list) like this<br />
&nbsp; <code>ol { list-style-type: none; counter-reset: list;}</code></li>
<li>Update counter variable for each \
<li> like this `ol&gt;li { counter-increment: list; } </li>
<li>Display the content of the new counter like this `ol&gt;li::before { content: counter(list, lower-alpha) &quot;) &quot;; }</li>
</ol>
<p><strong>Tricks</strong></p>
<ul>
<li>It&#8217;s a bit complex for multi-level ordered list, but the principle still applies</li>
<li>Some more has to be added to see hanging text like default ordered list display. This can be done by the following for modifying 2nd order level :
<pre>
ol ol {    
&nbsp; list-style-type: none;    
&nbsp; counter-reset: list;   
}     
ol ol>li::before {     
&nbsp; content: counter(list, lower-alpha) ") \00a0";
&nbsp; display: inline-block;
&nbsp; width: 1.5em;
&nbsp; text-align: right;
}    
ol ol>li {    
&nbsp; counter-increment: list;    
&nbsp; margin-left: .5em;    
&nbsp; text-indent: -1.5em;    
} 
</pre>
<p>Of course, several paramenters can be adjusted to fit into each individual case. These include margin-left, text-indent spaces and the counter number style, i.e. lower-alpha, lower-roman, decimal, etc.</p>
</li>
</ul>
<p>The post <a rel="nofollow" href="https://larrylai.com/css-list-item-style-a-b/">CSS List item style a) b)</a> appeared first on <a rel="nofollow" href="https://larrylai.com">LarryLai</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larrylai.com/css-list-item-style-a-b/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
