How to Block Distracting Websites on Your Laptop
Tags: digital-minimalism • Categories: Productivity
"What exactly did I do the last 30 minutes?"
I’m sure you’ve been there, asking that same question, staring blankly into your computer screen.
I’ve written about how I’m working to minimized distraction. For me, a big component of that is blocking distraction on the device I spend the most time: my laptop.
Here’s what I’m looking to do:
- Automatically block distracting websites, but allow an easy way to temporarily unblock them. Example: I want to block Amazon by default, but sometimes I want to jump on and buy something quickly.
- I don’t want to have to manage a schedule. Creating exceptions to schedules and then remembering to re-enable the schedule never works well.
- I don’t want crappy software that is going to slow down my computer or cause weird networking issues.
- I want it to be hard, but not impossible, to disable. One or two clicks to disable is too easy.
The Easy Way
For most folks, you’ll want to use one of the couple apps out there that do this for you. Here are some that I’ve tried:
- RescueTime
- Focus
- Freedom
- Cold Turkey
Focus is the best option I’ve found. It’s a simple and nicely designed app. Check it out!
The Hard Way
If you like tinkering with your system setup, read on.
The pre-built applications always seemed to do strange things to the networking stack on my computer or hog lots of resources (GBs of memory in some cases). This is probably due to how much I customize my computer.
Also, I found that if I disabled my "blocking schedule" it didn’t automatically re-enable. I would then find myself down the Twitter rabbit-hole with 20m wasted. That was a big issue for me.
Eventually, I got frustrated and built a solution which works surprisingly well:
- Maintain a simple file listing every host is distracting.
- Run a script every time the computer wakes up. I used
sleepwatcher
for this. - The script consumes a list of distracting hosts and adds them to
/etc/hosts
with a reference to a non-existent server. After trying a couple of tools, a node packagehostile
worked best.
1. Build a List of Distracting Websites
First, create a simple text file. Back it up on Gist or somewhere where it won’t be lost. Version tracking the file allows you to view a history of what websites are distracting over time.
I keep this file in my dotfiles
repo. Here’s what it looks like:
facebook.com
twitter.com
smile.amazon.com
(yes, that’s Amazon Smile since I have a browser extension to redirect me there)
Then you’ll want to clean the file, add www
variants of each host, and point them to 127.0.0.1
:
sed '/^$/d' ./distracting_websites.txt | sed $'s/(.*)/127.0.0.1 \1\n127.0.0.1 www.\1/' > ~/distracting_sites.txt
I put this script in the setup process of my dotfiles
for easy ad-hoc execution (you’ll want to continually update your distracting_websites.txt
as new things distract you).
2. Block all Distracting Websites with a Script
Below is a script that is run every time I wake my computer. Here’s what it does:
- Updates
/etc/hosts
usinghostile
and thedistracting_sites.txt
file - Clears system DNS cache
- Clears Safari cache, which seems to have its own DNS cache. Chrome does not.
# asdf is a node version management tool I use. Your exact execution paths will probably be different
/Users/mike/.asdf/installs/nodejs/12.14.1/bin/node
/Users/mike/.asdf/installs/nodejs/12.14.1/.npm/bin/hostile
load /Users/mike/distracting_sites.txt
# clear system cache
# https://apple.stackexchange.com/questions/303110/flush-cache-of-dns-on-macos-sierra-high-sierra/303119#303119
sudo killall -HUP mDNSResponder
# clear safari cache
osascript << EOF
tell application "Safari"
activate
end tell
tell application "System Events"
tell process "Safari"
tell menu bar 1 to tell menu bar item "Develop" to tell menu 1 to tell menu item "Empty Caches" to click
end tell
end tell
EOF
You can test this script by running it with sudo
:
sudo /usr/local/sbin/sleepwatcher --verbose --wakeup .wakeup
3. Run Website Blocking Script When your Computer Wakes from Sleep
First, install sleepwatcher
:
brew install sleepwatcher
Then, you’ll want to find the location of the plist file which starts up sleepwatcher
as a daemon process:
$ brew services
Name Status User Plist
sleepwatcher started root /Library/LaunchDaemons/homebrew.mxcl.sleepwatcher.plist
You’ll want to edit this plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>homebrew.mxcl.sleepwatcher</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/sbin/sleepwatcher</string>
<string>-V</string>
<string>-w /Users/mike/.wakeup</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/usr/local/var/log/sleepwatcher.log</string>
<key>StandardErrorPath</key>
<string>/usr/local/var/log/sleepwatcher.log</string>
</dict>
</plist>
Then, you’ll want to ensure the process runs as root and the script you created is executable:
chmod + /Users/mike/.wakeup
brew services stop sleepwatcher
sudo brew services start sleepwatcher
And… you’re done! Depending on your OS configuration you may need to grant some permissions on first run.
Was this overkill? Definitely. Does it prevent me from wasting any time on distracting websites? Absolutely.