[{"categories":["sysadmin"],"content":"The setup services.xrdp.enable = true; with defaultWindowManager = \u0026quot;xfce4-session\u0026quot;; on NixOS. Connect from macOS with a RDP client, and instead of a desktop you get either:\na black screen, or an error dialog: \u0026ldquo;Unable to load a failsafe session\u0026rdquo; with the message: Unable to determine failsafe session name. Possible causes: xfconfd isn\u0026#39;t running (D-Bus setup problem); environment variable $XDG_CONFIG_DIRS is set incorrectly (must include \u0026#34;/nix/store/\u0026lt;hash\u0026gt;-xfce4-session-.../etc\u0026#34;), or xfce4-session is installed incorrectly. First (wrong) fix The obvious move: xfce4-session: command not found shows up in journalctl -u xrdp-sesman, so just add the package:\nenvironment.systemPackages = with pkgs; [ xfce.xfce4-session ]; That gets rid of \u0026ldquo;command not found\u0026rdquo; — but now you get the failsafe-session error above instead. Progress, but still broken.\nRoot cause On a normal Linux distro, xfce4-session\u0026rsquo;s config lives under /etc/xdg, which is already in every process\u0026rsquo;s default $XDG_CONFIG_DIRS. On NixOS, the package\u0026rsquo;s config lives inside its own Nix store path (/nix/store/\u0026lt;hash\u0026gt;-xfce4-session-4.20.3/etc), and nothing sets $XDG_CONFIG_DIRS to include it — unless something wraps the environment for you.\nThat \u0026ldquo;something\u0026rdquo; is services.xserver.desktopManager.xfce. It\u0026rsquo;s not just a convenience wrapper for a login manager — it\u0026rsquo;s the thing that actually patches the session environment variables (XDG_CONFIG_DIRS, XDG_DATA_DIRS, etc.) so XFCE tools can find their own config at runtime. Installing xfce.xfce4-session as a bare package skips all of that wiring.\nThe real fix services.xserver.enable = true; services.xserver.desktopManager.xfce.enable = true; services.xrdp = { enable = true; defaultWindowManager = \u0026#34;xfce4-session\u0026#34;; openFirewall = true; }; Note there\u0026rsquo;s no displayManager here — xrdp spins up its own X session per RDP connection, it doesn\u0026rsquo;t use the system\u0026rsquo;s login manager. You only need the desktop manager to get the correct environment wrapping; you don\u0026rsquo;t need GDM/LightDM sitting on top of it.\nRemove the bare xfce.xfce4-session package once desktopManager.xfce is enabled — it already pulls in xfce4-session as a dependency, with the environment wired correctly this time.\nLesson On NixOS, \u0026ldquo;the binary is on PATH\u0026rdquo; and \u0026ldquo;the binary works correctly\u0026rdquo; are two different guarantees. Desktop environment packages usually carry NixOS-specific environment wiring that only gets set up through the matching services.xserver.desktopManager.* module — installing the raw package is not equivalent to enabling the module.\n","lang":"en","permalink":"https://profile.huyab.click/posts/nixos-xrdp-xfce4-session-failsafe/","section":"posts","summary":"Why adding the xfce4-session package alone breaks xrdp on NixOS, and the one-line fix that actually works.","tags":["nixos","xrdp","xfce"],"title":"NixOS xrdp black screen: \"Unable to load a failsafe session\""},{"categories":[],"content":"Self-hosting Vaultwarden (a Bitwarden-compatible server) behind a Cloudflare Tunnel, everything was smooth until one day the Chrome extension refused to log in with the utterly unhelpful message: \u0026ldquo;An error has occurred\u0026rdquo;. No error code, no details. Meanwhile the web vault (https://your-domain/) logged in just fine.\nStep 1: Check the container logs First rule of self-hosting debugging: always check logs first.\ndocker logs -f vaultwarden Logging in via web was clean:\nPOST /identity/connect/token =\u0026gt; 200 OK GET /api/sync =\u0026gt; 200 OK GET /api/accounts/profile =\u0026gt; 200 OK But trying to log in from the Chrome extension spammed this repeatedly:\nPOST /identity/accounts/prelogin/password =\u0026gt; 404 Not Found Same request retried every few seconds, eventually ending with:\nPOST /api/accounts/password-hint =\u0026gt; 400 Bad Request [ERROR] This server is not configured to provide password hints. Step 2: Root cause /identity/accounts/prelogin/password is a newer endpoint used by Bitwarden clients (including the Chrome extension) as part of the pre-login auth flow. The server returned 404 because the running Vaultwarden version simply didn\u0026rsquo;t implement that endpoint yet.\nChecked the running version:\ndocker logs vaultwarden 2\u0026gt;\u0026amp;1 | grep Version # Version 1.35.7 Fairly old. Meanwhile the Chrome extension auto-updates itself to the latest client, and the newer client expects the server to support the new login flow.\nLesson learned: when self-hosting a client-server app where the client auto-updates (browser extensions, mobile apps\u0026hellip;), keep the server in sync too. Version drift between client and server is one of the most common causes of confusing, generic-looking errors.\nStep 3: Update the server docker pull vaultwarden/server:latest docker compose up -d After upgrading to 1.37.1, the Chrome extension login worked immediately - no more 404 on prelogin/password.\nA few safety notes If you\u0026rsquo;re pinning :latest in compose.yml, the old image isn\u0026rsquo;t deleted automatically - it just gets untagged. docker images -a will still show the old image ID, so you can pin it back if you ever need to roll back. Back up your database before upgrading, even though version bumps rarely touch the schema. Better safe than sorry - especially if you\u0026rsquo;re also planning to switch database backends (e.g. SQLite ↔ Postgres) around the same time. Do those changes separately so it\u0026rsquo;s easier to isolate issues. docker logs -f \u0026lt;container\u0026gt; is your first and best debugging tool for self-hosted services - don\u0026rsquo;t guess, read the logs. Bottom line: sometimes a scary generic error like \u0026ldquo;An error has occurred\u0026rdquo; is just the server being older than the client expects. Upgrading to the latest version fixes it.\n","lang":"en","permalink":"https://profile.huyab.click/posts/vaultwarden-chrome-extension-login-error/","section":"posts","summary":"Debugging a self-hosted Vaultwarden issue where the Chrome extension fails to log in while the web vault works fine - turned out to be a stale server version.","tags":["docker","vaultwarden","selfhost","bitwarden","chrome"],"title":"Vaultwarden: Web login works but Chrome Extension says \"An error has occurred\""},{"categories":[],"content":"If your dev machine handles both Node.js and Python, sooner or later your disk will get crowded with:\nnode_modules .venv __pycache__ caches from poetry, pipx, uv, tox, and more These are 2 tools worth keeping in mind.\n1. npx npkill When you want to find and remove old node_modules folders, npkill is a very fast option:\nnpx npkill It scans from the current directory, lists detected node_modules, and shows their sizes so you can delete them interactively in the terminal.\nWhat I like about it:\nno global install needed easy to spot folders eating several GB interactive deletion, so no need for ugly find ... -exec rm -rf If you want to scan a specific directory:\nnpx npkill -d ~/Projects 2. uvx killpy If npkill is the cleanup tool for Node.js, then killpy feels like the Python equivalent:\nuvx killpy --path ~ killpy can find things like:\n.venv poetry environments conda environments envs from pipenv, pipx, pyenv, uv caches such as __pycache__, .pytest_cache, .mypy_cache The nice part is that it gathers everything in one place instead of forcing you to remember scattered paths across your home directory.\nIf you only want to scan the current folder:\nuvx killpy When should you use them? I usually run:\nnpx npkill when old Node.js repos are taking too much space uvx killpy --path ~ when I want to do a general Python cleanup on my machine Both tools fit the same pattern:\nrun once when needed no permanent install required very useful when your disk is full and you are not sure why If you work across multiple stacks, these 2 commands can save quite a few GB:\nnpx npkill uvx killpy --path ~ ","lang":"en","permalink":"https://profile.huyab.click/posts/npkill-killpy/","section":"posts","summary":"Two small but useful CLIs: \u003ccode\u003enpx npkill\u003c/code\u003e to clean up \u003ccode\u003enode_modules\u003c/code\u003e, and \u003ccode\u003euvx killpy\u003c/code\u003e to find and remove Python virtual environments and caches eating disk space.","tags":["nodejs","python","cli","tool","tip","disk"],"title":"2 Cleanup Tools for Node.js and Python"},{"categories":["Linux","NixOS"],"content":"Upgrading NixOS is a straightforward process, but it\u0026rsquo;s important to follow the correct steps to ensure a smooth transition. Here is a guide on how to upgrade your system to NixOS 25.11.\n1. List Current Channels First, it\u0026rsquo;s a good idea to verify your current channels.\nnix-channel --list 2. Add the New 25.11 Channel Add the new NixOS 25.11 channel to your system.\nsudo nix-channel --add https://nixos.org/channels/nixos-25.11 nixos 3. Update All Channels Update your channels to download the new package definitions.\nsudo nix-channel --update 4. Read the Release Notes Crucial Step: Before proceeding, make sure to read the release notes for any breaking changes that might affect your configuration.\nCheck the release notes at: nixos.org/manual/nixos/stable/release-notes\n5. Rebuild Your System Now, rebuild your system. This process will take some time as it downloads and compiles the new packages.\nUse the --upgrade flag to automatically apply fixes for some common changes.\nsudo nixos-rebuild switch --upgrade Alternatively, if you want to build and boot into the new system without activating it immediately:\nsudo nixos-rebuild boot --upgrade 6. Reboot If you used the boot command or want to be fully on the new system, perform a reboot.\nsudo reboot ","lang":"en","permalink":"https://profile.huyab.click/posts/nixos-upgrade-25-11/","section":"posts","summary":"A step-by-step guide to upgrading your NixOS system to the latest 25.11 release.","tags":["nixos","linux","upgrade","tutorial"],"title":"How to Upgrade NixOS to 25.11"},{"categories":[],"content":" 📖 Summary of The Art of Readable Code 1. Code Should Be Easy to Understand Key Idea: Minimize time-till-understanding.\nReadable code is more important than short code.\nExample:\n// Less clear return exponent \u0026gt;= 0 ? mantissa * (1 \u0026lt;\u0026lt; exponent) : mantissa / (1 \u0026lt;\u0026lt; -exponent); // Clearer if (exponent \u0026gt;= 0) { return mantissa * (1 \u0026lt;\u0026lt; exponent); } else { return mantissa / (1 \u0026lt;\u0026lt; -exponent); } 2. Packing Information into Names Names are mini-comments.\nUse specific and concrete words.\nAttach units or attributes if critical.\nExample:\n# Bad def GetPage(url): ... # Better def FetchPage(url): ... Example with units:\nvar elapsed_ms = (new Date()).getTime() - start_ms; 3. Names That Can’t Be Misconstrued Avoid ambiguous names.\nUse min_/max_ for limits, first/last for inclusive ranges, begin/end for inclusive-exclusive ranges.\nBoolean names should use is_, has_, can_.\nExample:\n# Bad read_password = True # unclear meaning # Better need_password = True 4. Aesthetics Code should look clean.\nRules: consistent layout, make similar code look similar, group related lines.\nUse helper methods to simplify long or repetitive test cases.\nExample:\n// Before assert(ExpandFullName(\u0026#34;Doug Adams\u0026#34;) == \u0026#34;Mr. Douglas Adams\u0026#34;); assert(ExpandFullName(\u0026#34;No Such Guy\u0026#34;) == \u0026#34;\u0026#34;); // After CheckFullName(\u0026#34;Doug Adams\u0026#34;, \u0026#34;Mr. Douglas Adams\u0026#34;, \u0026#34;\u0026#34;); CheckFullName(\u0026#34;No Such Guy\u0026#34;, \u0026#34;\u0026#34;, \u0026#34;no match found\u0026#34;); 5. Knowing What to Comment Comments should explain why, not repeat what.\nAvoid obvious comments.\nWrite notes that help future readers understand faster.\nExample:\n// Fast version of \u0026#34;hash = (65599 * hash) + c\u0026#34; hash = (hash \u0026lt;\u0026lt; 6) + (hash \u0026lt;\u0026lt; 16) - hash + c; 6. Making Comments Precise and Compact Keep comments short and exact.\nAvoid vague pronouns (“it”, “this”).\nProvide input/output examples, especially edge cases.\nExample:\n# Cuts off at max characters and appends \u0026#34;...\u0026#34; def Truncate(text, max_chars): ... 7. Making Control Flow Easy to Read Write if/else in a clear order.\nReturn early to reduce nesting.\nAvoid goto and do/while loops.\nExample:\n# Nested if user: if user.is_active: return True else: return False # Return early if not user: return False return user.is_active 8. Breaking Down Giant Expressions Split long expressions into smaller pieces.\nUse helper variables.\nApply De Morgan’s laws to simplify.\nExample:\n# Hard to read if not (file_exists and not file_is_empty): # Clearer missing_or_empty = (not file_exists) or file_is_empty if missing_or_empty: ... 9. Variables and Readability Fewer variables = easier to read.\nMinimize scope of variables.\nPrefer write-once variables.\nExample:\n# Bad: reusing variable result = query_db() result = format(result) # Better raw_result = query_db() formatted = format(raw_result) 10. Extracting Unrelated Subproblems Separate unrelated logic into helper functions.\nMakes code reusable and simplifies main functions.\nExample:\n# Before def find_closest_location(user, locations): best_dist = float(\u0026#34;inf\u0026#34;) for loc in locations: dist = compute_distance(user, loc) if dist \u0026lt; best_dist: best_dist = dist best_loc = loc return best_loc # After def distance_between(a, b): ... def find_closest_location(user, locations): return min(locations, key=lambda loc: distance_between(user, loc)) 11. One Task at a Time Each function should do only one job.\nSmall tasks are easier to test and maintain.\nExample:\n# Before: parsing + validation together def get_user_id(data): id = int(data.split(\u0026#34;,\u0026#34;)[0]) if id \u0026lt; 0: raise ValueError(\u0026#34;Invalid id\u0026#34;) return id # After: separated def parse_id(data): ... def validate_id(id): ... 12. Turning Thoughts into Code Write code that mirrors your thought process.\nUse expressive language and libraries.\nExample:\n# Thought: \u0026#34;get active users\u0026#39; emails\u0026#34; emails = [user.email for user in users if user.is_active] 13. Writing Less Code Less code = fewer bugs.\nDon’t implement unnecessary features.\nReuse libraries and tools.\nExample:\n# Instead of writing custom file search grep \u0026#34;keyword\u0026#34; *.txt 14. Testing and Readability Tests must be readable and maintainable.\nUse meaningful inputs.\nWrite descriptive test names.\nError messages should be clear.\nExample:\n# Bad def test_1(): assert f(123, 5) == 345 # Better def test_add_offset_to_id(): assert f(user_id=123, offset=5) == 345 15. Designing and Implementing a “Minute/Hour Counter” Example problem: count events by minute/hour.\nThree design approaches:\nNaive solution – simple but inefficient. Conveyor belt design – shift events forward. Time-bucketed design – divide into fixed buckets. Lesson: clear and maintainable design beats quick hacks.\nExample (simplified):\nclass MinuteHourCounter: def __init__(self): self.minute_buckets = [0] * 60 self.hour_buckets = [0] * 24 def record_event(self, timestamp): self.minute_buckets[timestamp.minute] += 1 self.hour_buckets[timestamp.hour] += 1 ","lang":"en","permalink":"https://profile.huyab.click/posts/the-art-of-readable-code/","section":"posts","summary":"Summary notes from The Art of Readable Code with practical examples and takeaways.","tags":["books","code","cleancode","java","js","python"],"title":"The Art of Readable Code"},{"categories":[],"content":"Convert k2pdfopt converts PDF to a more readable PDF with margin crop and reflow. pdf2epub converts PDF to EPUB with AI support. Translator translates ebooks through a Calibre plugin. k2pdfopt k2pdfopt -dev kpw -dpi 300 -mode fitwidth -as -ui- -o out.pdf input.pdf pdf2epub python main.py filename.pdf ","lang":"en","permalink":"https://profile.huyab.click/posts/kind-trick/","section":"posts","summary":"Small notes and commands for working more effectively with kind and related tooling.","tags":["ebook","tool","pdf"],"title":"Kind Trick"},{"categories":[],"content":"When search conditions depend on multiple related tables, query each table first, collect the shared IDs, combine them with AND or OR, and only then query the main table for display.\nhandle belongs to the UI layer server belongs to the business logic layer ","lang":"en","permalink":"https://profile.huyab.click/posts/search-trick/","section":"posts","summary":"Quick note on combining IDs from related tables before querying the main table for search results.","tags":["backend","search","sql"],"title":"Search Trick"},{"categories":[],"content":"Generate a public key from a private key ssh-keygen -y -f ~/.ssh/id_rsa \u0026gt; ~/.ssh/id_rsa.pub ","lang":"en","permalink":"https://profile.huyab.click/posts/ssh-trick/","section":"posts","summary":"Generate a public key from an existing private key with a single ssh-keygen command.","tags":["ssh","cli"],"title":"Ssh Trick"},{"categories":[],"content":"When you work with developers long enough, short forms show up everywhere: chat messages, PR comments, tickets, commit notes, and even source code.\nHere are some common abbreviations worth remembering.\nCommunication FYI = For Your Information BTW = By The Way IMO = In My Opinion IMHO = In My Humble Opinion LGTM = Looks Good To Me TBH = To Be Honest AFAIK = As Far As I Know Work and Process ETA = Estimated Time of Arrival WIP = Work In Progress RFC = Request For Comments POC = Proof of Concept MVP = Minimum Viable Product OOTB = Out Of The Box TBD = To Be Determined FYI often appears in issue comments when no action is required Programming and Systems nil = empty or null value in languages such as Go, Lua, and others EOF = End Of File OOM = Out Of Memory IO = Input / Output SDK = Software Development Kit API = Application Programming Interface CLI = Command Line Interface CI = Continuous Integration CD = Continuous Delivery or Continuous Deployment, depending on the team Finance and Operations DPD = Days Past Due SLA = Service Level Agreement SLO = Service Level Objective KPI = Key Performance Indicator The exact meaning sometimes depends on the team, so when in doubt, ask once and write it down. That saves more time than pretending to understand from context.\n","lang":"en","permalink":"https://profile.huyab.click/posts/common-dev-abbreviations/","section":"posts","summary":"A quick glossary of abbreviations developers often use in chats, code reviews, tickets, and docs.","tags":["glossary","devops","tip"],"title":"Common Dev Abbreviations"},{"categories":[],"content":" Essential tmux commands and shortcuts for productivity. Power by AI\nCheck current prefix tmux show -gv prefix ","lang":"en","permalink":"https://profile.huyab.click/posts/tmux-cheatsheet/","section":"posts","summary":"Compact tmux cheatsheet covering core commands and shortcuts for daily terminal work.","tags":[],"title":"Tmux Cheatsheet"},{"categories":[],"content":"We\u0026rsquo;ve all been there—looking at the messy code we just threw together, thinking, “I\u0026rsquo;ll clean this up someday.” We feel kinda relieved when it works, even if it’s ugly. Better something than nothing, right? And we all tell ourselves we’ll come back later to fix it. But of course, on days like that, we forget about LeBlanc’s Law:\n“Later” means “never.”\n","lang":"en","permalink":"https://profile.huyab.click/posts/later-means-never/","section":"posts","summary":"A reminder that postponing cleanup usually turns small messes into long-term maintenance debt.","tags":[],"title":"Later Means Never"},{"categories":[],"content":"When Jenkins fails because the SSH host key is missing, add the remote host to known_hosts inside the container:\ndocker exec -it \u0026lt;jenkins-container\u0026gt; bash mkdir -p /var/jenkins_home/.ssh ssh-keyscan -t ed25519 gitlab.com \u0026gt;\u0026gt; /var/jenkins_home/.ssh/known_hosts chown -R jenkins:jenkins /var/jenkins_home/.ssh chmod 600 /var/jenkins_home/.ssh/known_hosts ","lang":"en","permalink":"https://profile.huyab.click/posts/jenkins-ssh-key-error/","section":"posts","summary":"Fix Jenkins SSH host key errors by adding the remote host to known_hosts inside the container.","tags":["jenkins","ssh","gitlab"],"title":"Jenkins Ssh Key Error"},{"categories":[],"content":"ahfgeienlihckogmohjhadlkjgocpleb : Web Store : version 0_2 ddkjiahejlhfcafbddmgiahcphecmpfh : uBlock Origin Lite : version 2025_725_1450 fdidojpjkbpfplcdmeaaehnjfkgpbhad : OdooTerminal : version 11_9_1 fignfifoniblkonapihmkfakmlgkbkcf : Google Network Speech : version 1_0 ghbmnnjooekpmoecnnnilnnbdlolhkhi : Google Docs Offline : version 1_94_1 jlmpjdjjbgclbocgajdjefcidcncaied : daily.dev | The homepage developers deserve : version 3_37_6 ldgfbffkinooeloadekpmfoklnobpien : Raindrop.io : version 6_6_80 mhjfbmdgcfjbbpaeojofohoefgiehjai : Chrome PDF Viewer : version 1 nffaoalbilbmmfgbnbgppjihopabppdk : Video Speed Controller : version 0_9_2 nkeimhogjdpnpccoofpliimaahmaaome : Google Hangouts : version 1_3_24 nmmhkkegccagdldgiimedpiccmgmieda : Chrome Web Store Payments : version 1_0_0_6 nngceckbapebfimnlniiiahkandclblb : Bitwarden Password Manager : version 2025_7_0 aeblfdkhhhdcdjpifhhbdiojplfjncoa : 1Password – Password Manager : version 8_11_2_21 ahfgeienlihckogmohjhadlkjgocpleb : Web Store : version 0_2 ailcmbgekjpnablpdkmaaccecekgdhlh : Tab Manager by Workona : version 3_1_33 amfojhdiedpdnlijjbhjnhokbnohfdfb : eJOY AI Dictionary : version 7_1_0 apgeooocopnncglmnlngfpgggkmlcldf : Shortlink : version 0_0_7 bbiclfnbhommljbjcoelobnnnibemabl : ShowPassword : version 1_2_1 bcjindcccaagfpapjjmafapmmgkkhgoa : JSON Formatter : version 0_7_3 bmhfelbhbkeoldaiphchjibggnoodpcj : Mobile View Switcher : version 0_2_1 bnjjngeaknajbdcgpfkgnonkmififhfo : Fake Filler : version 4_1_0 bpggmmljdiliancllaapiggllnkbjocb : Ddict: AI Translation \u0026amp; Writing Assistant : version 6_2_15 caippejcknmhingeohbdohmolalmejpc : Chrome Extension Manager by cloudHQ : version 1_0_2_8 cclelndahbckbenkjhflpdbgdldlbecc : Get cookies.txt LOCALLY : version 0_7_0 cdockenadnadldjbbgcallicgledbeoc : VisBug : version 0_4_10 cekalaapeajnlhphgdpmngmollojdfnd : NetSuite Field Explorer : version 1_0_0 cfmcghennfbpmhemnnfjhkdmnbidpanb : Quick source viewer : version 1_4_0 chphlpgkkbolifaimnlloiipkdnihall : OneTab : version 1_86 cimiefiiaegbelhefglklhhakcgmhkai : Plasma Integration : version 2_0 cjpalhdlnbpafiamejdnhcphjbkeiagm : uBlock Origin : version 1_65_0 ckigbicapkkgfomcfmcbaaplllopgbid : OpenReplay Spot - Record \u0026amp; Report Bugs : version 1_0_24 clngdbkpkpeebahjckkjfobafhncgmne : Stylus : version 2_3_15 cpcifbdmkopohnnofedkjghjiclmhdah : NeatDownloadManager Extension : version 1_9_92 dbepggeogbaibhgnhhndojpepiihcmeb : Vimium : version 2_3 dbnjpielondlkmdjbembloegkaabfakc : Glot Extension : version 0_7_19 ddkjiahejlhfcafbddmgiahcphecmpfh : uBlock Origin Lite : version 2025_725_1450 dgmanlpmmkibanfdgjocnabmcaclkmod : Just Read : version 6_0_10 dhdgffkkebhmkfjojejmpbldmpobfkfo : Tampermonkey : version 5_3_3 djflhoibgkdhkhhcedjiklpkjnoahfmg : User-Agent Switcher for Chrome : version 2_0_1 dmednmeainmagnoalnnmbbkieonjpjfd : Folx : version 5_37 ecmlflnkenbdjfocclindonmigndecla : System Monitor : version 2_1_2 edacconmaakjimmfgnblocblbcdcpbko : Session Buddy : version 4_0_5 eenjdnjldapjajjofmldgmkjaienebbj : Copyfish 🐟 Free OCR Software : version 6_2_0 ehgcekpdldhgfjpionbkilpnaahjiejj : NetSuite Advanced Field Help : version 3_4 eiimnmioipafcokbfikbljfdeojpcgbh : BlockSite Block Websites \u0026amp; Stay Focused : version 6_8_1 eimadpbcbfnmbkopoojfekhnkhdbieeh : Dark Reader : version 4_9_110 emhgkpmcjiokblfofahdclcgldgflelc : 10 Minutes Email - 10 min disposable email : version 0_1_0 eningockdidmgiojffjmkdblpjocbhgh : Header Editor Lite : version 5_0_0_37 eofbapfmbfmpeplodnehlkkgpkklmapp : Polypane helper : version 2_0_0 eppiocemhmnlbhjplcgkofciiegomcon : Urban VPN Proxy : version 5_6_0 fdidojpjkbpfplcdmeaaehnjfkgpbhad : OdooTerminal : version 11_9_1 ficfmibkjjnpogdcfhfokmihanoldbfe : File Icons for GitHub and GitLab : version 1_6_0 fjnbnpbmkenffdnngjfgmeleoegfcffe : Stylish - Custom themes for any website : version 3_4_5 fmkadmapgofadopljbjfkapdkoienihi : React Developer Tools : version 6_1_5 fpnmgdkabkmnadcjpehmlllkndpkmiak : Wayback Machine : version 3_4_5 gabfmnliflodkdafenbcpjdlppllnemd : Save image as Type : version 1_2_4 gglbgdfbkaelbjpjkiepdmfaihdokglp : NetSuite: Saved Search and Dataset Export : version 4_0 ghbmnnjooekpmoecnnnilnnbdlolhkhi : Google Docs Offline : version 1_94_1 gjoijpfmdhbjkkgnmahganhoinjjpohk : Screenshot YouTube : version 3_0_0 gphhapmejobijbbhgpjhcjognlahblep : GNOME Shell integration : version 12 gpkildejogofhhobidokcjpolaikgldj : Webpage to PDF Converter : version 1_2 gppongmhjkpfnbhagpmjfkannfbllamg : Wappalyzer - Technology profiler : version 6_10_85 hbkblmodhbmcakopmmfbaopfckopccgp : Thunderbit: AI Web Scraper \u0026amp; Web Automation Agent : version 4_0_3 hfgkoaengklibhfagaababcngpehggmm : Mua Thông Minh : version 2_1_8 hlgbcneanomplepojfcnclggenpcoldo : Perplexity - AI Companion : version 1_0_21 hmbnbbbknglecphfogchkhpdjiodfclh : QuickForm - Autofill Forms Quickly : version 1_10_1 hmdmhilocobgohohpdpolmibjklfgkbi : Odoo Debug : version 5_0 hmigninkgibhdckiaphhmbgcghochdjc : Mouse Tooltip Translator - PDF \u0026amp; Netflix Youtube dual subs : version 0_1_195 hmlcjjclebjnfohgmgikjfnbmfkigocc : J2TEAM Security : version 2_2_8 hnmpcagpplmpfojmgmnngilcnanddlhb : Windscribe - Free Proxy and Ad Blocker : version 4_1_9 iahamcpedabephpcgkeikbclmaljebjp : Web Developer Checklist : version 2_0_3 icallnadddjmdinamnolclfjanhfoafe : FastForward : version 0_2383 idgpnmonknjnojddfkpgkljpfnnfcklj : ModHeader - Modify HTTP headers : version 7_0_9 ilcoelkkcokgeeijnopjnolmmighnppp : Ruto - XPath Finder : version 7_0_1 infppggnoaenmfagbfknfkancpbljcca : Automa : version 1_29_11 ipdjnhgkpapgippgcgkfcbpdpcgifncb : Emoji Keyboard by JoyPixels® : version 9_1_2 ipikiaejjblmdopojhpejjmbedhlibno : SwiftRead - read faster, learn more : version 5_9_2 jabopobgcpjmedljpbcaablpmlmfcogm : WhatFont : version 3_2_0 jdecachbikbkppkpjjgdmdghgdfffibi : NetSuite Utils : version 3_9_0_1 jgjaeacdkonaoafenlfkkkmbaopkbilf : ChatGPT for Google : version 5_5_1 jhnleheckmknfcgijgkadoemagpecfol : Auto Tab Discard (suspend) : version 0_6_8_2 jinjaccalgkegednnccohejagnlnfdag : Violentmonkey : version 2_31_0 jjmflmamggggndanpgfnpelongoepncg : Extensity : version 1_14_0 jjmnbidkmmabkalampbilajnheeokpoj : TLDR This - Free automatic text summary tool : version 2_0_5 jlgkpaicikihijadgifklkbpdajbkhjo : CrxMouse: Mouse Gestures : version 6_2_2 jllbemjkkabaohnjcnajhflahlkehmlf : Odoo Utility : version 4_1 jlmpjdjjbgclbocgajdjefcidcncaied : daily.dev | The homepage developers deserve : version 3_37_6 jnbbnacmeggbgdjgaoojpmhdlkkpblgi : WakaTime : version 4_1_0 kbfnbcaeplbcioakkpcpgfkobkghlhen : Grammarly: AI Writing and Grammar Checker App : version 14_1246_0 khncfooichmfjbepaaaebmommgaepoid : Unhook - Remove YouTube Recommended \u0026amp; Shorts : version 1_6_8 kkjfobdnekhdpmgomkpeibhlnmcjgian : website broken link and 404 error checker : version 1_1_1 kkmlkkjojmombglmlpbpapmhcaljjkde : Zhongwen: Chinese-English Dictionary : version 6_3_0 knbeilbpfnelpbeoofhnkfbfcldpfehn : Douyin Video Downloader : version 2_0_9 kniehgiejgnnpgojkdhhjbgbllnfkfdk : SimpleExtManager : version 1_4_11 ldbfanecnfeflgbmgkbmipobkmoolbjb : Owl devtools : version 1_3_0 ldgfbffkinooeloadekpmfoklnobpien : Raindrop.io : version 6_6_80 legimlagjjoghkoedakdjhocbeomojao : Persepolis Download Manager Integration : version 4_0_0 mbnmcpnoeglgibggfjdmjeffohfmhdjl : SDA - Auto Form : version 4_4_0 mdnleldcmiljblolnjhpnblkcekpdkpa : Requestly: Supercharge your Development \u0026amp; QA : version 25_7_21 mfjgefhkaljdlpmnnfcaebgmchfhakcf : Udemy Subtitle Translator - Yakuu : version 1_2_0_0 mhjfbmdgcfjbbpaeojofohoefgiehjai : Chrome PDF Viewer : version 1 mhnlakgilnojmhinhkckjpncpbhabphi : MaxAI: Ask AI anything as you browse (GPT, Gemini, Claude, Grok, etc.) : version 8_26_4 mnjggcdmjocbbbhaepdhchncahnbgone : SponsorBlock for YouTube - Skip Sponsorships : version 5_14 mooikfkahbdckldjjndioackbalphokd : Selenium IDE : version 3_17_2 mpbjkejclgfgadiemmefgebjfooflfhl : Buster: Captcha Solver for Humans : version 3_1_0 nbkomboflhdlliegkaiepilnfmophgfg : Custom Progress Bar for YouTube™ : version 3_6_34 nbokbjkabcmbfdlbddjidfmibcpneigj : SmoothScroll : version 1_7_7 neajdppkdcdipfabeoofebfddakdcjhd : Google Network Speech : version 1_0 nffaoalbilbmmfgbnbgppjihopabppdk : Video Speed Controller : version 0_9_2 nkeimhogjdpnpccoofpliimaahmaaome : Google Hangouts : version 1_3_24 nkokmeaibnajheohncaamjggkanfbphi : Save Image As PNG : version 1_0_3 nlbejmccbhkncgokjcmghpfloaajcffj : Hotspot Shield : version 5_2_11 nmmhkkegccagdldgiimedpiccmgmieda : Chrome Web Store Payments : version 1_0_0_6 nngceckbapebfimnlniiiahkandclblb : Bitwarden Password Manager : version 2025_6_1 oanlehpljgeknlohgbakodejdbingjpj : AliPrice Shopping Assistant for Shopee : version 4_0_4 oglffgiaiekgeicdgkdlnlkhliajdlja : YouTube Dubbing – Translate \u0026amp; Dub : version 3_0_4 oilacejfpoonhegdhlhklckannjhmdgk : YouTube Summary with ChatGPT Claude DeepSeek : version 2_1_1 ojfebgpkimhlhcblbalbfjblapadhbol : EditThisCookie (V3) : version 3_0_4 okpidcojinmlaakglciglbpcpajaibco : J2TEAM Cookies : version 1_0_4 onepmapfbjohnegdmfhndpefjkppbjkm : SuperCopy, Allow Right Click and Copy : version 0_1_18 oocalimimngaihdkbihfgmpkcpnmlaoa : Netflix Party is now Teleparty : version 5_2_9 oodfdmglhbbkkcngodjjagblikmoegpa : Url Shortener : version 2_1_3 padekgcemlokbadohgkifijomclgjgif : Proxy SwitchyOmega : version 2_5_21 pfnededegaaopdmhkdmcofjmoldfiped : Proxy SwitchyOmega 3 (ZeroOmega) : version 3_4_1 ppmnkcnnoclkpbbckblofjbjepocnflo : Ultra Button : version 2_1_0 ","lang":"en","permalink":"https://profile.huyab.click/posts/chrome-extension/","section":"posts","summary":"List of Chrome extensions and built-in components installed in the current browser profile.","tags":[],"title":"Chrome Extension"},{"categories":[],"content":"\u0026lt;field name=\u0026#34;line_ids\u0026#34;\u0026gt; \u0026lt;tree\u0026gt; \u0026lt;field name=\u0026#34;date_register\u0026#34; attrs=\u0026#34;{\u0026#39;column_invisible\u0026#39;:[(\u0026#39;parent.field_in_parent_record\u0026#39;, \u0026#39;=\u0026#39;, True)]}\u0026#34;/\u0026gt; \u0026lt;/tree\u0026gt; \u0026lt;/field\u0026gt; ","lang":"en","permalink":"https://profile.huyab.click/posts/odoo-hide-column-in-tree/","section":"posts","summary":"Use column_invisible in Odoo tree views to hide a column based on the parent record state.","tags":["odoo","xml","tree"],"title":"Odoo Hide Column in Tree"},{"categories":[],"content":"grep --context 3 \u0026#34;search_pattern\u0026#34; path/to/file grep --before-context 3 \u0026#34;search_pattern\u0026#34; path/to/file grep --after-context 3 \u0026#34;search_pattern\u0026#34; path/to/file grep -C 3 \u0026#34;search_pattern\u0026#34; path/to/file grep -A 3 \u0026#34;search_pattern\u0026#34; path/to/file grep -B 3 \u0026#34;search_pattern\u0026#34; path/to/file ","lang":"en","permalink":"https://profile.huyab.click/posts/grep-before-after/","section":"posts","summary":"Examples of grep context flags to show matching lines with output before and after.","tags":[],"title":"Grep Before After"},{"categories":[],"content":"Global location store is ~/.gitconfig\ngit config --global key value Local location store is .git/config\ngit config --local key value ","lang":"en","permalink":"https://profile.huyab.click/posts/git-config/","section":"posts","summary":"Quick notes on global and local Git configuration scopes and where they are stored.","tags":[],"title":"Git Config"},{"categories":[],"content":"Alternative cp command [dry run] rsync -hav --progress source dest --dry-run Alternative cp command rsync -hav --progress source dest ","lang":"en","permalink":"https://profile.huyab.click/posts/rsync/","section":"posts","summary":"Useful rsync commands as a safer and more flexible alternative to plain cp.","tags":[],"title":"Rsync"},{"categories":[],"content":"Error ventoy currently error when using nixos version 25\nsolution just export enviroment variable and append \u0026ndash;impure to the last command script\nexport NIXPKGS_ALLOW_INSECURE=1 nix run .#huy --impure ","lang":"en","permalink":"https://profile.huyab.click/posts/ventoy-in-nixos/","section":"posts","summary":"Notes on getting Ventoy working on NixOS 25 when the default setup runs into errors.","tags":[],"title":"Ventoy in Nixos"},{"categories":[],"content":"how to using chezmoi only one command chezmoi init --apply GITHUB_REPO example chezmoi init --apply git@github.com:nguyenhuy158/chezmoi\n","lang":"en","permalink":"https://profile.huyab.click/posts/chezmoi/","section":"posts","summary":"Quick start guide to initialize and apply a chezmoi dotfiles repository with one command.","tags":[],"title":"Chezmoi"},{"categories":[],"content":"Create branch git checkout -b branch_name Delete branch git checkout other_branch git branch -D branch_name git push origin --delete branch_name ","lang":"en","permalink":"https://profile.huyab.click/posts/git-branch/","section":"posts","summary":"Common Git branch commands for creating, deleting, and cleaning up branches.","tags":[],"title":"Git Branch"},{"categories":[],"content":"Một ngày của bạn trôi qua như thế nào thì một đời bạn cũng sẽ trôi qua như thế đấy. Chúng ta hận đời rồi quay lại mắng người thân. ","lang":"en","permalink":"https://profile.huyab.click/posts/one-day-one-life/","section":"posts","summary":"Short reflection on how daily habits quietly shape the direction of an entire life.","tags":[],"title":"One Day One Life"},{"categories":[],"content":"Use /usr/bin/env in Shell Scripts When writing shell scripts, avoid hardcoding the full path to the shell. Instead, use the environment path to make your script more portable across different systems.\n✅ Recommended: #!/usr/bin/env bash\n🚫 Not recommended: #!/usr/bin/bash\nUsing env ensures the system uses the correct version of the shell from the user\u0026rsquo;s environment.\n","lang":"en","permalink":"https://profile.huyab.click/posts/shell-env/","section":"posts","summary":"Why /usr/bin/env is a safer shebang choice for portable shell scripts across environments.","tags":[],"title":"Shell Env"},{"categories":[],"content":"In some situations, such as:\nYou are getting HTML content from email or the web Want to paste it into Slack neatly Or want to paste it into Hugo to write a blog without format errors Then Markdown is the best standard. But converting by hand is tiring. So\u0026hellip;\n🛠 Solution: Use Python to convert HTML → Markdown There are 2 extremely convenient libraries:\n1. html2text — easy to use, install and you\u0026rsquo;re ready to go pip install html2text import html2text html = \u0026#34;\u0026lt;b\u0026gt;Hello\u0026lt;/b\u0026gt; \u0026lt;a href=\u0026#39;https://example.com\u0026#39;\u0026gt;Click me\u0026lt;/a\u0026gt;\u0026#34; markdown = html2text.html2text(html) print(markdown) # **Hello** [Click me](https://example.com) markdownify — more advanced, highly customizable pip install markdownify from markdownify import markdownify as md html = \u0026#34;\u0026lt;h1\u0026gt;Title\u0026lt;/h1\u0026gt;\u0026lt;p\u0026gt;This is \u0026lt;b\u0026gt;bold\u0026lt;/b\u0026gt;\u0026lt;/p\u0026gt;\u0026#34; markdown = md(html) print(markdown) # # Title # This is **bold** ✨ Why use it? Slack does not support HTML ⇒ Markdown is needed Hugo also uses Markdown to write articles Work faster, less manual editing\n🎯 Small tip Use strip() after converting to remove blank lines: md = html2text.html2text(html).strip()\n","lang":"en","permalink":"https://profile.huyab.click/posts/convert-html-to-markdown/","section":"posts","summary":"Simple ways to convert HTML content into Markdown for easier editing and publishing.","tags":[],"title":"Convert Html to Markdown"},{"categories":[],"content":"When working with JSON data from different sources, you might see inconsistent key names, like:\n{ \u0026#34;tTien\u0026#34;: 1000, \u0026#34;ttien\u0026#34;: 1000, \u0026#34;tthue\u0026#34;: 100, \u0026#34;tThue\u0026#34;: 100, \u0026#34;TThue\u0026#34;: 100 } Different places use different names, which is annoying. Using try/except, if/else, or match/case makes the code messy and error-prone.\nSimple solution: Before processing, convert all keys to lowercase. It\u0026rsquo;s fast and easy to maintain: data = {k.lower(): v for k, v in original_data.items()} Now you can just use data['ttien'], data['tthue'] without writing long code.\nBonus: If keys have spaces or dashes (-, _), you can normalize further:\nimport re def normalize_key(k): return re.sub(r\u0026#39;\\W+\u0026#39;, \u0026#39;\u0026#39;, k).lower() data = {normalize_key(k): v for k, v in original_data.items()} ","lang":"en","permalink":"https://profile.huyab.click/posts/handle-json-key-case/","section":"posts","summary":"Normalize inconsistent JSON key casing before mapping data in your application.","tags":["json","python","data-cleaning","tip"],"title":"Handle Json Key Case"},{"categories":[],"content":"When writing a blog, you might need to use characters like \u0026gt;, \u0026lt;, \u0026lt;=, \u0026gt;=, \u0026amp;.\nTo avoid display errors, change them like this: \u0026gt; → \u0026gt; \u0026lt; → \u0026lt; \u0026lt;= → \u0026lt;= \u0026gt;= → \u0026gt;= \u0026amp; → \u0026amp; For example, the code displays correctly: if (a \u0026lt;= b \u0026amp;\u0026amp; b \u0026gt;= c) { return true; } ","lang":"en","permalink":"https://profile.huyab.click/posts/special-characters/","section":"posts","summary":"How to write special characters safely in Markdown without breaking your blog content.","tags":[],"title":"Special Characters"},{"categories":["chrome"],"content":"Extension to manager all (other) extensions is https://chromewebstore.google.com/detail/extensity/jjmflmamggggndanpgfnpelongoepncg\n","lang":"en","permalink":"https://profile.huyab.click/posts/best-chrome-extension/","section":"posts","summary":"Discover the best Chrome extension to manage all your other extensions effortlessly with Extensity!","tags":["chrome","extension","manager"],"title":"Best Chrome Extension"},{"categories":[],"content":"Want to move a repo from GitLab to GitHub and keep all commits, branches, and tags? Here\u0026rsquo;s a super simple way 👇\n#!/bin/bash # Replace these with your info GITLAB_REPO=\u0026#34;https://gitlab.com/yourname/your-repo.git\u0026#34; GITHUB_REPO=\u0026#34;https://github.com/yourname/your-repo.git\u0026#34; # Clone from GitLab git clone --mirror \u0026#34;$GITLAB_REPO\u0026#34; cd your-repo.git # Push to GitHub (with all history + branches + tags) git remote set-url origin \u0026#34;$GITHUB_REPO\u0026#34; git push --mirror # Done! echo \u0026#34;✅ Repo migrated from GitLab to GitHub!\u0026#34; ","lang":"en","permalink":"https://profile.huyab.click/posts/tip-move-repo-gitlab-github/","section":"posts","summary":"How to move a repo from GitLab to GitHub (or vice versa) and keep all history, branches, and tags with just a few bash commands.","tags":["git","github","gitlab","mirror","tip"],"title":"Tip Move Repo Gitlab Github"},{"categories":[],"content":"Want to see how much space Docker volumes are using? Easy!\nRun this command in the terminal:\ndocker system df -v ","lang":"en","permalink":"https://profile.huyab.click/posts/tip-check-docker-volume-size/","section":"posts","summary":"How to quickly check Docker volume size using the CLI.","tags":["docker","tip","volume"],"title":"Tip Check Docker Volume Size"},{"categories":[],"content":"Ghost is one of the best platforms for beginners who wanna start blogging fast. Below is a simple docker-compose.yml setup to get you going right away:\nservices: ghost: image: ghost container_name: ghost ports: - \u0026#34;2368:2368\u0026#34; environment: - NODE_ENV=development - database__connection__filename=/var/lib/ghost/content/data/ghost.db - url=http://localhost:2368 volumes: - ./ghost-data:/var/lib/ghost/content ","lang":"en","permalink":"https://profile.huyab.click/posts/deploy-ghost-with-docker/","section":"posts","summary":"Minimal Docker Compose setup to run Ghost locally or on a small server.","tags":[],"title":"Deploy Ghost With Docker"},{"categories":["vlogs"],"content":"Welcome to my blog! I\u0026rsquo;m Huy. I\u0026rsquo;m a developer, and I want to become a senior DevOps.\nThis blog shares my experience on the journey to becoming a senior DevOps. Hope you enjoy your time here!\n","lang":"en","permalink":"https://profile.huyab.click/posts/huy-path-senior-devops/","section":"posts","summary":"An introduction to the blog and the path I am taking toward becoming a stronger DevOps engineer.","tags":["devops","path","backend"],"title":"Huy's Path to Becoming a Senior DevOps"},{"categories":[],"content":"This site is where I collect technical notes that are still useful after the task is done.\nI write mostly about:\nDevOps workflows Linux and CLI tools browser and productivity tricks small fixes that save time later The goal is practical documentation, not polished theory. If a note helps me solve the same problem faster in the future, it belongs here.\n","lang":"en","permalink":"https://profile.huyab.click/about/","section":"","summary":"What this site is about and what you can expect from it.","tags":[],"title":"About"},{"categories":[],"content":"This page groups the machine-readable endpoints for the site:\nMain RSS feed Sitemap Search index JSON Posts RSS feed Notes RSS feed Tags RSS feed Categories RSS feed ","lang":"en","permalink":"https://profile.huyab.click/feeds/","section":"","summary":"RSS, sitemap, and search index links for the site.","tags":[],"title":"Feeds"},{"categories":[],"content":"Current focus:\ntightening CI and deployment reliability for this blog documenting small tools and command-line workflows that I reuse often improving bilingual content quality so English and Vietnamese pages stay consistent This page is a moving snapshot, not a changelog.\n","lang":"en","permalink":"https://profile.huyab.click/now/","section":"","summary":"A short snapshot of current priorities.","tags":[],"title":"Now"},{"categories":[],"content":"Use this page to jump into the blog\u0026rsquo;s main taxonomies:\ncategories for broad topic groups tags for more specific keywords ","lang":"en","permalink":"https://profile.huyab.click/taxonomies/","section":"","summary":"Central entry point for tags and categories.","tags":[],"title":"Taxonomies"},{"categories":[],"content":"Tools I reach for most often:\nmacOS for daily work Chrome for browser debugging and extension-heavy workflows VS Code and terminal-first tooling Hugo for this site GitHub Actions and Cloudflare for delivery This page stays intentionally short. If a tool keeps showing up in posts, it probably belongs here.\n","lang":"en","permalink":"https://profile.huyab.click/uses/","section":"","summary":"Current tools and setup.","tags":[],"title":"Uses"}]