Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/GoodiesHQ/headscale-admin
Admin Web Interface for juanfont/headscale
https://github.com/GoodiesHQ/headscale-admin
Last synced: 2 months ago
JSON representation
Admin Web Interface for juanfont/headscale
- Host: GitHub
- URL: https://github.com/GoodiesHQ/headscale-admin
- Owner: GoodiesHQ
- License: gpl-3.0
- Created: 2023-12-03T21:18:08.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-07-03T07:15:59.000Z (7 months ago)
- Last Synced: 2024-08-01T16:43:47.456Z (6 months ago)
- Language: Svelte
- Size: 532 KB
- Stars: 360
- Watchers: 11
- Forks: 24
- Open Issues: 12
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-repositories - GoodiesHQ/headscale-admin - Admin Web Interface for juanfont/headscale (Svelte)
README
# headscale-admin
Headscale-Admin is meant to be a simple, modern web interface for [juanfont/headscale](https://github.com/juanfont/headscale) - *"An open source, self-hosted implementation of the Tailscale control server."*
Headscale-Admin should currently be considered a beta application. It is very much still in active development and should not be treated as a final product, but when used properly, it should be safe to run in a production environment.
[![Star History Chart](https://api.star-history.com/svg?repos=goodieshq/headscale-admin&type=Timeline&size=mobile)](https://star-history.com/#goodieshq/headscale-admin&Timeline)
### Known Issues
- In headscale 0.23.0-alpha5, tags cannot be fully removed. [This is a bug #1849 in headscale](https://github.com/juanfont/headscale/issues/1849).
### Building
Headscale-Admin was built using [skeleton](https://github.com/skeletonlabs/skeleton) framework on top of SvelteKit + TailwindCSS. It uses svelte/adapter-static to produce only static files when built. They can be hosted on nearly any server or environment.
#### Endpoint
**Note:** If you are building Headscale-Admin from source and want to host it on an endpoint other than the base of the domain, e.g. "myheadscale.com/admin" then you must set the `ENDPOINT` environment variable when building. Otherwise, it will default to expecting to be hosted on the root path "myheadscale.com/" and redirects and resource loading will not work correctly if you place them in a child folder. Once built, it is recommended to rename the `build` directory to the same name as your `$ENDPOINT` variable so the requests can follow the folder structure and not have to be stripped or rewritten by a front end proxy. The provided Dockerfile shows this in practice.##### Clone the repository
Clone a specific version without code history
```
git clone --depth 1 --branch https://github.com/GoodiesHQ/headscale-admin
```Alternatively, you can just clone the main branch for the latest release or `git checkout ` for a specific version.
```
git clone https://github.com/GoodiesHQ/headscale-admin
```#### Set your ENDPOINT
If something other than the default '/' is desired, then set your `ENDPOINT` environment variable. The docker container uses the "/admin" endpoint by default, so that is what is shown in the examples.
Bash:
```
export ENDPOINT="/admin"
```Cmd.exe:
```
set ENDPOINT=/admin
```PowerShell:
```
$env:ENDPOINT=/admin
```#### Build
You can create the production build by running:
```
npm run build
```
This will create a `build` directory.#### Host Files
It is recommended that you replicate your path structure after the ENDPOINT you provided. If you used `/admin`, then rename the `build` directory as `admin` and place that directory in the root of your hosting. If you are hosting it on the root path (no `ENDPOINT` variable provided), then you can place the contents of the `build` directory directly into the root path.
### Build with Docker
The recommended way to deploy is by using docker. Pre-built images are provided and always use the `/admin` endpoint by default. If you want to build an image for a different endpoint, use build args.
```
# Using default /admin
docker build . -t headscale-admin
``````
# Use the root path
docker build . -t headscale-admin --build-arg ENDPOINT=
``````
# Using non-default /manager
docker build . -t headscale-admin --build-arg ENDPOINT=/manager
```Then run. The image uses port 80 for hosting HTTP and it is expected that a front end proxy service will perform SSL certificate management.
```
docker run -p 8000:80 headscale-admin
```#### Run With Docker
You can also use a pre-built image:
```
docker run -p 8000:80 goodieshq/headscale-admin:latest
```#### Docker Compose
It is common to want to host both headscale and headscale-admin in the same docker compose configuration. My recommended method is to use Traefik which I have been running in front of headscale with no issues. This is an example deployment using Traefik.
Assumptions:
- Host is running at `tailscale.example.com`
- Your SSL cert resolver is called `myresolver`
- Traefik connects to a backend network called `proxy`
- You are in the America/Los_Angeles time zone
- A local directory called 'conf' contains your headscale 'config.yaml'
- You are using SQLite for the headscale database.For larger deployments, it is recommended to use PostgreSQL. This can be done by:
- Adding a Postgres service to the docker-compose.yml file
- Created a non-external network called "backend"
- Assign the postgres service to "backend" network only
- Assign the headscale service to both "proxy" and "backend" networks to allow it to be reachable over the internet and also to reach the database without exposing the database to the public proxy network.
- Setting the Postgres settings in your config.yaml file```
version: "3.9"services:
headscale:
image: headscale/headscale:latest
container_name: headscale
restart: unless-stopped
environment:
- TZ=America/Los_Angeles
volumes:
- ./conf:/etc/headscale
- headscale-data:/var/lib/headscale
entrypoint: headscale serve
networks:
- proxy
labels:
traefik.enable: "true"
traefik.docker.network: "proxy"
# Configure service and router
traefik.http.services.headscale.loadbalancer.server.port: 8080
traefik.http.services.headscale.loadbalancer.server.scheme: http
traefik.http.routers.headscale.rule: Host(`tailscale.example.com`)
traefik.http.routers.headscale.entrypoints: websecure
traefik.http.routers.headscale.tls.certresolver: myresolver
traefik.http.routers.headscale.service: headscale
# Configure CORS middleware if needed
traefik.http.middlewares.headscale-cors.headers.accesscontrolallowmethods: "GET,POST,PUT,PATCH,DELETE,OPTIONS"
traefik.http.middlewares.headscale-cors.headers.accesscontrolallowheaders: "*"
traefik.http.middlewares.headscale-cors.headers.accesscontrolalloworiginlist: "" # Add other origins if needed
traefik.http.middlewares.headscale-cors.headers.accesscontrolmaxage: 100
traefik.http.middlewares.headscale-cors.headers.addvaryheader: true
traefik.http.routers.headscale.middlewares: headscale-cors
# UDP ports for DERP, etc
traefik.udp.services.headscale-udp-41641.loadbalancer.server.port: 41641
traefik.udp.services.headscale-udp-3478.loadbalancer.server.port: 3478headscale-admin:
image: goodieshq/headscale-admin:latest
container_name: headscale-admin
restart: unless-stopped
networks:
- proxy
labels:
traefik.enable: "true"
traefik.docker.network: "proxy"
traefik.http.services.headscale-admin.loadbalancer.server.port: 80
traefik.http.services.headscale-admin.loadbalancer.server.scheme: http
traefik.http.routers.headscale-admin.rule: Host(`headscale.example.com`) && PathPrefix(`/admin`)
traefik.http.routers.headscale-admin.entrypoints: websecure
traefik.http.routers.headscale-admin.tls.certresolver: myresolvernetworks:
proxy:
external: truevolumes:
headscale-data:
```To set up this environment, you need to have a Traefik configuration:
Create an external network called `proxy`. Anything on this network, even if it is in a different docker-compose.yml file, will be able to be reached by Traefik and can therefore be reached over the Internet based on your Traefik labels.
```
docker network create proxy
```You may need to play with your settings to get the right domain and SSL support working for you. This example uses cloudflare API and requires a `./env/cloudflare.env` (relative to docker-compose.yml) file to contain something like:
```
[email protected]
CF_API_KEY=0011223344556677889900aabbccddeeff000
```where the CF_API_KEY is your Global API key from your Cloudflare domain dashboard:
The Traefik docker-compose.yml:
```
version: "3.9"services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
command:
- "--api.insecure=true"
- "--log.level=DEBUG"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.dnschallenge=true"
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.myresolver.acme.email=myemail@example.com"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
- "--serverstransport.insecureskipverify=true"
env_file:
- ./env/cloudflare.env
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
networks:
- proxy
labels:
traefik.enable: "true"
traefik.docker.network: "proxy"
traefik.http.routers.traefik.tls.certresolver: myresolver
traefik.http.routers.traefik.rule: Host(`traefik.example.com`)
traefik.http.routers.traefik.middlewares: hsts-header
traefik.http.routers.traefik.service: api@internal
#
traefik.http.middlewares.hsts-header.headers.customResponseHeaders.Strict-Transport-Security: "max-age=63072000"networks:
proxy:
external: truevolumes:
letsencrypt: {}
```### Creating an API Key
Your first API key must be created using the `headscale` CLI.
Natively:
```
headscale apikey create
```Docker (running with container name "headscale"):
```
docker exec headscale headscale apikey create
```### Home Page
A brief overview of the HeadScale environment with the number of users, nodes, and routes.
### Users Page
An overview of all headscale Users with a List or Tile layout.
- Create, Rename, and Delete Users
- Create, View, and Expire PreAuth Keys
- List User's Nodes with Online Indicators### Nodes Page
An overview of all headscale Nodes with a List or Tile layout.
- Create and Delete Nodes
- Enable/Disable Advertised Routes
- Expire a Node### Deploy Page
A web utility to craft a "tailscale up" command when deploying new nodes.
### Settings Page
Store API URL and API Key information in the browser's LocalStorage. Set API refresh interval (how frequently users, preauth keys, nodes, and routes are updated). Use the legact headscale `/machines` API endpoint instead of `/nodes`. Enable/Disable console debugging (may get noisy).