Two nodes appear repeatedly #613

Closed
opened 2025-12-29 02:21:12 +01:00 by adam · 2 comments
Owner

Originally created by @flyzstu on GitHub (Jan 16, 2024).

Bug description

Recently I encountered a problem. I used docker-compose to set up headscale and tailscale, and used a reusable key to enable the built-in derp server. Every time the docker service is restarted, headscale gets a new tailscale node, which is not as expected. The expectation should be that the node should not change every time it is restarted.

Environment

  • OS: Linux Debian 12
  • Headscale version: 0.23.0-alpha2
  • Tailscale version: v1.56.1
  • Kernel version: 6.1.0-17-amd64
  • Headscale is behind a (reverse) proxy
  • Headscale runs in a container

To Reproduce

  1. docker-compose.yml
services:
  headscale:
    image: headscale/headscale:0.23.0-alpha2
    container_name: headscale
    hostname: headscale
    network_mode: host
    volumes:
      - ./headscale:/etc/headscale
    environment:
      - TZ=Asia/Shanghai   
    restart: always
    stop_grace_period: 2m
    command: headscale serve
  tailscale:
      hostname: tailscale
      container_name: tailscale
      image: tailscale/tailscale:v1.56.1
      environment:
        - TS_EXTRA_ARGS=--login-server=https:/domain:444 --accept-routes=false --accept-dns=false --advertise-routes=192.168.100.0/24 --authkey=token
        - TZ=Asia/Shanghai
      volumes:
        - /var/run/tailscale:/var/run/tailscale
        - ./tailscale:/var/lib
      devices:
        - /dev/net/tun:/dev/net/tun:rwm
      cap_add:
        - net_admin
        - sys_module
      restart: unless-stopped
      depends_on:
        headscale:
          condition: service_started
      networks:
        - default
networks:
  default:
    name: tailscale
    external: true
  1. my headscale config

server_url: https://domain:444
listen_addr: 0.0.0.0:444
metrics_listen_addr: 127.0.0.1:9090
grpc_listen_addr: 127.0.0.1:50443
grpc_allow_insecure: false
noise:
  private_key_path: /etc/headscale/noise_private.key
ip_prefixes:
  - 100.64.0.0/10
derp:
  server:
    enabled: true
    region_id: 999
    region_code: "headscale"
    region_name: "Headscale Embedded DERP"
    stun_listen_addr: "0.0.0.0:3478"
    private_key_path: /etc/headscale/private.key
  urls:
    # - https://controlplane.tailscale.com/derpmap/default
  # paths:
  #   - /etc/headscale/derp-example.yaml
  paths: []
  auto_update_enabled: true
  update_frequency: 24h
disable_check_updates: false
ephemeral_node_inactivity_timeout: 30m
node_update_check_interval: 10s
db_type: sqlite3
db_path: /etc/headscale/db.sqlite
acme_url: https://acme-v02.api.letsencrypt.org/directory
acme_email: ""

tls_letsencrypt_hostname: ""
tls_letsencrypt_challenge_type: HTTP-01
tls_letsencrypt_listen: ":http"
tls_cert_path: "/etc/headscale/fullchain.cer"
tls_key_path: "/etc/headscale/domain.key"
log:
  format: text
  level: info
acl_policy_path: ""
dns_config:
  override_local_dns: false

  nameservers:
    - 119.29.29.29

  domains: []
  magic_dns: false


  base_domain: arpa
unix_socket: /var/run/headscale/headscale.sock
unix_socket_permission: "0770"
logtail:
  # Enable logtail for this headscales clients.
  # As there is currently no support for overriding the log server in headscale, this is
  # disabled by default. Enabling this will make your clients send logs to Tailscale Inc.
  enabled: false

# Enabling this option makes devices prefer a random port for WireGuard traffic over the
# default static port 41641. This option is intended as a workaround for some buggy
# firewall devices. See https://tailscale.com/kb/1181/firewalls/ for more information.
randomize_client_port: true
  1. command:
headscale users c fly97
headscale pre create -u fly97 --reusable
# docker compose up -d
headscale node ls

image
when runs docker compose down and docker compose up; a new node will be in headscale:

# docker compose down; docker compose up -d
headscale node ls

image
Obviously the same node, but two nodes are created.
What should I do to avoid this?
I would be grateful for your reply!!

