DEV Community

Cason Adams
Cason Adams

Posted on • Edited on

Edge Router X | OpenWRT | Tailscale

Tailscale is an awesome opensource project. It leverages WireGuard to create a light weight VPN like connection.

I am using an EdgeRouter X with OpenWRT on it. This router is using a mipsle chipset.

Getting started

Build from source below or download the static bin file from builds

Clone the tailscale repo

git clone https://github.com/tailscale/tailscale.git

Build the mipsle binaries

Other options

GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -o tailscale tailscale.com/cmd/tailscale 
Enter fullscreen mode Exit fullscreen mode
GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -o tailscaled tailscale.com/cmd/tailscaled 
Enter fullscreen mode Exit fullscreen mode

Copy binaries to /usr/sbin/

scp <bins> root@<router-ip>:/usr/sbin/

Install deps

opkg update opkg install ca-bundle kmod-tun 
Enter fullscreen mode Exit fullscreen mode

Create /etc/init.d/tailscaled

NOTE line /usr/sbin/tailscale up is commented out remove comment after logging in manually

#!/bin/sh /etc/rc.common ### BEGIN INIT INFO # Provides: tailscaled # Description: tailscaled daemon service ### END INIT INFO USE_PROCD=1 # starts after network starts START=21 # stops before networking stops STOP=89 PROG=/usr/sbin/tailscaled start_service() { echo "starting tailscaled" procd_open_instance procd_set_param env SERVICE_RUN_MODE=1 procd_set_param command $PROG -state /etc/tailscale/tailscaled.state procd_set_param pidfile /var/run/tailscaled.pid procd_set_param stdout 1 procd_set_param stderr 1 procd_set_param respawn procd_close_instance # /usr/sbin/tailscale up } service_triggers() { procd_add_reload_trigger "tailscaled" } 
Enter fullscreen mode Exit fullscreen mode

Make the file executable

chmod +x /etc/init.d/tailscaled 
Enter fullscreen mode Exit fullscreen mode

Test service

/etc/init.d/tailscaled start
/usr/sbin/tailscale up

This should prompt with a url. Use this to authorize the device. If everything is good. Remove the comment in the /etc/init.d/tailscaled (tailscale up)

Enable service

/etc/init.d/tailscaled enable

Reboot

reboot
Verify things are working

Top comments (7)

Collapse
 
ichangemymind profile image
iChangeMyMind

I'm using:

Model: Xiaomi Redmi Router AC2100 Architecture: MediaTek MT7621 ver:1 eco:3 Firmware Version: OpenWrt SNAPSHOT r15976-8078d89a53 / LuCI Master git-21.050.34860-b8d2bcd Kernel Version: 5.4.100 
Enter fullscreen mode Exit fullscreen mode

and for the tailscale I downloaded from pkgs.tailscale.com/unstable/#static

I copied your procd script and after I chmod +x and run it I got this error

root@OpenWrt:~# /etc/init.d/tailscaled start ': No such file or directory.common 
Enter fullscreen mode Exit fullscreen mode

when I run tailscaled alone without using the procd it works but when I run it using procd I got that error again

how do I fix this?

Collapse
 
casonadams profile image
Cason Adams

What do your other service scripts look like that in, that /etc/init.d/ dir?

Maybe taking the first line from one of them and replace the first line in this script will correct the issue you are seeing?

Collapse
 
ichangemymind profile image
iChangeMyMind

here the inside of cron looks like:

#!/bin/sh /etc/rc.common # Copyright (C) 2006-2011 OpenWrt.org START=50 USE_PROCD=1 PROG=/usr/sbin/crond validate_cron_section() { uci_validate_section system system "${1}" \ 'cronloglevel:uinteger' } start_service() { [ -z "$(ls /etc/crontabs/)" ] && return 1 loglevel="$(uci_get "system.@system[0].cronloglevel")" [ -z "${loglevel}" ] || { /sbin/validate_data uinteger "${loglevel}" 2>/dev/null [ "$?" -eq 0 ] || { echo "validation failed" return 1 } } mkdir -p /var/spool/cron ln -s /etc/crontabs /var/spool/cron/ 2>/dev/null procd_open_instance procd_set_param command "$PROG" -f -c /etc/crontabs -l "${loglevel:-5}" for crontab in /etc/crontabs/*; do procd_set_param file "$crontab" done procd_set_param respawn procd_close_instance } service_triggers() { procd_add_validation validate_cron_section } 
Enter fullscreen mode Exit fullscreen mode

here the inside of boot looks like:

#!/bin/sh /etc/rc.common # Copyright (C) 2006-2011 OpenWrt.org START=10 STOP=90 uci_apply_defaults() { . /lib/functions/system.sh cd /etc/uci-defaults || return 0 files="$(ls)" [ -z "$files" ] && return 0 mkdir -p /tmp/.uci for file in $files; do ( . "./$(basename $file)" ) && rm -f "$file" done uci commit } boot() { [ -f /proc/mounts ] || /sbin/mount_root [ -f /proc/jffs2_bbc ] && echo "S" > /proc/jffs2_bbc mkdir -p /var/run mkdir -p /var/log mkdir -p /var/lock mkdir -p /var/state mkdir -p /var/tmp mkdir -p /tmp/.uci chmod 0700 /tmp/.uci touch /var/log/wtmp touch /var/log/lastlog mkdir -p /tmp/resolv.conf.d touch /tmp/resolv.conf.d/resolv.conf.auto ln -sf /tmp/resolv.conf.d/resolv.conf.auto /tmp/resolv.conf grep -q debugfs /proc/filesystems && /bin/mount -o noatime -t debugfs debugfs /sys/kernel/debug grep -q bpf /proc/filesystems && /bin/mount -o nosuid,nodev,noexec,noatime,mode=0700 -t bpf bpffs /sys/fs/bpf grep -q pstore /proc/filesystems && /bin/mount -o noatime -t pstore pstore /sys/fs/pstore [ "$FAILSAFE" = "true" ] && touch /tmp/.failsafe /sbin/kmodloader [ ! -f /etc/config/wireless ] && { # compat for bcm47xx and mvebu sleep 1 } /bin/config_generate uci_apply_defaults # temporary hack until configd exists /sbin/reload_config } 
Enter fullscreen mode Exit fullscreen mode

and here the inside of zerotier (installed using opkg) looks like:

#!/bin/sh /etc/rc.common START=90 USE_PROCD=1 PROG=/usr/bin/zerotier-one CONFIG_PATH=/var/lib/zerotier-one section_enabled() { config_get_bool enabled "$1" 'enabled' 0 [ $enabled -ne 0 ] } start_instance() { local cfg="$1" local port secret config_path local_conf path local args="" if ! section_enabled "$cfg"; then echo "disabled in config" return 1 fi config_get config_path $cfg 'config_path' config_get port $cfg 'port' config_get secret $cfg 'secret' config_get local_conf $cfg 'local_conf' path=${CONFIG_PATH}_$cfg # Remove existing link or folder rm -rf $path # Create link from CONFIG_PATH to config_path if [ -n "$config_path" -a "$config_path" != "$path" ]; then if [ ! -d "$config_path" ]; then echo "ZeroTier config_path does not exist: $config_path" 1>&2 return fi # ensure that the symlink target exists mkdir -p $(dirname $path) ln -s $config_path $path fi mkdir -p $path/networks.d # link latest default config path to latest config path rm -f $CONFIG_PATH ln -s $path $CONFIG_PATH if [ -n "$port" ]; then args="$args -p${port}" fi if [ -z "$secret" ]; then echo "Generate secret - please wait..." local sf="/tmp/zt.$cfg.secret" zerotier-idtool generate "$sf" > /dev/null [ $? -ne 0 ] && return 1 secret="$(cat $sf)" rm "$sf" uci set zerotier.$cfg.secret="$secret" uci commit zerotier fi if [ -n "$secret" ]; then echo "$secret" > $path/identity.secret # make sure there is not previous identity.public rm -f $path/identity.public fi if [ -f "$local_conf" ]; then ln -s "$local_conf" $path/local.conf fi add_join() { # an (empty) config file will cause ZT to join a network touch $path/networks.d/$1.conf } config_list_foreach $cfg 'join' add_join procd_open_instance procd_set_param command $PROG $args $path procd_set_param stderr 1 procd_close_instance } start_service() { config_load 'zerotier' config_foreach start_instance 'zerotier' } stop_instance() { local cfg="$1" # Remove existing link or folder rm -rf ${CONFIG_PATH}_${cfg} } stop_service() { config_load 'zerotier' config_foreach stop_instance 'zerotier' rm -f ${CONFIG_PATH} } 
Enter fullscreen mode Exit fullscreen mode

Everything looks similar to me? :/

Thread Thread
 
casonadams profile image
Cason Adams

any luck on this one?

Thread Thread
 
ichangemymind profile image
iChangeMyMind

Nope, I'm going back to zerotier The speed drawback is not that bad for my workflow anyway ¯_(ツ)_/¯

Thread Thread
 
casonadams profile image
Cason Adams

I am on an older kernel

Linux OpenWrt 4.14.209 #0 SMP Sun Dec 6 07:31:03 2020 mips GNU/Linux 
Enter fullscreen mode Exit fullscreen mode

so maybe there are some diffs. Tailscale is worth the pain to figure it out.

Collapse
 
casonadams profile image
Cason Adams

Thanks for the link to the unstable static bins! Saves a few steps!