lockin
Block distracting websites on Linux. No proxy, no browser extension, no MITM certificate.
lockin writes blocked domains to /etc/hosts and rejects QUIC/HTTP3 (UDP 443)
via nftables or iptables for every destination on the machine. A systemd
watchdog re-applies the block about once a minute.
Quick start
Linux with systemd. Run lockin as yourself. The tool calls sudo for
/etc/hosts and firewall rules. Do not run sudo lockin.
uv tool install lockin-blocker
lockin start --for 2h
lockin status
Browsers close on start. Save your work first. Reopen them after start so
they pick up DoH-disabled policies. Default mode is hardcore. lockin stop
is refused. Use lockin unlock --now to end early, or lockin start --soft if
you want lockin stop to work.
The command is lockin. The PyPI package is lockin-blocker.
Install
Python 3.11+, systemd, and nftables (or iptables).
uv tool install lockin-blocker # recommended
pip install lockin-blocker
./install.sh # same as uv/pip from PyPI, not a local checkout
lockin update # upgrade the CLI package
From a git clone, use ./scripts/dev-install instead of install.sh.
Read CHANGELOG when you upgrade.
Existing users
The first lockin start or lockin list copies packaged rules.yaml to
~/.config/lockin/rules.yaml once. Later upgrades do not merge new
defaults into that file. Edit your copy after reading the changelog.
If you have more than one rule and no default key, pass --rule every time,
or add default: social, so lockin start --for 2h works.
Usage
lockin start --for 2h Start with the default rule
lockin start --rule social --for 30m Named blocklist
lockin start --rule social,news --for 2h Stack blocklists
lockin start --until 17:00 Block until a clock time
lockin start --soft --for 30m Allow lockin stop
lockin status Remaining time (wall clock)
lockin status --json Machine-readable status
lockin extend 30 Add 30 minutes
lockin unlock 30 Early unlock after a cooldown (default 30)
lockin unlock --now End now
lockin stop End block (soft sessions only)
lockin list List rules
lockin doctor Installation health
lockin cleanup Strip leftovers (ends a live session)
lockin uninstall Remove system files
lockin update Upgrade the CLI package
Durations are 30m, 2h, 1h30m. Times are 17:00 or 9:30pm.
lockin status --json
When idle: {"active": false}.
When live:
| Key | Meaning |
|---|---|
active |
true |
rule_name |
Active rule(s), comma-joined if stacked |
end |
ISO end time (wall clock) |
remaining_seconds |
Seconds until end |
hosts |
"active" or "missing" |
hosts_count |
Domains in /etc/hosts |
firewall |
"active", "inactive", or "unknown" |
block_type |
Legacy "blacklist". Every rule is a blocklist. |
Expiry and teardown
lockin status is wall clock. Hosts, firewall, and policies come down on the
next watchdog tick (about 60s after end), not at the exact second. After a
reboot, QUIC can work until the first tick.
lockin update upgrades the CLI only. The copy under
/usr/local/lib/lockin/pkg refreshes on the next lockin start.
Notifications
Expiry, soft stop, and unlock --now try notify-send. If it is missing,
the block still ends.
Rules
Edit ~/.config/lockin/rules.yaml. Every rule is a blocklist. Listed
hostnames go into /etc/hosts. lockin expands a few common subdomains and
aliases. No globs. No allowlist. A legacy whitelists: key is still loaded as
blocklists.
default: social
blacklists:
social:
- twitter.com
- reddit.com
Firewall backends
nftables is the one lockin status can verify. iptables still rejects
UDP 443, but firewall in status JSON stays "unknown" because probe only
lists the nft table.
Browser policies
lockin writes enterprise policies that turn off DNS-over-HTTPS. Snap and
Flatpak Firefox often ignore /etc/firefox/policies. Use distro Firefox, or
close and reopen after policies land. Browsers are killed on start and at
expiry. You reopen them.
Troubleshooting
Hosts missing during a live block. Wait about a minute for the watchdog.
lockin cleanup ends the session.
Sites still blocked after expiry. Wait for the next tick, then
lockin cleanup if leftovers remain.
lockin stop refused. Hardcore mode. Use lockin unlock --now or wait.
lockin doctor fails. Fix the failed checks. Use lockin cleanup for
leftovers when no session should be running.
Uninstall
lockin uninstall
uv tool uninstall lockin-blocker
License
MIT
Release files for lockin-blocker 2026.8.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lockin_blocker-2026.8.2.tar.gz | 34.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lockin_blocker-2026.8.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 59.7 kB
Release files / lockin_blocker-2026.8.2.tar.gz
| Download URL | lockin_blocker-2026.8.2.tar.gz |
|---|---|
| Size | 34.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f55601a7d30fd8957e35567b96d123197a73d86a24c67e15a95a861ca8152eb8
|
|
BLAKE2b-256 checksum How to use checksums |
515e5f8a330c11cfe54f3d484d1b5539cad2d130861e5e294fcbde193d101676
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / lockin_blocker-2026.8.2-py3-none-any.whl
| Download URL | lockin_blocker-2026.8.2-py3-none-any.whl |
|---|---|
| Size | 25.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
af30c7f4a4748c68d08f16259aa67ea10379d66fa873199f697065509c1d2c80
|
|
BLAKE2b-256 checksum How to use checksums |
1f898e289cb2d8d7013a39b18986e1569ced49ff3115b77741b302f38a3d5a86
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|