Skip to content

feat(network): edit NetworkManager connections from Settings - #3727

Merged
bbedward merged 3 commits into
duxlabs-dev:masterfrom
Conava:network-manager-rework
Nov 14, 2026
Merged

bbedward merged 3 commits into
duxlabs-dev:masterfrom
Conava:network-manager-rework

Conversation

@Conava

@Conava Conava commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR adds a connection editor for NetworkManager profiles to the network settings. Ethernet, Wi-Fi, WireGuard, plugin VPN, Bluetooth and cellular profiles can be created and edited there, including 802.1X and most other kinds of enterprise network configs.

I wanted to set up eduroam for my university without reaching for nmcli or nm-connection-editor, and kept going until the network settings covered pretty much everything.

I just did a big rework of this PR today, see more in comments.

What it adds

  • A Connections page with every saved profile, grouped by type, to add, import, duplicate, export and forget them. Each network page links to it.
  • Profile types Settings doesn't edit (bond, bridge, VLAN, DSL, CDMA and others) are still listed there and open in nm-connection-editor or nmtui.
  • The hotspot gets its own page with security, band, channel, address and a QR code to join it. It only shows when an adapter can host one.
  • A Tailscale page for accounts, exit nodes and settings. Accounts can also be added on self-hosted servers like headscale.
  • Connectivity status and a button to log in to captive portals.
  • In the control center, VPN rows connect on click and get an Edit button, and Wi-Fi and Ethernet rows can open their profile in Settings.

Included bug fixes

  • The Wi-Fi settings page flickered on every background scan and rebuilt all its rows.
  • With two Wi-Fi adapters, saved networks could flip between in range and unavailable.
  • The control center's Wi-Fi device picker crowded the header, and its hotspot switch could be clicked while Wi-Fi was off.

Notes

  • While reworking it I removed editing for bond, bridge (and their port settings), VLAN, DSL and CDMA profiles, each in its own commit, so any of them can be brought back. This is because those options are outdated or not intended for Desktop use. I initially created them to cover all of NetworkManager, but this created unnecessary maintenance burden and translator work for options no one would ever use.
  • It adds about 100 new strings, mostly field labels in the editor.
  • Secrets are stored system-wide like today. feat(network): persist NM secrets to D-Bus Secret Service keyring #2970 covers keyring storage and I left it untouched here.
  • It raises the backend API version to 41, which settings: add firewall configuration page under network #4197 also takes, so whichever lands second needs a bump.

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that changes existing behavior)
  • Refactor / internal cleanup
  • Documentation
  • Other

Related issues

Closes #2964, closes #1461, closes #2403, closes #3940. Related to #2632 and #2965.

Partially fixes #4204: the control center part, where the VPN panel now opens the editor. The AnyConnect login failure is a separate problem.

Screenshots / video

screenshot_2026-11-08_22-52-06 screenshot_2026-11-08_23-34-23 screenshot_2026-11-08_23-34-30 screenshot_2026-11-08_23-34-49 screenshot_2026-11-08_23-35-04 screenshot_2026-11-08_23-35-20 screenshot_2026-11-08_23-35-25 screenshot_2026-11-08_23-35-35 screenshot_2026-11-08_23-35-39 screenshot_2026-11-08_23-35-44 screenshot_2026-11-08_23-35-47 screenshot_2026-11-08_23-36-16

Checklist

  • My code follows the conventions in CONTRIBUTING.md
  • I have tested my changes locally
  • New user-facing strings are wrapped in I18n.tr() with translator context, reusing existing terms where possible
  • Go changes: ran make fmt, added/updated tests, make test passes, and go mod tidy is clean
  • QML changes: ran make lint-qml with no new warnings
  • I have opened a corresponding pull request in dux-docs to document any new behaviors: docs(dms): document the NetworkManager connection editor dux-docs#160

Comment thread quickshell/Modals/WifiPasswordModal.qml Resolved
@Conava

Conava commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review, I will address all the requested changes tomorrow.

@apollo79

apollo79 commented Oct 9, 2026

