GoodiesHQ/headscale-admin

Refuses to accept API key

Opened this issue · 7 comments

Unable to authenticate API. I have a reverse proxy on a public IP handling Tailscale client traffic to a headscale server. This all works. I put the same URL (same as server_url in headscale config.yaml) https://xxxx.xxxx.com.au into the API URL field with an API Key but it does not accept it.

As I'm only testing I am running the docker container:

root@headscale:~# docker run -p 8000:80 goodieshq/headscale-admin:latest

Think I am having the same issue. Traefik v3 using docker compose for headscale and admin.


services:
  headscale:
    image: headscale/headscale:0.23.0-rc.1
    restart: unless-stopped
    container_name: headscale
    ports:
      - "8081:8080"
      - "9090:9090"
    volumes:
      - /home/ccigas/headscale/conf:/etc/headscale
    command: serve
    networks:
      - proxy
    labels:
      traefik.enable: "true"
      traefik.docker.network: "proxy"
      # Configure service and router
      traefik.http.services.headscale.loadbalancer.server.port: 8081
      traefik.http.services.headscale.loadbalancer.server.scheme: http-external
      traefik.http.routers.headscale.rule: Host(`tailscale.xxxxx.cc`)
      traefik.http.routers.headscale.entrypoints: https-external
      traefik.http.routers.headscale.tls.certresolver: cloudflare
      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: "Authorization,Content-Type,*"
      traefik.http.middlewares.headscale-cors.headers.accesscontrolalloworiginlist: "https://headscale.xxxxx.cc"  # 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: 3478

    headscale-admin:
      image: goodieshq/headscale-admin:latest
      container_name: headscale-admin
      restart: unless-stopped
      networks:
        - proxy
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.headscaleadmin.rule=Host(`headscale.xxxxx.cc`)"
        - "traefik.http.services.headscaleadmin.loadbalancer.server.port=80"
        - "traefik.http.routers.headscaleadmin-internal.rule=Host(`headscale.xxxxx.cc`) && PathPrefix(`/admin`)"
        - "traefik.http.routers.headscaleadmin-internal.entrypoints=http"
        - "traefik.http.routers.headscaleadmin-internal.middlewares=headscaleadmin-internal-https-redirect"
        - "traefik.http.middlewares.headscaleadmin-internal-https-redirect.redirectscheme.scheme=https"
        - "traefik.http.routers.headscaleadmin-internal-secure.rule=Host(`headscale.xxxxx.cc`)"
        - "traefik.http.routers.headscaleadmin-internal-secure.entrypoints=https"
        - "traefik.http.routers.headscaleadmin-internal-secure.tls=true"
        - "traefik.http.routers.headscaleadmin-internal-secure.service=headscaleadmin"
        - "traefik.docker.network=proxy"```

Just getting internal server error on this, error code 500. I have the legacy api unchecked. 

I think i have the same issue.
I tried it and all the docker contianers runing OK but when i click on save button on page „../admin/settings/“ i get error on caddy log:
error“:“reading: read tcp 172.18.0.2:37362->172.18.0.4:8080: read: connection reset by peer
and nothing saved and cant get to other pages of headscale-admin.
I also tried it with traefik and got the same error on treafik logs. I think this is caused by access rights between containers. But i don't know how i would solve it.

I'm running into similar issues, not sure how to debug. In an effort to get it working I ensure the containers networking used host directly and still no dice.

I believe the issue has been resolved in the dev branch by assembling the API URL in a different way. Please let me know if you still have issues and I will review the configuration. Use the :dev tag on docker.

I've tried the dev branch. the error is unfortunately still here. I'm sending the log from caddy and the contents of docker-compose. i hope this helps. maybe there is a bug in my setup.
caddy error:

{
  "level": "error",
  "ts": 1737138570.6733387,
  "logger": "http.handlers.reverse_proxy",
  "msg": "reading from backend",
  "error": "read tcp 172.18.0.2:44672->172.18.0.4:8080: read: connection reset by peer"
}
{
  "level": "error",
  "ts": 1737138570.6735127,
  "logger": "http.handlers.reverse_proxy",
  "msg": "aborting with incomplete response",
  "upstream": "172.18.0.4:8080",
  "duration": 0.000451265,
  "request": {
    "remote_ip": "104.28.205.169",
    "remote_port": "54541",
    "client_ip": "104.28.205.169",
    "proto": "HTTP/2.0",
    "method": "OPTIONS",
    "host": "gwt.domain.eu",
    "uri": "/api/v1/apikey",
    "headers": {
      "Sec-Gpc": [
        "1"
      ],
      "Accept-Encoding": [
        "gzip, deflate, br, zstd"
      ],
      "X-Forwarded-For": [
        "104.28.205.169"
      ],
      "Access-Control-Request-Headers": [
        "authorization"
      ],
      "Te": [
        "trailers"
      ],
      "User-Agent": [
        "Mozilla/5.0 (X11; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0"
      ],
      "Priority": [
        "u=4"
      ],
      "Sec-Fetch-Dest": [
        "empty"
      ],
      "Origin": [
        "https://gwta.domain.eu"
      ],
      "Dnt": [
        "1"
      ],
      "Accept": [
        "*/*"
      ],
      "Accept-Language": [
        "sk,cs;q=0.8,en-US;q=0.5,en;q=0.3"
      ],
      "X-Forwarded-Host": [
        "gwt.domain.eu"
      ],
      "Sec-Fetch-Mode": [
        "cors"
      ],
      "Referer": [
        "https://gwta.domain.eu/"
      ],
      "Sec-Fetch-Site": [
        "same-site"
      ],
      "Access-Control-Request-Method": [
        "GET"
      ],
      "X-Forwarded-Proto": [
        "https"
      ]
    },
    "tls": {
      "resumed": false,
      "version": 772,
      "cipher_suite": 4865,
      "proto": "h2",
      "server_name": "gwt.domain.eu"
    }
  },
  "error": "reading: read tcp 172.18.0.2:44672->172.18.0.4:8080: read: connection reset by peer"
}

docker compose:

services:
  headscale:
    container_name: headscale
    image: headscale/headscale:stable
    restart: unless-stopped
    environment:
      - TZ=Europe/Budapest
    volumes:
      - ./container-config:/etc/headscale
      - ./container-data:/var/lib/headscale
    entrypoint: headscale serve
    networks:
      - caddy
    labels:
      caddy: gwt.domain.eu
      caddy.reverse_proxy: "{{upstreams 8080}}"

  headscale-admin:
    image: goodieshq/headscale-admin:dev
    container_name: headscale-admin
    restart: unless-stopped
    networks:
      - caddy
    labels:
      caddy: gwta.domain.eu
      caddy.handle_path: "/admin/*"
      caddy.handle_path.0_rewrite: "* /admin{uri}"
      caddy.handle_path.1_reverse_proxy: "{{upstreams http 80}}"
      

networks:
  caddy:
    external: true

and for caddy docker:

services:
  caddy:
    container_name: caddy
    image: lucaslorentz/caddy-docker-proxy:ci-alpine
    ports:
      - 80:80
      - 443:443
    environment:
      - CADDY_INGRESS_NETWORKS=caddy
    networks:
      - caddy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./caddy_data:/data
      - ./caddy_config:/config
    restart: unless-stopped

networks:
  caddy:
    external: true

volumes:
  caddy_data: {}
  caddy_config: {}

Thanks.

I had this issue and I did a few things that fixed it:

  1. put headscale and headscale-admin on the same subdomain, with headscale-admin being using a pathprefix (hs.ex.com and hs.ex.com/admin)
  2. the listen to address in my headscale config was set to 127.0.0.1:8080 and needed to be set to 0.0.0.0:8080
  3. Because both services were being served (via traefik) on the same subdomain, I was able to scrap all the CORS stuff
zilexa commented

@Nortonko I also use caddy-docker-proxy and considering to switch to Headscale (currently using Wireguard and Wireguard-UI). I'd be very interested if you got this working via caddy-docker-proxy..