
[{"content":"","date":"Mon 20 April UTC 2026","externalUrl":null,"permalink":"/posts/","section":"Blog posts","summary":"","title":"Blog posts","type":"posts"},{"content":"","date":"Mon 20 April UTC 2026","externalUrl":null,"permalink":"/","section":"","summary":"","title":"","type":"page"},{"content":"","date":"Mon 20 April UTC 2026","externalUrl":null,"permalink":"/tags/ai/","section":"Tags","summary":"","title":"Ai","type":"tags"},{"content":"I want to be clear and upfront. Artificial intelligence is, and will continue to be, used on this site, though perhaps not in the way you might expect. There is a term, “AI slop”. I am not particularly fond of it, but it is widely used. There is a reasonably informative article on Wikipedia, so I will not attempt to rehash it here. If you are unfamiliar with the term, it is typically described as content generated by AI that lacks effort, quality, or meaning, often produced at scale for attention or gain.\nTo remove any doubt, I am making a genuine effort here. I cannot promise that everything I write will be of high quality, but I can say with confidence that I am not doing this for commercial gain or to chase attention. In truth, I do not mind if nobody reads it. I am writing for myself. If someone else happens to find value in it, or enjoys spending a few minutes reading, then that is a welcome bonus. For the first time, I am finding writing to be something I genuinely enjoy, and that alone is reason enough to continue.\nI have no intention of using AI to replace my thoughts, opinions, or experiences. I see it as a collaborator, closer to a sounding board than an author. The content here will always start and end with me. AI helps refine structure, challenge assumptions, and occasionally stop me from saying something I might later regret. It supports the process, but it does not define it.\nWhere AI is used more directly is in imagery. When images appear on this site, they are often generated rather than sourced, and that is a deliberate choice. Firstly, it helps maintain a degree of personal privacy by avoiding the need to share real photos or identifiable material. Secondly, it avoids reusing someone else’s work without clear ownership or attribution, something I would prefer to avoid entirely. Vendor provided assets are still used where appropriate, but beyond that, generated imagery offers a clean and controlled alternative that aligns with how I want this site to operate.\n","date":"Mon 20 April UTC 2026","externalUrl":null,"permalink":"/posts/slop/","section":"Blog posts","summary":"","title":"AI, this blog, and where I stand","type":"posts"},{"content":"","date":"Mon 20 April UTC 2026","externalUrl":null,"permalink":"/categories/blog/","section":"Categories","summary":"","title":"Blog","type":"categories"},{"content":"","date":"Mon 20 April UTC 2026","externalUrl":null,"permalink":"/series/blog/","section":"Series","summary":"","title":"Blog","type":"series"},{"content":"","date":"Mon 20 April UTC 2026","externalUrl":null,"permalink":"/tags/blog/","section":"Tags","summary":"","title":"Blog","type":"tags"},{"content":"","date":"Mon 20 April UTC 2026","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","date":"Mon 20 April UTC 2026","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"","date":"Mon 20 April UTC 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"Thu 16 April UTC 2026","externalUrl":null,"permalink":"/tags/developement/","section":"Tags","summary":"","title":"Developement","type":"tags"},{"content":"","date":"Thu 16 April UTC 2026","externalUrl":null,"permalink":"/tags/domains/","section":"Tags","summary":"","title":"Domains","type":"tags"},{"content":"I may have gone a little too far, but I\u0026rsquo;ve bought a new domain.\nMy domain list is growing.\nfromyouto.me, my email domain. cymylau.uk, my old blog site. techielab.org, used for my learning, and previously my \u0026ldquo;new\u0026rdquo; blog site. buildbreakunderstand.com, my current domain. But didn\u0026rsquo;t you just post My blog is dead, long live my blog?\nYes, this is awkward. This is the same content. However, after writing a recent blog post, I realised I hadn\u0026rsquo;t thought through a few bits.\ntechielab.org was a cheap domain. I bought it some time ago to host my lab content and to guarantee a unique namespace. Nothing more.\nWhen writing content, it just didn\u0026rsquo;t fit. Build. Break. Understand. My site\u0026rsquo;s motto. Why wasn\u0026rsquo;t this the domain?\nIt\u0026rsquo;s long, but at the heart of it, this is what my site is about. So there we are. I\u0026rsquo;ve updated my pipeline, changed a couple of variables, and now here we are.\nFor now. Until I have a new idea.\nbuildbreakunderstand.com\n","date":"Thu 16 April UTC 2026","externalUrl":null,"permalink":"/posts/toomanydomains/","section":"Blog posts","summary":"","title":"How many is too many domains?","type":"posts"},{"content":" Will Artificial Intelligence decrease my intelligence? # There is a narrative that AI is here to replace people. That might mean developers, writers, engineers, or whatever role happens to be under discussion that week.\nHonestly, this is a fair concern, and to some degree it has happened already. Computerised systems have been replacing roles for years. Go into your local supermarket. How many self-checkouts are there now?\nIt may eventually replace my role, but until then I\u0026rsquo;m embracing its capabilities. I do not use AI to replace core thinking, and I certainly do not rely on it to produce finished work without scrutiny.\nInstead, I use it in much the same way I have always used tools like spreadsheets, websites like Wikipedia or Stack Overflow. Dare I say odd \u0026ldquo;RTFM\u0026rdquo; moment when things got really hard?\nWhen I am working through something like a docker build that refuses to behave, a python function that is slowly evolving into something unmaintainable, or a fighting this Hugo blog theme that appears to have its own interpretation of reality, AI helps me explore options more quickly. It helps me sanity check my assumptions, and explain concepts in a way that actually sticks.\nRubber Duck evolved # In many ways, AI feels like an evolution of rubber duck debugging. Developers have long relied on the simple act of explaining a problem out loud to uncover the solution. It\u0026rsquo;s an old but extremely effective tool.\nTalking out loud about your code to a rubber duck allows you to hear / comprehend logic flaws, bugs, and glitches that would otherwise go unnoticed. It\u0026rsquo;s crazy effective. Sometimes you can\u0026rsquo;t see the wood for trees, you need another perspective.\nAI takes that concept a step further by responding, suggesting alternatives, and occasionally offering something genuinely useful. It is not perfect, and it can be confidently wrong in ways that are almost impressive.\nThat imperfection is part of what makes it useful. You shouldn\u0026rsquo;t blindly trust AI output. This forces a level of engagement and critical thinking that passive documentation never really demanded. If anything, using AI regularly has made me more sceptical and more inclined to validate what I am given, rather than less.\nTerminal Velocity # The real value, at least from my perspective, is not automation but acceleration. AI does not remove the need to do the work. It reduces the time it takes to get to a point where meaningful work can happen.\nTasks that would previously involve trawling through documentation, opening countless browser tabs, and slowly piecing together an answer can now be compressed into a much shorter feedback loop.\nThat shift changes how you approach problems. You are more willing to experiment, more inclined to try alternative approaches, and less concerned about getting it wrong on the first attempt. The cost of iteration is so much lower.\nWD40 # This fits neatly into how I enjoy learning. Iterative steps. Build something, then I\u0026rsquo;ll get all confident and that point will come where I break it. If I get it working again, I\u0026rsquo;ve got pretty decent fundamental knowledge.\n\u0026ldquo;Build. Break. Understand\u0026rdquo; is my site\u0026rsquo;s motto. Most of what exists under techielab.org is not there because it needed to be built, but because I wanted to understand how it worked.\nWD40 stands for Water Displacement Attempt 40. 39 previous attempts didn\u0026rsquo;t work, then it did.\nMisleading # Perhaps that is why the term “artificial intelligence” feels slightly misleading. It frames the technology as an imitation rather than a teammate or collaborator.\nIn practice, what I experience is far closer to a mentor. I ask questions, receive structured answers, sometimes questionable ones, and then refine those answers through my own understanding.\nThat loop feels much closer to working with another person than it does to using a traditional tool. AI never tires, never complains, and occasionally invents entirely new APIs with remarkable confidence.\nI joke that AI is like a puppy. It\u0026rsquo;ll give you the best joy, but it will crap on your carpet. It will eat your shoes. You cannot leave it alone, don\u0026rsquo;t get it wet and never feed it after midnight (I may be confusing puppies with gremlins, but, if you know you know). With time that relationship will grow, evolve and the accidents slow down (never go away, but become less of a daily issue. The odd blip will happen)\nThe right word? # Is “artificial” really the right word? I am not convinced that it is.\nArtificial suggests something fake or inferior. What we are dealing with feels probabilistic, context-aware, occasionally insightful, and occasionally completely wrong. In other words, it is not entirely unlike human intelligence.\nPerhaps the more interesting question is whether we have always overestimated how precise or deterministic intelligence needed to be in the first place.\nAI has not fundamentally changed how I work, but it has significantly altered how quickly I can think, test ideas, and learn from them.\nIf that is what we choose to label as artificial, then it may say more about our expectations of intelligence than it does about the technology itself.\n","date":"Tue 14 April UTC 2026","externalUrl":null,"permalink":"/posts/realinteligence/","section":"Blog posts","summary":"","title":"Is my intelligence becoming artificial?","type":"posts"},{"content":"","date":"Tue 14 April UTC 2026","externalUrl":null,"permalink":"/tags/opinion/","section":"Tags","summary":"","title":"Opinion","type":"tags"},{"content":"","date":"Tue 14 April UTC 2026","externalUrl":null,"permalink":"/tags/tech/","section":"Tags","summary":"","title":"Tech","type":"tags"},{"content":"","date":"Fri 10 April UTC 2026","externalUrl":null,"permalink":"/categories/security/","section":"Categories","summary":"","title":"Security","type":"categories"},{"content":"","date":"Fri 10 April UTC 2026","externalUrl":null,"permalink":"/tags/vulnerabilities/","section":"Tags","summary":"","title":"Vulnerabilities","type":"tags"},{"content":"There’s a part of most websites that rarely gets any attention, yet plays a critical role in how the internet quietly functions: /.well-known/.\nDefined in RFC 8615, the /.well-known/ directory is a standardised location for metadata about a site. It’s designed so that both humans and machines know exactly where to look for important information, without guesswork. Think of it as the “front desk” of your website. Not flashy, not interactive, but if it’s missing, everything becomes unnecessarily difficult.\nCommon examples include:\n/.well-known/security.txt – how to report security issues /.well-known/change-password – where users can update credentials /.well-known/openid-configuration – identity provider metadata The key idea is consistency. No hunting, no guessing URLs, no emailing info@, admin@, and hoping one lands. Just a known path that answers the question: “Where do I go for this?” And when it comes to security, that question matters more than most.\nReporting vulnerabilities shouldn’t feel like a heist movie # Imagine you’ve discovered a vulnerability in a website. If you’re an ethical hacker, you want to do the right thing. Report it responsibly. Help fix the issue.\nIf you’re not… well, you’ve got options and the uncomfortable truth is that reporting vulnerabilities is often harder than exploiting them. Computers are on 24/7. \u0026ldquo;We\u0026rsquo;re experiencing a larger call volume that typical, wait times may be elongated\u0026rdquo;. We\u0026rsquo;ve all experienced this\u0026hellip;\nNo clear contact details Generic inboxes with no response Legal ambiguity (“will I get in trouble for this?”) No acknowledgement or feedback It can feel less like responsible disclosure and more like trying to get a message to someone in a locked-down corporate bunker. Somewhere between Mission: Impossible and shouting into the void. This friction creates a big problem:\nEthical researchers may give up Findings may go unreported Or worse, vulnerabilities get disclosed publicly or sold None of these outcomes are ideal. If you make it hard to report issues, you’re not reducing risk. You’re just redirecting it.\nThis is where security.txt comes in and defined in RFC 9116. It provides a simple, standard way for organisations to publish security contact and policy information. It lives at:\nhttps://example.com/.well-known/security.txt\nNo guesswork. No detective work. Just a clear, structured file! Imagine that!!!!\nCore fields # A typical security.txt file includes:\nContact\nHow to report a vulnerability. This can be an email address, a web form, or even a bug bounty platform.\nContact: mailto:security@example.com\nExpires\nA timestamp indicating how long the file is valid. This prevents stale or abandoned contact details lingering forever.\nExpires: 2026-12-31T23:59:59Z\nPolicy\nA link to your vulnerability disclosure policy. This sets expectations for both parties.\nPolicy: https://example.com/security-policy\nAcknowledgments (optional)\nA hall of fame for researchers who report issues responsibly.\nEncryption (optional)\nA public key for secure communication, if sensitive details are being shared.\nWhy it matters # It lowers the barrier to doing the right thing. Instead of forcing researchers to improvise, it provides:\nA clear reporting path Defined expectations A signal that security is taken seriously It’s not a silver bullet. It won’t stop vulnerabilities. But it improves how they are handled, and that’s often where the real difference is made.\nTo borrow from The Matrix: you can take the red pill and see how deep the rabbit hole goes, or you can at least leave a note telling people where the entrance is.\nMy implementation # In the spirit of practicing what I preach, I’ve implemented a security.txt file for this site.\nYou can find it here: https://buildbreakunderstand.com/.well-known/security.txt\nIt’s intentionally simple (much like the author). Do your future self a favour and generate one for your site.\n","date":"Fri 10 April UTC 2026","externalUrl":null,"permalink":"/posts/securitytext/","section":"Blog posts","summary":"","title":"Vulnerability reporting made easier","type":"posts"},{"content":"I’ve officially retired my old blog, blog.cymylau.uk.\nThis will no doubt come as a devastating blow to all zero of my regular readers. Please take a moment.\nBack? Good.\nIn reality, I’m not convinced anyone ever read it, and I’m even less convinced anyone is reading this. That’s fine. This blog has never really been about that.\nIt’s a glorified diary with two purposes:\nGive me something technical to tinker with Let me get thoughts out of my head and onto “paper” The old site leaned heavily into the first point.\nIt was… complicated. Impressively, unnecessarily complicated. Layers of tech, multiple vendors, and enough moving parts to make a small enterprise system blush. I built it that way on purpose, because I thought it would be fun.\nIt was. Briefly, then it became work. This is a reset.\nJekyll is gone.\nThe Docker image is gone.\nOCI free tier is gone.\nWireGuard is gone.\nCloudflare Zero Trust is gone.\nGitHub Actions is gone.\nIf it had a YAML file, it probably got deleted and honestly, it feels great!\nWhat’s left is something simpler. Something I might actually keep running for more than a few months without redesigning it at 11pm on a Tuesday. I\u0026rsquo;m planning on pulling over some of the better content, to live here. I may rework some of it.\nIf you’re reading this, congratulations, you’ve found the new version. Let’s see how long this one lasts?!??!\n","date":"Thu 9 April UTC 2026","externalUrl":null,"permalink":"/posts/cymylau/","section":"Blog posts","summary":"","title":"My blog is dead, long live my blog!","type":"posts"},{"content":"","date":"Thu 9 April UTC 2026","externalUrl":null,"permalink":"/categories/opinion/","section":"Categories","summary":"","title":"Opinion","type":"categories"},{"content":"","date":"Sat 4 April UTC 2026","externalUrl":null,"permalink":"/tags/apple/","section":"Tags","summary":"","title":"Apple","type":"tags"},{"content":"","date":"Sat 4 April UTC 2026","externalUrl":null,"permalink":"/tags/brave/","section":"Tags","summary":"","title":"Brave","type":"tags"},{"content":"","date":"Sat 4 April UTC 2026","externalUrl":null,"permalink":"/tags/firefox/","section":"Tags","summary":"","title":"Firefox","type":"tags"},{"content":"","date":"Sat 4 April UTC 2026","externalUrl":null,"permalink":"/categories/privacy/","section":"Categories","summary":"","title":"Privacy","type":"categories"},{"content":"","date":"Sat 4 April UTC 2026","externalUrl":null,"permalink":"/tags/privacy/","section":"Tags","summary":"","title":"Privacy","type":"tags"},{"content":"","date":"Sat 4 April UTC 2026","externalUrl":null,"permalink":"/tags/security/","section":"Tags","summary":"","title":"Security","type":"tags"},{"content":"You probably use Google services, such as search, gmail, or youtube. I do, it\u0026rsquo;s very hard to not use their excelent tools. This is not a “Google is bad” rant, far from it. Technically, their search engine is one of the most impressive systems ever built. I am not happy with the business model dynamic, that needs improvement. I’ve hit a point where I’m no longer comfortable with the status-quo. Ultimately I’m fed up with being the product.\nYour Digital Self # In the movie \u0026ldquo;The Matrix\u0026rdquo; released in 1999 computers have enslaved humans to become batteries (heat power source) that power the computers. In a pivotal scene the character Morpheus (played by Laurence Fishburne) explains to Neo (Keanu Reeves) how the computers know how to virtually render their virtual image inside the virtual world of the matrix:\n\u0026ldquo;your appearance now is what we call residual self-image. It is the mental projection of your digital self.\u0026rdquo;\nThis is happening now when you use a service like google search. Digital services form opinions of your digital self. Everytime you use a google service, you leave a small trace of the real you.\nWhat computer you use; is it an iPhone, Android? What time of day do you use it? What phrases have you searched for previously? What is your age? What is your sex? Where are you? Collectively, they form something incredibly valuable: A high-confidence model of you\nNot just who you are, but what you’re likely to do next. That’s your digital self.\nSearch is not neutral # Search for:\nbest VPN buy running shoes cloud backup solution What you’ll see:\nSponsored results at the top Sometimes more ads at the bottom This isn’t just “some ads”, this is a real-time auction system, where companies bid to google to show their adverts to you, based on your digital self. This is a search in google for the word hammer. I\u0026rsquo;m signed into google, it knows I do a lot of DIY, that I\u0026rsquo;m based in the UK plus a whole heap of other factors I won\u0026rsquo;t define here.\nIf you search Google for “hammer”, you’ll likely see something different to me. Maybe you’re into sharks (hammerhead), live in Hammersmith, or play Warhammer. I’ll admit I’m reaching with this example but that’s the point. Even a simple word like “hammer” isn’t neutral once it’s filtered through your digital profile.\nHow not to be a product # One option is to pay for a search engine.\nPay, did you say pay?\nWe all pay. It\u0026rsquo;s how the transaction is formed is the key point in changing your experience. I would rather be a customer, than the product. I\u0026rsquo;ve chosen to do this using Kagi. There are others available, and this isn\u0026rsquo;t about me trying to sell you Kagi. Kagi quoting time:\nSo lets compare, searching \u0026ldquo;hammer\u0026rdquo; kagi.\nNo adverts, a cleaner view of the internet without advertising. No sponsored links, this is how the internet used to be a long time ago.\nAnother kagi quote (last one I promise)\nIn 2022, advertisers spent $185.35 billion to influence your search results. By 2028, they\u0026rsquo;ll spend $261 billion. This isn\u0026rsquo;t just numbers - it\u0026rsquo;s an arms race for your attention.\nSlightly dramatic, but it shows the scale of the problem.\nThe internet experience I want # Ad free internet is the internet experience I want, kagi provides this. Also, they’ve got \u0026ldquo;Sherlock Bones\u0026rdquo; dog as a homepage companion (other options available) which I’ll admit was a completely irrational win for me. I love dogs, so I’m immediately more positive towards the product. And that’s kind of the point. It’s a tiny, almost meaningless preference but it’s exactly the sort of signal that ends up in your digital profile and used against you.\nYou have also learnt that I love the Matrix movie; another small snippet that says something about me. Who I am.\nYou’re always part of the transaction. The only question is which side you’re on.\n","date":"Sat 4 April UTC 2026","externalUrl":null,"permalink":"/posts/youreaproduct/","section":"Blog posts","summary":"","title":"Tell me you're a product, without telling me you're a product.","type":"posts"},{"content":"I quit.\nNo long goodbye. No gradual tapering off. Just a clean break from something that had been part of my daily routine for years.\nFirefox is gone.\nBefore you assume burnout, frustration, or some dramatic failure, it is none of those things. In fact, this is a story about improvement. About tightening control. About refining a setup that already worked well, but could work better.\nThis is the story of why I moved from Firefox to Brave.\nThe starting point: a “privacy-first” Firefox setup # For years, Firefox was the obvious choice.\nIt aligned with everything I care about:\nOpen source foundations Strong privacy stance Deep customisation via about:config Policy control through policies.json A hardened setup tuned exactly how I wanted My configuration was not default. It was deliberate.\nTelemetry disabled Fingerprinting resistance enabled State partitioning enforced DNS handled at the network layer (no DoH in browser) Extensions reduced to essentials only It worked. And it worked well.\nBut it came at a cost.\nThe hidden tax of control # Running a hardened Firefox setup is not “set and forget”.\nIt is:\nContinuous tuning Reading changelogs to ensure settings still apply Watching for breaking changes Maintaining user.js consistency across devices Explaining to yourself, repeatedly, why each setting exists This is the trade-off: control versus simplicity.\nAnd over time, I started asking a simple question:\nWhat if I could get 80–90% of this outcome, with 20% of the effort?\nEnter Brave # Brave was not new to me. It had always been “that Chromium browser with opinions”.\nBut I had dismissed it previously for a few reasons:\nChromium base (less ideological appeal than Firefox) Built-in crypto features I had no interest in A perception that it was “privacy-lite” rather than “privacy-first” Revisiting it with a more pragmatic lens changed that view.\nThe Mac factor # Running entirely within the Apple ecosystem changes the equation.\nOn macOS, I care about:\nBattery efficiency Native performance on Apple Silicon Smooth rendering and scrolling Minimal system overhead Brave, being Chromium-based, benefits heavily from optimisation in this space.\nThe result is noticeable:\nFaster page loads Lower perceived latency Better responsiveness under load Firefox is good. Brave is simply sharper here.\nPrivacy without the constant tweaking # The real shift was not performance. It was philosophy.\nBrave makes strong privacy decisions by default:\nAggressive tracker and ad blocking (no extension required) First-party storage isolation concepts baked in Fingerprinting protections enabled out of the box HTTPS upgrades automatic Shields model that is visible and understandable per-site This is important.\nWith Firefox, I engineer my privacy posture.\nWith Brave, I inherit it.\nThat difference matters more than I expected.\nFewer moving parts # My Firefox setup relied on:\nBrowser configuration Extensions Network-level DNS filtering Brave allowed me to reduce that stack:\nBuilt-in blocking replaces uBlock-style needs Cleaner extension footprint Less risk of extension-based supply chain issues Fewer components to audit and trust In a security mindset, fewer moving parts usually wins.\nThe Chromium reality # There is an uncomfortable truth here.\nMost of the modern web is built and tested against Chromium.\nThat leads to:\nFewer compatibility issues Better support for newer web standards Less time troubleshooting odd rendering bugs Switching to Brave reduced friction in subtle ways:\nFewer sites breaking Less need to “just try another browser” More consistency across devices What I gave up # This was not a free upgrade. There are trade-offs.\nI lost:\nDeep, granular configuration via about:config The philosophical alignment with a non-Chromium engine Some of the satisfaction that comes with fully owning the stack Brave is opinionated. You accept its model more than you shape it.\nFor some, that is a dealbreaker.\nWhat I gained # In return, I gained:\nA simpler setup Strong privacy defaults without constant tuning Better performance on macOS Reduced maintenance overhead A browser that “just works” more often Most importantly, I gained time.\nThe real reason I quit # This was not about Firefox being bad.\nIt is still one of the best browsers available, especially for those who want absolute control.\nThis was about recognising that my priorities had shifted.\nI no longer wanted to:\nContinuously maintain a browser configuration Revalidate settings after updates Treat my browser like a project I wanted something closer to:\nSecure. Private. Fast. Done.\nBrave gets me close enough to that ideal.\nFinal thoughts # If you are deeply invested in control, Firefox remains unmatched.\nIf you are looking for a balance between:\nstrong privacy solid performance low maintenance then Brave is worth serious consideration.\nThis was not a rage quit.\nIt was a pragmatic one.\nAnd sometimes, that is the more meaningful move.\n","date":"Wed 25 March UTC 2026","externalUrl":null,"permalink":"/posts/bravemoveidedicedtoquit/","section":"Blog posts","summary":"","title":"A Brave move? Why I decided to quit...","type":"posts"},{"content":"","date":"Wed 25 March UTC 2026","externalUrl":null,"permalink":"/categories/browser/","section":"Categories","summary":"","title":"Browser","type":"categories"},{"content":"","date":"Wed 25 March UTC 2026","externalUrl":null,"permalink":"/categories/macos/","section":"Categories","summary":"","title":"Macos","type":"categories"},{"content":" Building a Privacy-Aware Outbound DNS Architecture # DNS is often treated as a simple plumbing layer. Most folks just use whatever DNS provider they get with their ISP.\nISP DNS isn\u0026rsquo;t bad, its perfectly fine if you are happy with the ISP knowing every website / query you make and that some queiries may be blocked by the ISPs resolvers due to pressures to restrict the internet.\nThis article isn\u0026rsquo;t about breaking the law. It is about privacy, and what I am doing to ensure that my privacy, in an online world is balanced. I may not always get it right.\nDone properly, DNS becomes far more than name just domain resolution. It becomes:\nA policy engine. A privacy boundary. A routing signal source. A security control layer. My goal is to have reasonable DNS security and I\u0026rsquo;m using the following services to get to a goodish DNS position.\nControlD for upstream security and filtering. UniFi DNS visibility for policy-based routing. AdGuard Home for \u0026ldquo;fail fast\u0026rdquo; and to control IPv6 behaviour for Unifi policy-based routing. The goal is not just blocking ads or annoyances. It is building layered DNS roles with clear responsibility boundaries and functions.\nHigh-Level Architecture # flowchart BT Client[\"Client Devices\"] --\u003e AdGuard[\"AdGuard Home\"] AdGuard --\u003e UniFi[\"UniFi Gateway DNS Visibility\"] UniFi --\u003e ControlD[\"ControlD (DoH)\"] ControlD --\u003e Internet[\"Internet\"] Each layer has a defined responsibility and purpose.\nLayer 1. ControlD, Outbound Security and Privacy Layer # Purpose # ControlD is my outbound resolver for the entire network.\nIts role:\nBlock malicious domains such as phishing and malware. Filter tracking and ads. Enforce adult content restrictions. Block newly registered domains. Provide encrypted DNS-over-HTTPS. Configuration Overview # AI Malware Filter: Aggressive. Block TTL: 30 seconds. Redirect TTL: 30 seconds. Bypass TTL: 60 seconds. Compatibility Mode: Enabled with IPv6 support. Connection Method: DNS-over-HTTPS. Why ControlD # ControlD acts as the external security boundary.\nIt ensures:\nPrivacy from ISP DNS, with encrypted transport using DoH. Centralised filtering logic. Uniform outbound DNS policy. ControlD only sees the UniFi gateway as the querying client, not individual devices. This reduces external fingerprinting and protects internal device visibility.\nLayer 2. UniFi DNS Visibility, Policy-Based Routing Engine # Purpose # UniFi DNS is not the primary filtering layer.\nIt exists for policy-based routing.\nFor example:\nSend bing.com search traffic via WAN2. Route certain SaaS applications via VPN. Direct specific domains down specific egress paths. UniFi can only create routing policies if it sees DNS queries and their answers.\nIf clients bypass UniFi for DNS, policy-based routing breaks.\nDesign Insight # UniFi does not need to be the filtering authority. It needs visibility.\nThis layer ensures:\nDNS queries are visible to the gateway. Routing decisions can be domain-aware. Traffic engineering works predictably. This is DNS as a routing signal, not just name resolution.\nLayer 3. AdGuard Home, IPv6 Control and Client Enforcement # The Problem # UniFi policy-based routing is reliably enforced on IPv4.\nIf clients receive IPv6 AAAA records, they may:\nBypass IPv4 routing rules. Exit via unintended WAN interfaces. Avoid policy enforcement. The Solution # AdGuard Home sits closest to clients and:\nFilters AAAA records. Prevents IPv6 bypass scenarios. Enforces Safe Search policies. Adds browsing security and parental controls. Enabled Features # AdGuard browsing security web service. AdGuard parental control web service. Safe Search enabled for: Bing. DuckDuckGo. Ecosia. Google. Pixabay. Yandex. Safe Search disabled for YouTube. AdGuard ensures IPv6 does not undermine the IPv4 routing strategy.\nWhy Layer Instead of Consolidate # Many setups collapse DNS into a single resolver.\nThat works. Layering provides:\nClear separation of concerns. Easier troubleshooting. Explicit trust boundaries. More predictable routing behaviour. Reduced information leakage. Each system has a defined job.\nLayer Responsibility\nAdGuard Client control and IPv6 containment UniFi Routing visibility and policy-based routing ControlD External filtering and encrypted upstream\nPrivacy Properties of This Design # ISP cannot see plaintext DNS queries. The external resolver cannot fingerprint internal devices. Clients cannot bypass routing via IPv6. Malicious domains are blocked upstream. Newly registered domains are filtered aggressively. This is DNS used intentionally as a security primitive.\nOperational Lessons Learned # Keep TTL values low when testing routing behaviour. Always validate AAAA suppression if enforcing IPv4 routing. Confirm UniFi sees DNS answers before debugging policy-based routing. Test Safe Search enforcement per search engine. DNS misconfiguration often looks like routing issues. In reality, it is frequently resolver behaviour.\nFuture Improvements # DNS logging pipeline into a SIEM. Split-horizon DNS for lab zones. DNSSEC validation testing. Conditional forwarding for internal domains. Automated configuration backups. Conclusion # DNS is no longer just name resolution.\nIn a homelab built with security in mind, it becomes:\nA privacy boundary. A routing intelligence feed. An enforcement layer. A threat mitigation control. By layering AdGuard Home, UniFi, and ControlD, I built a DNS architecture that is:\nPrivacy-aware. Routing-aware. IPv6-conscious. Security-focused. Predictable. If you are building a security-first homelab, start treating DNS as architecture, not plumbing.\n","date":"Tue 13 January UTC 2026","externalUrl":null,"permalink":"/posts/privacyawaredns/","section":"Blog posts","summary":"","title":"Building a Privacy-Aware Outbound DNS Architecture","type":"posts"},{"content":"","date":"Tue 13 January UTC 2026","externalUrl":null,"permalink":"/tags/dns/","section":"Tags","summary":"","title":"Dns","type":"tags"},{"content":"","date":"Wed 3 December UTC 2025","externalUrl":null,"permalink":"/tags/beginners/","section":"Tags","summary":"","title":"Beginners","type":"tags"},{"content":"","date":"Wed 3 December UTC 2025","externalUrl":null,"permalink":"/categories/development/","section":"Categories","summary":"","title":"Development","type":"categories"},{"content":"","date":"Wed 3 December UTC 2025","externalUrl":null,"permalink":"/tags/learning/","section":"Tags","summary":"","title":"Learning","type":"tags"},{"content":"","date":"Wed 3 December UTC 2025","externalUrl":null,"permalink":"/tags/python/","section":"Tags","summary":"","title":"Python","type":"tags"},{"content":"When I first started learning Python, I thought variables behaved the same way they did in other languages I’d played with.\nAssign a value, copy a value, change one, and the other should stay the same… right?\nWell, not quite.\nConsider this tiny snippet that really confused me in the beginning:\nVariableA = 1 VariableB = VariableA VariableA =+ 1 print(VariableB) At first glance, I expected:\n1 But Python printed:\n2 What?!\nThe Confusion # I assumed that VariableB held its own copy of the value 1 at the moment it was assigned.\nSo when VariableA changed later, surely VariableB should remain untouched.\nWhat I didn’t realise was:\nVariables in Python don’t store data—they store references to objects\nVariableA doesn’t “contain” 1. It points to the integer object 1.\nWhen you do:\nVariableB = VariableA you’re not copying the value — you’re copying the reference.\nAnd then… the biggest “aha” moment:\nVariableA =+ 1 is not the same as:\nVariableA += 1 The version with =+ simply assigns positive 1 to the variable.\nSo this line:\nVariableA =+ 1 means:\nVariableA = +1 You are reassigning VariableA to the integer 1 again — not incrementing it.\nWhich means the code is actually doing this under the hood:\nVariableA = 1 VariableB = 1 VariableA = 1 # again print(1) So why did your version print 2?\nBecause in your real test, you probably used +=, not =+.\nAnd that difference is where Python once confused a lot of us.\nThe Real Behaviour (with +=) # If you intended to increment VariableA, the correct operator is:\nVariableA += 1 Now we get:\nVariableA = 1 VariableB = VariableA # both reference \u0026#39;1\u0026#39; VariableA += 1 # VariableA now references a NEW \u0026#39;2\u0026#39; object print(VariableB) # still \u0026#39;1\u0026#39; And the output becomes:\n1 Because integers are immutable in Python — modifying them actually creates a new object.\nWhy This Mattered to Me # This tiny detail: =+ vs +=, \u0026ldquo;references vs values\u0026rdquo; or \u0026ldquo;immutability vs mutability\u0026rdquo;. The first time I realised Python had its own internal logic that didn’t always match what I assumed. You know what they say about assumption - it makes a fool of us both!\n","date":"Wed 3 December UTC 2025","externalUrl":null,"permalink":"/posts/pythonvariables/","section":"Blog posts","summary":"","title":"Python, Explained — Variables That Aren’t What They Seem","type":"posts"},{"content":"","date":"Wed 3 December UTC 2025","externalUrl":null,"permalink":"/tags/variables/","section":"Tags","summary":"","title":"Variables","type":"tags"},{"content":"","date":"Sat 20 September UTC 2025","externalUrl":null,"permalink":"/tags/encryption/","section":"Tags","summary":"","title":"Encryption","type":"tags"},{"content":"","date":"Sat 20 September UTC 2025","externalUrl":null,"permalink":"/tags/storage/","section":"Tags","summary":"","title":"Storage","type":"tags"},{"content":"You could think about data-at-rest encryption a little like the OSI model we use for networks: a layered system where each tier plays a distinct role. You would not trust a network defended at only one layer, and storage is no different. Every layer has blind spots, but when those layers stack neatly on top of each other, they cover one another\u0026rsquo;s weaknesses. That is what turns ordinary encryption-at-rest into proper defence-in-depth.\nStorage Encryption Layers # flowchart TB L0[\"0 - BIOS\"] L1[\"1 - Drive Encryption\"] L2[\"2 - RAID\"] L3[\"3 - Volume(s)\"] L4[\"4 - File System\"] L5[\"5 - Application\"] L0 --\u003e L1 --\u003e L2 --\u003e L3 --\u003e L4 --\u003e L5 Detailed Breakdown # flowchart TB BIOS[\"BIOSEnsures firmware integrity and a measured or secure boot path.Examples: UEFI Secure Boot, TPM measured boot.Strength: helps prevent early-boot tampering and enforces a trusted boot chain.\"] Drive[\"DriveProvides full-disk or hardware-based encryption for physical drives.Examples: BitLocker, LUKS, self-encrypting drives.Strength: strong protection for lost or stolen drives, with transparent boot after unlock.\"] RAID[\"RAIDEncrypts at the controller or array level across multiple disks.Example: controller-level RAID encryption.Strength: protects data spread across disks and can remain transparent to the operating system.\"] Volumes[\"Volume(s)Encrypts logical volumes or containers rather than raw disks.Examples: VeraCrypt volumes, LVM with dm-crypt.Strength: flexible targeting of specific volumes while remaining transparent to applications.\"] FileSystem[\"File SystemEncrypts individual files or directories on the file system.Examples: EFS on Windows, GnuPG, age.Strength: offers granular control, per-file sharing, and key separation.\"] Application[\"ApplicationEncrypts sensitive fields, columns, or entire tables inside the application or database.Examples: SQL Server TDE, MongoDB FLE, application-level cryptography.Strength: protects data even if backups or disks are exposed, and supports granular access control.\"] BIOS --\u003e Drive --\u003e RAID --\u003e Volumes --\u003e FileSystem --\u003e Application Extended Considerations # Beyond the layers shown above, consider cloud object and blob storage encryption. Cloud providers often encrypt objects at rest, such as with S3 SSE or Azure Storage Service Encryption. Customers can usually bring their own keys (BYOK) for stronger control and clearer separation of duties.\nBackups, snapshots, and archival media need their own encryption and key management, especially when they are held offsite or by third parties. They are often the forgotten copy of your production data, which makes them a particularly tempting target.\nSwap and page files deserve attention too. Encrypt swap space, or use memory encryption features where they are available, to reduce the chance of sensitive data being written from RAM to disk in plain text.\nKey management is where many otherwise sensible encryption designs fail. Use a dedicated KMS or HSM where appropriate, enforce least privilege, rotate keys deliberately, and audit access carefully.\nAccess controls and secrets management should sit alongside encryption rather than behind it. Strong IAM, managed secrets, and audit logging reduce the exposed attack surface and make misuse easier to spot.\nKeys # There is little point in encrypting data if the keys that provide access to it live in the same system with the same trust boundary. Sometimes that is unavoidable, but it should be a conscious decision rather than an accident. Always consider the key-handling options available to you, and remember that if you lose the keys, it is unlikely you will get the data back. This is a large topic in its own right, but at minimum, make sure you have encrypted backups and a key-management process you trust.\nConclusion # Storage encryption is not just \u0026ldquo;turning on BitLocker\u0026rdquo;. Like the OSI model, each layer addresses different threats. By combining multiple layers with solid key management and access controls, you build a more resilient defence for data at rest.\n","date":"Sat 20 September UTC 2025","externalUrl":null,"permalink":"/posts/storagelayercake/","section":"Blog posts","summary":"","title":"Storage Encryption Cake Mix","type":"posts"},{"content":"","date":"Wed 22 February UTC 2023","externalUrl":null,"permalink":"/tags/commands/","section":"Tags","summary":"","title":"Commands","type":"tags"},{"content":"","date":"Wed 22 February UTC 2023","externalUrl":null,"permalink":"/tags/git/","section":"Tags","summary":"","title":"Git","type":"tags"},{"content":"Git is brilliant when it behaves and deeply memorable when it does not. This post is a small collection of commands I reach for when I need to get back to a known-good place without turning the moment into a drama.\nThink of it as a memory jog: quick reminders for common setup and branch workflow tasks.\nInitial Configuration # git config --global user.name \u0026#34;rich\u0026#34; git config --global user.email \u0026#34;noreply@fromyouto.me\u0026#34; git config --global fetch.prune true Branch Workflow # Create a branch, and switch to it.\ngitGraph commit branch feature/my-change commit git switch main git pull git switch -c feature/my-change Running\ngit branch\nShould now show\n* feature/my-change main Do some work, create files. In relevant directory, add files to be tracked.\ngit add .\nWhen ready, create a commit with a good message (Future you, take note!).\ngitGraph commit branch feature/my-change commit id: \"Test function\" commit id: \"Fix syntax\" commit id: \"Enable Log\" git commit -m \u0026quot;description of changes\u0026quot;\nPublish the branch\ngit push -u origin feature/my-change\nDanger Will Robinson, Danger! # Need to delete a branch, you can\u0026rsquo;t delete the active branch so switch to alternatuve first.\ngit switch main git branch -d feature/my-change or to force a delete\ngit branch -D feature/my-change When Your Branch Is Behind Main # Gotten left behind? If your local branch was created some time ago, an option is to rebase.\nSometimes you start a feature branch, do a bit of work, and then main moves on without you. Your branch still works from the old starting point, but it is now missing the latest commits from main.\ngitGraph commit id: \"A\" commit id: \"B\" branch feature checkout feature commit id: \"C\" checkout main commit id: \"D\" commit id: \"E\" In that shape, feature contains your work at C, but it does not contain the newer main commits D and E. Rebasing replays your feature work on top of the latest main, which makes the branch look as though you started from the current version.\ngitGraph commit id: \"A\" commit id: \"B\" commit id: \"D\" commit id: \"E\" branch feature checkout feature commit id: \"C'\" That can be useful because it:\nkeeps the pull request history easier to read tests your work against the latest version of main avoids a merge commit just to catch up often makes conflicts smaller and easier to understand The usual flow is:\ngit fetch origin git switch feature/my-change git rebase origin/main If the branch has already been pushed, update the remote branch with:\ngit push --force-with-lease Use --force-with-lease instead of plain --force; it checks that you are not overwriting someone else\u0026rsquo;s newer work by accident.\n","date":"Wed 22 February UTC 2023","externalUrl":null,"permalink":"/posts/git/","section":"Blog posts","summary":"","title":"GIT Helper","type":"posts"},{"content":"","date":"Wed 22 February UTC 2023","externalUrl":null,"permalink":"/tags/version-control/","section":"Tags","summary":"","title":"Version-Control","type":"tags"},{"content":"","date":"Wed 22 February UTC 2023","externalUrl":null,"permalink":"/tags/workflow/","section":"Tags","summary":"","title":"Workflow","type":"tags"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"}]