Copy link
Copy Markdown
Member
669006018-efde8bb1-2dc3-444a-89a0-8ad51193f04a I would like to see it if this form got another pass in a similar way to other settings forms a few days ago. Right noe, it looks a bit cluttered and all over the place with different alignments for fields etc. 669005980-e05994e4-b65f-4f55-a227-6a7d83148240 I am not sure if these form fields are the correct ones. I have only seen fully rounded big ones for search and password input when it is the only field (like on the lock screen or for authentication. It is possible that this is what we have already but make sure it aliens with the rest of the shell. 669006231-542673e1-7067-4894-9654-306f60df70b0 Idea: make log out a seconday (tonal) button maybe. I think having one primary action is nicer here.

@Conava

Conava commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

@bbedward thanks for the review, all seven comments are addressed in the new commit:

  • every write path outside the editor saves to disk again
  • wired profiles per device survive the startup order
  • the Tailscale login page reopens on a second click
  • the enterprise connect prompt needs only username and password again, and gets focus on open
  • the "all users" note reads the profile's permissions
  • every new term has translator context

I also went over the whole PR once more and fixed a few things of the same kind: Enter moves through the enterprise form again, error toasts say what failed, and dropdowns go back to the real value after a rejected change.

Still open questoin: Should I make the Wi-Fi password prompt movable again (like the Polkit dialog)? It was switched from a floating window to a modal in #2651, which feels weird now that it can be a pretty big window.

@Conava

Conava commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

@apollo79 thanks for the design feedback, I'm looking into it. I'll fix what I can and then maybe raise a discussion in the dms-design channel, since frontend design isn't my greatest strength.

@purian23

Copy link
Copy Markdown
Member

@apollo79 thanks for the design feedback, I'm looking into it. I'll fix what I can and then maybe raise a discussion in the dms-design channel, since frontend design isn't my greatest strength.

No worries, just general guidelines that can be tweaked post PR.

@Conava

Conava commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

@apollo79 thanks again for the design pass, I went over the forms.

Changes:

  • The enterprise form is one column now. Every dropdown has its label on the left like Security, including Authentication and Inner authentication, and the Exact/Suffix choice got its own "Match type" row instead of sitting unlabeled next to the server field.
  • Switches, dropdowns and the warning text share one inset, and Advanced is a single card now, so nothing sits at its own indent anymore.
  • Every field in the form has an icon, so the certificate and cipher fields don't stand out.
  • Log out on the Tailscale page is a tonal button, so Add account is the only primary action there.
  • In the Settings connection editor the password fields were taller than the other text fields. They match now.

What I left as is:

  • The big rounded fields in the Wi-Fi prompt. They were set by BB recently on Oct 5 in commit b81373a, which moved the network prompts, polkit and the greeter to the expressive field, and the shake on a wrong password only exists on that field. So I made the rest of the form follow it. I did not want to override that decision without a good reason so I left it as is.
screenshot_2026-10-11_23-15-09 screenshot_2026-10-11_23-15-17 screenshot_2026-10-11_23-15-43 screenshot_2026-10-11_23-16-09

@apollo79

apollo79 commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Thank you @Conava for working on the design! It looks a lot better now.
I just want to make sure this is consistent with the rest of the shell / settings, so here is two similar pages that should be aligned or that this could use as inspiration:
dms_capture_1791754294776
The different here is that everything is contained and an item in the connected list. I actually think this exact page doesn't look good with the new higher fields and this
dms_capture_1791754338428
being the focused state. So maybe something can be done here.

What could be another inspiration is this kind of popup (also exists for window rules):
dms_capture_1791754366954
You can maybe take a look at these. The main difference is the contained list style as well here.

Another suggestion: Make the "Add account" (and log out) action a FAB like on other pages
dms_capture_1791754450215
This unifies it with the existing style and also takes away the empty space left of the buttons.

Last thing: It should not be possible for the popup to become bigger than the settings window. This is also a thing that current popups already do.

@Conava

Conava commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor Author

Alright I created 2 options here to make the popup smaller than the settings window, let me know which one you guys prefer.

Option 1: Scrollable popup:
screenshot_2026-10-12_19-40-57

Option 2: No more popups, everything as a settings window:
screenshot_2026-10-12_20-51-17

@georgestafilidis

Copy link
Copy Markdown
Contributor

I like the page more ngl

@apollo79

Copy link
Copy Markdown
Member

I am voting for the smaller popup since it aligns with what we already have in other parts of the settings like window rules etc and I am for standardization / unification.

@Conava

Conava commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

I also like the page a lot more, maybe the window rules need a change :)

@Conava

Conava commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

I went with option 2 (the settings page) and pushed it, since I like it a lot more. I do have the other version ready locally so if the maintainers disagree that a super quick change.

@apollo79

Copy link
Copy Markdown
Member

I went with option 2 (the settings page) and pushed it, since I like it a lot more. I do have the other version ready locally so if the maintainers disagree that a super quick change.

I have no problem with the page, would like some unification then though throughout the settings. Problem is that for very short forms it doesn't really make sense but for example the keybind / window rule forms are also quite long so it would fit there. And for short ones it is also not too bad probably.

@Conava

Conava commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

