headscale
headscale copied to clipboard
Any WEB UI planned?
Hi there,
First, very nice project 😊 Testing it right now and works rock solid.
Do you have any planned to integrate a Web UI like the Tailscale one?
I guess for that TLS would need to be enforce, but I guess this is doable. The WebUI can talk to the backend API and automatically register new nodes one the user is logged in.
I think this would be very handy and provide an experience really close to what Tailscale is doing 😊
The UI itself should be fairly quick to create, it's more the interaction with the backend that could be challenging I guess.
Let me know what's your plan.
Kr.
We are currently adding a HTTP API, so making this will become possible within a couple of releases.
That said I dont have any concrete plans to add a web ui other than "down the line".
My priorities are driven by my need and I might work on Terraform provider first. Of course if someone would be willing to sponsor the feature, then the priorities could shift.
We are currently adding an HTTP API, so making this will become possible within a couple of releases.
That said I don't have any concrete plans to add a web UI other than "down the line".
My priorities are driven by my need and I might work on Terraform provider first. Of course, if someone would be willing to sponsor the feature, then the priorities could shift.
I’m a Flutter(Android, iOS, Web) developer in my company (actually I’m because of funds and economy of the company a FullStack (the only) developer in a microservices backend and an event-driven mobile app 🤣). I'll be happy to sponsor this feature. If the UI is made in Flutter it can take less than a week (and can be exported as a Windows/macOS app), if prefer a proper web framework can take a little longer because of MVC and management of components.
@fdelucchijr we would appreciate help. I have some concerns with using Flutter, which is mainly that it would mean that the current maintainers would have to learn a new language (Dart) and Flutter as a framework.
But I am happy to have a chat and be convinced :)
Other than that I would probably opt for Elm + TailwindCSS as that is what I know. I assume using something like Typescript + Vue would make it accessible for contributors.
@kradalby I have been thinking about this since I wrote the previous message. Flutter Web is good for web apps, but I feel that for the classic control panel it doesn't make much sense, Is some sort of overpowered. At some point, I will make a control panel with flutter just to be able to control the headscale server from my cell phone or without exposing the WebGUI (LoL 🤣).
Elm looks super interesting! I would love to learn it, but it is true that with typescript there would be more flexibility for contributors. Tailwind I think is a very good option, in combination with Vue it can be perfect to make maintenance and development easiest possible.
The following steps should understand which usecases should go into the screens, and make a mockup of the layout. (At this point we don't need to choose a language yet, nor the complete API, just understand what the webpage should cover)
Is the conversation on this topic ok here? or is it preferred by a special chat?
What about just having a Web UI completely decoupled from the server? That way anyone who wants to have different UIs can develop them or use them on their own, being in Flutter, Elm or Vue.
Sounds good, but I think would make a lot more variable the development and if theres no "oficial" web gui gonna come up a lot of unmantained or incompatible versions of the same panel.
@kradalby Say is in development an api. I think with proper docs should be enough for anybody to make a external webgui, and adding a bool parameter to deactivate the internal is more like a'cherry on top (for my idea of a Flutter mobile app this would be awesome).
Obviously this isn't my choice, as implies a handful of definitions in the complete project approach.
Deploy a headscale container with all the components and other with just the server with a companion container for the webgui is something interesting for k8s, tho.
The API might be available as beta and "subject to change" in the version after next. It will support OpenAPI so client code can be generated.
The API will open for anyone to make a WebUI, so @cgrs, feel free :)
I would assume that at some point we might include one, and having a collected effort might make more sense.
Also having everything in the same binary would be neat and easy to ship around.
Might be an unpopular opinion, or .. not..
... but, how about not making a web APP at all... and instead, just having the server render some simple html with current status to start with, ... and then maybe adding a few endpoints that can take form submissions to change things down the line.
By this I mean, how about just using go templates for showing a mix of current config and state, and having a few blue links and buttons scattered around to do some common things and move around, ... and relying on simple re-rendering of a page for any complicated UX transitions.
... how it looks can be prettied up well enough with some basic CSS, ... and you could even do things like show/hide and tabs using CSS, ... if that's where things go (spoiler, radio-buttons are mutually exclusive like tabs and can be made to look like so).
Reason I'm leaning toward this solution (over any of the javascript/typescript/wasm + framework-du-jour), is because I think:
a) majority of tailscale (by proxy headscale) users, myself included, would probably appreciate simplicity in their stack b) we'd end up not fragmenting or burdening end users with different UIs that are a potential source of confusion / analysis-paralysis during adoption phase, and a potential support / maintenance burden or a distraction down the road. c) requires very little no additional dependencies or toolchain changes d) requires very little to no additional cognitive load to maintain / build / run .. and extend with new features, as they appear on the back end.
None of that would be necessarily exclusive to having a well thought out API as well ... but having the info laid out in a browser would be a bit more friendly to casual users (folks who don't manage VPNs for a living or as part of their critical role at a company or similar).
Security wise, beyond basic TLS, we'd probably be mostly good with just some basic cryptographic xsrf tokens stuffed in form fields and some explicit http headers (CSP, x-frame-options, that kind of stuff).... not sure how we'd think about identity in the web ui in the first place ... oauth?
development process wise - a good start would be to expose just the read-only status somehow safely, before allowing state mutations through the webui.
I'm just a weekend code (w)hacker but am a Tailscale (UI/coordinator) user, and my 2p go to a decoupled UI as a simple but modern web gui (precompiled js please). How about something based on Svelte (or Svelte Kit) which is succinct and easy to grok for new developers? Then you smart lot can concentrate on the API and coordinator itself.
I suggest using some straightforward decoupled React +Tailwind UI. It is very popular and it is easier to recruit contributors :)
@kradalby, sorry because of my hiatus, the holidays have been a mess. There's news on the API progress? I've already made a Figma board and started a mood board of different self-hosted solutions to make a wireframe of the UI.
Seen that there's still a debate on how to implement the WebUI at a technical level, I will stick to the conceptual level for now. Probably will drop the Figma board here when I have some of the modules ready.
I will maintain my opinion in a Tailwind-Vue combo, and really don't care much about the coupling in the server-client, but I really think there's a need for a Headscale officially maintained WebUI that at least show the state of the service and allow the admin to configure some settings (the more the better). This will expand the project as the best self-hosted VPN solution for regular users out there.
The Tailscale gui for iOS and android is built using gio
i used to use flutter and changed to gio because it’s golang and you don’t get road blocked for doing low level aspects as much as you do with flutter.
We could quite quickly build the web , task tray, desktop and mobile clients using gio I feel .
also because it’s golang it makes it easier because the frontend and backend are all in golang so the same team can work on both.
we can base on
https://github.com/tailscale/tailscale-android
they use https://github.com/tailscale/walk to build their windows desktop gui.
At the time gio was not mature enough for windows compile targets. That’s maybe why they did not use it. It definitely is now.
Gio uses the standard golang build tags to include OS specific golang code .
i have GRPC and GRPC-web working between a gio frontend and go backend too. It just uses a slight fork of the improbable GRPC lib to use a slightly different web socket lib that works with WASM ( which is what gio web builds as ).
using GRPC makes forward engineering happen and supports schema evolution so that if the API on the server changes the clients will not break at runtime . Use buf to manage GRPC and we are good !!
@fdelucchijr I have not been working on this for a bit, had a break so no news atm. I can see myself starting to play around with headscale in a bit, but not yet.
As for my opinion/decision towards WebUI:
I have decided that if I will work on it, be involved and do possibly a good batch of the work, I will write it in Elm + TailwindCSS (or something like F#/Fable).
The reasoning for this is that I am doing this project for fun, and if I am to enjoy doing this, I cannot use JavaScript/Typescript/Vue/React as I do not find it fun to work with. I do enjoy working with Elm.
I do not intend to mandate that the project is done in Elm, this is mostly to make it clear that if I start it, or am to contribute, that will be the language. If anyone feel strongly about choosing more mainstream tech, that is fine, but then they better start working on it before I get to it and uphold a good enough quality (whatever-that-means).
I have no timeline for when I will consider diving into this as I don't personally need a WebUI for headscale.
As for other implementation details, I think for a WebUI to be viable, it must be embedded in the binary and served without any extra setup. Luckily Go is reasonably good at this.
Is there an HTTP API planned? If there was one I'd make a webui.
Is there a link to the Figma screens ?
would be great to have a look at it
@endigma HTTP API already introduced (see #204).
@endigma HTTP API already introduced (see #204).
docs for routes/payloads anywhere?
docs for routes/payloads anywhere?
May by here: https://github.com/juanfont/headscale/tree/main/gen/openapiv2/headscale/v1
Cool, I'm probably gonna make a webui then. will post updates when there's something to look at.
Also could be useful: https://github.com/juanfont/headscale/blob/73497382b7002050b85f6e919f2fc6b9616b4c80/app.go#L415-L434
This is the relevant part: https://github.com/juanfont/headscale/issues/234#L433.
Before we set of in multiple different directions, what is your idea of what you would like to achieve with the UI @endigma ?
@kradalby
My plan is to re-implement what's in the official tailscale UI likely with Svelte/Tailwind or Pico. If the limitation is in endpoints I'd likely yield feature wise until they are completed. I don't have the time to really dig into learning the whole headscale codebase, but I can handle a front-end.
ok, just be aware, the API is not stable, and we will change it a fair amount in the upcoming releases.
0.13.0-beta3 is the first release with the API available. But we already have plans to change it quite a bit based on #311.
It supports OpenAPI v2, so if you are planning to contribute it, find a code generator for the API so we get in all the consistency :)
I'll look into code generation, may be able to use swagger to generate a stub client.
Sounds about right, OpenAPI is what swagger was renamed into. Feel free to reach out to me on Discord if you want to discuss something.
@kradalby
My plan is to re-implement what's in the official tailscale UI likely with Svelte/Tailwind or Pico. If the limitation is in endpoints I'd likely yield feature wise until they are completed. I don't have the time to really dig into learning the whole headscale codebase, but I can handle a front-end.
If you start a repo prease add me. Or if you gonna add a PR, mention me, I will happily help you. I have had a complete JS to TS migration in the past 2 weeks but in the following time I will be fully able to help. I think my project in Figma gonna be saved until there's a usable UI so we can design with peace of mind and usage experience. In the past few days, I add some ideas such as Netmaker's node view to the management screen.
Actually, before we set out in many different directions, can we please take a step back and write up a proposal on design and requirements so we don't do double work and ensure it is maintainable?
A bit like #311
@endigma @fdelucchijr
@fdelucchijr @kradalby
I'm happy to tackle this solo as a separate project but if you want to be a part of it you can find my contact info on my website. Reach out and we can discuss working as a team.
One thing that's set in stone is it's definitely not going to be part of this repo, merging a full ts/js/svelte project into an existing go repo sounds like a nightmare.
I'm also in the discord under @endigma4426
if you don't have telegram.
Following up on this to see if there's been any movement from anyone involved
Following up on this to see if there's been any movement from anyone involved
A sveltekit/tailwind based web UI is now available, can be found here.
Barring anyone else coming up with their own implementation, what needs to be asked now is the appetite to integrate (or not integrate) this web UI into headscale itself. Here's some considerations that need to be thought out before charging ahead:
(Programming) Language Considerations
There's a bit of talk in this whole thread about sticking to minimal raw HTML/CSS, which I initially tried with alpinejs and htmx. This concept was abandoned, as I (like most people) learned the hard way why all the popular frameworks are compiled javascript languages. Basic things like type checking (typescript), modular css (postcss), and scope management is nearly impossible in vanilla javascript, and makes any serious project quickly become spaghetti.
So the web ui is a mix of svelte-kit (framework), tailwind/daisyui (css) and typescript, compiled down to static html/js/css. This is a good middle ground with low dependencies and meeting the core requirement (being able to be hosted statically). Speaking of which:
Integration with Headscale
Right now it's a bit tricky to use the UI, as it needs to be hosted separately, and CORS needs injection if the hosting isn't on the same subdomain. The CORS issue is fixable, but anything further will depend on the headscale maintainer's appetite to integrate a separate project. So I can see three options with integration:
- No Integration at all
- Just keeping it separate, the way it is. Makes it harder to host, but that way the two projects aren't interdependent on eachother. Being able to configure CORS (in the headscale 17.0 roadmap) will ease the pain here a bit, but it will still be too much of a hassle for the average person to figure out.
- Dynamic Integration
- Have the headscale server be configurable to automatically host a "web" folder located in the same location as the binary. This is a good middle ground, the only additional requirement for installation being the need to extract the site to the same location as headscale. The site is entirely static and client driven so there's no particular permissions to worry about (well aside from a bad party messing with the files, but an intruder with that access has already pwned the environment).
- Full Integration
- Embed the site into headscale's binary. This is by far the best experience for end users (no additional configuration required), but also the most intrusive to maintain. It would also mean headscale would have to package the site's builds with headscale directly.
Authentication
The current system saves an API key to the browser local storage, which isn't ideal, but works. Doing so can potentially be exploited by XSS, but XSS protections are in place with CSP enabled on build. It's a good enough solution, but eventually it would be nice if headscale could be an OIDC relying party for the site, same way it works with tailscale. How this will work with the app is something I haven't investigated and will probably need cooperation with the headscale maintainers if it's a wanted feature.
ACL management
ACL Management is a hard concept to gui-fy, but it's on my immediate radar. The big stopping block is that there is no way to update ACLs via the API, which will be required for this feature to exist. I can start some of that work, but it'll be a big task to manage.
Source code management
There were rumblings about putting the web source into the same repo, which I wouldn't necessarily recommend. If it was all static HTML/CSS/JS, that would be a strong possibility, but not for anything compiled. However if the headscale maintainers want to fork it, I can potentially move development off my own repo.
Thoughts? Many of these considerations need the headscale folks to be on board for implementation, so it's a question of how much they want to get tied to using this UI (if at all).
Now that the API is clearly in a workable state I may take a proper stab at my own UI, not to stomp on the one routerino made though, just my own take.
I'm working professionally with SK/TW now which means I'll probably ironically take the approach routerino abandoned and try low-JS-ing it using some serverside work.
May never go anywhere but I'll post here when/if there's anything to see.
I like the idea of a headscale UI for those that need to use a UI to configuration the server. However, it should be separated from the headscale server itself. The server works, and many users dont need or want the extra bloat of a UI they arent going to use.
Additionally, if the built UI artefacts are loaded from a directory, why bundle that into another service? Host the files with a service designed to do that. Something like an nginx container receiving proxy connections for the UI route (i.e /ui/
).
I like the idea of a headscale UI for those that need to use a UI to configuration the server. However, it should be separated from the headscale server itself. The server works, and many users dont need or want the extra bloat of a UI they arent going to use.
Additionally, if the built UI artefacts are loaded from a directory, why bundle that into another service? Host the files with a service designed to do that. Something like an nginx container receiving proxy connections for the UI route (i.e
/ui/
).
Just to be clear 'bloat' is a very subjective term here. The site is 60kb large when compressed and does not use any server resources beyond the download when requested.
I like the idea of a headscale UI for those that need to use a UI to configuration the server. However, it should be separated from the headscale server itself. The server works, and many users dont need or want the extra bloat of a UI they arent going to use.
id argue the reason all these wg abstractions are popular is because of the ux and user friendly interfaces. otherwise we would all still be doing it from the cli.
My plan for this would be "Full integration", this means that the UI is bundled with the binary, so it is all shipped together. If you dont want it, there can be a flag to disable it.
However, I do not want it to be presented with the UX we currently have for API keys etc, so it would be a fair amount of backend changes to allow for both or:
- Authentication with Tailscale (something like their Nginx auth, but built in)
- Leveraging the OpenID Connect implementation.
This will be fully transparent for the users and provide a smooth user experience. In addition, it would open for machines in the "correct" namespace/user to have only access to their own stuff etc.
I do not have a specific plan on how to achieve this yet, and it will require quite a bit of work, some sort of ACL for user/api access.