Files
lg_update_blocker/README.md
T
Rene Kievits b137bf9eda
Build / build (push) Failing after 1m50s
init commit
2026-09-05 22:27:44 +02:00

145 lines
6.0 KiB
Markdown

<p align="center">
<img src="assets/icon400.png" width="120" alt="LG Update Blocker">
</p>
# LG Update Blocker
A webOS homebrew app that gets rid of the *"a new software version is
available"* popup LG shows on every boot — without touching the firmware
itself, and fully reversible.
Built for a rooted **LG CX (webOS 5)**, but nothing in it is model specific: it
only ever probes for things and acts on what it actually finds on your TV.
![screenshot](docs/screenshot.png)
## Why the popup keeps coming back
The Homebrew Channel's own *Block system updates* toggle only writes four
hostnames into `/etc/hosts` at boot. That is not enough in practice:
* it misses several update hostnames (`nsu`, `*-ssl`, the CDN aliases),
* it does nothing about a firmware image the TV **already downloaded** — a
staged update keeps prompting even when the update servers are unreachable,
* it leaves the auto-update settings and the update services alone.
This app covers all of that, and re-applies everything on each boot (webOS
resets `/`, `/tmp` and the mount namespace on every start).
## Protection layers
| Layer | What it does | Default |
| --- | --- | --- |
| **Block LG update servers** | Points `snu`/`su`/`nsu.lge.com`, their TLS variants, the `-dev` fallbacks and the CDN aliases at `127.0.0.1` in `/etc/hosts` | on |
| **Delete staged firmware** | Wipes the update image staged in `/mnt/lg/cmn_data/swupdate` | on |
| **Lock the staging folder** | Bind-mounts an empty read-only directory over it, so nothing can be staged again | off |
| **Turn off auto-update settings** | Reads every `com.webos.settingsservice` category, switches off each update-related key it finds, and remembers the original values | on |
| **Stop update services at boot** | Stops the update-related upstart jobs discovered in `/etc/init` (advanced) | off |
Every layer is undone by **Remove protection**, which also restores the
settings from the backup it made.
## Requirements
* A rooted webOS TV with the [Homebrew Channel](https://github.com/webosbrew/webos-homebrew-channel)
installed and its root status showing **ok**.
* The app's own service needs root. On first launch it asks the Homebrew
Channel to elevate it (`elevateService`, falling back to running
`elevate-service` through `exec`), then restarts itself. The header badge
turns green when it worked.
## Install
### Through the Homebrew Channel (repository)
Add the repository once — *Homebrew Channel → Settings → Add repository*:
```
https://github.com/<owner>/<repo>/releases/latest/download/apps.json
```
The app then shows up in the Homebrew Channel list, and every new release you
tag is picked up automatically (that URL always points at the newest release).
### Manually
Download the `.ipk` from the release and:
```sh
ares-install com.rkievits.lgupdateblocker_1.0.0_all.ipk
ares-launch com.rkievits.lgupdateblocker
```
## Using it
Navigate with ▲▼, select with OK, leave with BACK.
1. Check the layers you want (the defaults are a good start).
2. **Apply protection** — the log pane shows exactly what was changed.
3. Reboot and confirm the popup is gone.
Other buttons: **Purge staged update** (wipe a downloaded image right now),
**Remove protection** (undo everything), **Refresh status**, and
**Diagnostics** (dumps OS info, mounts, discovered settings, the tail of
`/etc/hosts` and the boot-hook log — handy for a bug report).
## What it touches
| Path | Purpose |
| --- | --- |
| `/etc/hosts` | Blocked hostnames, between `# >>> lg-update-blocker >>>` markers. Bind-mounted from `/tmp/lgupdateblocker-hosts` because `/` is read-only |
| `/var/lib/webosbrew/init.d/lgupdateblocker` | Boot hook, run by the Homebrew Channel startup script; re-applies the enabled layers |
| `/var/lib/webosbrew/lgupdateblocker/` | `config.json`, `hosts.txt`, `settings-backup.json`, `boot.log` |
| `/mnt/lg/cmn_data/swupdate` | Staged firmware, emptied (and optionally locked) |
Nothing is written to system partitions, and no LG binaries are patched or
replaced.
## Troubleshooting
* **Badge says "no root"** — open the Homebrew Channel, verify *Root status* is
`ok`, then relaunch this app. If the Homebrew Channel itself is unelevated,
fix that first (its Settings screen has a button for it).
* **Popup still appears after a reboot** — run *Diagnostics* and look at the
boot-hook log at the bottom. It records, per boot, whether the hosts entries
were added, what was purged and which jobs were stopped.
* **Belt and braces** — a hosts file only helps if the TV uses DNS. Blocking
`snu.lge.com`, `su.lge.com` and `nsu.lge.com` on your router or Pi-hole as
well is the one measure that also survives a factory reset.
* **Forced *app* updates** (the *"You must update this app to launch it"*
dialog) are a different mechanism — that is what
[LG App Update Blocker](https://github.com/dr0dr1dr2dr3/lgappupdateblocker)
is for. This app deliberately leaves the `lgtvsdp.com` hosts alone, since
blocking those also breaks the store and several other services.
## Building
No bundler, no runtime dependencies — `tools/build.js` copies `app/` and
`service/` into `build/` and substitutes the app id and version.
```sh
npm install # only the ares CLI
npm run dist # build + package + manifest, output in dist/
npm run deploy # ares-install the resulting ipk
```
## Releasing
`.github/workflows/release.yml` builds on every push. Tag a commit `v<version>`
(matching `version` in `package.json`) and the workflow additionally publishes a
release containing:
* `com.rkievits.lgupdateblocker_<version>_all.ipk`
* `com.rkievits.lgupdateblocker.manifest.json` — Homebrew Channel manifest,
with the absolute ipk URL, its sha256 and size
* `apps.json` — the one-package repository index used by the repository URL above
* `description.html` — the long description shown in the Homebrew Channel
The app id lives in exactly one place: the `name` field of `package.json`.
Change it there and everything (appinfo, service name, Luna URIs, manifest)
follows.
## License
MIT