[{"content":"I have been eying implementing OIDC in the homelab for a while now. After a lot of research, while I found out Authentik is much more diverse and detailed, I went with the simpler solution. I will explain below how to connect Pocket ID to a standalone Proxmox VE installation using OpenID Connect, or OIDC.\nThe result is a Proxmox login flow where users authenticate through Pocket ID using a passkey. Proxmox users and groups are created automatically, while administrator permissions are assigned through a Pocket ID group instead of directly to individual users.\nThis guide is based on a working configuration using:\nProxmox VE 9.2 Pocket ID running as a self-hosted service. I am assuming you have already done this properly. Nginx Proxy Manager as the HTTPS reverse proxy An internal DNS server for local DNS rewrites (optional; you can do it in some other ways) A standalone, non-clustered Proxmox VE installation For this tutorial, we will use the example Proxmox hostname:\nhttps://proxmox.yourdomain.com The example Pocket ID hostname is:\nhttps://pocketid.yourdomain.com Replace all example domains, group names, usernames, and network addresses with values appropriate for your environment.\nImportant Safety Requirements Do not remove or disable the standard Proxmox PAM realm.\nKeep these recovery methods available:\nroot@pam login through the Proxmox web interface SSH key access to the Proxmox host Direct LAN access to the Proxmox management interface Pocket ID should be an additional authentication method, not the only way to administer the host.\nKeep an existing root@pam browser session and an SSH session open while configuring and testing OIDC.\nExample Architecture Component Example Proxmox hostname https://proxmox.yourdomain.com Pocket ID hostname https://pocketid.yourdomain.com Reverse proxy Nginx Proxy Manager Proxmox upstream https://PROXMOX-LAN-IP:8006 Internal DNS Local DNS rewrite to the reverse proxy If you have multiple standalone Proxmox installations, configure a separate Pocket ID OIDC client and Proxmox realm on each one. Do not assume configuration is shared between hosts.\nStep 1: Confirm Your Proxmox Version Connect to the Proxmox host through SSH or its local shell and run:\npveversion -v The tested installation used:\nproxmox-ve: 9.2.0 pve-manager: 9.2.2 libpve-access-control: 9.1.1 Recent Proxmox VE releases support automatic OIDC user creation, automatic group creation, group claims and group-membership overwrite.\nStep 2: Check Whether OIDC Group Options Are Available Do not use this command:\npveum realm add --help It fails because pveum does not use the usual subcommand --help format:\nUnknown option: help 400 unable to parse option The correct Proxmox command is:\npveum help realm add To display only the relevant OIDC options, use:\npveum help realm add 2\u0026gt;\u0026amp;1 | grep -E \\ \u0026#39;groups-claim|groups-autocreate|groups-overwrite|username-claim|autocreate\u0026#39; A compatible Proxmox installation should show options including:\n--autocreate --groups-autocreate --groups-claim --groups-overwrite --username-claim You can also inspect the API schema:\npvesh usage /access/domains --verbose 2\u0026gt;\u0026amp;1 | grep -E \\ \u0026#39;groups-claim|groups-autocreate|groups-overwrite|username-claim|openid\u0026#39; Step 3: Configure the Proxmox HTTPS URL and Reverse Proxy The browser-facing Proxmox hostname must already work over HTTPS before configuring OIDC.\nA reverse proxy is not mandatory. However, Proxmox must have a stable, browser-accessible HTTPS URL with a trusted certificate before the OIDC client is configured.\nFor example, your internal DNS may resolve:\nproxmox.yourdomain.com → REVERSE-PROXY-LAN-IP Nginx Proxy Manager then forwards the request to:\nhttps://PROXMOX-LAN-IP:8006 Configure Nginx Proxy Manager The Nginx Proxy Manager proxy host for proxmox.yourdomain.com should use:\nSetting Value Domain Name proxmox.yourdomain.com Scheme https Forward Hostname or IP PROXMOX-LAN-IP Forward Port 8006 Websockets Support Enabled Cache Assets Disabled Force SSL Enabled HTTP/2 Support Enabled WebSocket support is required for Proxmox noVNC, browser terminals, and interactive console sessions.\nIf the existing proxy already loads Proxmox correctly and consoles work, avoid adding unnecessary custom directives.\nIf Nginx Proxy Manager reports upstream certificate verification errors because Proxmox uses a self-signed certificate, the following directive may be added to the proxy host\u0026rsquo;s Advanced section:\nproxy_ssl_verify off; This affects only the connection between Nginx Proxy Manager and the Proxmox upstream. Browser-facing HTTPS should still use a valid certificate.\nDo not place an additional Nginx Proxy Manager Access List or forward-auth layer in front of Proxmox. Proxmox is already the OIDC client, and a second authentication layer can interfere with redirects, API requests, and WebSocket connections.\nConfirm that the Proxmox hostname works without a certificate warning:\ncurl -I https://proxmox.yourdomain.com/ Also confirm that the Proxmox host can reach Pocket ID directly:\ncurl -fsS \\ https://pocketid.yourdomain.com/.well-known/openid-configuration | python3 -m json.tool This test must work from the Proxmox host, not only from a workstation browser. Proxmox performs server-side OIDC discovery and token exchange.\nStep 4: Create Pocket ID Groups Open Pocket ID and create two user groups.\nFor example:\nproxmox_users proxmox_admins The groups have separate purposes:\nproxmox_users allows ordinary access to this Proxmox installation. proxmox_admins identifies users who should receive the Proxmox Administrator role. Add your initial administrator account to both groups.\nUse simple lowercase group names containing letters, numbers, hyphens, or underscores. Most importantly, record the exact spelling.\nProxmox treats these as different group names:\nproxmox-admins proxmox_admins A hyphen and an underscore are not interchangeable.\nStep 5: Create a Dedicated Pocket ID OIDC Client In Pocket ID, open the OIDC client section and create a new client.\nUse a descriptive name such as:\nProxmox Set the callback URL to exactly ( no trailing slash):\nhttps://proxmox.yourdomain.com Do not use any of these variations:\nhttps://proxmox.yourdomain.com/ https://proxmox.yourdomain.com:8006 https://PROXMOX-LAN-IP:8006 https://proxmox.yourdomain.com/callback https://proxmox.yourdomain.com/api2/json/access/openid/login The callback must match the browser-facing Proxmox base URL.\nUnder Allowed User Groups, select:\nproxmox_users proxmox_admins A new Pocket ID OIDC client does not allow anyone to sign in until you select the allowed users or groups. Use Unrestrict only if you intentionally want every Pocket ID user to access this Proxmox login.\nAfter saving the client, securely copy:\nClient ID Client Secret Do not publish either value in screenshots, terminal output, or documentation. If any part of the client secret becomes visible, rotate it in Pocket ID and update the Proxmox realm.\nStep 6: Add the OpenID Connect Realm in Proxmox Log in to https://proxmox.yourdomain.com using root@pam.\nNavigate to:\nDatacenter → Permissions → Realms → Add → OpenID Connect Server Enter the following settings:\nField Value Issuer URL https://pocketid.yourdomain.com Realm pocketid Client ID Client ID generated by Pocket ID Client Key Client secret generated by Pocket ID Scopes openid profile email groups Autocreate Users Enabled Username Claim username Autocreate Groups Enabled Groups Claim groups Overwrite Groups Enabled Query userinfo endpoint Enabled Default Disabled during initial testing Leave these fields empty unless your identity provider specifically requires them:\nACR Values Audiences Prompt Why Use the Username Claim? Use:\nusername This creates a Proxmox account similar to:\nyouruser@pocketid Using the email claim would create a longer account name similar to:\nuser@example.com@pocketid The Proxmox interface offers supported username mappings such as username, email and the OIDC subject. Do not manually enter preferred_username when the Proxmox interface provides username.\nStep 7: Verify the Saved Realm On the Proxmox host, inspect the realm configuration:\ngrep -A20 \u0026#39;^openid: pocketid\u0026#39; /etc/pve/domains.cfg A working configuration should resemble:\nopenid: pocketid client-id REDACTED issuer-url https://pocketid.yourdomain.com autocreate 1 client-key REDACTED default 0 groups-autocreate 1 groups-claim groups groups-overwrite 1 query-userinfo 1 scopes openid profile email groups username-claim username Always redact the client ID and client key before sharing this output publicly.\nStep 8: Understand Proxmox OIDC Group Names This is one of the most important details in the configuration.\nProxmox does not use the Pocket ID group name unchanged. It appends the OIDC realm name as a suffix.\nFor example, Pocket ID sends:\nproxmox_admins The Proxmox realm is:\npocketid Proxmox therefore creates:\nproxmox_admins-pocketid The ordinary user group becomes:\nproxmox_users-pocketid Do not guess these final names. Perform the first login and inspect the automatically created groups.\nStep 9: Perform the First Passkey Login Keep the existing root@pam browser session open.\nOpen a private or incognito browser window. Visit https://proxmox.yourdomain.com. Select the pocketid realm. Click the OpenID login button. Confirm that the browser redirects to the correct Pocket ID domain. Authenticate with a registered passkey. Confirm that the browser returns to https://proxmox.yourdomain.com. At this stage, authentication may succeed while no nodes or resources are visible. This does not necessarily mean OIDC failed.\nIt usually means the new user has been created successfully but does not yet have a Proxmox permission assignment.\nStep 10: Verify the Automatically Created User On the Proxmox host, run:\npveum user list | grep \u0026#39;@pocketid\u0026#39; A successfully created account should appear similar to:\nyouruser@pocketid Inspect the relevant user and group entries:\ngrep -E \\ \u0026#39;proxmox_(users|admins)-pocketid|@pocketid\u0026#39; \\ /etc/pve/user.cfg Example:\nuser:youruser@pocketid:1:0:First:Last:user@example.com::: group:proxmox_admins-pocketid:youruser@pocketid:: group:proxmox_users-pocketid:youruser@pocketid:: This output reveals the exact group names Proxmox created.\nStep 11: Assign Administrator Permission to the Imported Group Assign permissions to the automatically created group, not directly to the user.\nFor the example group:\nproxmox_admins-pocketid Run:\npveum acl modify / \\ --group proxmox_admins-pocketid \\ --role Administrator The path / applies the role to the entire Proxmox installation.\nVerify the permission:\npveum acl list | grep pocketid The result should resemble:\n/ Administrator group proxmox_admins-pocketid Avoid Creating the Wrong Group One easy mistake is manually creating a group with hyphens while Pocket ID sends a group containing underscores.\nFor example, this manually created group:\nproxmox-admins-pocketid is different from the automatically imported group:\nproxmox_admins-pocketid If the Administrator ACL is assigned to the wrong group, authentication succeeds but the user may see no Proxmox nodes or resources.\nThe solution is to assign the ACL to the exact group shown in /etc/pve/user.cfg:\npveum acl modify / \\ --group proxmox_admins-pocketid \\ --role Administrator After confirming that the correct ACL works, remove any incorrect ACL and unused lookalike group.\nInspect the supported deletion syntax before removing an ACL:\npveum help acl delete The unused group can be removed with:\npveum group delete proxmox-admins-pocketid Never delete the group that contains the active OIDC user.\nStep 12: Sign In Again and Verify Access Sign out of the Pocket ID Proxmox session. Open a fresh private browser window. Visit https://proxmox.yourdomain.com. Select the pocketid realm. Authenticate with a passkey. The Proxmox node and permitted resources should now appear.\nThe permission chain is:\nPocket ID user → Pocket ID proxmox_admins group → OIDC groups claim → Proxmox proxmox_admins-pocketid group → Administrator role on / No direct user ACL is required.\nHow Automatic Group Updates Work The realm has these options enabled:\ngroups-autocreate 1 groups-overwrite 1 groups-autocreate allows Proxmox to create groups received through the OIDC groups claim.\ngroups-overwrite makes the identity provider authoritative for that OIDC user\u0026rsquo;s group membership during login.\nFor example, if a user is removed from proxmox_admins in Pocket ID, the user should lose membership in proxmox_admins-pocketid after the next successful login.\nThis makes permission management cleaner than assigning Administrator directly to individual OIDC accounts.\nStep 13: Verify Passkey Authentication To test the complete passkey flow rather than an existing Pocket ID browser session:\nSign out of Pocket ID. Open a new private browser window. Visit the Proxmox login page. Select the pocketid realm. Confirm the redirect goes to the legitimate Pocket ID hostname. Complete the passkey prompt. Confirm the browser returns to Proxmox. Confirm the logged-in user ends with @pocketid. Pocket ID handles the passkey authentication. Proxmox does not receive or store the passkey.\nWhy the Proxmox Host Shell Asks for a Login An OIDC user is a Proxmox application identity. It is not automatically a local Linux account on the Proxmox host.\nFor example:\nyouruser@pocketid may exist in the Proxmox access-control database, but it does not exist in:\n/etc/passwd Therefore, opening the host shell from the Proxmox interface while signed in through OIDC may display a Linux login prompt.\nThis differs from a root@pam session because root@pam maps to the real local Linux root account.\nThis is not an OIDC configuration failure.\nA practical operating model is:\nTask Authentication Proxmox web interface Pocket ID passkey VM and LXC administration Pocket ID passkey Guest console access Pocket ID passkey Proxmox host shell root@pam or local Linux credentials Direct host maintenance SSH key Identity-provider failure recovery root@pam or SSH key Step 14: Test Break-Glass Recovery After Pocket ID login works, test what happens when Pocket ID is unavailable.\nBefore stopping Pocket ID, verify both recovery methods:\nssh root@PROXMOX-LAN-IP Also verify that root@pam still works through the Proxmox web interface.\nStop the Pocket ID container or service using the command appropriate for your environment.\nFor a Proxmox LXC container, that may resemble:\npct shutdown CONTAINER-ID --timeout 60 pct status CONTAINER-ID Test the following:\nPocket ID login should fail because the identity provider is unavailable. root@pam login should continue to work. SSH key access to the Proxmox host should continue to work. Restart Pocket ID:\npct start CONTAINER-ID pct status CONTAINER-ID Confirm that the Proxmox host can reach OIDC discovery again:\ncurl -fsS \\ https://pocketid.yourdomain.com/.well-known/openid-configuration \\ \u0026gt;/dev/null \u0026amp;\u0026amp; echo \u0026#34;Pocket ID discovery reachable\u0026#34; Then repeat the private-window passkey login.\nTroubleshooting OIDC Login Works but No Proxmox Nodes Are Visible This usually means authentication succeeded, but the user has no ACL.\nCheck the imported groups:\ngrep -E \u0026#39;pocketid|@pocketid\u0026#39; /etc/pve/user.cfg Assign the Administrator role to the exact imported administrator group:\npveum acl modify / \\ --group EXACT_IMPORTED_GROUP_NAME \\ --role Administrator Do not assume hyphens and underscores are equivalent.\nRedirect URI Mismatch Confirm that the Pocket ID callback is exactly:\nhttps://proxmox.yourdomain.com Do not append a slash, port number, or callback path.\nUser is created, but Groups Are Missing Verify that the realm contains:\nscopes openid profile email groups groups-claim groups groups-autocreate 1 Also verify that the Pocket ID user belongs to the expected groups and that those groups are allowed to use the OIDC client.\nProxmox Interface Works but noVNC Does Not Check that Nginx Proxy Manager has WebSocket support enabled.\nAlso confirm that no access list or second authentication proxy is intercepting WebSocket requests.\nInspect Proxmox Authentication Logs journalctl -f \\ -u pveproxy \\ -u pvedaemon Recent OIDC-related messages can be filtered with:\njournalctl --since \u0026#34;-10 minutes\u0026#34; | grep -Ei \u0026#39;openid|oidc|authentication|realm|group\u0026#39; Inspect Users, Groups and Permissions pveum realm list pveum user list pveum group list pveum acl list Final Verification Checklist Pocket ID The ordinary user group exists. The administrator group exists. The administrator account belongs to both groups. A dedicated OIDC client exists for this Proxmox installation. The callback is exactly https://proxmox.yourdomain.com. The client ID and secret are stored securely. Proxmox Realm The realm ID is pocketid. The issuer URL is the Pocket ID base URL. The username claim is username. The scopes are openid profile email groups. Automatic user creation is enabled. The groups claim is groups. Automatic group creation is enabled. Group overwrite is enabled. The userinfo endpoint option is enabled. The PAM realm remains available. Permissions The OIDC user was created successfully. The exact imported group names were checked in /etc/pve/user.cfg. The Administrator ACL is assigned to the actual imported administrator group. No direct Administrator ACL is required for the individual user. No unused lookalike group remains with hyphens or underscores in the wrong places. Reverse Proxy The Proxmox hostname has a valid certificate. Nginx Proxy Manager forwards to HTTPS port 8006. WebSocket support is enabled. noVNC and browser consoles work. No second authentication layer is placed in front of Proxmox. Recovery root@pam remains usable. SSH key access remains usable. Pocket ID login fails safely while Pocket ID is stopped. Local PAM and SSH access continue working while Pocket ID is unavailable. Passkey login works again after Pocket ID restarts. Conclusion Pocket ID provides a clean passkey-based login experience for Proxmox VE without replacing the local PAM or SSH recovery paths.\nThe most important implementation detail is group naming. Proxmox automatically appends the realm suffix to groups received from Pocket ID. Always inspect the generated groups after the first login instead of manually guessing their final names.\nOnce the correct imported group receives the Administrator ACL, Pocket ID group membership becomes the source of authorization. Users can then be granted or removed from Proxmox administration through Pocket ID without assigning permissions directly to each Proxmox account.\nOIDC should remain an additional management layer. Keep root@pam and SSH keys available so that Proxmox remains recoverable even when Pocket ID or the reverse proxy is unavailable.\nLet me know if this helped or if you have implemented something similar like with Authentik.\n","permalink":"https://rabin.blog/how-to-configure-pocket-id-passkey-login-for-proxmox-ve-with-oidc-groups/","summary":"\u003cp\u003eI have been eying implementing OIDC in the homelab for a while now. After a lot of research, while I found out Authentik is much more diverse and detailed, I went with the simpler solution. I will explain below how to connect Pocket ID to a standalone Proxmox VE installation using OpenID Connect, or OIDC.\u003c/p\u003e\n\u003cp\u003eThe result is a Proxmox login flow where users authenticate through \u003cstrong\u003ePocket ID using a passkey\u003c/strong\u003e. Proxmox users and groups are created automatically, while administrator permissions are assigned through a Pocket ID group instead of directly to individual users.\u003c/p\u003e","title":"How to Configure Pocket ID Passkey Login for Proxmox VE with OIDC Groups"},{"content":"If a Dell OptiPlex Micro running Proxmox stays around 70+ °C at low load, check whether Linux is using the performance CPU governor with intel_pstate active; switching to powersave and persisting it with a small systemd oneshot service can drop temperatures kind of, magically.\nProblem: Proxmox Host Stayed Hot Even After Hardware Maintenance\nThis incident happened on a Dell OptiPlex 7070 Micro running Proxmox VE as an always-on homelab control-plane node. To avoid exposing private infrastructure details, I will call the machine Proxmox node-02 for the readers.\nThe symptom was simple but worrying: CPU temperatures were sitting around 71–72°C during normal operation. That is not necessarily an instant danger for an Intel CPU, but it is warmer than I wanted for a 24/7 mini PC running critical home services.\nThe worrying part was that normal hardware maintenance had already been done:\nThermal paste had been replaced. The internal CPU fan had been replaced. The chassis had been cleaned. The node was still functional, but thermal headroom looked poor. Because the machine hosted services such as Proxmox workloads, Home Assistant, MQTT, Zigbee2MQTT, and UPS monitoring, the concern was not only noise or comfort. The concern was the long-term reliability of a machine that was expected to stay online all day.\nAt that point, I was scratching my head because if I wanted to replace this machine, it would take out some significant money.\nBefore spending any money, I checked the operating system\u0026rsquo;s power-management state.\nAssessment: The CPU Governor Was the Real Clue The important discovery was that the CPU frequency governor was set to performance, while Intel P-state management was active.\nCommands used to check the governor cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 2\u0026gt;/dev/null | sort -u cat /sys/devices/system/cpu/intel_pstate/status 2\u0026gt;/dev/null The incident result was:\nperformance active That combination explained why a small, always-on Proxmox machine could remain hotter than expected. With the performance governor, the system prefers higher performance states instead of aggressively lowering frequency during lighter periods. On a tiny Dell Micro chassis, that can mean a warmer CPU package even when the machine is not doing heavy work.\nThe package path that did not work A common older Linux answer is to install cpufrequtils and run cpufreq-set. On this Debian/Proxmox environment, that path failed:\napt install -y cpufrequtils cpufreq-set -r -g powersave The relevant failure was:\nPackage cpufrequtils is not available, but is referred to by another package. Error: Package \u0026#39;cpufrequtils\u0026#39; has no installation candidate -bash: cpufreq-set: command not found That failure was not a blocker. Because the kernel cpufreq sysfs interface was present, the governor could be changed directly by writing powersave into each CPU\u0026rsquo;s scaling_governor file.\nSolution: Persist the Powersave Governor with systemd The fix was to set every CPU core governor to powersave and make that setting persistent at boot with a systemd oneshot service.\nThe immediate manual command is:\nfor g in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo powersave \u0026gt; \u0026#34;$g\u0026#34; done cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 2\u0026gt;/dev/null | sort -u Expected result:\npowersave However, a manual sysfs write is not enough because it may be lost after reboot, kernel changes, or later power-management changes. That is why the permanent solution uses systemd.\nHighlighted solution for Proxmox Dell OptiPlex Micro high CPU temperature If your Proxmox Dell OptiPlex Micro has high idle or low-load CPU temperatures and cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor | sort -u returns performance, create /etc/systemd/system/cpu-governor-powersave.service and set the CPU governor to powersave on boot. This was the fix that changed the host from roughly 71–72 °C to a much healthier temperature range of 41–45 °C.\nCopy-Paste Fix Code Run the following commands as root on the Proxmox host. Proxmox hosts commonly use root shells, so the commands below intentionally do not include sudo.\ncat \u0026gt; /etc/systemd/system/cpu-governor-powersave.service \u0026lt;\u0026lt;\u0026#39;EOF\u0026#39; # ============================================================ # Script Name: cpu-governor-powersave.service # Description: # Sets CPU frequency governor to powersave on boot for lower # thermal load on an always-on Proxmox mini PC. # # Dependencies: # - Linux cpufreq sysfs interface # - systemd # # Usage: # systemctl enable --now cpu-governor-powersave.service # # Notes: # - This intentionally favors thermal stability over maximum # burst CPU performance. # - Hostname and LAN details are intentionally not embedded. # ============================================================ [Unit] Description=Set CPU governor to powersave After=multi-user.target [Service] Type=oneshot ExecStart=/bin/sh -c \u0026#39;for g in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo powersave \u0026gt; \u0026#34;$g\u0026#34;; done\u0026#39; RemainAfterExit=yes [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now cpu-governor-powersave.service Is this the same code still active on the original node? Yes. I rechecked the live Proxmox host before finalizing this article. The public version above removes private comments such as the original node label, but the active service logic is the same. The live service still uses:\nType=oneshot ExecStart=/bin/sh -c \u0026#39;for g in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo powersave \u0026gt; \u0026#34;$g\u0026#34;; done\u0026#39; RemainAfterExit=yes WantedBy=multi-user.target The service is currently enabled and active (exited), which is the expected state for a successful one-shot service with RemainAfterExit=yes.\nHow to Verify the Fix After enabling the service, verify three things:\nThe service is enabled. The service ran successfully. The current governor is powersave. systemctl status cpu-governor-powersave.service --no-pager systemctl is-enabled cpu-governor-powersave.service systemctl is-active cpu-governor-powersave.service cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 2\u0026gt;/dev/null | sort -u cat /sys/devices/system/cpu/intel_pstate/status 2\u0026gt;/dev/null sensors Expected governor and P-state output:\npowersave active On the live host, verification showed:\ncpu-governor-powersave.service: enabled cpu-governor-powersave.service: active CPU governors: powersave intel_pstate: active The current observed thermal reading was also healthy for this machine class:\nCPU package: about 43°C CPU cores: about 41–44°C PCH: about 42°C NVMe: about 35°C Temperatures vary with ambient room temperature, dust, BIOS profile, workload, paste quality, and fan condition. The important point is not that every Dell Micro will show the same number. The significant point is that the governor changed from performance to powersave and the thermal baseline dropped substantially.\nWhy I Did Not Use Cron A cron entry could repeatedly write powersave into sysfs. For example, someone might suggest running a line every few minutes or at reboot. I did not choose that approach because this is not a recurring task. It is a boot-time configuration state.\nWhy systemd is the better fit Correct lifecycle: the governor only needs to be applied at boot or when the service is explicitly restarted. Clear status: systemctl status cpu-governor-powersave.service shows whether the fix ran successfully. Better logging: failures appear in the journal with the service name. No repeated writes: cron would keep writing the same value forever even when nothing changed. Cleaner operations: the service can be enabled, disabled, restarted, inspected, and documented like other host configuration. Boot ordering: systemd makes it explicit that this runs as part of the normal boot target. Use cron for repeated scheduled work. Use systemd for machine state that should be applied and tracked as part of boot. This CPU governor fix is the second category.\nObserved Result Before the fix, CPU temperatures were observed around 71–72°C, even after paste replacement, fan replacement, and cleaning.\nImmediately after switching to powersave, temperatures dropped into a much healthier range. The incident note recorded readings such as:\nCPU package: about 56°C CPU cores: about 52–56°C PCH: about 56°C NVMe: about 38°C On later live verification, the same host was even cooler under its then-current workload:\nCPU package: about 43°C CPU cores: about 41–44°C PCH: about 42°C NVMe: about 35°C That changed the decision. Instead of replacing the Dell OptiPlex Micro because it appeared too hot for 24/7 use, the host remained in service, and the hardware replacement wasn\u0026rsquo;t necessary.\nTroubleshooting and Edge Cases If /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor does not exist Your kernel, CPU driver, BIOS settings, or virtualization environment may not expose cpufreq governor controls in the same way. Check:\nls /sys/devices/system/cpu/cpu0/cpufreq/ cat /sys/devices/system/cpu/intel_pstate/status 2\u0026gt;/dev/null cat /sys/devices/system/cpu/amd_pstate/status 2\u0026gt;/dev/null If there is no cpufreq sysfs interface, this exact fix does not apply. Look at BIOS power settings, kernel CPU frequency drivers, and Proxmox/kernel documentation for your CPU generation.\nIf the service is active but the governor is still performance Check for another tool or service changing the governor after boot:\nsystemctl list-unit-files | grep -Ei \u0026#39;power|tuned|cpufreq|thermald\u0026#39; journalctl -b --no-pager | grep -Ei \u0026#39;governor|cpufreq|pstate|tuned|thermald\u0026#39; If another service deliberately sets performance, do not blindly fight it. Decide which policy should own CPU power management and disable or reconfigure the conflicting service.\nIf temperatures are still high after powersave Then the governor was not the only problem. Continue with normal thermal checks:\nConfirm the fan actually spins and ramps under load. Check heatsink mounting pressure and paste application. Clean dust from intake and exhaust paths. Review BIOS thermal profile, Intel Turbo Boost, C-states, SpeedStep, and Speed Shift. Check whether a VM, LXC, backup, or indexing task is creating real load. Compare idle temperature after 10–15 minutes of low load. For Your Checklist If you found this article because your Proxmox Dell OptiPlex Micro is running hot, follow this order before replacing hardware:\nCheck current temperatures with sensors. Check the current CPU governor with cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 2\u0026gt;/dev/null | sort -u. Check P-state mode with cat /sys/devices/system/cpu/intel_pstate/status 2\u0026gt;/dev/null. If the governor is performance, test powersave manually. If temperatures improve, install the cpu-governor-powersave.service systemd service. Reboot during a maintenance window and verify the governor remains powersave. Only then decide whether hardware replacement is still justified. Bottom line: for this Proxmox Dell OptiPlex Micro high-temperature case, the root cause was not failed cooling hardware. The CPU governor was set to performance. Changing it to powersave and persisting that state with a systemd oneshot service fixed the thermal baseline and avoided an unnecessary device replacement.\nRelated reading Back up Proxmox configuration with Git Fix Intel e1000e network hangs on Proxmox ","permalink":"https://rabin.blog/fix-proxmox-high-cpu-temperature-using-cpu-governor-trick/","summary":"\u003cp\u003eIf a Dell OptiPlex Micro running Proxmox stays around 70+ °C at low load, check whether Linux is using the \u003ccode\u003eperformance\u003c/code\u003e CPU governor with \u003ccode\u003eintel_pstate\u003c/code\u003e active; switching to \u003ccode\u003epowersave\u003c/code\u003e and persisting it with a small systemd oneshot service can drop temperatures kind of, magically.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: Proxmox Host Stayed Hot Even After Hardware Maintenance\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis incident happened on a Dell OptiPlex 7070 Micro running Proxmox VE as an always-on homelab control-plane node. To avoid exposing private infrastructure details, I will call the machine \u003cstrong\u003eProxmox node-02\u003c/strong\u003e for the readers.\u003c/p\u003e","title":"Fix Proxmox High CPU Temperature on Dell OptiPlex Micro: The CPU Governor Trick"},{"content":"This incident happened on a Dell OptiPlex Micro running Proxmox VE. The machine is my always-on Node02 host and carries critical home infrastructure:\nHome Assistant AdGuard Home Unbound DNS MQTT Zigbee2MQTT Other LAN support services At first, this looked like a disaster spread across half the house. That host is the backbone for the living room stack. It runs Home Assistant and several supporting services, so when its network dies, the failure can look like everything is broken at once. That is what makes these incidents so sneaky - the real problem is hidden behind a long chain of symptoms.\nThe hardware in question is a Dell OptiPlex 7070 Micro using an Intel I219-LM NIC with the e1000e driver. During the incident, the kernel repeatedly logged:\ne1000e 0000:00:1f.6 eno2: Detected Hardware Unit Hang: That message matters because it is not just a harmless warning; it means the NIC hardware or driver has wedged hard enough that the interface can stop behaving normally. If your host depends on that NIC for DNS, automation, and service reachability, the whole homelab can appear to collapse.\nWhen the Dell system appeared to hang, the impact looked much bigger than a single server issue:\nSmart devices stopped behaving normally. As they depend on Home Assistant. Smart-device schedules did not run. DNS via AdGuard Home and Unbound stopped working. The browser fails to work on other machines. Home Assistant and automation services became unreachable. The visible symptom was “ the system hung,” but the important detail was that many services failed together because they shared one network path through the Proxmox host.\nAssessment: It Was a Network Driver Hang, Not Just “The Server Froze” The key kernel log signature was:\ne1000e 0000:00:1f.6 eno2: Detected Hardware Unit Hang The affected machine and NIC details:\nHostProxmox Node02 / pve-node02HardwareDell OptiPlex Micro class systemNICIntel I219-LMLinux drivere1000eInterfaceeno2Failure signatureDetected Hardware Unit Hang\nThis type of failure can make the host look dead from the network even if the kernel is still running. That explains why Home Assistant, DNS, MQTT, and Zigbee-related services all disappeared together.\nUseful diagnosis commands journalctl --list-boots journalctl -b -k --no-pager | grep -Ei \u0026#39;e1000e|Detected Hardware Unit Hang|eno2\u0026#39; ethtool -i eno2 ethtool -k eno2 ethtool -S eno2 | grep -Ei \u0026#39;err|drop|timeout|restart|reset|collision|crc|fifo|carrier|watchdog\u0026#39; If you see repeated Detected Hardware Unit Hang messages for e1000e, treat the NIC/driver path as a prime suspect.\nSolution Summary: Proxmox Intel e1000e Hardware Unit Hang Fix The solution has two layers:\nPrimary mitigation: disable problematic offload features on the Intel e1000e interface using ethtool, and make that persistent with a systemd service. Safety net: add a systemd watchdog timer that checks recent kernel logs for Detected Hardware Unit Hang, rate-limits recovery attempts, resets eno2 only when needed, and reapplies the offload mitigation after a reset. This is intentionally not just a cron job. The systemd timer gives better logging, service status, timer visibility, and failure semantics.\nFix Part 1: Disable Intel e1000e Offloads Persistently The first fix is to disable NIC offloads that are commonly involved in Intel e1000e hardware-unit hang issues.\nCreate the systemd service cat \u0026gt;/etc/systemd/system/disable-nic-offload-eno2.service \u0026lt;\u0026lt;\u0026#39;EOF\u0026#39; [Unit] Description=Disable NIC offloading for Intel e1000e interface eno2 After=network-pre.target Wants=network-pre.target [Service] Type=oneshot ExecStart=/sbin/ethtool -K eno2 gso off gro off tso off tx off rx off rxvlan off txvlan off sg off RemainAfterExit=yes [Install] WantedBy=multi-user.target EOF Enable it systemctl daemon-reload systemctl enable --now disable-nic-offload-eno2.service Verify it systemctl is-enabled disable-nic-offload-eno2.service systemctl is-active disable-nic-offload-eno2.service ethtool -k eno2 | grep -E \u0026#39;tcp-segmentation-offload|generic-segmentation-offload|generic-receive-offload|rx-checksumming|tx-checksumming|scatter-gather|rx-vlan-offload|tx-vlan-offload\u0026#39; On the active Node02 host, the verified offload state is:\nrx-checksumming: off tx-checksumming: off scatter-gather: off tx-scatter-gather: off tx-scatter-gather-fraglist: off [fixed] tcp-segmentation-offload: off generic-segmentation-offload: off generic-receive-offload: off rx-vlan-offload: off tx-vlan-offload: off Fix Part 2: Add a systemd Watchdog for Self-Recovery The offload service is the main mitigation. The watchdog is a second layer: if the NIC still logs a fresh Detected Hardware Unit Hang and the host is still alive, it tries to reset eno2.\nImportant: this is the exact logic currently active on Node02. It uses a 5-minute journal lookback, not 2 minutes, because the systemd timer runs every 2 minutes with AccuracySec=30s. A strict 2-minute lookback could miss an event if the timer fires late.\nCreate the watchdog script cat \u0026gt;/usr/local/sbin/e1000e-eno2-watchdog \u0026lt;\u0026lt;\u0026#39;EOF\u0026#39; #!/usr/bin/env bash set -u set -o pipefail IFACE=\u0026#34;eno2\u0026#34; LOOKBACK=\u0026#34;5 minutes ago\u0026#34; LOCK=\u0026#34;/run/e1000e-${IFACE}-watchdog.lock\u0026#34; STAMP=\u0026#34;/run/e1000e-${IFACE}-last-reset\u0026#34; MIN_RESET_INTERVAL_SECONDS=600 exec 9\u0026gt;\u0026#34;$LOCK\u0026#34; flock -n 9 || exit 0 if ! journalctl -k --since \u0026#34;$LOOKBACK\u0026#34; --no-pager \\ | grep -Eqi \u0026#34;e1000e .*${IFACE}: Detected Hardware Unit Hang|Detected Hardware Unit Hang\u0026#34;; then exit 0 fi now=\u0026#34;$(date +%s)\u0026#34; last=0 [ -f \u0026#34;$STAMP\u0026#34; ] \u0026amp;\u0026amp; last=\u0026#34;$(cat \u0026#34;$STAMP\u0026#34; 2\u0026gt;/dev/null || echo 0)\u0026#34; if [ $((now - last)) -lt \u0026#34;$MIN_RESET_INTERVAL_SECONDS\u0026#34; ]; then logger -t e1000e-watchdog \u0026#34;hardware hang detected on ${IFACE}, but reset suppressed by rate limit\u0026#34; exit 0 fi logger -t e1000e-watchdog \u0026#34;hardware hang detected on ${IFACE}; resetting NIC\u0026#34; if ! ip link set \u0026#34;$IFACE\u0026#34; down; then logger -t e1000e-watchdog \u0026#34;failed to bring ${IFACE} down; NIC reset incomplete\u0026#34; exit 1 fi sleep 2 if ! ip link set \u0026#34;$IFACE\u0026#34; up; then logger -t e1000e-watchdog \u0026#34;failed to bring ${IFACE} up; NIC reset incomplete\u0026#34; exit 1 fi # Re-apply the offload mitigation after link reset, just in case. ethtool -K \u0026#34;$IFACE\u0026#34; gso off gro off tso off tx off rx off rxvlan off txvlan off sg off 2\u0026gt;/dev/null || \\ logger -t e1000e-watchdog \u0026#34;warning: unable to re-apply offload mitigation on ${IFACE}\u0026#34; date +%s \u0026gt;\u0026#34;$STAMP\u0026#34; logger -t e1000e-watchdog \u0026#34;NIC reset completed for ${IFACE}\u0026#34; EOF chmod +x /usr/local/sbin/e1000e-eno2-watchdog Create the watchdog service cat \u0026gt;/etc/systemd/system/e1000e-eno2-watchdog.service \u0026lt;\u0026lt;\u0026#39;EOF\u0026#39; [Unit] Description=Watch for Intel e1000e hardware hangs and reset eno2 After=network-online.target [Service] Type=oneshot ExecStart=/usr/local/sbin/e1000e-eno2-watchdog EOF Create the watchdog timer cat \u0026gt;/etc/systemd/system/e1000e-eno2-watchdog.timer \u0026lt;\u0026lt;\u0026#39;EOF\u0026#39; [Unit] Description=Run e1000e eno2 watchdog every 2 minutes [Timer] OnBootSec=2min OnUnitActiveSec=2min AccuracySec=30s Unit=e1000e-eno2-watchdog.service [Install] WantedBy=timers.target EOF Enable the timer systemctl daemon-reload systemctl enable --now e1000e-eno2-watchdog.timer Why the script exits non-zero on reset failure If ip link set eno2 down or ip link set eno2 up fails, the watchdog must not pretend recovery succeeded. The script exits with status 1 before writing the reset stamp. That prevents a failed reset from being hidden by the 10-minute rate limit.\nWhy I Did Not Use the Cron One-Liner A suggested cron approach looked like this:\n*/2 * * * * dmesg -T --since \u0026#34;2 min ago\u0026#34; 2\u0026gt;/dev/null | grep -qi \u0026#34;hardware unit hang\u0026#34; \u0026amp;\u0026amp; \\ ip link set eno2 down \u0026amp;\u0026amp; sleep 2 \u0026amp;\u0026amp; ip link set eno2 up This can work as a quick test, but I do not recommend it for a critical Proxmox host running DNS and smart-home services.\nProblems with the cron approach No robust service status: systemd gives systemctl status, exit codes, and timer visibility. No lock by default: overlapping cron runs are possible unless you add flock. No rate limit by default: a recurring log message could flap the interface repeatedly. Too narrow timing window: a strict 2-minute lookback can miss an event if the scheduler runs late. Weak failure semantics: if reset fails, cron can hide the failure unless explicitly logged and checked. No offload reapply: the one-liner brings the link back but does not reapply the ethtool -K mitigation. Harder monitoring: systemd timer and service logs are easier to inspect with journalctl. The systemd version keeps the same recovery idea but makes it operationally safer.\nVerification Commands Use these commands after installing the fix:\nsystemctl status disable-nic-offload-eno2.service --no-pager -l systemctl status e1000e-eno2-watchdog.timer --no-pager -l systemctl list-timers e1000e-eno2-watchdog.timer --no-pager systemctl status e1000e-eno2-watchdog.service --no-pager -l ethtool -k eno2 | grep -E \u0026#39;tcp-segmentation-offload|generic-segmentation-offload|generic-receive-offload|rx-checksumming|tx-checksumming|scatter-gather|rx-vlan-offload|tx-vlan-offload\u0026#39; journalctl -k --since \u0026#34;24 hours ago\u0026#34; --no-pager | grep -i \u0026#34;hardware unit hang\u0026#34; || true journalctl -t e1000e-watchdog --since \u0026#34;24 hours ago\u0026#34; --no-pager || true Current verified Node02 state At the time of finalizing this post, Node02 reported:\ndisable-nic-offload-eno2.service: enabled, active e1000e-eno2-watchdog.timer: enabled, active watchdog next run: scheduled every 2 minutes selected eno2 offloads: off recent hardware unit hangs: none in last 24 hours watchdog action logs: no entries No watchdog action logs is healthy here. It means the timer is running, but it has not found a fresh NIC hang to recover from.\nOptional External Monitoring with Uptime Kuma The watchdog is local to the Proxmox host. For better visibility, monitor the host from another machine outside the failure domain. In my setup, Uptime Kuma runs on a separate mini PC.\nSuggested Uptime Kuma monitor tree:\nNode02 / Living Room Critical Stack ├── Node02 host ping: 192.168.XX.2 ├── Node02 Proxmox UI: https://192.168.XX.2:8006 ├── Home Assistant HTTP: http://\u0026lt;ha-ip\u0026gt;:8123 ├── AdGuard DNS query: @\u0026lt;adguard-ip\u0026gt; google.com A ├── MQTT TCP: \u0026lt;mqtt-ip\u0026gt;:1883 ├── Zigbee2MQTT UI: http://\u0026lt;z2m-ip\u0026gt;:8080 └── Router/gateway ping: 192.168.XX.1 Keep the router/gateway check as an independent baseline. If the router is up but Node02, Home Assistant, AdGuard, MQTT, and Zigbee2MQTT fail together, suspect the Node02 host or NIC path.\nFinal Notes and Escalation Path This fix is a practical mitigation, not a guarantee that the Intel NIC can never hang again.\nIf Detected Hardware Unit Hang returns repeatedly even after offloads are disabled, I would escalate in this order:\nVerify offloads are still disabled after reboot or kernel updates. Check cable and switch port. Update or test a different Proxmox kernel during a maintenance window. Move critical services or management traffic to a different NIC path, such as USB Ethernet or another host. Consider replacing the host if the integrated NIC remains unreliable. Bottom line: the most searchable solution for this class of issue is: disable Intel e1000e offloads with ethtool -K, persist it with systemd, and use a rate-limited systemd watchdog timer instead of a raw cron job for emergency NIC reset recovery.\nRelated reading Upgrade Proxmox 8 to 9 safely Reduce high Proxmox CPU temperatures ","permalink":"https://rabin.blog/fix-intel-e1000e-detected-hardware-unit-hang-on-proxmox/","summary":"\u003cp\u003eThis incident happened on a Dell OptiPlex Micro running Proxmox VE. The machine is my always-on Node02 host and carries critical home infrastructure:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eHome Assistant\u003c/li\u003e\n\u003cli\u003eAdGuard Home\u003c/li\u003e\n\u003cli\u003eUnbound DNS\u003c/li\u003e\n\u003cli\u003eMQTT\u003c/li\u003e\n\u003cli\u003eZigbee2MQTT\u003c/li\u003e\n\u003cli\u003eOther LAN support services\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAt first, this looked like a disaster spread across half the house. That host is the backbone for the living room stack. It runs Home Assistant and several supporting services, so when its network dies, the failure can look like everything is broken at once. That is what makes these incidents so sneaky - the real problem is hidden behind a long chain of symptoms.\u003c/p\u003e","title":"Fix Intel e1000e “Detected Hardware Unit Hang” on Proxmox"},{"content":"There are two kinds of Uptime Kuma migrations:\nThe one that works. The one where people export JSON, assume life is good, then discover half their setup is missing. This guide is for the first one.\nThe safest and least error-prone way to migrate Uptime Kuma is:\nMove the ENTIRE data directory.\nNot screenshots.\nNot copy-paste.\nNot “I exported a backup JSON so I should be fine.”\nThe actual source of truth is the database and app data.\nWhat Actually Needs to Be Backed Up Uptime Kuma stores everything in its data directory.\nCritical files:\nkuma.db kuma.db-wal kuma.db-shm uploads/ The important one is the kuma.db - the rest can be ignored.\nkuma.db That is your monitors, notifications, users, settings, status pages, and integrations.\nIf you lose that file, congratulations, you now own an empty monitoring dashboard.\nBefore You Start Recommended Approach Stop Uptime Kuma completely Copy the entire data folder Restore the folder on the new system Start Uptime Kuma again This avoids:\nSQLite corruption Partial copies Missing WAL data Broken monitors Silent failures METHOD 1 — Docker-Based Uptime Kuma Migration This is the most common setup.\nStep 1 — Find Your Data Directory services: uptime-kuma: image: louislam/uptime-kuma:latest container_name: uptime-kuma volumes: - /opt/uptime-kuma:/app/data In this example:\n/opt/uptime-kuma Is your actual data?\nStep 2 — Stop the Container docker stop uptime-kuma Step 3 — Create a Proper Backup tar -czvf uptime-kuma-backup.tar.gz -C /opt uptime-kuma Step 4 — Move Backup to New Server scp uptime-kuma-backup.tar.gz user@newserver:/root/ Step 5 — Install Fresh Uptime Kuma on New Server docker compose up -d Then stop it again:\ndocker stop uptime-kuma Step 6 — Restore Your Backup rm -rf /opt/uptime-kuma/* tar -xzvf uptime-kuma-backup.tar.gz -C /opt/ Step 7 — Start Uptime Kuma docker start uptime-kuma METHOD 2 — Direct Install Migration (Non-Docker) Step 1 — Find the Data Directory find / -type f -name \u0026#34;kuma.db\u0026#34; 2\u0026gt;/dev/null Step 2 — Stop Uptime Kuma Properly Check systemd first systemctl status uptime-kuma sudo systemctl stop uptime-kuma If using PM2 pm2 list pm2 stop uptime-kuma If manually started ps aux | grep node kill PID Step 3 — Backup the Data Folder tar -czvf uptime-kuma-direct-backup.tar.gz -C /opt/uptime-kuma data Step 4 — Move Backup to New Server scp uptime-kuma-direct-backup.tar.gz user@newserver:/root/ Step 5 — Install Fresh Uptime Kuma git clone https://github.com/louislam/uptime-kuma.git cd uptime-kuma npm install Step 6 — Restore Data rm -rf /opt/uptime-kuma/data/* tar -xzvf uptime-kuma-direct-backup.tar.gz -C /opt/uptime-kuma/ Step 7 — Start Uptime Kuma Again sudo systemctl start uptime-kuma The Migration Method People SHOULD Use If you want the least chance of disaster:\nDocker Bind-mounted persistent volume Nightly tar backup rsync to NAS This is boring.\nBoring is good.\nBoring restores at 2AM when something dies.\nWhat NOT To Do Do NOT rely only on JSON export.\nInside Settings → Backup, there is a JSON export.\nTreat it as convenience, not disaster recovery.\nDo not use it for full state backup.\nRecommended Backup Script #!/bin/bash BACKUP_DIR=\u0026#34;/backup/uptime-kuma\u0026#34; DATE=$(date +%F-%H%M) mkdir -p \u0026#34;$BACKUP_DIR\u0026#34; docker stop uptime-kuma tar -czvf \u0026#34;$BACKUP_DIR/uptime-kuma-$DATE.tar.gz\u0026#34; -C /opt uptime-kuma docker start uptime-kuma Final Thoughts People massively overcomplicate monitoring stacks.\nUptime Kuma itself is actually simple.\nThe important thing is respecting the database.\nIf you:\nstop the service properly move the entire data folder restore it cleanly then migration is usually painless.\nIf you skip steps because “it should probably work”\u0026hellip;\nthat is usually where the suffering begins.\nRelated reading Automate Dockerized n8n backups Back up Proxmox configuration with Git ","permalink":"https://rabin.blog/how-to-properly-backup-move-uptime-kuma-docker-or-direct/","summary":"\u003cp\u003eThere are two kinds of Uptime Kuma migrations:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eThe one that works.\u003c/li\u003e\n\u003cli\u003eThe one where people export JSON, assume life is good, then discover half their setup is missing.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eThis guide is for the first one.\u003c/p\u003e\n\u003cp\u003eThe safest and least error-prone way to migrate Uptime Kuma is:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eMove the ENTIRE data directory.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eNot screenshots.\u003cbr\u003e\nNot copy-paste.\u003cbr\u003e\nNot “I exported a backup JSON so I should be fine.”\u003c/p\u003e\n\u003cp\u003eThe actual source of truth is the database and app data.\u003c/p\u003e","title":"How to Properly Backup, Move, and Migrate Uptime Kuma (Docker + Direct Install)"},{"content":"Stop treating your Proxmox configuration like it\u0026rsquo;s disposable. Start treating it like code.\nGitHub: ruhanirabin/pve-config-git\nThe Problem: Configuration Drift Is a Silent Killer I\u0026rsquo;ve been running Proxmox for years. Multiple nodes, dozens of VMs, complex network configs, storage pools, custom scripts. And like many of you, I made changes directly on the host. A quick edit to /etc/network/interfaces here, a storage tweak there, a firewall rule adjustment to get something working.\nIt worked fine until it didn\u0026rsquo;t.\nOne Tuesday evening, I updated a network bridge configuration. The change seemed innocent enough. I rebooted the node to apply it, and\u0026hellip; silence. The node never came back online. No SSH, no web UI, nothing.\nI had to drive to the data center, plug in a crash cart, and spend three hours troubleshooting what should have been a five-minute fix. The root cause? A typo in a bridge name that I introduced during the edit. But here\u0026rsquo;s the kicker: I had no idea what the previous working configuration looked like.\nI had backups of my VMs. I had snapshots of VM disks. But I had zero history of my node configuration changes.\nSound familiar?\nThe Realization: Proxmox Config Is Infrastructure Code Here\u0026rsquo;s what most Proxmox operators get wrong: they treat VM backups as sufficient protection. They\u0026rsquo;re not.\nVM backups protect your virtual machines. They do not protect:\nYour network configuration ( /etc/network/interfaces) Your storage definitions ( /etc/pve/storage.cfg) Your cluster settings ( /etc/pve/corosync.conf) Your custom firewall rules ( /etc/pve/firewall/*.fw) Your node-specific scripts and cron jobs Your SSH keys and authentication settings When your node configuration breaks, VM backups are useless. You can\u0026rsquo;t restore a VM if the node won\u0026rsquo;t boot. You can\u0026rsquo;t migrate VMs if the network is misconfigured.\nYour Proxmox configuration is infrastructure code. And infrastructure code deserves version control.\nWhat I Actually Needed I looked at existing solutions:\nProxmox Backup Server: Excellent for VM backups. Overkill and complex just for config. rsync to remote server: Gets the files there, but no change history. No, \u0026ldquo;What changed last Tuesday?\u0026rdquo; etckeeper: Close, but Proxmox stores critical config in /etc/pve/ which is a special FUSE mount, not a standard filesystem. Manual git init: Doable, but I needed automation. I needed it to commit on schedule and on shutdown without me remembering to do it. What I needed was specific:\nAutomatic – Set it and forget it Git-based – Full change history, diffs, rollbacks Proxmox-aware – Knows where the config files actually live Safe – Won\u0026rsquo;t break if Git is temporarily unreachable Notified – Tell me when backups succeed or fail Nothing existed that checked all these boxes.\nSo I built it.\nIntroducing: Proxmox (PVE) Config Git PCG is a lightweight, purpose-built toolkit that treats your Proxmox node configuration like the code it is.\nIt does one thing and does it well: automatically snapshots your Proxmox configuration to a private Git repository, on schedule and on shutdown, with Telegram or webhook notifications.\nWhat It Actually Does Every hour (configurable), PCG:\nCollects your Proxmox configuration files Commits them to a local Git repository if anything changed Pushes to your private GitHub/GitLab remote Sends you a notification (optional) On node shutdown:\nRuns one final backup before the system halts Ensures you have the last known good config The result? A complete, timestamped history of every configuration change on your node. If something breaks, you can:\nSee exactly what changed and when See who changed it (commit author tracking) Roll back to any previous working state Compare configurations across nodes What It Does NOT Do Let\u0026rsquo;s be crystal clear: This is not a VM backup tool.\nPCG (Config Backup)Proxmox Backup Server (VM Backup)Backs up /etc/pve/*.cfg and custom shell scriptsBacks up VM disk imagesTracks config change historyCreates VM snapshotsLets you restore network/storage configsLets you restore VM dataLightweight (\u0026lt;1MB scripts)Full backup serverGit-based versioningImage-based snapshots\nYou need both. PCG protects your node configuration. Proxmox Backup Server (or vzdump) protects your VM data.\nHow It Works (The Technical Bits) Proxmox config backup to Git version control for PVE nodes. Version 7.26.\nPCG is built on a simple philosophy: use the right tool for each job.\nBash for the scripts (Proxmox is a Debian-based system; Bash is native) systemd timers for scheduling (already running, rock solid) Git for versioning (proven, decentralized, diff-friendly) SSH keys for authentication (standard, secure) The File Collection Strategy PCG collects configuration from these locations:\n/etc/pve/ # Proxmox VE configuration /etc/network/interfaces # Network configuration /etc/hosts, /etc/hostname # Host identification /etc/resolv.conf # DNS settings /root/custom-scripts/ # Your custom automation (optional) It uses a whitelist approach: only explicitly listed paths are backed up. No accidental inclusion of sensitive files like private keys or passwords.\nThe Safety Mechanisms I\u0026rsquo;ve built in multiple layers of safety:\nDeduplication – Only commits when files actually change Local-first – Works with local Git repo even if remote is down Auto-retry – Queues pushes when network is temporarily unavailable Shutdown protection – Won\u0026rsquo;t run duplicate backups during reboots Lock file guards – Prevents concurrent execution Test mode – PCG_TEST_MODE=true for safe testing Getting Started Prerequisites You\u0026rsquo;ll need:\nA Proxmox VE node (obviously) A private GitHub repository (empty, initialized) An SSH key added to your GitHub account A Telegram bot (optional but recommended for notifications) Installation Option 1: One-liner bootstrap (easiest)\nRun this in your Proxmox VE shell (not inside a VM):\nbash -c \u0026#34;$(curl -fsSL https://raw.githubusercontent.com/ruhanirabin/pve-config-git/main/install.sh)\u0026#34; The bootstrap will:\nCheck dependencies Detect any existing/legacy installation Show you a pre-install simulation Guide you through configuration interactively Option 2: Clone and install\ngit clone https://github.com/ruhanirabin/pve-config-git.git cd pve-config-git sudo ./bin/pcg install Initial Configuration The installer will prompt you for:\nGit remote URL – Your private repo (SSH: git@github.com:you/repo.git or HTTPS) Local repo path – Where to store the local Git repo ( /root/pve-config by default) Branch name – Usually main Commit identity – Your name and email for Git commits Log retention – How long to keep local logs (14 days default) Notifications – Telegram and/or webhook configuration Post-Install Verification # Run health check pcg doctor # Run manual backup (test it works) pcg backup # Send test notification pcg notify \u0026#34;PCG is now protecting this node\u0026#34; Daily Usage Once installed, PCG is largely invisible. It runs automatically:\n# Check what the timer is doing systemctl status pcg-backup-config.timer # View recent backup logs journalctl -u pcg-backup-config.service -n 20 # Run a manual backup pcg backup # Check overall health pcg doctor --json When Things Go Wrong \u0026ldquo;I broke my network config, and the node won\u0026rsquo;t connect\u0026rdquo;\nFrom another machine with Git access:\n# Clone your config repo git clone git@github.com:you/proxmox-config.git cd proxmox-config # Find the last working network config git log --oneline -10 # View the diff between last working and broken git diff HEAD~2 HEAD -- etc/network/interfaces # Copy the working config back (via IPMI/KVM or physical access) # Then reboot \u0026ldquo;I want to see what changed last week\u0026rdquo;\ncd /root/pve-config git log --since=\u0026#34;1 week ago\u0026#34; --oneline \u0026ldquo;I need to apply the same config to a second node\u0026rdquo;\n# On node 2, clone the config git clone git@github.com:you/proxmox-config.git /root/pve-config # Copy relevant configs (be careful!) # Then commit node 2\u0026#39;s identity separately Real-World Scenarios Scenario 1: The Botched Firewall Rule You add a firewall rule to /etc/pve/firewall/cluster.fw to block a suspicious IP. Hours later, you realize you used the wrong CIDR notation and locked yourself out of the web UI.\nWith PCG:\n# SSH into the node (you can still do this; firewall rules don\u0026#39;t affect established SSH) ssh root@proxmox-node# Restore last working firewall config cd /root/pve-config git checkout HEAD~1 -- etc/pve/firewall/cluster.fw cp etc/pve/firewall/cluster.fw /etc/pve/firewall/cluster.fw# Reload firewall pvefw reload Total downtime: 2 minutes. Without PCG? Hope you remember the exact syntax or have a screenshot.\nScenario 2: The Storage Migration Gone Wrong You\u0026rsquo;re migrating from local storage to a Ceph cluster. You update /etc/pve/storage.cfg with the new Ceph configuration. The GUI shows the storage as active, but VMs won\u0026rsquo;t start.\nWith PCG:\n# Check what actually changed cd /root/pve-config git diff HEAD~1 etc/pve/storage.cfg # Ah, you see the typo in the monhost IP address # Fix it in the live config, commit the correction git add etc/pve/storage.cfg git commit -m \u0026#34;fix: correct Ceph monhost IP\u0026#34; Scenario 3: The \u0026ldquo;What Changed?\u0026rdquo; Mystery Your Proxmox cluster has been acting strangely for days. You suspect a configuration change but nobody admits to making one.\nWith PCG:\ncd /root/pve-config # See all changes in the last 7 days git log --since=\u0026#34;7 days ago\u0026#34; --pretty=format:\u0026#34;%h - %an, %ar : %s\u0026#34; # See the actual diff for a specific commit git show abc1234 # There\u0026#39;s your smoking gun: someone changed corosync.conf Architecture Decisions (Why I Built It This Way) Why Git Instead of Rsync or Tarballs? Rsync gives you the latest state. Git gives you every state with metadata about who changed what and when.\nWhen your node is down, you want to browse history from your laptop. You want to compare. You intend to roll back. Git is the right tool.\nWhy systemd Instead of Cron? Native integration: Proxmox uses systemd. Timers are more reliable than cron for system services. Shutdown hooks: systemd can trigger backups on shutdown. Cron can\u0026rsquo;t. Status visibility: systemctl status gives you real insight into what\u0026rsquo;s happening. Why Bash Instead of Python/Go? Zero dependencies: Proxmox already has Bash. No package installation needed. Readability: Anyone who manages Proxmox knows Bash basics. Debuggability: When something breaks at 2 AM, you can read and understand the code immediately. Why Not Just Use etckeeper? etckeeper is great for /etc/. Proxmox configuration lives in /etc/pve/, which is a FUSE mount, not a standard filesystem. etckeeper doesn\u0026rsquo;t handle this gracefully. PCG is built specifically for Proxmox\u0026rsquo;s architecture.\nRoadmap and Contributing PCG is stable and in active use on my own infrastructure. Future enhancements I\u0026rsquo;m considering:\nMulti-node cluster config comparison – Detect config drift across nodes Pre-commit validation – Check config syntax before allowing commits Ansible/Puppet export – Generate automation manifests from running config Web dashboard – Optional web UI for browsing config history Contributions are welcome. The codebase is intentionally simple and well-commented.\nThe Bottom Line If you run Proxmox in production and you\u0026rsquo;re not versioning your configuration, you\u0026rsquo;re one typo away from a very bad day.\nPCG is the safety net I wish I\u0026rsquo;d had years ago. It\u0026rsquo;s saved me multiple times already. It will save you too.\nGet it: github.com/ruhanirabin/pve-config-git\nQuestions? Open an issue on GitHub.\nFound this useful? Star the repo and tell other Proxmox operators.\nBuilt by someone who learned the hard way so you don\u0026rsquo;t have to.\nRelated reading Back up and restore Home Assistant with Git Upgrade Proxmox 8 to 9 safely ","permalink":"https://rabin.blog/proxmox-config-backup-git-version-control-pve-nodes/","summary":"\u003cp\u003e\u003cstrong\u003eStop treating your Proxmox configuration like it\u0026rsquo;s disposable. Start treating it like code.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eGitHub:\u003c/strong\u003e \u003ca href=\"https://github.com/ruhanirabin/pve-config-git\"\u003eruhanirabin/pve-config-git\u003c/a\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"the-problem-configuration-drift-is-a-silent-killer\"\u003eThe Problem: Configuration Drift Is a Silent Killer\u003c/h2\u003e\n\u003cp\u003eI\u0026rsquo;ve been running Proxmox for years. Multiple nodes, dozens of VMs, complex network configs, storage pools, custom scripts. And like many of you, I made changes directly on the host. A quick edit to \u003ccode\u003e/etc/network/interfaces\u003c/code\u003e here, a storage tweak there, a firewall rule adjustment to get something working.\u003c/p\u003e","title":"Proxmox Config Backup to Git – Version Control for Your PVE Nodes"},{"content":"Let’s get one thing out of the way:\nProxmox upgrades are not fragile.\nPeople are.\nMost guides assume:\nnothing goes wrong you don’t interrupt anything you don’t get stuck in a pager you don’t panic halfway That’s not reality.\nThis guide is based on an actual upgrade — including:\ninterrupted upgrade broken package state lock issues recovery If you follow this, you’ll finish the upgrade even if things go sideways.\n🧭 What This Covers Proxmox VE 8 → 9 No-subscription repo Single-node homelab (or small cluster) GPU passthrough setups (Plex, etc.) Recovery from broken upgrades ⚠️ Before You Start (Do Not Skip This) 1. Backup If your backups are “probably fine”, they are not fine.\nBackup all VMs and containers Test restore if you’re serious 2. Upgrade to latest Proxmox 8 first apt update apt dist-upgrade 3. Run the upgrade checker pve8to9 --full You want:\n❌ 0 failures ⚠️ warnings are acceptable Proxmox upgrade pre-check summary\n4. Disk space df -h / Minimum:\n5GB usable 10GB preferred Here is an example:\nroot@pve2:~# df -h / Filesystem Size Used Avail Use% Mounted on /dev/mapper/pve-root 94G 11G 79G 12% / 🛑 Stop Everything (Yes, Everything) Before touching repositories:\nFrom UI: Node → Bulk Actions → Bulk Shutdown\nThis is not optional if you care about stability.\nBulk Shutdown option in Proxmox\nWhy? Because during upgrade:\nnetworking restarts services reload kernel changes Running VMs during this:\ncan hang can corrupt writes can behave unpredictably You gain nothing by keeping them running.\n🚀 Phase 1 — Switch Repositories 1. Switch Debian to Trixie sed -i \u0026#39;s/bookworm/trixie/g\u0026#39; /etc/apt/sources.list 2. Remove old Proxmox repo rm /etc/apt/sources.list.d/pve-install-repo.list 3. Add Proxmox 9 repo (no-subscription) cat \u0026gt; /etc/apt/sources.list.d/proxmox.sources \u0026lt;\u0026lt; EOF Types: deb URIs: http://download.proxmox.com/debian/pve Suites: trixie Components: pve-no-subscription Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg EOF 4. Remove Ceph repo (if unused) rm /etc/apt/sources.list.d/ceph.list 2\u0026gt;/dev/null rm /etc/apt/sources.list.d/ceph.sources 2\u0026gt;/dev/null Here is how it should go as an example:\nroot@pve2:~# sed -i \u0026#39;s/bookworm/trixie/g\u0026#39; /etc/apt/sources.list root@pve2:~# rm /etc/apt/sources.list.d/pve-install-repo.list root@pve2:~# cat \u0026gt; /etc/apt/sources.list.d/proxmox.sources \u0026lt;\u0026lt; EOF Types: deb URIs: http://download.proxmox.com/debian/pve Suites: trixie Components: pve-no-subscription Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg EOF root@pve2:~# rm /etc/apt/sources.list.d/ceph.list 2\u0026gt;/dev/null rm /etc/apt/sources.list.d/ceph.sources 2\u0026gt;/dev/null root@pve2:~# 5. Update apt update 6. Verify apt policy You should NOT see:\n❌ bookworm You SHOULD see:\n✅ trixie ✅ pve-no-subscription Example of the apt policy command:\nPackage files: 100 /var/lib/dpkg/status release a=now 500 http://download.proxmox.com/debian/pve trixie/pve-no-subscription amd64 Packages release o=Proxmox,a=stable,n=trixie,l=Proxmox Debian Repository,c=pve-no-subscription,b=amd64 origin download.proxmox.com 500 https://deb.nodesource.com/node_22.x nodistro/main amd64 Packages release o=. nodistro,a=nodistro,n=nodistro,l=. nodistro,c=main,b=amd64 origin deb.nodesource.com 500 http://security.debian.org/debian-security trixie-security/main amd64 Packages release v=13,o=Debian,a=stable-security,n=trixie-security,l=Debian-Security,c=main,b=amd64 origin security.debian.org 500 http://deb.debian.org/debian trixie-updates/main amd64 Packages release v=13-updates,o=Debian,a=stable-updates,n=trixie-updates,l=Debian,c=main,b=amd64 origin deb.debian.org 500 http://deb.debian.org/debian trixie/contrib amd64 Packages release v=13.4,o=Debian,a=stable,n=trixie,l=Debian,c=contrib,b=amd64 origin deb.debian.org 500 http://deb.debian.org/debian trixie/main amd64 Packages release v=13.4,o=Debian,a=stable,n=trixie,l=Debian,c=main,b=amd64 origin deb.debian.org 🔥 Phase 2 — The Upgrade apt dist-upgrade This process may show you additional screens. For example the below screen you can either PG DN multiple times, to go to the end or simply press q\nLinux terminal output about ping configuration.\n⚠️ What Will Trip You Up Pager screen You’ll see: lines xx-xx (END)\nPress: q\nGit update notes: git-daemon security changes.\nConfig prompts (Y/I/N/O/D/Z)\nIf unsure: → press Enter\nYou may see other screens like this below, just keep the local version if you are not sure:\nGrub configuration options\n💥 If You Interrupt the Upgrade Recovery ps aux | grep apt kill -9 \u0026lt;PID\u0026gt; dpkg --configure -a apt -f install apt dist-upgrade Repeat until clean.\n✅ Phase 3 — Finalization Check version pveversion This command should output something like this below, note the version number is 9.x.x.\nroot@pve2:~# pveversion pve-manager/9.1.7/16b139a017452f16 (running kernel: 6.8.12-20-pve) Reboot reboot Or you can just click on the UI.\nReboot button in a Proxmox interface.\nThe reboot process will take some time. Once it is done, do not forget to force refresh your web access UI. (usually cmd+R or ctrl+R)\nProxmox Virtual Environment console\nConfirm kernel uname -r ⚠️ Important Change /etc/sysctl.conf is no longer used\nMove configs to: /etc/sysctl.d/\n🔍 Post-Upgrade Checks You should only do this if any of your VM is running plex and uses NVidia card passthrough.\nGPU check nvidia-smi NVENC check ffmpeg -encoders | grep nvenc Real test ffmpeg -f lavfi -i testsrc=duration=5:size=1280x720:rate=30 \\ -c:v h264_nvenc -f null - 🧹 Cleanup apt autoremove apt modernize-sources Example apt autoremove. Press Y to remove:\nroot@pve2:~# apt autoremove REMOVING: libxenmisc4.17 proxmox-kernel-6.8.12-17-pve-signed Summary: Upgrading: 0, Installing: 0, Removing: 2, Not Upgrading: 0 Freed space: 579 MB Continue? [Y/n] Y Here is the example of apt modernize-sources. Press Y to continue.\nroot@pve2:~# apt modernize-sources The following files need modernizing: - /etc/apt/sources.list - /etc/apt/sources.list.d/pve-enterprise.list - /etc/apt/sources.list.d/pvetest-for-beta.list Modernizing will replace .list files with the new .sources format, add Signed-By values where they can be determined automatically, and save the old files into .list.bak files. This command supports the \u0026#39;signed-by\u0026#39; and \u0026#39;trusted\u0026#39; options. If you have specified other options inside [] brackets, please transfer them manually to the output files; see sources.list(5) for a mapping. For a simulation, respond N in the following prompt. Rewrite 3 sources? [Y/n] Y Modernizing /etc/apt/sources.list... - Writing /etc/apt/sources.list.d/debian.sources Modernizing /etc/apt/sources.list.d/pve-enterprise.list... Modernizing /etc/apt/sources.list.d/pvetest-for-beta.list... 🤦‍♂️Gotcha - apt modernize-sources Be careful about the command apt modernize-sources, this will add back the enterprise repo, and that will start to give you errors when running apt-get update command.\nProxmox apt-get update error 401 Unauthorized\nNow run these commands.\nrm /etc/apt/sources.list.d/pve-enterprise.sources rm /etc/apt/sources.list.d/pve-enterprise.list 2\u0026gt;/dev/null Now test the apt update command. And it should be as you see below, without errors.\nroot@pve2:~# apt update Hit:1 http://security.debian.org/debian-security trixie-security InRelease Hit:2 http://deb.debian.org/debian trixie InRelease Hit:3 http://deb.debian.org/debian trixie-updates InRelease Hit:4 https://deb.nodesource.com/node_22.x nodistro InRelease Hit:5 http://download.proxmox.com/debian/pve trixie InRelease All packages are up to date. 🤦‍♂️Gotcha - Proxmox NAG Screen is Back? This can happen in some occasion. You will notice the nag screen about Proxmox does not have a subscription notice. In this case use this one liner script from Proxmox Post Install Community Script. It is safe but as usual always inspect the source just to be sure.\nHere is the one liner, you must run this inside PVE Shell (not inside a container).\nbash -c \u0026#34;$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/post-pve-install.sh)\u0026#34; Additional Instructions:\nIt is recommended to answer “yes” (y) to all options presented during the process. But use your best judgement as sometimes not all answer\u0026rsquo;s needs to be Y.\n🧠 Final Thought You just need to follow the steps, be vigilant and it will be alright. If your upgrade depends on luck instead of control, then you’re doing it wrong 😊.\nRelated reading Back up Proxmox configuration with Git Fix Intel e1000e network hangs on Proxmox ","permalink":"https://rabin.blog/upgrade-proxmox-8-to-9-without-breaking-your-homelab/","summary":"\u003cp\u003e\u003cstrong\u003eLet’s get one thing out of the way:\u003c/strong\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eProxmox upgrades are not fragile.\u003cbr\u003e\nPeople are.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eMost guides assume:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003enothing goes wrong\u003c/li\u003e\n\u003cli\u003eyou don’t interrupt anything\u003c/li\u003e\n\u003cli\u003eyou don’t get stuck in a pager\u003c/li\u003e\n\u003cli\u003eyou don’t panic halfway\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eThat’s not reality.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis guide is based on an actual upgrade — including:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003einterrupted upgrade\u003c/li\u003e\n\u003cli\u003ebroken package state\u003c/li\u003e\n\u003cli\u003elock issues\u003c/li\u003e\n\u003cli\u003erecovery\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIf you follow this, you’ll finish the upgrade even if things go sideways.\u003c/p\u003e","title":"Upgrade Proxmox 8 to 9 Without Breaking Your Homelab"},{"content":"Your Downloads folder is a graveyard. PDFs from 2023, installer files for software you already installed, and random screenshots you took once and never looked at again.\nAnd every time you open it, you think: “I should clean this up.”\nThen you don\u0026rsquo;t.\nI built this script because I was tired (and also lazy) of that cycle. It\u0026rsquo;s not fancy stuff. It just works.\nThe Problem Nobody Talks About Most “cleanup” solutions are too aggressive. They delete stuff you needed. Or they\u0026rsquo;re too manual, which means you won\u0026rsquo;t do it. The sweet spot is:\nAuto-sort downloads by type so you can find things Stage old files for deletion, don\u0026rsquo;t nuke them immediately Give you a grace period to recover anything you actually need That\u0026rsquo;s exactly what this script does.\nHow It Works (The 90-Day Rule) Day 0: Download lands in root → Auto-sorted to category folder Day 60: Still untouched in Documents/Images → Moved to Trash-Temp Day 90: Still in Trash-Temp → Permanently deleted Total lifecycle: 90 days. That\u0026rsquo;s enough time to realize you need something, but not so long that you\u0026rsquo;re hoarding garbage forever.\nThe Folder Structure Downloads/ ├── 01-Software/ # .exe, .msi, .dmg, .pkg ├── 02-WordPress/ # Plugin/theme ZIPs (pattern-matched) ├── 03-Documents/ # PDFs, Office docs, CSVs ├── 04-Images/ # Screenshots, photos, videos ├── 05-Archives/ # .zip, .7z, .rar ├── 06-Code-Scripts/ # .py, .js, .json, etc. └── 99-Trash-Temp/ # Staging area for deletion Safety First The script never touches:\nThe script file itself The log file Anything outside your Downloads folder Files aren\u0026rsquo;t deleted immediately. They sit in 99-Trash-Temp for 30 days. If you panic, you can recover them. The log tells you exactly what was moved and when.\nSetup Instructions Windows 11 (Native) Download the script from [GIST] Place it in your Downloads folder (e.g., D:\\Data\\Downloads\\2026\\) Edit the path in the script (line ~17) to match your Downloads location: $BasePath = \u0026quot;C:\\Users\\YourName\\Downloads\u0026quot; Run once manually to test: cd D:\\Data\\Downloads\\2026 .\\Downloads-Weekly-Cleanup.ps1 -WhatIf The -WhatIf flag shows what it would do without actually doing it. Schedule it to run weekly: $Action = New-ScheduledTaskAction -Execute \u0026quot;powershell.exe\u0026quot; -Argument \u0026quot;-ExecutionPolicy Bypass -File D:\\Data\\Downloads\\2026\\Downloads-Weekly-Cleanup.ps1\u0026quot; $Trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At \u0026quot;09:00\u0026quot; $Settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries Register-ScheduledTask -TaskName \u0026quot;Downloads Cleanup\u0026quot; -Action $Action -Trigger $Trigger -Settings $Settings macOS PowerShell works on macOS. Install it:\nbrew install powershell Then follow the Windows instructions, but change paths:\n$BasePath = \u0026#34;/Users/YourName/Downloads\u0026#34; For scheduling, use launchd instead of Task Scheduler. Create ~/Library/LaunchAgents/com.downloads.cleanup.plist:\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;UTF-8\u0026#34;?\u0026gt; \u0026lt;!DOCTYPE plist PUBLIC \u0026#34;-//Apple//DTD PLIST 1.0//EN\u0026#34; \u0026#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd\u0026#34;\u0026gt; \u0026lt;plist version=\u0026#34;1.0\u0026#34;\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;Label\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;com.downloads.cleanup\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;ProgramArguments\u0026lt;/key\u0026gt; \u0026lt;array\u0026gt; \u0026lt;string\u0026gt;/usr/local/bin/pwsh\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;-File\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;/Users/YourName/Downloads/Downloads-Weekly-Cleanup.ps1\u0026lt;/string\u0026gt; \u0026lt;/array\u0026gt; \u0026lt;key\u0026gt;StartCalendarInterval\u0026lt;/key\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;Weekday\u0026lt;/key\u0026gt; \u0026lt;integer\u0026gt;1\u0026lt;/integer\u0026gt; \u0026lt;key\u0026gt;Hour\u0026lt;/key\u0026gt; \u0026lt;integer\u0026gt;9\u0026lt;/integer\u0026gt; \u0026lt;key\u0026gt;Minute\u0026lt;/key\u0026gt; \u0026lt;integer\u0026gt;0\u0026lt;/integer\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;/plist\u0026gt; Load it:\nlaunchctl load ~/Library/LaunchAgents/com.downloads.cleanup.plist Linux Install PowerShell:\n# Ubuntu/Debian sudo apt update sudo apt install -y powershell # Or install from Microsoft repo (recommended) wget -q \u0026#34;https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb\u0026#34; sudo dpkg -i packages-microsoft-prod.deb sudo apt update sudo apt install -y powershell Edit the script path:\n$BasePath = \u0026#34;/home/YourName/Downloads\u0026#34; Use cron for scheduling:\n# Edit crontab crontab -e # Add line for Sunday 9 AM 0 9 * * 0 /usr/bin/pwsh -File /home/YourName/Downloads/Downloads-Weekly-Cleanup.ps1 Configurable Variables At the top of the script, you can adjust:\nparam( [switch]$WhatIf, # Dry run mode [int]$TrashDays = 30, # Days before trash is deleted (default: 30) [int]$AgingDays = 60 # Days before aging to trash (default: 60) ) More aggressive cleanup:\n.\\Downloads-Weekly-Cleanup.ps1 -AgingDays 30 -TrashDays 14 More lenient:\n.\\Downloads-Weekly-Cleanup.ps1 -AgingDays 90 -TrashDays 60 Customizing File Patterns The script has two places you can customize:\n1. Extension-to-Folder Mapping (~line 30) $Folders = @{ \u0026#39;01-Software\u0026#39; = @(\u0026#39;.exe\u0026#39;, \u0026#39;.msi\u0026#39;, \u0026#39;.msix\u0026#39;, \u0026#39;.dmg\u0026#39;, \u0026#39;.pkg\u0026#39;) \u0026#39;03-Documents\u0026#39; = @(\u0026#39;.pdf\u0026#39;, \u0026#39;.docx\u0026#39;, \u0026#39;.csv\u0026#39;, \u0026#39;.txt\u0026#39;) \u0026#39;04-Images\u0026#39; = @(\u0026#39;.jpg\u0026#39;, \u0026#39;.png\u0026#39;, \u0026#39;.mp4\u0026#39;, \u0026#39;.mov\u0026#39;) # ... add your own } 2. WordPress Patterns (~line 44) If you work with WordPress, add plugin patterns:\n$WordPressPatterns = @( \u0026#39;*placescale*.zip\u0026#39;, \u0026#39;*woocommerce*.zip\u0026#39;, \u0026#39;*your-plugin*.zip\u0026#39; ) What the Log Looks Like [2026-03-26 17:36:15] [INFO] Organization complete: 0 moved, 0 skipped, 0 errors [2026-03-26 17:36:15] [WARN] Aged file moved: [03-Documents] old-invoice.pdf (79d old) [2026-03-26 17:36:15] [WARN] Deleted: jetbrains-fonts.zip (12.49 MB) - Last modified: 01/25/2026 Everything is timestamped. If you need to recover something, you\u0026rsquo;ll know exactly when it was moved or deleted.\nWhy Not Just Use Any Existing Tool? CCleaner/BleachBit: Too aggressive. No staging. You find out too late. macOS Automator: Works, but fragile. Breaks silently. Manual cleanup: You won\u0026rsquo;t do it. Would you? This script gives you structure and safety. The 90-day lifecycle means you\u0026rsquo;re not hoarding, but you\u0026rsquo;re also not panicking.\nDownload Get the script from [ GIST ]\nFork it. Modify it. Make it yours. The code is straightforward PowerShell—no dependencies, no external calls, no surprises.\nI use this every week. It works.\nRelated reading Back up a Dockerized n8n instance to GitHub or GitLab Back up and restore Home Assistant with Git ","permalink":"https://rabin.blog/auto-organize-downloads-folder-powershell-script-windows-mac-linux/","summary":"\u003cp\u003eYour Downloads folder is a graveyard. PDFs from 2023, installer files for software you already installed, and random screenshots you took once and never looked at again.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eAnd every time you open it, you think: \u003cem\u003e“I should clean this up.”\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThen you don\u0026rsquo;t.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eI built this script because I was tired (and also lazy) of that cycle. It\u0026rsquo;s not fancy stuff. It just works.\u003c/p\u003e\n\u003ch2 id=\"the-problem-nobody-talks-about\"\u003eThe Problem Nobody Talks About\u003c/h2\u003e\n\u003cp\u003eMost “cleanup” solutions are too aggressive. They delete stuff you needed. Or they\u0026rsquo;re too manual, which means you won\u0026rsquo;t do it. The sweet spot is:\u003c/p\u003e","title":"Auto-Organize Downloads Folder Powershell Script | Windows/macOS/Linux"},{"content":" How to bulletproof your workflow automations with dead-simple, automated backups—even if you’re not a Linux wizard.\nWhy You Absolutely Need to Back Up n8n (Especially on Docker + SQLite) n8n is the backbone of your workflow automation, orchestrating everything from business logic to personal productivity hacks. But if you’re running n8n in Docker (the way 90% of us do), and especially if you’re using the default SQLite database, you are one corrupted file, failed disk, or accidental docker rm away from total workflow extinction.\nWhy?\nSQLite is a single file. Great for simplicity, terrible for resilience. Docker containers can be deleted, rebuilt, or migrated at any time. Automated backup = Zero downtime, zero tears. Storing backups offsite (like GitLab or GitHub) = Safety against ransomware and hardware failures. Bottom line: If your n8n automations matter at all, you should automate your backups now—not after you lose everything.\nPrerequisites You’ll need:\nn8n running in Docker (hosted anywhere: VPS, home server, cloud). Your n8n instance uses SQLite (the default DB for new installs). Shell access to your Docker host (SSH or web console). A GitLab or GitHub account with a private repository for storing your backups. SSH keys configured for push access to your repo from the server. Step 1: Verify n8n Is Using SQLite Before you start, check that your n8n is using SQLite.\nSSH into your Docker host and run:\ndocker exec -it \u0026lt;n8n_container_name\u0026gt; printenv | grep DB_TYPE If it returns sqlite, you’re good.\nOr, check for the file:\ndocker exec -it \u0026lt;n8n_container_name\u0026gt; ls /home/node/.n8n/database.sqlite If you see database.sqlite, you’re running SQLite.\nStep 2: Set Up Your Backup Repo 1. Create a private repo on GitLab or GitHub (e.g., n8n-backups).\n2. Clone it to your server:\ngit clone git@\u0026lt;git-provider\u0026gt;:\u0026lt;your-username\u0026gt;/\u0026lt;your-repo\u0026gt;.git /opt/n8n-backups cd /opt/n8n-backups 3. Configure your git user (inside the repo):\ngit config --local user.name \u0026#34;YourName\u0026#34; git config --local user.email \u0026#34;your-email@example.com\u0026#34; 4. Make sure your SSH key is added to your git provider for passwordless pushes.\n(a) Add your server public key into github or gitlab\nCheck if There’s an SSH Key:\nls -l ~/.ssh/id_rsa.pub\nIf not, generate one:\nssh-keygen -t rsa -b 4096 -C \u0026quot;n8n-backup@yourhost\u0026quot; -N \u0026quot;\u0026quot; -f ~/.ssh/id_rsa\nAdd the Public Key to GitHub/Gitlab\ncat ~/.ssh/id_rsa.pub\n(b) Once that is done, run this to test.\nssh -T git@gitlab.com ssh -T git@github.com Step 3: The Automated Backup Script Below is a no-nonsense, production-ready shell script to:\nCopy your live database.sqlite from the n8n container, Save it with a unique timestamp, (Optionally) encrypt it, Commit and push to GitLab/GitHub only if the file changed, Automatically prune backups older than 14 days. Save this as backup-n8n.sh:\n#!/bin/bash # CONFIGURATION - Change these to your environment! N8N_CONTAINER=\u0026#34;your_n8n_container_name\u0026#34; BACKUP_DIR=\u0026#34;/opt/n8n-backups\u0026#34; DATE=$(date +\u0026#34;%Y-%m-%d-%H%M%S\u0026#34;) BACKUP_FILE=\u0026#34;database_${DATE}.sqlite\u0026#34; ENCRYPT=0 # Set to 1 to enable GPG encryption echo \u0026#34;Backing up n8n database from container $N8N_CONTAINER to $BACKUP_DIR/$BACKUP_FILE...\u0026#34; # Copy sqlite file from the container docker cp $N8N_CONTAINER:/home/node/.n8n/database.sqlite $BACKUP_DIR/$BACKUP_FILE # Optional: Encrypt the backup file if [ \u0026#34;$ENCRYPT\u0026#34; -eq 1 ]; then echo \u0026#34;Encrypting $BACKUP_FILE with GPG...\u0026#34; gpg --symmetric --cipher-algo AES256 --batch --passphrase \u0026#34;YOUR_STRONG_PASSWORD\u0026#34; -o \u0026#34;${BACKUP_DIR}/${BACKUP_FILE}.gpg\u0026#34; \u0026#34;${BACKUP_DIR}/${BACKUP_FILE}\u0026#34; rm -f \u0026#34;${BACKUP_DIR}/${BACKUP_FILE}\u0026#34; BACKUP_FILE=\u0026#34;${BACKUP_FILE}.gpg\u0026#34; fi # Change to backup directory cd $BACKUP_DIR # Set git user (optional for each run, safe for automation) git config --local user.name \u0026#34;YourName\u0026#34; git config --local user.email \u0026#34;your-email@example.com\u0026#34; # Add the backup file git add $BACKUP_FILE # Commit only if there are changes (advanced: skip commit if file is identical) if ! git diff --cached --quiet; then git commit -m \u0026#34;Automated n8n sqlite backup $DATE\u0026#34; git push origin main echo \u0026#34;Backup committed and pushed to remote!\u0026#34; else echo \u0026#34;No changes detected in the database backup. Skipping commit.\u0026#34; fi # Cleanup old backups (older than 14 days) find $BACKUP_DIR/database_*.sqlite* -type f -mtime +14 -delete echo \u0026#34;Backup script complete.\u0026#34; Make it executable:\nchmod +x backup-n8n.sh Step 4: Automate with Cron Schedule it (for example, daily at 2am):\ncrontab -e Add:\n0 2 * * * /opt/n8n-backups/backup-n8n.sh \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 Step 5: How to Restore a Backup Stop your n8n Docker container: docker stop \u0026lt;n8n_container_name\u0026gt; If the backup is encrypted, decrypt it first: gpg --decrypt database_YYYY-MM-DD-HHMMSS.sqlite.gpg \u0026gt; database_YYYY-MM-DD-HHMMSS.sqlite Copy a backup into place: docker cp /opt/n8n-backups/database_YYYY-MM-DD-HHMMSS.sqlite \u0026lt;n8n_container_name\u0026gt;:/home/node/.n8n/database.sqlite Start n8n: docker start \u0026lt;n8n_container_name\u0026gt; That’s it. You’re live again.\nTroubleshooting Common Issues Permission denied (publickey):\nDouble-check your SSH keys and make sure your backup user has push rights to your repo. Multiple backups with the same timestamp:\nUse seconds in your filename as shown. You’ll never get duplicates. “Nothing to commit” in git:\nThe script now skips the commit if the file hasn’t changed—less noise in your Git history. Backup file encryption:\nIf you lose your GPG passphrase, you lose access to your backup. Use with care. Final Thoughts: Paranoia is a Virtue Automated backups aren’t “paranoid,” they’re smart. SQLite is fast and light, but not invincible.\nWith this setup, your n8n workflows can survive anything—hardware failures, accidental wipes, or the classic “I don’t know what happened, boss, it just disappeared.”\nMake this script your insurance policy.\nSet it, forget it, and sleep easy.\nRelated reading Back up and migrate Uptime Kuma safely Version-control Home Assistant backups ","permalink":"https://rabin.blog/automated-backups-dockerized-n8n-sqlite-gitlab-github/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003cem\u003eHow to bulletproof your workflow automations with dead-simple, automated backups—even if you’re not a Linux wizard.\u003c/em\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"why-you-absolutely-need-to-back-up-n8n-especially-on-docker--sqlite\"\u003eWhy You Absolutely Need to Back Up n8n (Especially on Docker + SQLite)\u003c/h2\u003e\n\u003cp\u003en8n is the backbone of your workflow automation, orchestrating everything from business logic to personal productivity hacks. But if you’re running n8n in Docker (the way 90% of us do), and especially if you’re using the default SQLite database, \u003cstrong\u003eyou are one corrupted file, failed disk, or accidental \u003ccode\u003edocker rm\u003c/code\u003e away from total workflow extinction\u003c/strong\u003e.\u003c/p\u003e","title":"Effortless Automated Backups for Your Dockerized n8n (SQLite) to GitLab or GitHub"},{"content":"Are you looking to clean up your WordPress database by removing unused or abandoned post meta fields? Over time, your WordPress database can accumulate meta fields from plugins and themes you no longer use. In this guide, I’ll show you how to remove specific meta fields safely from your wp_postmeta table using a simple SQL query.\nBefore You Begin Before executing any database modifications, it’s crucial to:\nCreate a complete backup of your WordPress database Test the backup to ensure it’s valid and restorable Identify the meta fields you want to remove, here is how to identify them. Access your database through phpMyAdmin or similar tool The SQL Query Here’s the SQL query that will remove specific meta fields from your WordPress database:\nDELETE FROM wp_postmeta WHERE meta_key IN ( \u0026#39;_shortpixel_status\u0026#39;, \u0026#39;litespeed-optimize-size\u0026#39;, \u0026#39;litespeed-optimize-set\u0026#39;, \u0026#39;sq_question\u0026#39;, \u0026#39;sq_answer\u0026#39; ); Understanding the Query Let’s break down what this query does:\nDELETE FROM wp_postmeta: Specifies we’re removing data from the postmeta table WHERE meta_key IN (...): Defines which specific meta keys we want to delete The list in parentheses contains the meta keys to be removed Implementation Methods Method 1: Using phpMyAdmin Log in to your phpMyAdmin Select your WordPress database Click on the “SQL” tab Paste the query Click “Go” to execute Method 2: Using WordPress Functions If you want to implement this in a plugin or theme, use the following PHP code:\nglobal $wpdb; $wpdb-\u0026gt;query(\u0026#34; DELETE FROM {$wpdb-\u0026gt;postmeta} WHERE meta_key IN ( \u0026#39;_shortpixel_status\u0026#39;, \u0026#39;litespeed-optimize-size\u0026#39;, \u0026#39;litespeed-optimize-set\u0026#39;, \u0026#39;sq_question\u0026#39;, \u0026#39;sq_answer\u0026#39; ) \u0026#34;); Important Considerations Table Prefix: If your WordPress installation uses a different table prefix (not ‘wp_’), modify the query accordingly. Selective Deletion: The provided query removes ALL instances of these meta keys for ALL posts. To target specific posts, add additional WHERE conditions. Plugin Dependencies: Ensure the meta fields you’re removing aren’t required by any active plugins or themes. Performance Impact: On large databases, consider running the query during low-traffic periods. Why Clean Up Meta Fields? Removing unused meta fields offers several benefits:\nReduces database size Improves backup efficiency Enhances database query performance Maintains a cleaner database structure Best Practices Always maintain current backups before database modifications Document which meta fields you’ve removed Test your website thoroughly after removing meta fields Consider using a staging environment for initial testing Conclusion Cleaning up unused post meta fields is a valuable database maintenance task. While the process is straightforward, always approach database modifications with caution and proper preparation. Regular database maintenance helps keep your WordPress site running efficiently and reduces unnecessary data storage.\nFAQs Q: Will removing these meta fields affect my site’s functionality?\nA: If the meta fields belong to deactivated plugins or themes, there should be no impact. Always verify before deletion.\nQ: How can I identify unused meta fields?\nA: Review your active plugins and themes, and use database inspection tools to identify orphaned or unused meta fields.\nQ: Is this process reversible?\nA: No, once deleted, meta fields cannot be recovered unless restored from a backup. Always back up before proceeding.\nRemember: Database modifications should be performed with caution. If you’re unsure, consult a WordPress developer or database administrator.\nNeed help optimizing your WordPress database? Contact me for a professional database cleanup service. ","permalink":"https://rabin.blog/how-to-remove-unused-post-meta-fields-from-wordpress-postmeta-table-sql-query/","summary":"\u003cp\u003eAre you looking to clean up your WordPress database by removing unused or abandoned post meta fields? Over time, your WordPress database can accumulate meta fields from plugins and themes you no longer use. In this guide, I’ll show you how to remove specific meta fields safely from your \u003cstrong\u003ewp_postmeta\u003c/strong\u003e table using a simple SQL query.\u003c/p\u003e\n\u003ch2 id=\"before-you-begin\"\u003eBefore You Begin\u003c/h2\u003e\n\u003cp\u003eBefore executing any database modifications, it’s crucial to:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eCreate a complete backup of your WordPress database\u003c/li\u003e\n\u003cli\u003eTest the backup to ensure it’s valid and restorable\u003c/li\u003e\n\u003cli\u003eIdentify the meta fields you want to remove, \u003cstrong\u003e\u003ca href=\"/how-to-find-unused-postmeta-fields-in-wordpress-database-sql-query/\"\u003ehere is how to identify them\u003c/a\u003e\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003eAccess your database through \u003cstrong\u003e\u003cem\u003ephpMyAdmin\u003c/em\u003e\u003c/strong\u003e or similar tool\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"the-sql-query\"\u003eThe SQL Query\u003c/h2\u003e\n\u003cp\u003eHere’s the SQL query that will remove specific meta fields from your WordPress database:\u003c/p\u003e","title":"How to Remove Unused Post Meta Fields from WordPress Postmeta Table – SQL Query"},{"content":"WordPress databases can become cluttered over time, especially when you frequently install and uninstall plugins. One common source of database bloat is unused postmeta fields. In this guide, we’ll show you how to identify these unnecessary fields and explain why cleaning them up is crucial for your website’s performance.\nWhy Should You Care About Unused Postmeta Fields? Before diving into the technical details, let’s understand the benefits of maintaining a clean WordPress database:\nImproved Performance: Fewer database entries mean faster query execution times Reduced Backup Size: Smaller database size leads to quicker backup processes Better Server Resources: Optimized database requires less server memory and CPU usage Easier Maintenance: Clean database structure simplifies troubleshooting and updates Cost Efficiency: Smaller database size might reduce hosting costs in the long run Finding Unused Postmeta Fields Here are several SQL queries you can use to inspect your WordPress database for unused postmeta fields:\n1. List All Unique Meta Keys SELECT DISTINCT meta_key FROM wp_postmeta ORDER BY meta_key; This query helps you get an overview of all meta fields in your database.\nHere is a sample output from it.\nUnused postmeta fields that were leftover from previous plugins or themes\n2. Check Usage Frequency SELECT meta_key, COUNT(*) as count FROM wp_postmeta GROUP BY meta_key ORDER BY count DESC; This helps identify which fields are frequently used and which might be candidates for cleanup.\nFrequenty used postmeta fields\n3. Identify Plugin-Related Meta Keys SELECT DISTINCT meta_key FROM wp_postmeta WHERE meta_key LIKE \u0026#39;_%\u0026#39; ORDER BY meta_key; This query specifically looks for meta keys that typically belong to plugins.\n4. Track Last Usage SELECT pm.meta_key, MAX(p.post_modified) as last_used FROM wp_postmeta pm JOIN wp_posts p ON p.ID = pm.post_id GROUP BY pm.meta_key ORDER BY last_used DESC; This helps identify obsolete meta fields that haven’t been used recently.\nFind the last updated postmeta fields\nBest Practices for Cleaning Postmeta Fields When cleaning up your database, follow these important guidelines:\nAlways Back Up First: Create a complete database backup before making any changes Document Everything: Keep a record of the meta keys you plan to remove Test in Staging: Never perform cleanup operations directly on a production site Verify Plugin Status: Double-check that related plugins are truly deactivated Gradual Cleanup: Remove data in small batches to avoid server overload Identifying Leftover Plugin Data Look for these patterns when identifying unused meta fields:\nMeta keys prefixed with plugin-specific identifiers Fields with timestamps older than your plugin uninstallation dates Meta keys with zero or very low usage counts Fields associated with post types that no longer exist Tools to Help Consider using these tools for database maintenance:\nWP-CLI for running database queries Advanced Database Cleaner plugin PhpMyAdmin for direct database access SQL query tools like MySQL Workbench Conclusion You can find the post here on how to cleanup those unused fields. Regular maintenance of your WordPress database, including cleaning up unused postmeta fields, is essential for optimal website performance. By following the queries and best practices outlined above, you can maintain a lean and efficient database structure.\nRemember to always prioritize safety when performing database operations and maintain proper backups before making any changes.\nFAQs Q: How often should I clean unused postmeta fields?\nA: Perform a cleanup every 3-6 months, or after uninstalling major plugins.\nQ: Will removing unused meta fields break my site?\nA: Not if you follow proper backup procedures and verify that the fields are truly unused.\nQ: How much space can I save by cleaning unused meta fields?\nA: This varies, but sites can frequently reduce their database size by 10-30% through proper cleanup.\nRemember to replace wp_ with your actual database prefix in all queries. If you’re not comfortable working directly with SQL, consider seeking professional assistance or using WordPress database cleanup plugins.\nNeed help optimizing your WordPress database? Contact me for a professional database cleanup service. Related reading Remove unused WordPress post meta safely ","permalink":"https://rabin.blog/how-to-find-unused-postmeta-fields-in-wordpress-database-sql-query/","summary":"\u003cp\u003eWordPress databases can become cluttered over time, especially when you frequently install and uninstall plugins. One common source of database bloat is unused postmeta fields. In this guide, we’ll show you how to identify these unnecessary fields and explain why cleaning them up is crucial for your website’s performance.\u003c/p\u003e\n\u003ch2 id=\"why-should-you-care-about-unused-postmeta-fields\"\u003eWhy Should You Care About Unused Postmeta Fields?\u003c/h2\u003e\n\u003cp\u003eBefore diving into the technical details, let’s understand the benefits of maintaining a clean WordPress database:\u003c/p\u003e","title":"How to Find Unused Postmeta Fields in WordPress Database – SQL Query"},{"content":" Easily automate Home Assistant config backups to GitHub or GitLab with step-by-step scripts and instant restore tips.\nHome Assistant is the brains of your smart home, but even the most seasoned tinkerers have experienced the frustration of a corrupted SD card, accidental misconfiguration, or a failed upgrade. What if you could instantly roll back to a working state or migrate your entire setup to a new server with just one script? That’s the power of automated versioned backups with GitHub or GitLab.\nIn this guide, you’ll learn how to fully automate Home Assistant configuration backups to a private Git repository (GitHub or GitLab), with a built-in safety net for easy restoration—no more manual copying or guesswork.\nWhy Should You Back Up Your Home Assistant Configuration? Protect Against Data Loss: Hardware failure, power loss, or SD card corruption can wipe out months (or years) of tweaks and automations. Safe Experimentation: Easily roll back breaking changes, failed updates, or botched YAML edits. Portability: Instantly migrate your Home Assistant to new hardware, a fresh install, or another location. Version History: See exactly when and how your setup changed, and who changed it (if you collaborate). Peace of Mind: Sleep better knowing your smart home is always just a git pull away from full recovery. Prerequisites Home Assistant installed (Home Assistant OS, Supervised, Container, or Core). Access to the Home Assistant file system (via SSH \u0026amp; Terminal add-on or host SSH). A GitHub or GitLab account with a private repository created for backups. Basic Git knowledge (cloning, committing, pushing). (Optional but recommended) A private SSH key set up for authentication. Step 1: Prepare Your Home Assistant for Git Backups 1. Access Your Home Assistant Terminal Use the official Terminal \u0026amp; SSH add-on in Home Assistant, or SSH into your host (for advanced installations). 2. Generate or Place Your SSH Key If you don’t have an SSH key, generate one: ssh-keygen -t ed25519 -C \u0026quot;your-email@example.com\u0026quot; Save it to /config/ssh/id_ed25519 for persistence. Add the public key ( id_ed25519.pub) to your GitHub or GitLab account under SSH Keys. 3. Initialize a Git Repo (If Not Already Initialized) In your Home Assistant config directory:\ncd /config git init 4. Add Your Remote Repo For GitHub: git remote add origin git@github.com:YourUsername/your-ha-repo.git For GitLab: git remote add origin git@gitlab.com:YourUsername/your-ha-backup.git 5. Set Your Git User Info (Local) git config user.name \u0026#34;Your Name\u0026#34; git config user.email \u0026#34;your@email.com\u0026#34; Step 2: Create the Backup Script Place this as /config/git-auto-backup.sh:\n#!/bin/bash LOGFILE=\u0026#34;/config/git-auto-backup.log\u0026#34; { echo \u0026#34;\u0026#34; echo \u0026#34;===== Backup run at $(date \u0026#39;+%Y-%m-%d %H:%M:%S\u0026#39;) =====\u0026#34; cd /config || { echo \u0026#34;Failed to cd /config\u0026#34;; exit 1; } # Set Git user info (change as needed) git config user.name \u0026#34;Your Name\u0026#34; git config user.email \u0026#34;your@email.com\u0026#34; # Add all changes git add . # Commit and push only if there are staged changes if ! git diff --cached --quiet; then git commit -m \u0026#34;Auto-backup: $(date \u0026#39;+%Y-%m-%d %H:%M:%S\u0026#39;)\u0026#34; \u0026amp;\u0026amp; GIT_SSH_COMMAND=\u0026#34;ssh -i /config/ssh/id_ed25519 -o UserKnownHostsFile=/config/ssh/known_hosts\u0026#34; git push origin main STATUS=$? if [ $STATUS -eq 0 ]; then echo \u0026#34;Backup and push succeeded.\u0026#34; else echo \u0026#34;Push failed with exit code $STATUS.\u0026#34; fi else echo \u0026#34;No changes to commit.\u0026#34; fi echo \u0026#34;===== End run =====\u0026#34; } \u0026gt;\u0026gt; \u0026#34;$LOGFILE\u0026#34; 2\u0026gt;\u0026amp;1 Make the script executable:\nchmod +x /config/git-auto-backup.sh Step 3: Automate Backups with Home Assistant (No Cron Needed!) Cron is not available on Home Assistant OS by default.\nInstead, use a Shell Command and a time-based Automation.\nA. Add Shell Command In your configuration.yaml:\nshell_command: git_auto_backup: /bin/bash /config/git-auto-backup.sh Looks like this, it may have multiple entries.\nHome Assistant Configuration Yaml file \u0026lsquo;Shell Command\u0026rsquo; Section\nB. Create a Time-Based Automation Add this automation (via UI or in YAML):\nalias: Home Assistant Nightly Git Backup trigger: - platform: time at: \u0026#39;03:00:00\u0026#39; action: - service: shell_command.git_auto_backup mode: single Now, every night at 3am, your config is safely backed up to your Git repo!\nYou can also do the above using HA UI.\nHome Assistant Sample Automation\nStep 4: Restore from Backup (Disaster Recovery) Here’s a safe restore script that will backup your current config before restoring:\n#!/bin/bash # Restore script: /config/git-restore-backup.sh BACKUP_DIR=\u0026#34;/config_backup_$(date \u0026#39;+%Y%m%d-%H%M%S\u0026#39;)\u0026#34; echo \u0026#34;Backing up current /config to $BACKUP_DIR\u0026#34; cp -a /config \u0026#34;$BACKUP_DIR\u0026#34; cd /config || exit 1 # Set git user info git config user.name \u0026#34;Your Name\u0026#34; git config user.email \u0026#34;your@email.com\u0026#34; # Fetch latest from main branch GIT_SSH_COMMAND=\u0026#34;ssh -i /config/ssh/id_ed25519\u0026#34; git fetch origin main # Hard reset to remote main branch GIT_SSH_COMMAND=\u0026#34;ssh -i /config/ssh/id_ed25519\u0026#34; git reset --hard origin/main echo \u0026#34;Restore complete. Your /config now matches the remote backup.\u0026#34; Don’t forget to make it executable:\nchmod +x /config/git-restore-backup.sh Run it manually when you need to restore.\nBest Practices \u0026amp; Tips Use a `` file to exclude secrets, database files, and cache: secrets.yaml *.db .cloud/ .storage/ (Customize for your setup.) Always use private repositories for Home Assistant config backups. Regularly check your backup log ( /config/git-auto-backup.log) to ensure successful runs. Test your restore process on a test system before disaster strikes. Conclusion Automating Home Assistant config backups with GitHub or GitLab ensures your smart home brain is always safe and portable, no matter what happens. With just a few scripts and Home Assistant’s built-in automation, you get versioned, remote, restorable backups—completely hands-off.\nStay smart, stay backed up, and never fear a Home Assistant experiment again!\nDid this guide help you? Share it with other smart home fans or leave a comment with your own backup tips!\nRelated reading Back up Dockerized n8n to GitHub or GitLab Version-control Proxmox configuration ","permalink":"https://rabin.blog/how-to-automatically-backup-restore-home-assistant-github-gitlab/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003cem\u003eEasily automate Home Assistant config backups to GitHub or GitLab with step-by-step scripts and instant restore tips.\u003c/em\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003cp\u003eHome Assistant is the brains of your smart home, but even the most seasoned tinkerers have experienced the frustration of a corrupted SD card, accidental misconfiguration, or a failed upgrade. What if you could instantly roll back to a working state or migrate your entire setup to a new server with just one script? That’s the power of automated versioned backups with GitHub or GitLab.\u003c/p\u003e","title":"How to Automatically Back Up and Restore Your Home Assistant Configuration to GitHub or GitLab (with Zero Downtime)"},{"content":"Do you know you can setup your Macbook Pro so that it can work like a desktop?\nIt\u0026rsquo;s actually pretty simple.\nHere is what you will need for the setup: A good monitor, it is better if the device is 2K or 4K and at least 26 inches of size. Typically, these monitors comes with HDMI connection option.\nUSB-C to HDMI cable, this will connect your MacBook pro 2016 or later version to the monitor. Also provide audio routing if your monitor comes with Speakers.\nA bluetooth wireless keyboard. Logitech has a good working capability with MacBooks.\nA bluetooth wireless mouse, Logitech MX Anywhere 2 is a great option for this.\nHow do you set it up: First connect your bluetooth wireless keyboard and mouse with your Macbook Now you can close the lid of your Macbook to sleep position Attach the power supply Attach the USB-C to HDMI cable from your MacBook pro to your monitor Turn on the Monitor if it is not already At this point Macbook will wake up from sleep without opening the lid It will ask you to enter your Macbook Password to continue You can use your wireless bluetooth keyboard and mouse to continue your work Setup your monitor as extended desktop from display options After this process, you will adjust your desktop resolution as the way that fits best for the monitor you have.\nMacBook Pro Connections\nFrom this point forward, you can just unplug the MacBook when you go back home. And, when you come back to work, you just plug in two cables. Power and USB-C to HDMI to the MacBook.\nThat\u0026rsquo;s all.\nRelated reading Useful power tools for a new Mac Scan receipts and documents to PDF with an iPhone ","permalink":"https://rabin.blog/setup-macbook-desktop/","summary":"\u003cp\u003e\u003cstrong\u003eDo you know you can setup your Macbook Pro so that it can work like a desktop?\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eIt\u0026rsquo;s actually pretty simple.\u003c/p\u003e\n\u003ch2 id=\"here-is-what-you-will-need-for-the-setup\"\u003eHere is what you will need for the setup:\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eA good monitor, it is better if the device is \u003ca href=\"https://amzn.to/2MWbja2\"\u003e2K or 4K\u003c/a\u003e and at least \u003ca href=\"https://amzn.to/2MWbja2\"\u003e26 inches\u003c/a\u003e of size. Typically, these monitors comes with HDMI connection option.\u003cbr\u003e\n\u003cimg alt=\"Dell UltraSharp\" loading=\"lazy\" src=\"/wp-content/uploads/2026/02/how-to-setup-your-macbook-as-a-desktop-2.webp\"\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://amzn.to/2MkwAJB\"\u003eUSB-C to HDMI\u003c/a\u003e cable, this will connect your MacBook pro 2016 or later version to the monitor. Also provide audio routing if your monitor comes with Speakers.\u003cbr\u003e\n\u003cimg alt=\"USB C to HDMI\" loading=\"lazy\" src=\"/wp-content/uploads/2026/02/how-to-setup-your-macbook-as-a-desktop-3.webp\"\u003e\u003c/li\u003e\n\u003cli\u003eA bluetooth wireless keyboard. \u003ca href=\"https://amzn.to/2yHk58R\"\u003eLogitech has\u003c/a\u003e a good working capability with MacBooks.\u003cbr\u003e\n\u003cimg alt=\"Logitech Bluetooth Keyboard\" loading=\"lazy\" src=\"/wp-content/uploads/2026/02/how-to-setup-your-macbook-as-a-desktop-4.webp\"\u003e\u003c/li\u003e\n\u003cli\u003eA bluetooth wireless mouse, \u003ca href=\"https://amzn.to/2K7Qb2N\"\u003eLogitech MX Anywhere 2\u003c/a\u003e is a great option for this.\u003cbr\u003e\n\u003cimg alt=\"A bluetooth wireless mouse, Logitech MX Anywhere 2\" loading=\"lazy\" src=\"/wp-content/uploads/2026/02/how-to-setup-your-macbook-as-a-desktop-5.webp\"\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"how-do-you-set-it-up\"\u003eHow do you set it up:\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFirst connect your bluetooth wireless keyboard and mouse with your Macbook\u003c/li\u003e\n\u003cli\u003eNow you can close the lid of your Macbook to sleep position\u003c/li\u003e\n\u003cli\u003eAttach the power supply\u003c/li\u003e\n\u003cli\u003eAttach the \u003ca href=\"https://amzn.to/2MkwAJB\"\u003eUSB-C to HDMI\u003c/a\u003e cable from your MacBook pro to your monitor\u003c/li\u003e\n\u003cli\u003eTurn on the Monitor if it is not already\u003c/li\u003e\n\u003cli\u003eAt this point Macbook will wake up from sleep without opening the lid\u003c/li\u003e\n\u003cli\u003eIt will ask you to enter your Macbook Password to continue\u003c/li\u003e\n\u003cli\u003eYou can use your wireless bluetooth keyboard and mouse to continue your work\u003c/li\u003e\n\u003cli\u003eSetup your monitor as extended desktop from display options\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAfter this process, you will adjust your desktop resolution as the way that fits best for the monitor you have.\u003c/p\u003e","title":"How to Setup Your Macbook as a Desktop"},{"content":"Last updated: 31 July 2026.\nThis policy explains how rabin.blog handles information when you visit the site. Rabin.blog is a static publication operated by Ruhani Rabin. It does not provide visitor accounts, process payments, or contain a contact form. Posts may accept moderated comments through the self-hosted service described below.\nInformation processed when you visit When your browser requests a page or file, the hosting and content-delivery infrastructure may process standard technical request information. This can include your IP address, the requested URL, date and time, referring page, browser and operating-system details, and information needed to detect abuse or delivery errors.\nThis technical information is used to deliver and secure the site, diagnose problems, and understand aggregate traffic. The hosting provider may retain request or security logs under its own operational and legal requirements.\nCookies and local browser storage The static Rabin.blog pages do not set first-party cookies. The comment service sets a short-lived, cryptographically signed cookie after a comment is submitted. This lets the commenter edit or delete that comment for up to 15 minutes; it is not used for advertising or cross-site tracking.\nThe PaperMod interface uses your browser\u0026rsquo;s local storage for two preferences:\npref-theme remembers whether you selected the light or dark theme. menu-scroll-position remembers the navigation menu\u0026rsquo;s horizontal position. These values stay in your browser, are not sent to Rabin.blog as part of normal page requests, and can be removed through your browser\u0026rsquo;s site-data controls. The on-site search runs in your browser against a search index served from Rabin.blog; search terms are not submitted to an external search service.\nComments Posts use a self-hosted instance of Isso at comments.rabin.blog. Submitting a comment requires a display name, email address, and comment text. The website field is removed, and links in published comment text are displayed as non-clickable text. A submitted comment is held for moderation before it appears publicly.\nThe comment service stores the submitted name, email address, comment text, page address, timestamps, moderation state, and an anonymized form of the requesting IP address. Names and approved comment text are public. Email addresses and IP information are not displayed publicly and are used for moderation, abuse prevention, commenter identity, and administration. Comment data is stored on infrastructure controlled by Ruhani Rabin and included in encrypted off-site backups.\nComment avatars are provided through Gravatar. To request an avatar, Isso derives a hash from the submitted email address; the visitor\u0026rsquo;s browser then requests the image from Gravatar. Gravatar therefore receives the email-derived hash and standard request information such as the visitor\u0026rsquo;s IP address and browser details. Gravatar is operated by Automattic and applies its own privacy terms.\nComments may be rejected or removed when they are spam, abusive, unlawful, off-topic, or otherwise unsuitable for publication. A commenter may use the contact method below to request correction or deletion of personal information associated with a comment.\nPrivacy-focused analytics Rabin.blog may use Umami Analytics to understand aggregate use of the site. When enabled, Umami does not use cookies or cross-site tracking. It records anonymous usage information such as page views, referring URLs, browser, operating system, device type, and approximate country. Rabin.blog will not use Umami\u0026rsquo;s optional identification features to associate activity with a named person, email address, or user account.\nAnalytics information is used to understand which content is useful, diagnose site problems, and improve navigation and performance. Retention will be limited according to the analytics configuration and operational need.\nExternal links Articles may link to third-party websites, social networks, software projects, or services. Those sites receive information when you choose to follow a link and apply their own privacy policies. Rabin.blog is not responsible for their content or privacy practices.\nThe contact link below opens ruhanirabin.com. Information submitted there is handled under the privacy terms presented on that website.\nSharing and disclosure Rabin.blog does not sell or rent visitor information. Technical information may be processed by service providers necessary to host, secure, deliver, or measure the site. Information may also be disclosed when required by law or when reasonably necessary to protect the site, its visitors, or the rights and safety of others.\nRetention and your choices Preference values remain in local storage until you remove them. Hosting logs and analytics records are kept only for operational, security, legal, and aggregate measurement needs, with specific periods depending on the configured provider and service.\nYou can clear local storage through your browser, block third-party requests with browser privacy controls, or contact Ruhani Rabin about access, correction, or deletion concerns that apply to information controlled through Rabin.blog. Some requests may be limited by legal obligations or legitimate record-keeping and security needs.\nContact For questions or concerns about this policy or privacy on Rabin.blog, use the Ruhani Rabin contact page.\nChanges to this policy This policy may be updated when the site\u0026rsquo;s hosting, analytics, or visitor features change. The date at the top of this page will show the latest revision.\n","permalink":"https://rabin.blog/privacy-policy/","summary":"\u003cp\u003eLast updated: 31 July 2026.\u003c/p\u003e\n\u003cp\u003eThis policy explains how \u003ccode\u003erabin.blog\u003c/code\u003e handles information when you visit the\nsite. Rabin.blog is a static publication operated by Ruhani Rabin. It does not\nprovide visitor accounts, process payments, or contain a contact form. Posts\nmay accept moderated comments through the self-hosted service described below.\u003c/p\u003e\n\u003ch2 id=\"information-processed-when-you-visit\"\u003eInformation processed when you visit\u003c/h2\u003e\n\u003cp\u003eWhen your browser requests a page or file, the hosting and content-delivery\ninfrastructure may process standard technical request information. This can\ninclude your IP address, the requested URL, date and time, referring page,\nbrowser and operating-system details, and information needed to detect abuse\nor delivery errors.\u003c/p\u003e","title":"Privacy Policy"},{"content":"Finding the perfect used car can feel like navigating a maze, but with the right tools to help, you can steer clear of lemons and drive away with a reliable used car. Let\u0026rsquo;s explore how to navigate the used car buying process with confidence.\nUnderstanding the Used Car Market Understanding the Used Car Market\nOverview of Used Vehicle Listings Navigating the world of used vehicle listings can be overwhelming, but smart car search tools can help. These tools aggregate car listings from multiple car sites, including giants like Autotrader and Cars.com, as well as dealership inventory feeds. Some platforms combine dealership and private seller listings, giving you a comprehensive view of the market value all in one place. Whether you prefer the extensive selection of AutoTempest or the straightforward return policies of CarMax and Carvana, understanding these options is key.\nImportance of Vehicle History Reports When it comes to buying a used car, vehicle history reports are invaluable. Services like Carfax reveal critical information such as accident history, title issues, and mileage discrepancies. Many car sites now integrate Carfax or offer free vehicle history options, making it easier to compare multiple vehicles\u0026rsquo; histories side-by-side. Prioritizing listings with a free vehicle history report or Carfax report helps you quickly eliminate risky used vehicles and focus on well-documented cars, reducing the risk of costly surprises later.\nKey Factors to Consider When Buying a Used Car A smart car search tool can help streamline the car-buying process. These tools help you find used cars for sale that fit your needs and budget by allowing car shoppers to compare pricing guides, check vehicle history, and more. This data-driven approach reduces guesswork and empowers the car buyer to get the best deal. Combined with alerts for new car listings and instant price quotes, car shoppers can quickly secure great deals, improving the overall car-buying experience and saving time. By using smart filters and cross-site comparisons, you can streamline your car shopping and find the right used car.\nEssential Tools to Help You Find the Right Used Car Essential Tools to Help You Find the Right Used Car\nUsing Carfax for Vehicle History When buying a used car, accessing vehicle history reports is essential, and Carfax is a well-known option. These reports are crucial tools to help the car buyer uncover potential issues that might not be visible during a simple inspection.\nCarfax and similar services reveal critical information like accident history, title problems, mileage discrepancies, and service records. This vehicle history insight allows you to make an informed decision and avoid used vehicles with hidden issues, giving you peace of mind.\nExploring Cargurus for Listings To help you find the best deals and get a sense of market value, car sites like CarGurus, Cars.com, and Autotrader are invaluable. These platforms provide extensive car listings, car reviews, and market insights to help you find the right used car.\nReading car reviews helps you understand common issues and reliability ratings for different vehicles.\nThey also provide valuable data, tools can help you negotiate prices and understand the market value of used cars at various dealership locations or from private sellers.\nAlerts for Similar Vehicles To stay ahead in the competitive used car buying market, smart car search tools can help you set up real-time alerts for new car listings that match your criteria. These alerts are based on price drops, mileage thresholds, and newly added vehicle history reports, ensuring you never miss a potential deal. You can combine alerts with quick checks of pricing guides like Kelley Blue Book and quickly assess market value. These tools help you decide whether to pursue a listing and find the perfect used car that fits your needs.\nEvaluating Your Options: Buyer vs. Dealership Pros and Cons of Buying from a Private Seller For the budget-conscious car buyer, private sellers sometimes offer lower asking prices on a used car, but there are limited buyer protections. Always proceed with caution when buying a used car from a private seller. For private sellers, accurate descriptions and a linked vehicle history report can increase trust and speed up the sale. When considering a private seller, ensure you prioritize having a thorough inspection conducted.\nBenefits of Purchasing from a Dealership When buying a used car, prioritize listings from reputable used car dealerships and dealerships that offer inspection reports or extended warranties. When comparing listings on car sites, check dealer car reviews and ratings to ensure you’re dealing with trustworthy sellers. Optimized listings with detailed vehicle history, pricing transparency, and quality photos drive more qualified leads for dealers. Don\u0026rsquo;t forget to verify return policies and warranties if buying a used car from a dealership.\nNegotiating as a Car Buyer When you negotiate with a dealer or private seller on a used car, bring up market value data from pricing guides to justify your offer. Using Kelley Blue Book can help you find the market value and will empower the car buyer in the negotiation process. If two dealers list the same used vehicle at different prices, use that information in negotiations. Clarify warranty or return policies if purchasing from a dealership and negotiate the price with market value backing from sources like Kelley Blue Book.\nTest Driving and Inspecting Used Vehicles Preparing for a Test Drive After using tools to help reduce your options to a shortlist, schedule test drives to evaluate handling, comfort, and any abnormal noises. A test drive is essential to validate the vehicle\u0026rsquo;s condition beyond photos and vehicle history reports. The tools can help you narrow down choices, but nothing replaces a thorough test drive when finding the perfect used car that fits your needs. During the test drive, assess the reliability by listening for unusual sounds.\nWhat to Look for During a Vehicle Inspection Always arrange an independent inspection for a used car, especially for higher-mileage or high-value used vehicles.\nA qualified mechanic can identify hidden problems not apparent in a vehicle history report or a Carfax report.\nBy conducting this inspection, you ensure that you make an informed decision, because the tools can help point you in the right direction but can\u0026rsquo;t replace a professional. Be sure to use Kelley Blue Book as one of these tools to help.\nUnderstanding Car Reviews and Their Importance Read car reviews and market value insights on car sites like CarGurus, Cars.com, and Autotrader to understand common issues, reliability ratings, and dealer performance.\nCustomer car reviews of dealerships and individual car dealers are also vital to help you find the right used car.\nThis research supports your negotiation strategy and trust in the seller when buying a used car. The insights will help you find a reliable used car.\n","permalink":"https://rabin.blog/tools-help-searching-right-used-car/","summary":"\u003cp\u003eFinding the perfect used car can feel like navigating a maze, but with the right tools to help, you can steer clear of \u003cem\u003elemons\u003c/em\u003e and drive away with a reliable used car. Let\u0026rsquo;s explore how to navigate the used car buying process with confidence.\u003c/p\u003e\n\u003ch2 id=\"understanding-the-used-car-market\"\u003eUnderstanding the Used Car Market\u003c/h2\u003e\n\u003cfigure\u003e\n    \u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2026/02/tools-to-help-you-searching-for-the-reliable-used-b9a.webp\"\n         alt=\"Understanding the Used Car Market\"/\u003e \u003cfigcaption\u003e\n            \u003cp\u003eUnderstanding the Used Car Market\u003c/p\u003e\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003ch3 id=\"overview-of-used-vehicle-listings\"\u003eOverview of Used Vehicle Listings\u003c/h3\u003e\n\u003cp\u003eNavigating the world of used vehicle listings can be overwhelming, but smart car search tools can help. These tools aggregate car listings from multiple car sites, including giants like Autotrader and Cars.com, as well as dealership inventory feeds. Some platforms combine dealership and private seller listings, giving you a comprehensive view of the market value all in one place. Whether you prefer the extensive selection of AutoTempest or the straightforward return policies of CarMax and Carvana, understanding these options is key.\u003c/p\u003e","title":"Tools to Help You Searching for a Reliable Used Car"},{"content":"You\u0026rsquo;ve just got your new Mac. What\u0026rsquo;s next?\nWell, now you need to get hold of all the power tools you need for your new Mac. The right software and tools enable us to accomplish our goals much more efficiently by using less amount of time.\nMacOS platform is well known for their software stability. There could be a long list of software if we go down to the general direction of software selection. I will try not to go overboard with this.\nAudience: Management, Developer or Designer.\nReminder: A good quality MacOS software is not free most of the time. But, it is well worth the investment.\nNow let\u0026rsquo;s take a look at the \u0026ldquo;Must\u0026rdquo; haves Mac software below:\niTerm2 iTerm 2\niTerm2 is a replacement for Terminal and the successor to iTerm. It works on Macs with macOS 10.10 or newer. iTerm2 brings the terminal into the modern age with features you never knew you always wanted. The features will blow you out of your mind - https://www.iterm2.com/features.html\nPrice: Free - https://www.iterm2.com/downloads.html\nAppCleaner AppCleaner\nAppCleaner is a small application which allows you to thoroughly uninstall unwanted apps. Installing an application distributes many files throughout your System using space of your Hard Drive unnecessarily.AppCleaner finds all these small files and safely deletes them. Simply drop an application onto the AppCleaner window. It will find for the related files and you can delete them by clicking the delete button.\nPrice: Free - http://freemacsoft.net/appcleaner/\nTransmit Transmit\nThe gold standard of macOS file transfer apps just drove into the future. Transmit 5 is here. Upload, download, and manage files on tons of servers with an easy, familiar, and powerful UI. It’s quite good.\nTransmit now connects to 11 new cloud services, like Backblaze B2, Box, Google Drive, DreamObjects, Dropbox, Microsoft Azure, and Rackspace Cloud Files. And yes, Transmit still handles the classics — FTP, SFTP, WebDAV, and S3 — better than any. We make complex services drag-and-drop simple.\nPrice: $45 - https://panic.com/transmit/\nImageOptim ImageOptim\nImageOptim is excellent for publishing images on the web (easily shrinks images “Saved for Web” in Photoshop). It\u0026rsquo;s useful for making Mac and iPhone/iPad applications smaller (if you configure Xcode to allow better optimization).\nImageOptim removes EXIF meta­data, such as GPS position and camera\u0026rsquo;s serial number, so that you can publish images without exposing private information (but there\u0026rsquo;s an option to keep the meta­data if you need it).\nPrice: Free - https://imageoptim.com/mac\nBartender Bartender\nBartender 3 lets you organize your menu bar icons, by hiding them, rearranging them, show hidden items with a click or keyboard shortcut and have icons show when they update.There are many ways to configure Bartender as you wish. Give it a go and find out.\nPrice: $15 - https://www.macbartender.com/\nSublime Text Sublime Text\nA sophisticated text editor for code, markup and prose. It\u0026rsquo;s one of it\u0026rsquo;s kind. Superior performance and features. Once you go to this tool, there is no turning back.\nPrice: $80 - http://www.sublimetext.com/\naText aText\naText accelerates your typing by replacing abbreviations with frequently used phrases you define. With aText you can easily avoid typing the same thing over and over. Features; autocomplete, auto correction and predefined list of auto replacement texts.\nPrice: $4.99 - http://www.trankynam.com/atext/\nDefault Folder X Default Folder X\nMake your Open and Save dialogs work as quickly as you do. Reopen recently closed Finder windowsCopy and Move files in file dialogsSupports tabbed Finder windowsNow in your Finder toolbars too.\nPrice: $49 - https://www.stclairsoft.com/DefaultFolderX/index.html\nMagnet Magnet\nMagnet keeps your workspace organized. Activated by dragging, customizable keyboard shortcuts or via menu bar, Magnet declutters your screen by snapping windows into organized tiles. Fullscreen, halves, quarters \u0026amp; thirds. Up to six external displays supported. The potential combinations are endless.\nDrag windows to the corners and Magnet snaps them into quarters. Use side edges to arrange horizontal and vertical halves.\nPrice: $2 ~ $5 - http://magnet.crowdcafe.com/index.html\nClipy Clipy\nClipy is a Clipboard extension app for macOS. Free, simple and robust.\nPrice: Free - https://clipy-app.com/\nGIPHY Capture GIPHY Capture\nGIPHY Capture is the best way to create GIFs on your Mac. This free app is simple, powerful, and easy enough for pretty much anyone.\nPrice: Free - https://giphy.com/apps/giphycapture\nThe Unarchiver The Unarchiver\nOpen any archive in seconds. The Unarchiver is the only app you need to open RAR on Mac. It’s times more powerful than the native macOS utility and supports infinitely more archive formats.\nPrice: Free - https://theunarchiver.com\nThis is a good list you can go with. I will update this from time to time.\nRelated reading Set up a MacBook as a desktop computer Run MAME arcade games on macOS ","permalink":"https://rabin.blog/power-tools-mac/","summary":"\u003cp\u003eYou\u0026rsquo;ve just got your new Mac. What\u0026rsquo;s next?\u003c/p\u003e\n\u003cp\u003eWell, now you need to get hold of all the power tools you need for your new Mac. The right software and tools enable us to accomplish our goals much more efficiently by using less amount of time.\u003c/p\u003e\n\u003cp\u003eMacOS platform is well known for their software stability. There could be a long list of software if we go down to the general direction of software selection. I will try not to go overboard with this.\u003c/p\u003e","title":"Power Tools You Need for Your New Mac"},{"content":"I have started using OpenLiteSpeed and CyberPanel for easier Litespeed management. You can have a tremendous amount of performance for a low price. That will be another story to tell.\nCyberPanel UI might not be the most intuitive, but it is very workable and stable to use, even for a production setup.\nBut, be cautious about the server settings and harden the server for maximum security.\nHere is how CyberPanel usually looks like:\nCyberPanel Before Applying Dark Theme\nIf you work long hours and stare at this screen, I think you can quickly get eye strain from it. This is why they have a panel called “Design” located on the left sidebar after the “Version Management” menu item.\nNow, let\u0026rsquo;s take a look at the dark theme mod for CyberPanel:\nCyberPanel Dark Theme CSS mod\nThis modification is easy and can be applied and implemented in less than a minute. I have already created the CSS class modifications.\nLink to the CSS file.\nCheck the GitHub Repo for Updates.\nYou can copy the code.\nGo to the Design Tab Paste the code into the editor Press the “Save Changes” button And, that\u0026rsquo;s it. The process is shown below:\nCyberPanel Dark Mode - How to Apply Changes\nYou can go further and customize the code according to your own needs.\nThe code below could be outdated by the time you are reading it, go to the repo for the latest code.\nIf you like this, don\u0026rsquo;t forget to join my YouTube Channel.\nRelated reading Renew Let\u0026rsquo;s Encrypt certificates manually Create a static Publii blog hosted on Netlify ","permalink":"https://rabin.blog/true-dark-theme-cyberpanel-openlitespeed-ui/","summary":"\u003cp\u003eI have started using OpenLiteSpeed and CyberPanel for easier Litespeed management. You can have a tremendous amount of performance for a low price. That will be another story to tell.\u003c/p\u003e\n\u003cp\u003eCyberPanel UI might not be the most intuitive, but it is very workable and stable to use, even for a production setup.\u003c/p\u003e\n\u003cp\u003eBut, be cautious about the server settings and harden the server for maximum security.\u003c/p\u003e\n\u003cp\u003eHere is how CyberPanel usually looks like:\u003c/p\u003e","title":"True Dark Theme for CyberPanel OpenLiteSpeed UI"},{"content":"If you are like me, you have tried and explored many static site generators such as Hugo, Jekyll \u0026amp; so on. But there is a bit of a learning curve when you start to use static site generators. The core objective for this article is to make one understand how to make a static blog with Publii and host it for free at Netlify.\nThe points mentioned below are the cautions of using static site generators: You need to be handy with command-line tools, Ruby and few other console utilities There aren\u0026rsquo;t plenty of visual editors for them, it takes much more time to compose a post or page or configuring the website Requires a handful of knowledge about GIT and GIT-based processing tools You will need to process all the files on your desktop or laptop, though some online platforms can help you generate the files too (Namely Netlify) If you ask me, I don\u0026rsquo;t think an average person can handle all the advanced tools had to publish a static blog site perfectly.\nBut, why static blog site? Why not WordPress? With static HTML, it is much simpler. You write the code (together with content). Then, once it’s on the server, it stays as it is. There’s no background processing going on – the HTML files are there in their finished form.\nOn the other hand, WordPress is a content management system that uses PHP and a database. That means that when someone visits your WordPress site, your server “generates” your site by:\nExecuting the PHP code to render the HTML version of your site Querying your database to get the content to plot into that HTML WordPress sites require PHP and database (MySQL or similar) processing engines, which means it requires a server that you need to pay for. It also requires more RAM and CPU power to make calls to the database and process PHP scripts.\nHere are some of the benefits of a static (blog) site: It is extremely fast because the generated pages are HTML files, you can even get score up to 99/100 in google page speed score It is more secure because there are no dynamic calls to PHP or MySQL It can run in a very low overhead server because it does not require CPU-based processing to process PHP or MySQL Database calls So I went to search for a solution that can enable me to use the static site or static blog without going through all the complications or the trouble of editing the posts.\nThen I found Publii - it is a desktop-based application (macOS, Windows, Linux) that enables you to generate a static site or static blog without going through the trouble of all the static site generators.\nWhat is Publii? Publii is an app that brings a new concept to the web-development table; the first desktop static-website CMS. Designed with the simplicity for beginners to use but boasting extensive options and functionalities that allow experienced web developers to make more complex modifications, Publii creates a safe, fast static website without all the hassle.\nBefore starting using Publii it is important to understand that while it is technically a CMS (Content Management System), it does not work in the same way as other CMSs you may have seen such as WordPress or Joomla!. Usually, the defining characteristic of a CMS is that it is software that runs on a server; first, you must buy hosting that provides you with access to a server, then upload the CMS files to the server and install it directly there.\nWhat this means is that everything related to your website is run on the server; if you want to create a new post, edit a category, or add images to your site, you must first login to the CMS on the server and make your changes there. You must be constantly connected to the internet for this so that any changes can be sent to the software as you make them. Though it\u0026rsquo;s possible to create the website offline and then transfer it to your server, it\u0026rsquo;s not an easy process and is prone to issues. — Cited from their documentation\nThe Advantages of Publii: It uses desktop-based CMS software, CMS does not need PHP or MySQL on the server-side Can work on low-resource servers because the generated site is pure HTML format Ability to configure and tweak settings of the website from the desktop application Ability to inject codes in the header and footer or add custom files (like .htaccess) to the file system\nVisual editor for posts and pages\nSupport for AMP site generation Support for Image uploading and compress them automatically Connect to multiple types of hosting targets such as Netlify, Amazon s3, SFTP or just local folder structure\nOn the fly change themes and see preview locally Lazy Loading Images Gallery support Twitter, Facebook, and OpenGraph tags support Comments system provided via Disqus comments Ability to use Featured images Ability to Generate Table of Contents for posts SEO Tweaks per post or sitewide Post Properties Tweaks\nNavigation menu editor Highly secured due to the nature of the static website You do not need to update the CMS library at the server, just upgrade the desktop software Disadvantages: You will need your desktop application to make changes on your website Some advanced configuration might not be possible Does not have a built-in comments system Making a static page requires a bit of work (eg. Hide it \u0026amp; exclude it from the - in this way you can make static pages) No grammar or spelling tools available Not many themes available Get free hosting with Netlify If you are not aware of Netlify; you can Deploy modern static websites with Netlify. Get CDN, Continuous deployment, 1-click HTTPS, and all the services you need. And there is a free tier plan available.\nFirst, an account at netlify. Once you are done with the signup process, you can log in to the site and create a static site just by download and dragging this file in your netlify dashboard.\nNetlify - drag and drop HTML\nThis action will create an empty site with an empty HTML file. Which will look something like below:\nNetlify - Site created\nCopy the Netlify URL( somename.netilify.com) as a reference, which we will need later for configuring Publii.\nNow, Go to “Site Settings” and Copy the API ID of the site, we will use this later to connect Publii to netlify.\nNetlify - Site Details\nOnce this process is done, go to netlify user settings page to create a token. You can access this via the right side top corner icon.\nNetlify - Access Token 1\nCreate the token, you can give it a name like “ Publii“, we will use this information later to configure server details at the Publii desktop application.\nToken for Publii\nCopy the generated token and keep it safe.\nInstall Publii Now you should download and install the Publii desktop application. Once it is installed, you can go ahead and create a new website from the application.\nPublii - New Website\nOnce a website is created, you can access the server settings from the left-side menu.\nConnect to Netlify Netlify Specific Settings for Server\nFrom the left menu panel, Select Server Now Choose “Netlify” as the protocol Copy and paste the netlify generated URL (Select HTTPS) For Site ID: Paste the API ID of the site (Shown earlier) For Netlify Token: Paste the generated Token Then Click Test Connection to test the integration\nExample of successful connection. Configure Site and Theme properties at Publii You can configure various site related and theme properties from the Publii application.\nPublii - Theme Related Settings for the Website\nYou can access theme related settings above.\nPublii - Settings for the Website\nThe other website settings and tweaks\nSee a Preview of your site locally Preview Website Locally\nWhen you click \u0026quot; Preview your changes\u0026quot;, it will generate the site locally and open in your default browser.\nSync your site with Netlify Preview Website Locally\nPublii - Sync Website Process\nWhen you are ready, you can use the \u0026quot; Sync your website\u0026quot; button to sync the changes in netlify. It may take a minute or so.\nSee your site online Once the \u0026quot; Sync your website\u0026quot; process is finished, you can head over to your netlify admin and enter the site profile you have created. Click on the “ Deploy” menu item to see the deploy messages. Once it says “ Published” in the badge, your site is online. You can use the Netlify URL to access your website.\nNetlify - Published\nOptional: Add a custom domain You can add a custom domain to your netlify account, which can be used as the main domain for your website. You can find the instructions here.\nAdd domain to Netlify\nPlease note, once you use netlify DNS for your domain name, it might take 8-24 hours to propagate the changes. Once the domain is ready, netlify will provide a LetsEncrypt certificate for your domain automatically.\nnetlify will provide a LetsEncrypt certificate for your domain automatically\nOptional - Optimize Content using Netlify You can also configure netlify to optimize your resources on their CDN side. To accomplish this, simply head over to your site settings, Then select \u0026quot; Build \u0026amp; Deploy\u0026quot; and go to the \u0026quot; Asset Optimization\u0026quot; part. You can select the options as you see below.\n\u0026lsquo;Build \u0026amp; Deploy\u0026rsquo; and go to \u0026lsquo;Asset Optimization\u0026rsquo;\nBy default, Disable Asset Optimization is selected, you can uncheck that and select the options you like to have. Then \u0026quot; Save\u0026quot; the settings.\nOptional: Add a Contact Form using TypeForm You can create great-looking contact forms using TypeForm.\nConclusion I hope you have some insights of creating your Static Blog site by using this article. Yes, there is some preliminary process involved, but once you can get this ready, you will be able to blog - for free. While being free, you also get an excellent performance out of your website. You can create a blog in this process which costs:\nHosting (Netlify, GitHub Pages, GitLab Pages etc.): $0.0 CMS Tool Publii: $0.0 Domain name: $10/year ","permalink":"https://rabin.blog/static-blog-publii-host-free-netlify/","summary":"\u003cp\u003eIf you are like me, you have tried and explored many static site generators such as Hugo, Jekyll \u0026amp; so on. But there is a bit of a learning curve when you start to use static site generators. The core objective for this article is to make one understand how to make a static blog with Publii and host it for free at Netlify.\u003c/p\u003e\n\u003ch2 id=\"the-points-mentioned-below-are-the-cautions-of-using-static-site-generators\"\u003eThe points mentioned below are the cautions of using static site generators:\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eYou need to be handy with command-line tools, Ruby and few other console utilities\u003c/li\u003e\n\u003cli\u003eThere aren\u0026rsquo;t plenty of visual editors for them, it takes much more time to compose a post or page or configuring the website\u003c/li\u003e\n\u003cli\u003eRequires a handful of knowledge about GIT and GIT-based processing tools\u003c/li\u003e\n\u003cli\u003eYou will need to process all the files on your desktop or laptop, though some online platforms can help you generate the files too (Namely Netlify)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIf you ask me, I don\u0026rsquo;t think an average person can handle all the advanced tools had to publish a static blog site perfectly.\u003c/p\u003e","title":"Create a Static Blog with Publii and Host for Free at Netlify"},{"content":"This only applies to existing domains that already have pre-existing certificates from LetsEncrypt.\nIf you have not noticed, when you are using Let\u0026rsquo;s Encrypt SSL certificates, they will only give the first SSL certificate for 3 months. Subsequently, you will need to generate/renew the SSL certificate.\nIf you are running custom droplets or servers, you might need to use the “sudo” command-line interface to renew it. This can apply to servers from DigitalOcean.com, Linode, Amazon AWS Machines and upCloud.\nStep 1 Login to your SSH interface. Switch to sudo mode if you prefer.\nStep 2 Stop the NGINX or Apache web server, because letencrypt needs to use port 80 to bind the certificate.\nCommand (usable on CentOS 7x or similar):\nsudo systemctl stop nginx\nOnce this is done, move on to step 3\nStep 3 Now generate a certificate for your existing website. This is why we have used the sub-command certonly\nsudo /usr/bin/letsencrypt certonly -d domain.com\nSuccess message from LetsEncrypt\nStep 4 Once this is done, you need to start your web server again\nsudo systemctl start nginx\nOptional: You can find more information from this forum post at DigitalOcean.\nRelated reading Create a static Publii blog hosted on Netlify ","permalink":"https://rabin.blog/how-to-renew-letsencrypt-ssl/","summary":"\u003cp\u003eThis only applies to existing domains that already have pre-existing certificates from LetsEncrypt.\u003c/p\u003e\n\u003cp\u003eIf you have not noticed, when you are using Let\u0026rsquo;s Encrypt SSL certificates, they will only give the first SSL certificate for 3 months. Subsequently, you will need to generate/renew the SSL certificate.\u003c/p\u003e\n\u003cp\u003eIf you are running custom droplets or servers, you might need to use the “sudo” command-line interface to renew it. This can apply to servers from DigitalOcean.com, Linode, Amazon AWS Machines and upCloud.\u003c/p\u003e","title":"How to Renew LetsEncrypt SSL Certificates"},{"content":"In the last few years, It dramatically changed how many ways we can use our phones for multiple different purposes. Phones have become smarter and more useful. Just a few years back, it was essential for me to use a flatbed scanner for all types of scanning needs. This includes scanning photos or scanning a document, sometimes even receipts.\nWhen Apple released iOS 14, there are some significant usability improvements came along with it. Such as one, scanning documents or receipts. This feature has been built into the Native Apple Notes app.\nNow, let us take a look at how easily you can scan a set of documents with your phone and make them PDF for further use or to share in multiple places.\nWhat will you need to do this? Your iPhone Your document pages you would like to scan Step 1 - Prepare your Document Page Put one of your document pages in a place where it is sufficiently lighted. It is preferred not to put them in a place where something cast some shadows. Generally, a tabletop with natural lighting would do it.\nStep 2 - Prepare your phone First, open up your Apple Notes app on your phone. Now, create a new Note.\nWhen you enter the new note, you will see few icons on top of your virtual keyboard.\nTap and Hold the Camera Icon to display few camera options. One of the Option is \u0026ldquo;Scan Documents\u0026rdquo;\nOpen the Scan Document Camera\nStep 3 Open the Scan Documents camera option and it will open the Camera for this specific purpose. When you are in the camera mode, turn \u0026quot; AUTO\u0026quot; to \u0026quot; Manual\u0026quot;, located top right corner of the Camera view.\nManual Mode will give you much greater control over the border selection.\nStep 4 Now place your camera above the document you would like to scan, try to fit it in the camera frame. A yellow highlight will be visible when the document in scanning mode.\nYellow highlight will identify the scanning area\nStep 5 You can snap the photo and it should detect the borders of the document with an outline.\nAdjust the border before saving the stack\nYour current snap will be added to the stack on the right bottom of your screen. You can continue snapping more photos and they will be added to the stack. In this way, the stack will be one PDF file.\nYou can also finish the process and Start scanning a new document to make new PDF stacks. Just repeat the process from Step 1 to 5.\nThe stacks of photos will be added to your new Note, and you can tap them to view, share in email or WhatsApp. You can also save it to your cloud storage like OneDrive or Apple Cloud.\nThe whole process is fairly simple and does not require and 3rd party apps to accomplish this job.\nHave fun scanning with your iPhone (Or iPad).\nTIPS: You can adjust the color profile of the camera if you prefer to take black and white photos or grayscale ones.\nYou can adjust the color profile of the camera\nRelated reading Set up a MacBook as a desktop computer Useful power tools for a new Mac ","permalink":"https://rabin.blog/how-scan-receipts-documents-pdf-iphone/","summary":"\u003cp\u003eIn the last few years, It dramatically changed how many ways we can use our phones for multiple different purposes. Phones have become smarter and more useful. Just a few years back, it was essential for me to use a flatbed scanner for all types of scanning needs. This includes scanning photos or scanning a document, sometimes even receipts.\u003c/p\u003e\n\u003cp\u003eWhen Apple released iOS 14, there are some significant usability improvements came along with it. Such as one, scanning documents or receipts. This feature has been built into the Native Apple Notes app.\u003c/p\u003e","title":"How to Scan Receipts and Documents to PDF with iPhone"},{"content":"Can you remember the days with the Arcade games at the mall or the shops?\nYou would, if you grew up during the 80s-90s era.\nWell, there was Atari and Nintendo. But the real fun was always at the Arcade shops.\nEarlier this week, I realized how much I have missed those games, nearly 30 years later.\nSo I dug out the emulator software for mac and the process to put those games back in my MacBook Pro.\nIt is fairly simple, just follow the steps below and you will be crushing the keyboard in no time filled with joy. You will definitely rewind back to the 90s.\nSo what is MAME? Technical abbreviation of M.A.M.E = Multiple Arcade Machine Emulator\nMultiple Arcade Machine Emulator\nM.A.M.E. as an archive of the retro software that runs arcade systems from the 80s and 90s. The developers tried their best to make the software systems that ran/run on arcade based computer\u0026rsquo;s emulation. If you want to run some older arcade games, aside from having an authentic arcade machine, your best option would be the M.A.M.E. project.\nStep 1 OpenEMU\nGet the OpenEmu software for mac. With OpenEmu, it is extremely easy to add, browse, organize and with a compatible game pad, play those favorite games (ROMs) you already own.\nMake sure you download the Experimental version\nDownload Experimental\nNote: Here are the special instructions for mac, because usually macOS blocks 3rd party applications.\nOpenEmu screen on a mac\nNote: What are the ROM?- ROMs are the files for the games, each game has one or more ROM files in their \u0026ldquo;.zip\u0026rdquo; package.\nStep 2 Extract the OpenEmu zip file in a folder of your choosing. See example below\nYou can create a new folder under your user folder\nNow, Right click and open the OpenEmu app. The system will show you a warning, in that dialog, choose \u0026quot; Open\u0026quot;.\nStep 3 Once it is open, you should see the screens with the downloadable options.\nNow select all the options, if they are not already selected. This will download all the necessary modules for the application.\nOnce all the downloads are done, you will see an empty screen of OpenEmu (Shown in Step 1).\nStep 4 At this step you can configure your controls. There is a variety of options to choose from. Go to Menu, OpenEmu \u0026gt; Preferences\nPreferences \u0026gt; Controls\nSelect your desired control settings from here.\nStep 5 Now you can start installing the games in this OpenEmu library.\nGo to Finder / Downloads — where you have the game ROM zip files Drag them to the main window of OpenEmu This will install the selected games and organize it like a library Games added to the OpenEmu library\nCadillacs and Dinosaurs Screenshot\nVoila! There is no longer a need for a time machine to go back to your childhood memories.\nWhere Can I get the Game ROMs? Here is a list of websites you can download ROMs\nhttps://www.romspedia.com/roms/mame https://www.gamulator.com/roms/mame https://www.emuparadise.me/M.A.M.E._-_Multiple_Arcade_Machine_Emulator_ROMs/7 https://coolrom.com.au/roms/mame/ https://romsmode.com/roms/mame https://www.romsformame.com/index.php?p=57 Bonus: How to play MAME arcade games in Windows PC?\nRelated reading Useful power tools for a new Mac Set up a MacBook as a desktop computer ","permalink":"https://rabin.blog/mame-arcade-games-macos-how-to/","summary":"\u003cp\u003eCan you remember the days with the Arcade games at the mall or the shops?\u003c/p\u003e\n\u003cp\u003eYou would, if you grew up during the 80s-90s era.\u003c/p\u003e\n\u003cp\u003eWell, there was Atari and Nintendo. But the real fun was always at the Arcade shops.\u003c/p\u003e\n\u003cp\u003eEarlier this week, I realized how much I have missed those games, nearly 30 years later.\u003c/p\u003e\n\u003cp\u003eSo I dug out the emulator software for mac and the process to put those games back in my MacBook Pro.\u003c/p\u003e","title":"MAME Arcade Games – macOS – How to?"},{"content":"Active tools, experiments, and public project work.\nExeRoam July 1, 2026\nExeRoam is a small Windows launcher for applications stored in portable folders.\nView ExeRoam on GitHub\nServus May 4, 2026\nAutomates the recurring chores that eat sysadmin time — disk reports, log cleanup, service monitoring, and resource alerts.\nView Servus on GitHub\n","permalink":"https://rabin.blog/projects/","summary":"\u003cp\u003eActive tools, experiments, and public project work.\u003c/p\u003e\n\u003ch2 id=\"exeroam\"\u003eExeRoam\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003eJuly 1, 2026\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eExeRoam is a small Windows launcher for applications stored in portable folders.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/ruhanirabin/ExeRoam\"\u003eView ExeRoam on GitHub\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"servus\"\u003eServus\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003eMay 4, 2026\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eAutomates the recurring chores that eat sysadmin time — disk reports, log cleanup, service monitoring, and resource alerts.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/ruhanirabin/servus\"\u003eView Servus on GitHub\u003c/a\u003e\u003c/p\u003e","title":"Projects"},{"content":"I Help Product Teams Build Clearer, Simpler Products that Drives Retention. Looking for my product, UX and AI advisory work? Visit my main website\nI work with founders and product leaders who are building real products under real constraints. Over the last three decades, I’ve helped teams move from idea to market, untangle bloated UX, scale platforms used by millions, and make better product decisions earlier.\nI do not decorate interfaces or chase trends. My part is to bring clarity for you - on what to build, what to fix, when to stop, what to stop, and where technology including AI and automation adds value.\nShortlinks\nContact Form\n","permalink":"https://rabin.blog/about-me/","summary":"\u003ch2 id=\"i-help-product-teams-build-clearer-simpler-products-that-drives-retention\"\u003eI Help Product Teams Build Clearer, Simpler Products that Drives Retention.\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eLooking for my product, UX and AI advisory work?\u003c/strong\u003e\n\u003ca href=\"https://www.ruhanirabin.com/\"\u003eVisit my main website\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eI work with founders and product leaders who are building real products under real constraints. Over the last three decades, I’ve helped teams move from idea to market, untangle bloated UX, scale platforms used by millions, and make better product decisions earlier.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eI do not decorate interfaces or chase trends. My part is to bring clarity for you - on what to build, what to fix, when to stop, what to stop, and where technology including AI and automation adds value.\u003c/p\u003e","title":"Who is Ruhani Rabin?"}]