Self-Hosted Diaries (2025.3)

Pi-Hole and NextDNS are great for filtering out domain-based ads and malware but they don’t do anything about ads (or even just stupid content) from a ‘safe’ domain. For that ‘last mile’, you need some form of browser-based ad-blocking. When I switched to Firefox earlier this year, it was a good opportunity to revisit my custom ad-blocking rules to see if I could clean up some of crap that is so common across the websites I visit.


 

Self-hosted Series

This post is part of a series, check out the other posts!


 

Quick Links


Starting point

Over the last year or two, Google has been making some moves that ultimately have/will lead to the end of one of the most effective browser based ad-blockers. As I run network-wide DNS-based ad-blocking, this may affect me less than others but DNS-based blocking doesn’t catch everything and you really do need browser-based blocking to handle the last-mile.

I don’t blame Google for making these moves — they are an ad company which naturally puts them at odds with ad-blocking, but with the writing on the wall for uBlock Origin (in Chrome), I cut over to Firefox. As I run multiple machines where I want to maintain a consistent rule-set, this was a good opportunity to spend a bit of time on refining my ‘last-mile’ ad-block process. uBlock Origin supports the idea of cloud storage to handle synchronizing rules between machines, but I wanted to take this a bit further.

The one thing that you can do with browser-based shenanigans is to restructure a website.

  • Your favourite website changed the colour of a button that you don’t like? Override that

  • Don’t care about sports/arts/entertainment/business/weather on your preferred news site? Hide it

  • A website you visit often has a fixed divider that just isn’t big enough (Azure DevOps I’m looking at you) - resize it

  • A site has a button placed way out in left field? Move it

And then the rabbit hole got deeper:

  • Could we hide entire products/brands/categories on Amazon?

  • What about blocking out specific channels on YouTube? (AI generated puke, I’m looking at you)

  • Can we filter out entire subreddits on Reddit?

[Back to Top]

Step 1 - Building out the Rules

We’ll jump right into it, the super star that makes all the magic happen is…

 

:has-text(/your-text-here/i)

Find the element archetype you want to clean up, append that magic block and go on a censoring spree. It’s a slow, iterative and cumulative process as you build out your desired filters, but it gets better over time.

Note: the optional element in red allows the filtering to be case-insensitive.

Amazon