Yes thats a valid point.
When we have a decision for the page solution here I am also willing to work on the other settings windows next. I also think that for very short ones it should stay a popup, but for longer ones it feels wrong.

@apollo79

apollo79 commented Nov 2, 2026

Copy link
Copy Markdown
Member

I almost forgot about this one but it's a good one imo. @Conava I know you aren't available right now but we need to finalize this (except if the devs don't like it)

@Conava

Conava commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

I almost forgot about this one but it's a good one imo. @Conava I know you aren't available right now but we need to finalize this (except if the devs don't like it)

What do you think is needed to finalize here? The page vs popup would need a maintainer decision imo but apart from that I dont have any open todos in my notes regarding this PR.

@apollo79

apollo79 commented Nov 2, 2026

Copy link
Copy Markdown
Member

What do you think is needed to finalize here? The page vs popup would need a maintainer decision imo but apart from that I dont have any open todos in my notes regarding this PR.

I will need to clone this and take a look to give feedback on the UI. Then maybe another review from Claude / the maintainers and a decision if they want this and the subpage vs popup.

@Conava

Conava commented Nov 8, 2026

Copy link
Copy Markdown
Contributor Author

/claude review

@github-actions

github-actions Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Claude review

8 issues to fix. The PR also conflicts with master: the rebase must port 19f3e58 (OpenVPN challenge prompts, now in WifiConnectForm.qml) and fe133e0 (Tailscale localapi).

  • Stored 802.1X cert/key paths are re-read as new files on any edit, so root-only keys fail and readable ones turn into blobs, core/internal/server/network/enterprise.go:357
  • Hotspot address is always empty (the code expects the wrong D-Bus type), so saving the card wipes a custom subnet, core/internal/server/network/backend_networkmanager_hotspot.go:715
  • Ethernet disconnect reconnects right away on another autoconnect profile, core/internal/server/network/backend_networkmanager_ethernet.go:314
  • Bond option rows write on fill, so opening a bond marks it changed, quickshell/Modules/Settings/NetworkConnection/ConnectionBondSection.qml:260
  • API gate 38 is already met by master without these features, so APIVersion needs a bump, quickshell/Services/DMSNetworkService.qml:119
  • Cached Tailscale auth URL can be stale or belong to another login, quickshell/Services/TailscaleService.qml:252
  • Tailscale tab never notices operator permission granted from a terminal, quickshell/Modules/Settings/NetworkTailscaleTab.qml:59
  • Settings VPN list cannot cancel an activating VPN, quickshell/Modules/ControlCenter/Details/VpnProfileDelegate.qml:80

Checked: Go network editor, codec, enterprise, wifi/vpn/hotspot/ethernet backends, tailscale manager and handlers, the QML/Go socket protocol, QML services, ConnectionEditor.js, settings pages and dialogs, deprecated shims, raw views, generated mocks, i18n. Model: claude-opus-5-5.

@github-actions github-actions Bot added core Go daemon and CLI under core/ feature fix ui Quickshell UI under quickshell/ labels Nov 8, 2026
@github-actions

github-actions Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Claude review

3 new issues to fix. The earlier hotspot address comment still applies: hotspotAddressFromSettings still asserts []map[string]any. All other earlier findings are fixed.

  • The Connections page Disconnect still lets NM bring up another autoconnect wired profile, core/internal/server/network/backend_networkmanager_connections.go:351
  • Add account can open the previous account's pending login URL, core/internal/server/tailscale/handlers.go:256
  • The Tailscale Login button reuses the noun Login term with no context, quickshell/Modules/Settings/NetworkTailscaleTab.qml:456

Checked: Go editor codec, update and enterprise code, the NM wifi/vpn/hotspot/ethernet/priority/agent backends, Tailscale manager, handlers and operator, APIVersion and the QML gates, the Go/QML socket protocol, mocks, QML services, ConnectionEditor.js, settings pages and indices, Wi-Fi/enterprise forms, control center details, deprecated shims, raw views, i18n. Model: claude-opus-5-5.

@Conava

Conava commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor Author

@purian23 @bbedward I revisited this PR: merged master, fixed the issues Claude foundand went over a few decisions again.

My initial goal was parity with NetworkManager's GUI and TUI tools. I reconsidered that and removed the profile types that have little practical use on a graphical desktop or belong to technology that is largely obsolete:

  • bond
  • bridge
  • the port settings of bond and bridge
  • VLAN
  • DSL/PPPoE
  • CDMA

Profiles of those types still show up under Connections and offer to be opened in nm-connection-editor or nmtui instead of the Settings. Each removal is its own commit, so if you disagree with one of them it can be brought back. The PR is smaller for it, with less to maintain and less work for the translators.

Other changes since the last round:

  • The hotspot has its own page with all of its settings (security, hidden network, band, channel, address).
  • The control center VPN panel opens the editor instead of its old credentials panel, fixing the control center part of GUI Setting openconnect VPN doesn't save credentials correctly #4204, and its links to Settings when empty (Control Center: VPN Tab: Showing import text when list is empty but no button #3940). Wi-Fi and Ethernet rows can open their profile in Settings too.
  • Tailscale accounts can be added on self-hosted servers like headscale.
  • Profiles whose secrets are kept in another app, like the Proton VPN app, can be opened and saved without losing them.
  • A few smaller bugs on master are fixed along the way, mainly a flickering Wi-Fi settings page.

The PR description and screenshots have all been updated to reflect the newest version.

@apollo79 The UI also got some upgrades and improvements, so now you can use the most recent version if you still want to go over the UI.

@github-actions

github-actions Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Claude review

No issues found. The three findings from the last round are fixed: Connections page Disconnect now calls Device.Disconnect() for wired profiles, addProfile clears the pending auth URL before the prompt, and the Tailscale login button has its own verb term with context. The earlier hotspot address comment is left to the author's reply.
Checked: 9225309 (wired deactivate path and its test, Tailscale addProfile auth URL handling against the QML loginRequested flow, the new i18n term), on top of the earlier full-PR rounds. Model: claude-opus-5-5.

@Conava

Conava commented Nov 8, 2026

Copy link
Copy Markdown
Contributor Author

The one unresolved issue from last round (The hotspot address one) doesn't apply: gonetworkmanager's GetSettings() runs the result through decodeSettings, which turns []map[string]dbus.Variant into []map[string]interface{} and unwraps the values, so the assertion gets the type it expects. The test fixture uses that same type.
The other 3 are fixed.

@bbedward
bbedward force-pushed the network-manager-rework branch from 9225309 to 2e384b4 Compare November 14, 2026 16:50
@github-actions

github-actions Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Claude review

1 issue to fix. It comes from 2e384b4, which made plugin VPNs partial in the editor while this PR still hides their credentials panel. The PR description also still says plugin VPN, Bluetooth and cellular profiles can be created and edited in Settings.

  • Plugin VPN username/password can no longer be edited anywhere: the expand panel is hidden whenever the editor is supported, and the editor no longer has VPN sections, quickshell/Modules/ControlCenter/Details/VpnProfileDelegate.qml:116

Checked: 2e384b4 on top of the earlier full-PR rounds: the trimmed Go signature table against every key the remaining QML sections and new-profile templates write, agentOwnsSecret and its secret merge, the connectivity read moved into StartMonitoring, the canCreate removal, APIVersion 42 and the QML gates, section loading by URL with required properties, the EnterpriseConfig.js split and leftover callers of removed JS functions, control center and Settings VPN flows. Model: claude-opus-5-5.


DActionButton {
anchors.verticalCenter: parent.verticalCenter
visible: root.canExpand && !(root.showsEditButton && !root.isTransient)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Plugin VPNs (OpenVPN, OpenConnect, ...) can't have their credentials edited anywhere now. This hides the expand panel, which holds the username/password/save-credentials fields, whenever the editor is supported, in both the control center and the Settings VPN tab. But since 2e384b4 the editor treats vpn as partial: it only shows General and IP, plus "Open in …", and that row only appears if nm-connection-editor or nmtui is installed.

Example: an OpenVPN profile on master can save a username and password from the expand panel. On this branch, the row only shows Edit, and the editor has no credential fields.

Fix: show Edit instead of expand only for WireGuard, and keep the expand panel for the other VPN types.

Suggested change
visible: root.canExpand && !(root.showsEditButton && !root.isTransient)
visible: root.canExpand && !(root.showsEditButton && !root.isTransient && root.profile?.type === "wireguard")

(Do the same for the Edit button's visible at line 104, or show both buttons for plugin VPNs.)

@github-actions

github-actions Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Claude review

No issues found. The last finding is fixed: plugin VPNs keep their credentials panel, and only WireGuard profiles, which the editor fully covers, hide it in favor of Edit. Transient profiles keep the panel as before.
Checked: b50db71 (editorReplacesPanel against the type values Go sends, vpn or wireguard, both delegate hosts in the control center and Settings VPN tab, and the transient case), on top of the earlier full-PR rounds. Model: claude-opus-5-5.

@bbedward
bbedward merged commit ee191d7 into duxlabs-dev:master Nov 14, 2026
7 checks passed
@Conava
Conava deleted the network-manager-rework branch November 14, 2026 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Go daemon and CLI under core/ feature fix ui Quickshell UI under quickshell/

Projects

None yet

5 participants