Install tailscale on IPFire?

When I follow the instructions at tailscale.com for performing a linux install, their script doesn’t recognize IPFire’s linux. While a Pakfire install would be most preferable, I’d be willing to interface with tailscale support to at least try to get IPFire support added to their script – but I’ll need to know a few more specifics on what exactly to tell them.

# curl -fsSL https://tailscale.com/install.sh | sh
Couldn't determine what kind of Linux is running.
You could try the static binaries at:
https://pkgs.tailscale.com/stable/#static

If you'd like us to support your system better, please email support@tailscale.com
and tell us what OS you're running.

Please include the following information we gathered from your system:

OS=other-linux
VERSION=
PACKAGETYPE=
UNAME=Linux ipfire.brazoslink.net 6.1.45-ipfire #1 SMP PREEMPT_DYNAMIC Tue Aug 15 21:32:54 GMT 2023 x86_64 Intel(R) Celeron(R) CPU J1900 @ 1.99GHz GenuineIntel GNU/Linux

NAME="IPFire"
VERSION="2.27"
ID=ipfire
VERSION_ID=2
PRETTY_NAME="IPFire 2.27 (x86_64) - core180"
ANSI_COLOR="0:31"
[root@ipfire ~]#

FWIW I want to configure tailscale in order to get past MetroNet’s CGNAT.

Wireguard currently is not part of IPFire. Personally doubt that without wireguard support IpFire could be a suitable environment for Tailscale.

However: personal opinion only.

2 Likes

Yeah, looks like that’s indeed the case. Insufficient due diligence on my part before trying to set it up in the first place. I’ll have to either use OpenVPN to do a site-to-site, or just use Anydesk to remote control a box inside that network.

I may necrobump, but this is actually the first topic coming in search so I wanted to share how I managed to setup tailscale manually based on qnap package (I think)
pkgs.tailscale.com/stable/#static

cd /root
#download
wget https://pkgs.tailscale.com/stable/tailscale_1.78.1_amd64.tgz
#extract
tar xvf tailscale_1.78.1_amd64.tgz
#rename for simplicity
mv tailscale_1.78.1_amd64 tailscale
cd tailscale
ln -s /root/tailscale/tailscaled /usr/sbin/tailscaled

create unit

vim /etc/init.d/tailscale

#!/bin/sh 
 
SERVICE_NAME="tailscale" 
PID_FILE="/var/run/tailscale/tailscaled.pid" 
LOG_FILE="/var/run/tailscale/tailscaled.log" 
STATE_FILE="/var/run/tailscale/tailscaled.state" 
SOCKET_FILE="/var/run/tailscale/tailscaled.sock" 
PORT="41641" 
 
SERVICE_COMMAND="/usr/sbin/tailscaled \ 
--state=${STATE_FILE} \ 
--socket=${SOCKET_FILE} \ 
--port=$PORT" 
 
start_daemon() { 
    local ts=$(date --iso-8601=second) 
    echo "${ts} Starting ${SERVICE_NAME} with: ${SERVICE_COMMAND}" >>${LOG_FILE} 
    ${SERVICE_COMMAND} >>${LOG_FILE} 2>&1 & 
    if [ -n "${PID_FILE}" ]; then 
        echo "$!" >"${PID_FILE}" 
    else 
        wait_for_status 0 
    fi 
} 
 
stop_daemon() { 
    if [ -n "${PID_FILE}" -a -r "${PID_FILE}" ]; then 
        local PID=$(cat "${PID_FILE}") 
        local ts=$(date --iso-8601=second) 
        echo "${ts} Stopping ${SERVICE_NAME} service PID=${PID}" >>${LOG_FILE} 
        kill -TERM $PID >>${LOG_FILE} 2>&1 
        wait_for_status 1 || kill -KILL $PID >>${LOG_FILE} 2>&1 
        if [ -f "${PID_FILE}" ]; then 
            rm -f "${PID_FILE}" >/dev/null 
        fi 
    fi 
} 
 
