headscale一键安装脚本

tomosak11个月前Linux683

ssh登录root账号

cd /home

nano /home/headscale.sh

输入以下内容

#!/bin/bash

plain='\033[0m'
red='\033[0;31m'
blue='\033[1;34m'
pink='\033[1;35m'
green='\033[0;32m'
yellow='\033[0;33m'

OS_ARCH=''

HOME_PATH='/etc/headscale'

DATA_PATH='/var/lib/headscale'

TEMP_PATH='/var/run/headscale'

BINARY_FILE_PATH='/usr/local/bin/headscale'

SERVICE_FILE_PATH='/etc/systemd/system/headscale.service'

declare -r STATUS_RUNNING=1
declare -r STATUS_NOT_RUNNING=0
declare -r STATUS_NOT_INSTALL=255

function LOGE() {
  echo -e "${red}[ERR] $* ${plain}"
}

function LOGI() {
  echo -e "${green}[INF] $* ${plain}"
}

function LOGD() {
  echo -e "${yellow}[DEG] $* ${plain}"
}

arch_check() {
  LOGI "检测当前系统架构中..."
  OS_ARCH=$(arch)
  LOGI "当前系统架构为 ${OS_ARCH}"
  if [[ ${OS_ARCH} == "x86_64" || ${OS_ARCH} == "x64" || ${OS_ARCH} == "amd64" ]]; then
    OS_ARCH="amd64"
  elif [[ ${OS_ARCH} == "aarch64" || ${OS_ARCH} == "arm64" ]]; then
    OS_ARCH="arm64"
  else
    OS_ARCH="amd64"
    LOGE "检测系统架构失败,使用默认架构: ${OS_ARCH}"
  fi
  LOGI "系统架构检测完毕,当前系统架构为:${OS_ARCH}"
}