Here, I'm interested in cleaning up the Deals page: my thought process is that I like to browse through the Deals page, perhaps looking for random impulse/super-sale items, but there are definitely things that I'm not interested in:

  • Brands (i.e., Apple)

  • Product categories (i.e., sweaters -- this isn't something I'm going to impulse buy)

  • Specific products (i.e., a specific coffee maker -- I already have one, so I won't be buying a second one)

  • Alphabet-soup products and companies -- you know the type, where the company name is a random jumble of letters and the product is just copy-paste-generic-crap

For each thing you want to block, I've found you need two entries:

 

amazon.ca##li.dcl-carousel-element.a-carousel-card:has-text(/thing-you-dont-care-about/i)
amazon.ca##div.GridItem-module__container_PW2gdkwTj1GQzdwJjejN:has-text(/thing-you-dont-care-about/i)

You do need to be a bit cautious (sometimes being more-vague with your filters, sometimes more-specific) otherwise you might accidentally block items/categories you are interested in. For example, let's say you do want to see phone accessories, chargers, cables etc. but you don't want to see anything Apple-specific. If you were to add a block for Apple, you would definitely be inadvertently blocking some/many things that you might be interested in as many of them will use Apple in the description. So you might build out a few blocks that are more granular:

  • for Apple

  • for iPhone

  • for iPad

  • etc.

Will you still [inadvertently] block stuff? Yes, but it’s a balancing act. The ‘clean-up’ process is pretty fun to watch in real-time — the product blocks get lazy-loaded and then hidden by the ad-blocking.

Ad-block on Amazon purging items/brands/categories you don’t care about

 

 

Sometimes, you can throw a :not in there to simplify your life. For example, on the main Amazon page, the only block I might be interested in will be ‘Keep Shopping For’, so I have the following rules to allow it, but filter the rest

amazon.ca###desktop-grid-1:not(:has-text(Keep))
amazon.ca###desktop-grid-2:not(:has-text(Keep))
amazon.ca###desktop-grid-3:not(:has-text(Keep))
amazon.ca###desktop-grid-4:not(:has-text(Keep))
amazon.ca###desktop-grid-5:not(:has-text(Keep))
amazon.ca###desktop-grid-6:not(:has-text(Keep))
amazon.ca###desktop-grid-7:not(:has-text(Keep))
amazon.ca###desktop-grid-8:not(:has-text(Keep))

Example: only allowing the ‘Keep shopping for’ block on the main Amazon landing page

Reddit

I admit, I didn’t look too hard, but from what I can tell, there isn’t an option in Reddit to say “please don’t show me this subreddit ever again, I’m not interested”. Enter ad-block. Again, I’ve found that you need two rules to hide things fully (one to hide from the top carousel, and the other to hide from the main listing):

reddit.com##article.m-0.w-full:has-text(/r\/boring-subreddit/i)
reddit.com##faceplate-tracker.shrink-0.list-none.inline-flex.overflow-hidden.rounded-\[16px\].mr-md:has-text(/r\/boring-subreddit/i)

YouTube

Again, you can use this to filter out channels you never want to see again because you find them boring or… you know the channels: the ones that are purely text-to-speech product-puke. Like before, I found that you need a couple rules to hide the channels (one hides it from the general listing, the other hides it from search results):

 
youtube.com##ytd-rich-item-renderer:has-text(AI-slop-channel)
youtube.com##.ytd-video-renderer:has-text(AI-slop-channel)

Bonus: if you want to just rid yourself of YouTube shorts…

 
youtube.com##ytd-video-renderer.ytd-item-section-renderer.style-scope:has-text(SHORTS)

Creating your own lists

So the wonderful thing about uBlock (and other ad-blockers) is that you can leverage lists of things to block. Most of the time, we leverage lists curated by others but nothing stops us from making our own list. At a high level, we just need a text file to be accessible by the browser - where and how you get that text file is up to you.

One easy (and free) way to do it is to use GitHub.

  1. Create your lists of rules, optionally organizing them into subfolders and multiple lists (so you can easily troubleshoot by turning off an individual list)

  2. Create an account and somehow, get your list into GitHub

  3. In uBlock, import your list

The signature for your list will be something like:

 
https://raw.githubusercontent.com/your-github-username/github-repository-name/refs/heads/your-branch/optional-folders-for-organization/your-rule-textfile.txt

My Workflow

For myself, I run my own self-hosted Gitea instance at home, where I have a repository for holding all the ad-blocking rules (both for PiHole and for uBlock). Since I batch out a whole bunch of rules at a time, I threw together a quick little desktop app to build out rules for a bunch of websites I regularly visit.

Once I have a bunch of rules done up, I do a pull-request which then triggers a sync from my local Gitea instance to GitHub. In my uBlock configuration, I import all of the GitHub-hosted rules. Since I have a ton of different files, I also keep an index.txt file that contains a list of all the GitHub files in a ready to copy-paste format so I can readily deploy to a new machine if needed.

Using Amazon for example, I will have my app open while I do a quick scroll through the deals page and add blocks as I go — it doesn’t help me this time, but after the rules get integrated, I’ll never see those annoyances again.

At the time of this post, I have 62-lists and just under 9500 rules defined.

Bonus: you can use uBlock (with these lists) on Firefox for Android as well

Bonus shenanigans

Above, I alluded to the idea of if you don’t like the way a website is laid out - you can change it (to a degree). For that, I use a tool called Stylebot. As real-world example, for work, we use a tool called Azure DevOps and for the pipeline details page, the individual job steps are in a fixed-sized column that just isn’t wide enough to show the full text some/most of the time.

Since I am dialed in for 4K/8K and have resolution for days, it’s all kinds of frustrating to then have a (web!) UI that feels like it’s fixed to 1280x960 or something silly — with the double-whammy of the obsession of (web!) UI to have gobs and gobs of white space for the sake of white space.

Rant aside. For Stylebot, the corrective override is

 
/* This makes the steps column (visible during a pipeline run) wider so we can see more */
.bolt-master-panel {
  width: 750px;
}

Set the styling override to your AzDo portal’s wildcard URL (so, https://your-azdo-url.com/*) and you’re set. Depending on your resolution (and size needs), you can play around with the size there

[Back to Top]


Summary

A lot of the websites that I visit tend to have a lot if crap on there, with a smattering of things that might be a bit interesting mixed in. Being able to filter out the crap helps to keep the experience more enjoyable and ultimately save me time — I’m never going to be interested in X,Y,Z so having to scroll through it again and again is no good for anyone.

Sometimes, websites will have “hide this” functionality and while that is a definite improvement over not having that option, this only hide’s that specific instance — another similar post can be made tomorrow and you’ll just have to hide it all over again. Being able to permanently block things categorically means, you only have to be annoyed by any given thing once (or certainly only a few times).

[Back to Top]


Product links may be affiliate links: MinMaxGeek may earn a commission on any purchases made via said links without any additional cost to you.

Next
Next

Build Log: Table Saw Mobile Base & Outfeed