daemon_status() { 
    if [ -n "${PID_FILE}" -a -r "${PID_FILE}" ]; then 
        if kill -0 $(cat "${PID_FILE}") >/dev/null 2>&1; then 
            return 
        fi 
        rm -f "${PID_FILE}" >/dev/null 
    fi 
    return 1 
} 
 
wait_for_status() { 
    # 20 tries 
    # sleeps for 1 second after each try 
    local counter=20 
    while [ ${counter} -gt 0 ]; do 
        daemon_status 
        [ $? -eq $1 ] && return 
        counter=$((counter - 1)) 
        sleep 1 
    done 
    return 1 
} 
 
ensure_tun_created() { 
    # Create the necessary file structure for /dev/net/tun 
    if ([ ! -c /dev/net/tun ]); then 
        if ([ ! -d /dev/net ]); then 
            mkdir -m 755 /dev/net 
        fi 
        mknod /dev/net/tun c 10 200 
        chmod 0755 /dev/net/tun 
    fi 
 
    # Load the tun module if not already loaded 
    if (!(lsmod | grep -q "^tun\s")); then 
        insmod /lib/modules/tun.ko 
    fi 
} 
 
case $1 in 
start) 
    if daemon_status; then 
        echo "${SERVICE_NAME} is already running" 
        exit 0 
    else 
        echo "Starting ${SERVICE_NAME} ..." 
        ensure_tun_created 
        start_daemon 
        exit $? 
    fi 
    ;; 
stop) 
    if daemon_status; then 
        echo "Stopping ${SERVICE_NAME} ..." 
        stop_daemon 
        exit $? 
    else 
        echo "${SERVICE_NAME} is not running" 
        exit 0 
    fi 
    ;; 
status) 
    if daemon_status; then 
        echo "${SERVICE_NAME} is running" 
        exit 0 
    else 
        echo "${SERVICE_NAME} is not running" 
        exit 3 
    fi 
    ;; 
log) 
    exit 0 
    ;; 
*) 
    echo "command $1 is not implemented" 
    exit 0 
    ;; 
esac

start unit

/etc/init.d/tailscale start

authenticate

./root/tailscale/tailscale

It works, but I had to do a bit of tweaking.

  1. I have changed insmod /lib/modules/tun.ko to modprobe tun
  2. Removed backslashes from SERVICE_COMMAND and put it in one line.

:slight_smile: :+1:

along with those changes i change tailscales log location to/var/log/tailscale and had to do mkdir before starting