create_or_delete_path() {
  if [[ $# -ne 1 ]]; then
    LOGE "invalid input,should be one paremete,and can be 0 or 1"
    exit 1
  fi
  if [[ "$1" == "1" ]]; then
    LOGI "Will create ${HOME_PATH} and ${DATA_PATH} and ${TEMP_PATH} for headscale..."
    rm -rf ${HOME_PATH} ${DATA_PATH} ${TEMP_PATH} /home/headscale
    mkdir -p ${HOME_PATH} ${DATA_PATH} ${TEMP_PATH} /home/headscale
    if [[ $? -ne 0 ]]; then
      LOGE "create ${HOME_PATH} and ${DATA_PATH} and ${TEMP_PATH} for headscale failed"
      exit 1
    else
      LOGI "create ${HOME_PATH} adn ${DATA_PATH} and ${TEMP_PATH} for headscale success"
    fi
  elif [[ "$1" == "0" ]]; then
    LOGI "Will delete ${HOME_PATH} and ${DATA_PATH} and ${TEMP_PATH}..."
    rm -rf ${HOME_PATH} ${DATA_PATH} ${TEMP_PATH} /home/headscale
    if [[ $? -ne 0 ]]; then
      LOGE "delete ${HOME_PATH} and ${DATA_PATH} and ${TEMP_PATH} failed"
      exit 1
    else
      LOGI "delete ${HOME_PATH} and ${DATA_PATH} and ${TEMP_PATH} success"
    fi
  fi
}

download_headscale() {
  LOGD "开始下载headscale..."
  arch_check

  local headscale_version_temp=$(curl -Ls "https://api.github.com/repos/juanfont/headscale/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
  headscale_version=${headscale_version_temp:1}

  LOGI "将选择使用版本:${headscale_version}"
  local DOWANLOAD_URL="https://github.com/juanfont/headscale/releases/download/${headscale_version_temp}/headscale_${headscale_version}_linux_${OS_ARCH}"

  create_or_delete_path 1
  wget --output-document=${BINARY_FILE_PATH} ${DOWANLOAD_URL}

  chmod +x ${BINARY_FILE_PATH}

  if [[ $? -ne 0 ]]; then
    LOGE "Download headscale failed,plz be sure that your network work properly and can access github"
    create_or_delete_path 0
    exit 1
  else
    LOGI "下载headscale成功"
  fi
}

install_service() {
  LOGD "开始安装headscale systemd服务..."
  if [ -f "${SERVICE_FILE_PATH}" ]; then
    rm -rf ${SERVICE_FILE_PATH}
  fi
  touch ${SERVICE_FILE_PATH}
  if [ $? -ne 0 ]; then
    LOGE "create service file failed,exit"
    exit 1
  else
    LOGI "create service file success..."
  fi
  cat >${SERVICE_FILE_PATH} <<EOF
[Unit]
Description=headscale controller
After=syslog.target
After=network.target
[Service]
Type=simple
User=headscale
Group=headscale
ExecStart=${BINARY_FILE_PATH} serve
Restart=on-failure
RestartSec=30s
RestartPreventExitStatus=23
LimitNPROC=10000
LimitNOFILE=1000000

NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=${DATA_PATH} ${TEMP_PATH}
AmbientCapabilities=CAP_NET_BIND_SERVICE
RuntimeDirectory=headscale

[Install]
WantedBy=multi-user.target
EOF
  chmod 644 ${SERVICE_FILE_PATH}
  systemctl daemon-reload
  LOGD "安装headscale systemd服务成功"
}

config_headscale() {
  touch ${DATA_PATH}/db.sqlite

  useradd headscale -d /home/headscale -m
  chown -R headscale:headscale ${DATA_PATH}

  touch ${HOME_PATH}/config.yaml
  if [ $? -ne 0 ]; then
    LOGE "create config.yaml file failed,exit"
    exit 1
  else
    LOGI "create config.yaml file success..."
  fi

  ip=`curl -sL -4 ip.sb`

  echo ""
  read -p " 请输入服务端口[100-65535的一个数字,默认8080]:" port
  [[ -z "${port}" ]] && port=8080
  if [[ "${port:0:1}" = "0" ]]; then
    LOGE "端口不能以0开头${plain}"
    exit 1
  fi
  LOGI " 服务地址为:http://${ip}:${port}"

  cat >${HOME_PATH}/config.yaml <<EOF
server_url: http://${ip}:${port}
listen_addr: 0.0.0.0:${port}
metrics_listen_addr: 127.0.0.1:9090

grpc_listen_addr: 0.0.0.0:50443
grpc_allow_insecure: false

private_key_path: ${DATA_PATH}/private.key
noise:
  private_key_path: ${DATA_PATH}/noise_private.key

ip_prefixes:
  - fd7a:115c:a1e0::/48
  - 10.10.0.0/16

derp:
  server:
    enabled: false
    region_id: 999
    region_code: "headscale"
    region_name: "Headscale Embedded DERP"
    stun_listen_addr: "0.0.0.0:3478"
  urls:
    - https://controlplane.tailscale.com/derpmap/default
  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: ${DATA_PATH}/db.sqlite

acme_url: https://acme-v02.api.letsencrypt.org/directory
acme_email: ""
tls_letsencrypt_hostname: ""
tls_client_auth_mode: relaxed
tls_letsencrypt_cache_dir: ${DATA_PATH}/cache
tls_letsencrypt_challenge_type: HTTP-01
tls_letsencrypt_listen: ":http"
tls_cert_path: ""
tls_key_path: ""

log:
  format: text
  level: info

acl_policy_path: ""

dns_config:
  override_local_dns: true
  nameservers:
    - 8.8.8.8
  domains: []
  magic_dns: false
  base_domain: example.com

unix_socket: ${TEMP_PATH}/headscale.sock
unix_socket_permission: "0770"

logtail:
  enabled: false

randomize_client_port: false
EOF
}

enable_headscale() {
  systemctl enable headscale
  if [[ $? == 0 ]]; then
    LOGI "设置headscale开机自启成功"
  else
    LOGE "设置headscale开机自启失败"
  fi
}

start_headscale() {
  if [ -f "${SERVICE_FILE_PATH}" ]; then
    systemctl start headscale
    sleep 1s
    status_check
    if [ $? == ${STATUS_NOT_RUNNING} ]; then
      LOGE "start headscale service failed,exit"
      exit 1
    elif [ $? == ${STATUS_RUNNING} ]; then
      LOGI "start headscale service success"
    fi
  else
    LOGE "${SERVICE_FILE_PATH} does not exist,can not start service"
    exit 1
  fi
}

restart_headscale() {
  if [ -f "${SERVICE_FILE_PATH}" ]; then
    systemctl restart headscale
    sleep 1s
    status_check
    if [ $? == 0 ]; then
      LOGE "restart headscale service failed,exit"
      exit 1
    elif [ $? == 1 ]; then
      LOGI "restart headscale service success"
    fi
  else
    LOGE "${SERVICE_FILE_PATH} does not exist,can not restart service"
    exit 1
  fi
}

stop_headscale() {
  LOGD "开始停止headscale服务..."
  status_check
  if [ $? == ${STATUS_NOT_INSTALL} ]; then
    LOGE "headscale did not install,can not stop it"
    exit 1
  elif [ $? == ${STATUS_NOT_RUNNING} ]; then
    LOGI "headscale already stoped,no need to stop it again"
    exit 1
  elif [ $? == ${STATUS_RUNNING} ]; then
    if ! systemctl stop headscale; then
      LOGE "stop headscale service failed,plz check logs"
      exit 1
    fi
  fi
  LOGD "停止headscale服务成功"
}

install_headscale() {
  LOGD "开始安装headscale..."
  if [[ $# -ne 0 ]]; then
    download_headscale $1
  else
    download_headscale
  fi

  config_headscale
  install_service

  enable_headscale && start_headscale
  headscale namespaces create default
  LOGI "安装headscale成功,已启动成功"
}

uninstall_headscale() {
  echo ""
  LOGD "开始卸载headscale..."
  pidOfheadscale=$(pidof headscale)
  if [ -n ${pidOfheadscale} ]; then
    stop_headscale
  fi

  create_or_delete_path 0 && rm -rf ${SERVICE_FILE_PATH} && rm -rf ${BINARY_FILE_PATH}
  userdel -r headscale
  groupdel headscale

  if [ $? -ne 0 ]; then
    LOGE "卸载headscale失败,请检查日志"
    exit 1
  else
    LOGI "卸载headscale成功"
  fi
}

register_node() {
  echo ""
  while true
  do
    read -p "请输入key:" key
    if [[ -z "${key}" ]]; then
      LOGE "输入错误,请重新输入!${plain}"
    else
      break
    fi
  done
  LOGI "输入的key为:$key"
  headscale -n default nodes register --key $key
  headscale nodes list
}

status_check() {
  if [[ ! -f "${SERVICE_FILE_PATH}" ]]; then
    return ${STATUS_NOT_INSTALL}
  fi
  temp=$(systemctl status headscale | grep Active | awk '{print $3}' | cut -d "(" -f2 | cut -d ")" -f1)
  if [[ x"${temp}" == x"running" ]]; then
    return ${STATUS_RUNNING}
  else
    return ${STATUS_NOT_RUNNING}
  fi
}

show_status() {
  status_check
  case $? in
  0)
    echo -e "[INF] headscale状态: ${yellow}未运行${plain}"
    ;;
  1)
    echo -e "[INF] headscale状态: ${green}已运行${plain}"
    ;;
  255)
    echo -e "[INF] headscale状态: ${red}未安装${plain}"
    ;;
  esac
}

show_menu() {
  echo -e "
  ${green}headscale管理脚本${plain}
  ${green}0.${plain} 退出脚本
  ${green}1.${plain} 安装服务
  ${green}2.${plain} 卸载服务
  ${green}3.${plain} 启动服务
  ${green}4.${plain} 停止服务
  ${green}5.${plain} 重启服务
  ${green}6.${plain} 查看节点
  ${green}7.${plain} 添加节点
 "
  show_status
  echo && read -p "请输入选择[0-7]:" num
  case "${num}" in
  0)
    exit 0
    ;;
  1)
    install_headscale && show_menu
    ;;
  2)
    uninstall_headscale && show_menu
    ;;
  3)
    start_headscale && show_menu
    ;;
  4)
    stop_headscale && show_menu
    ;;
  5)
    restart_headscale && show_menu
    ;;   
  6)
    headscale nodes list && show_menu
  ;;  
  7)
    register_node && show_menu
  ;; 
  *)
    LOGE "请输入正确的选项 [0-7]"
    ;;
  esac
}

start_to_run() {
  clear
  show_menu
}

start_to_run

chmod +x /home/headscale.sh

/home/.headscale.sh


如果开启 headscale 后网速慢的问题

config.yaml 修改 dns

dns_config:  # Whether to prefer using Headscale provided DNS or use local.
  override_local_dns: false

  # List of DNS servers to expose to clients.
  nameservers: 
     - 8.8.8.8



标签: headscale

相关文章

Windows连接headscale

1、导入Windows连接headscale需要的注册表,新建文本文件,拷贝下面代码,修改LoginURL,修改整个文件名为tailscale.reg,双击,导入Windows注册表Windows Registry Editor Version 5.00...

headscale常用命令

namespaceheadscale namespace list # 查看所有的namespace headscale namespace create default # 创建namespace hea...

群晖系统安装Tailscale客户端连接到HeadScale

群晖系统安装Tailscale客户端连接到HeadScale

群晖系统安装Tailscale客户端连接到HeadScaleTailscale客户端连接到HeadScale 群晖安装Tailscale套件后无需登录,ssh连接客户端群晖执行: http://你的公网IP或者域名:8181,这个按照实际端口映射情况修改,比如内网8181映射为18181,对外就...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。