Originally created by @flyzstu on GitHub (Jan 16, 2024). <!-- Before posting a bug report, discuss the behaviour you are expecting with the Discord community to make sure that it is truly a bug. The issue tracker is not the place to ask for support or how to set up Headscale. Bug reports without the sufficient information will be closed. Headscale is a multinational community across the globe. Our language is English. All bug reports needs to be in English. --> ## Bug description <!-- A clear and concise description of what the bug is. Describe the expected bahavior and how it is currently different. If you are unsure if it is a bug, consider discussing it on our Discord server first. --> Recently I encountered a problem. I used docker-compose to set up headscale and tailscale, and used a reusable key to enable the built-in derp server. Every time the docker service is restarted, headscale gets a new tailscale node, which is not as expected. The expectation should be that the node should not change every time it is restarted. ## Environment <!-- Please add relevant information about your system. For example: - Version of headscale used - Version of tailscale client - OS (e.g. Linux, Mac, Cygwin, WSL, etc.) and version Linux - Kernel version - The relevant config parameters you used - Log output --> - OS: Linux Debian 12 - Headscale version: 0.23.0-alpha2 - Tailscale version: v1.56.1 - Kernel version: 6.1.0-17-amd64 <!-- We do not support running Headscale in a container nor behind a (reverse) proxy. If either of these are true for your environment, ask the community in Discord instead of filing a bug report. --> - [ ] Headscale is behind a (reverse) proxy - [x] Headscale runs in a container ## To Reproduce <!-- Steps to reproduce the behavior. --> 1. docker-compose.yml ```yml services: headscale: image: headscale/headscale:0.23.0-alpha2 container_name: headscale hostname: headscale network_mode: host volumes: - ./headscale:/etc/headscale environment: - TZ=Asia/Shanghai restart: always stop_grace_period: 2m command: headscale serve tailscale: hostname: tailscale container_name: tailscale image: tailscale/tailscale:v1.56.1 environment: - TS_EXTRA_ARGS=--login-server=https:/domain:444 --accept-routes=false --accept-dns=false --advertise-routes=192.168.100.0/24 --authkey=token - TZ=Asia/Shanghai volumes: - /var/run/tailscale:/var/run/tailscale - ./tailscale:/var/lib devices: - /dev/net/tun:/dev/net/tun:rwm cap_add: - net_admin - sys_module restart: unless-stopped depends_on: headscale: condition: service_started networks: - default networks: default: name: tailscale external: true ``` 2. my headscale config ```yml server_url: https://domain:444 listen_addr: 0.0.0.0:444 metrics_listen_addr: 127.0.0.1:9090 grpc_listen_addr: 127.0.0.1:50443 grpc_allow_insecure: false noise: private_key_path: /etc/headscale/noise_private.key ip_prefixes: - 100.64.0.0/10 derp: server: enabled: true region_id: 999 region_code: "headscale" region_name: "Headscale Embedded DERP" stun_listen_addr: "0.0.0.0:3478" private_key_path: /etc/headscale/private.key urls: # - https://controlplane.tailscale.com/derpmap/default # paths: # - /etc/headscale/derp-example.yaml paths: [] auto_update_enabled: true update_frequency: 24h disable_check_updates: false ephemeral_node_inactivity_timeout: 30m node_update_check_interval: 10s db_type: sqlite3 db_path: /etc/headscale/db.sqlite acme_url: https://acme-v02.api.letsencrypt.org/directory acme_email: "" tls_letsencrypt_hostname: "" tls_letsencrypt_challenge_type: HTTP-01 tls_letsencrypt_listen: ":http" tls_cert_path: "/etc/headscale/fullchain.cer" tls_key_path: "/etc/headscale/domain.key" log: format: text level: info acl_policy_path: "" dns_config: override_local_dns: false nameservers: - 119.29.29.29 domains: [] magic_dns: false base_domain: arpa unix_socket: /var/run/headscale/headscale.sock unix_socket_permission: "0770" logtail: # Enable logtail for this headscales clients. # As there is currently no support for overriding the log server in headscale, this is # disabled by default. Enabling this will make your clients send logs to Tailscale Inc. enabled: false # Enabling this option makes devices prefer a random port for WireGuard traffic over the # default static port 41641. This option is intended as a workaround for some buggy # firewall devices. See https://tailscale.com/kb/1181/firewalls/ for more information. randomize_client_port: true ``` 3. command: ```bash headscale users c fly97 headscale pre create -u fly97 --reusable # docker compose up -d headscale node ls ``` ![image](https://github.com/juanfont/headscale/assets/94161727/c78c59d4-0a9c-4234-9094-bf6c48cf14e6) when runs docker compose down and docker compose up; a new node will be in headscale: ```bash # docker compose down; docker compose up -d headscale node ls ``` ![image](https://github.com/juanfont/headscale/assets/94161727/e2388baa-b486-43a7-9063-72cc5cc0c02b) Obviously the same node, but two nodes are created. What should I do to avoid this? I would be grateful for your reply!!
adam added the bug label 2025-12-29 02:21:12 +01:00
adam closed this issue 2025-12-29 02:21:12 +01:00
Author
Owner

@lcuwx2016 commented on GitHub (Jan 16, 2024):

The reason may be the variable of TS_STATE_DIR is not set in docker-compose.yml.
image

@lcuwx2016 commented on GitHub (Jan 16, 2024): The reason may be the variable of **TS_STATE_DIR is not set** in docker-compose.yml. ![image](https://github.com/juanfont/headscale/assets/31233561/fba2debe-3681-498d-8149-834ed6bf480f)
Author
Owner

@flyzstu commented on GitHub (Jan 16, 2024):

The reason may be the variable of TS_STATE_DIR is not set in docker-compose.yml. image

Thanks for your help, this problem was successfully solved! This reminds me that I need to develop good documentation reading habits. Case Closed.

@flyzstu commented on GitHub (Jan 16, 2024): > The reason may be the variable of **TS_STATE_DIR is not set** in docker-compose.yml. ![image](https://private-user-images.githubusercontent.com/31233561/296957609-fba2debe-3681-498d-8149-834ed6bf480f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MDUzODg1OTksIm5iZiI6MTcwNTM4ODI5OSwicGF0aCI6Ii8zMTIzMzU2MS8yOTY5NTc2MDktZmJhMmRlYmUtMzY4MS00OThkLTgxNDktODM0ZWQ2YmY0ODBmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDAxMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwMTE2VDA2NTgxOVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTY4MmFmMTRjZDk5NjU3YTY4Yjk0MDU5ZTM4MTJhYzQ1N2Q4MzU0YzQxZDMzNDhmODVkZWY1MjJmMWM2YTgwNzUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.22m-7tpab-uEC2ZSUJvUv8Z-av-cvB90EZLASHpNrVc) Thanks for your help, this problem was successfully solved! This reminds me that I need to develop good documentation reading habits. Case Closed.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/headscale#613