[root@diamond ~]# mkdir /var/run/tailscale
[root@diamond ~]# mkdir /var/log/tailscale
2025-02-13T13:35:45-06:00 Starting tailscale with: /usr/sbin/tailscaled --state=/var/run/tailscale/tailscaled.state --socket=/var/run/tailscale/tailscaled.sock --port=41641
2025/02/13 13:35:45 logtail started
2025/02/13 13:35:45 Program starting: v1.80.0-t4f4686503-gccb3ce01b, Go 1.23.5: []string{"/usr/sbin/tailscaled", "--state=/var/run/tailscale/tailscaled.state", "--socket=/var/run/tailscale/tailscaled.sock", "--port=41641"}
2025/02/13 13:35:45 LogID: 5890928039ddec10643ad7f5e9f8152ded88a74ba1ac915c2a0461520f4c73ed
2025/02/13 13:35:45 logpolicy: using system state directory "/var/lib/tailscale"
logpolicy.ConfigFromFile /var/lib/tailscale/tailscaled.log.conf: open /var/lib/tailscale/tailscaled.log.conf: no such file or directory
logpolicy.Config.Validate for /var/lib/tailscale/tailscaled.log.conf: config is nil
2025/02/13 13:35:45 dns: [rc=unknown ret=direct]
2025/02/13 13:35:45 dns: using "direct" mode
2025/02/13 13:35:45 dns: using *dns.directManager
2025/02/13 13:35:45 dns: inotify addwatch: context canceled
2025/02/13 13:35:46 wgengine.NewUserspaceEngine(tun "tailscale0") ...
2025/02/13 13:35:46 dns: [rc=unknown ret=direct]
2025/02/13 13:35:46 dns: using "direct" mode
2025/02/13 13:35:46 dns: using *dns.directManager
2025/02/13 13:35:46 link state: interfaces.State{defaultRoute=red0 ifs={green0:[192.168.4.1/24] red0:[12.118.x.x/30]} v4=true v6=false}
2025/02/13 13:35:46 onPortUpdate(port=41641, network=udp6)
2025/02/13 13:35:46 router: using firewall mode pref 
2025/02/13 13:35:46 router: default choosing iptables
2025/02/13 13:35:46 router: disabling tunneled IPv6 due to system IPv6 config: disable_ipv6 is set
2025/02/13 13:35:46 onPortUpdate(port=41641, network=udp4)
2025/02/13 13:35:46 magicsock: disco key = d:680444b652eccc9f
2025/02/13 13:35:46 Creating WireGuard device...
2025/02/13 13:35:46 Bringing WireGuard device up...
2025/02/13 13:35:46 Bringing router up...
2025/02/13 13:35:46 external route: up
2025/02/13 13:35:46 Clearing router settings...
2025/02/13 13:35:46 Starting network monitor...
2025/02/13 13:35:46 Engine created.
2025/02/13 13:35:46 pm: migrating "_daemon" profile to new format
2025/02/13 13:35:46 logpolicy: using system state directory "/var/lib/tailscale"
2025/02/13 13:35:46 got LocalBackend in 12ms
2025/02/13 13:35:46 Start
2025/02/13 13:35:46 Backend: logs: be:5890928039ddec10643ad7f5e9f8152ded88a74ba1ac915c2a0461520f4c73ed fe:
2025/02/13 13:35:46 Switching ipn state NoState -> NeedsLogin (WantRunning=false, nm=false)
2025/02/13 13:35:46 blockEngineUpdates(true)
2025/02/13 13:35:46 health(warnable=wantrunning-false): error: Tailscale is stopped.
2025/02/13 13:35:46 wgengine: Reconfig: configuring userspace WireGuard config (with 0/0 peers)
2025/02/13 13:35:46 wgengine: Reconfig: configuring router
2025/02/13 13:35:46 wgengine: Reconfig: configuring DNS
2025/02/13 13:35:46 dns: Set: {DefaultResolvers:[] Routes:{} SearchDomains:[] Hosts:0}
2025/02/13 13:35:46 dns: Resolvercfg: {Routes:{} Hosts:0 LocalDomains:[]}
2025/02/13 13:35:46 dns: OScfg: {}

cant seem to ssh into the firewall through it but it does run and connect to the service

The latest IPfire (196) supports WireGuard. How difficult is it to connect IPfire to TailScale network in 2025?

Is there any support in WebGUI for TailScale?

What about IPfire running on ARM platform, like RPI? Is it possible to add TailScale?

Any alternative to tailscale, like headscale, firezone, netbird, netmaker?

YT video comparing several VPN overlay networks

Important point from the YT video is that TailScale does’t have open source coordination server but there is open source server HeadScale…

1 Like

Hi all! I successfully installed and configured Tailscale using the instructions in this topic. Thank you Maciej Klimas, Tomek for the step by step guide.

I’m sorry for the noob question, but how to enable Tailscale as service so it starts automatically at boot time?

For the information of those reading this thread.

WireGuard has been available since IPFire version 2.29 – Core Update 195.

Regards

Yeah, sure. I knew it when I posted. My problem is that I’m behind a CGNAT and the modem my ISP provided me can’t operate in bridge mode. My actual setup has a DMZ in modem pointing to my IPFire box Red IP.

I can connect with Tailscale despite this unusual and definitely not ideal setup but can’t with WireGuard.

My network knowledge is very limited, despite my love for the area, but by what I’ve read, to use WireGuard I need a VPS, correctly?

And this is why I tried using Tailscale and posted here (just to clarify for anyone who may be reading this thread).

Anyway, thanks for your reply!

1 Like

You don’t need to configure WireGuard on IPFire when using Tailscale. From my own - limited - testing I see that Tailscale already uses WireGuard internally and handles NAT traversal itself, so it works even behind CGNAT. IPFire won’t ‘see’ the Tailscale network unless you intentionally set up subnet routing.