Skip to content

luci-app-rustdesk-server: depend on rustdesk-server package - #9058

Open
luminoso wants to merge 1 commit into
openwrt:masterfrom
luminoso:feature/rustdesk-server-package
Open

luminoso wants to merge 1 commit into
openwrt:masterfrom
luminoso:feature/rustdesk-server-package

Conversation

@luminoso

Copy link
Copy Markdown
Contributor

Description

Supersedes #8946 and follows the review there: the server files belong in the packages feed, and the uci-defaults and keep.d files in the app were band-aids.

The app now depends on rustdesk-server (openwrt/packages#30572) and drops everything that package now owns: the init script, the UCI config, the uci-defaults script, the keep.d list, the two /usr/libexec wrappers and the ucode rpcd plugin. Installing luci-app-rustdesk-server pulls in hbbs and hbbr, so nothing has to be copied to the router by hand.

What changed in the view:

  • Talks to ubus directly: service list for instance status, rc list for the boot state, rc init for the service buttons and for regenerating the key, file read and file remove for the key pair. No custom rpcd plugin.
  • Layout is four sections: Status (version and a table with the Enabled and Service Status per component), Service Control (Start, Stop, Restart, Start at Boot toggle), Public Key (with Copy and Regenerate Key) and Configuration (hbbs and hbbr tabs).
  • The Binary column is gone, the package ships the binaries.
  • New open_firewall option replaces the banner that asked users to write firewall rules. The init script in the package publishes the fw4 rules through procd.
  • ACL is scoped to the actual paths: hbbs --version may be executed, the two key files may be read and written, and rc init is limited to rustdesk-server.

Fixes #8935: the uci-defaults script that rewrote enabled to 0 on every install is gone.

Migration note: installs of the previous app version own /etc/init.d/rustdesk-server and /etc/config/rustdesk-server. With opkg, remove the old luci-app-rustdesk-server before installing the new one. apk resolves the move in one transaction.

Only luci-app-rustdesk-server.pot was regenerated; .po files are left to Weblate.

Screenshot or video of changes (if applicable)

Maintainer (preferred)

@luminoso


Tested on

OpenWrt version: SNAPSHOT r36377-b6ba4e9142 (x86/64, QEMU/KVM)
LuCI version: master (26.262.38237~359bc59)
Web browser(s):

Checked in the VM: the four Service Control buttons; Regenerate Key (stop, remove both key files, start, new key shown); a restricted user with only the read ACL sees the page and gets denied on the write calls; sysupgrade keeps the config and key pair (the #8935 scenario).


Checklist

  • (Nice to have) Includes what Issue it closes (e.g. openwrt/luci#issue-number).
  • (Nice to have) Includes what it depends on (e.g. openwrt/packages#pr-number in sister repo).

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 new commit.


Generated by Claude Code

"write": {
"uci": [ "rustdesk-server" ],
"ubus": {
"rc": [ "init" ]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rpcd ubus ACLs grant object+method only, with no filtering on call arguments (rpc_login_setup_acl_scope()), so this lets anyone holding this app's write ACL run rc init with any name/action — i.e. start, stop, enable or disable every init script on the box. The ACL being replaced was path-scoped (/etc/init.d/rustdesk-server start|stop|restart|...: ["exec"]), so this is a widening, and it contradicts the PR description's "rc init is limited to rustdesk-server". Either keep the file-exec grants and drive the buttons through fs.exec, or drop the claim from the description.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, rpcd cannot scope rc init by argument. 415a633 goes back to path-scoped exec: the buttons and the regenerate flow call /etc/init.d/rustdesk-server through file exec, and the write ACL lists the five allowed actions. rc is gone from the write scope. Verified in a VM as a user holding only this app's ACL: the five calls succeed, while rc init on any service and file exec /etc/init.d/dropbear restart are denied.

Comment on lines +103 to +106
return init('stop').then(() => Promise.all([
L.resolveDefault(fs.remove(KEY_PRIV)),
L.resolveDefault(fs.remove(KEY_PUB))
])).then(() => init('start'));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fs.remove is ubus file.remove, but the app's write scope declares only "rc": [ "init" ] under ubus — the call succeeds solely because luci-base grants "file": [ "remove" ] globally in its write scope. Since the read scope does declare "file": [ "read", "exec" ] rather than leaning on luci-base, was omitting "remove" from the write scope intentional? As written, a user granted this app's ACLs but not luci-base write gets a silent no-op here (L.resolveDefault swallows the denial) and the service restarts with the old key pair.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not intentional. 415a633 adds "file": [ "remove" ] to the write scope. Retested as a user without luci-base write: both keys are removed and a new public key appears after the restart.

Comment on lines +194 to +195
o = s.taboption('hbbs', form.Flag, 'open_firewall', _('Open firewall ports'));
o.description = _('Open the ID and relay server ports (TCP and UDP) in the firewall for all zones');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this flag also governs hbbr's ports per README.md:34-36, yet it only appears on the ID Server tab, so someone configuring the relay won't find it. Was placing it under hbbs rather than in the shared status area intentional?


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to a new General tab, first in the Configuration section, with a description saying it covers the ports of both daemons. README updated to match.

The app shipped the init script, the UCI config, a uci-defaults script,
a sysupgrade keep list and two /usr/libexec wrappers, but not the hbbs
and hbbr binaries, so every user had to fetch those by hand. Those
files now live in the rustdesk-server package in the packages feed,
and installing luci-app-rustdesk-server pulls it in. The uci-defaults
script that rewrote enabled to 0 on every install is gone with them,
which is the same removal PR openwrt#8946 proposed.

The view talks to ubus directly now: service list for the instance
status, rc list for the boot state, file read and remove for the key
pair, and the init script through file exec for the service buttons
and for regenerating the key, with the ACL listing the five allowed
actions. The ucode rpcd plugin is dropped. The binary column is gone,
since the package now ships hbbs and hbbr, but the view keeps the per
component Enabled column, the Start, Stop and Restart buttons and the
Start at Boot toggle. A new open_firewall option replaces the banner
that asked for hand written firewall rules.

Installs of the previous version own /etc/init.d/rustdesk-server and
/etc/config/rustdesk-server. With opkg the old luci-app-rustdesk-server
has to be removed before the new one is installed; apk resolves the move
within one transaction.

Fixes: openwrt#8935
Co-authored-by: David Mandy <smallprogramzhusir@gmail.com>
Signed-off-by: Guilherme Cardoso <luminoso@gmail.com>
@luminoso
luminoso force-pushed the feature/rustdesk-server-package branch from ce85b40 to 415a633 Compare September 22, 2026 07:50
Comment on lines +30 to +34
return fs.exec('/etc/init.d/rustdesk-server', [action]).then(res => {
if (res.code !== 0)
throw new Error(_('Action %s failed with exit code %d').format(action, res.code));
return res;
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pressing Stop on an already-stopped service will now pop an error notification: for procd services stop ends in procd_kill (rc.common:156-163), and its ubus call service delete exits non-zero once the service is no longer registered with procd. Unless the packaged init script defines service_stopped, was treating every non-zero exit as a failure intended, or should stop be exempt?


Generated by Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

luci-app-rustdesk-server: retaining configuration updates will revert the configuration

2 participants