Create Surfshark wireguard connection on OpenWrt easily

Should I just use your forked script here :

That would seem to just add the snippet as it is found natively in your script

I found your issue here

Thanks for all your help

Yes, you can do that. The credit goes to @yazdan though.

You will still need the cron entries as well.

Thanks - my man - I appreciate your modesty - and yes @yazdan deserves the credit for being the founder and innovator - like Henry Ford - but we have to give Elon Musk - some credit for Tesla as well
Moreover, I want to thank you greatly for your patience, kindness - and tutelage in assisting me in order to get this up and running.
God Bless You and Your Friends and Family -

Thank you one more again

Getting this error in your fork and when I add snippet to @yazdan script

parse error: Invalid numeric literal at line 1, column 42

cat | head -n20

I am going to do a fresh OpenWRT install hnyman Build for Netgear R7800
maybe I mucked up everything on this router

Q1 - Should I use @yazdan script for initial install / and then replace @yazdan script with yours for
automated cron job ?

I ask because I have never had issue with @yazdan script - this is why I will do fresh install.
Anyway - thanks for all your assistance

This is an error from jq that parses your config.json. So there is a misconfiguration of your config.json following the change to your full path to the script.

I diff’d the repo and my local copy that runs here and they are identical.

There is no need to re-flash.

Post the cd command that gets you to your


What do you use as an editor? vi, nano, a windows editor.

I would strongly suggest using “nano” to edit config files.

If you count characters including spaces from the start of your config.json you’ll see the point at which jq parse fails.

parse error: Invalid numeric literal at line 1, column 42

I suggest you copy the config.json.sample from the repo and use nano to re-edit it.

1 Like

Dear RuralRoots,
I did as you suggested - thanks for that I got your fork's to run / install properly
using this command ./ - I got

Loggin in if needed ...
Getting the list of servers ...
Selecting servers ...
Generating keys ...
Checking pubkey ...
Unauthorized. Please run again

running - ./ -f everything completed successfully

Loggin in if needed ...
Getting the list of servers ...
servers list already exist
Selecting servers ...
Generating keys ...
wg keys already exist
Registring pubkey ...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   102    0    44  100    58    165    218 --:--:-- --:--:-- --:--:--   387
Generating profiles...
generating config for

The issue may have been not configuring config.json.sample properly
as you suggested using nano.

Regarding the cron job - for my install folder - I am using as seen below

mkdir -p /root/wgapi/

So - would the correct / appropriate cron job ( s ) be as below :
After I mkdir wg.log in my install folder - i.e. - /root/wgapi

0 0 * * * now=$(date) ; echo "$now Start of Day - wg.log" >/root/wgapi/wg.log 2>&1  ## clear wg.log daily @ 00:00
5 00 * * * /root/wgapi/ -f -g >>/root/wgapi/wg.log 2>&1 ## force registration daily @00:05
10 00 * * */root/wgapi/wgapi/ -g >>/root/wgapi/wgapi/wg.log 2>&1 ## run once daily @00:10 after force

No. remove the /root/wgapi/ folder.

./ "means current working directory" ie. when you cd /mnt/shared/wgapi ./ simply means run from here.

The cron needs to know the Full Path to know where the script is located. Ergo, /mnt/shared/wgapi/. So use the cron entries I posted verbatim.

I keep encountering this last issue. Seems that I don't know how to create /mnt/shared directory.
When creating my usb exroot - I put /dev/sda1
Mount point = / ( root ) - should it be mount point = overlay instead ?
I Googled /mnt/shared - and I got cifs - windows - samba - basically information about file sharing. My setup is not that elaborate or sophisticated.
Is there an installation directory that I can use which is less complex to use for the cron job ?
Maybe something like -

mkdir -p /mnt/opt/wgapi

I successfully run AdguardHome on / from this directory on my current setup

Anyway - no matter the outcome of this attempt to get this working; I wish to thank you to the Nth degree for sticking with me - through all my fumbling, stumbling and ignorance. I am not ashamed that there are many things that I simply don't know. I try to the best of my ability to find the answers on my own ( in part - not to become a perpetual giant PITA ) ; however, there are times where I still remain in the dark - and have to reach out in order to led into the light.
Thanks RuralRoots - hopefully - this will be it on this topic.

PS - If you do suggest an alternate installation folder / directory - if you would include an illustration of the correct corresponding cron job I would appreciate it -

Yes, I was curious about that when you were talking overlay.

I’m not up on, but I’ll get back to you to work it out.

The cron was just a way to set and forget and the log was just to check key update because there wasn’t any visibility.

You can still run this once a day to update. /mnt/shared/wgapi/ -f -g
Wait a few minutes and run /mnt/shared/wgapi/ -g

find / -iname Should return path.

Thanks I will run that command and report back shortly. I am truly amazed by your knowledge and expertise. Thank you so very much for pointing me in the right directions - and most of all for your patience. I am a retired HS English Teacher - and this was not always among my best qualities. So, I especially appreciate and respect the courtesy and kindness you have shown throughout my struggles here. Hopefully, others will benefit from - the " alls well that ends well " culmination of our interchanges.

Here's my current version of the script:
Still fine tuning but it works well for public key registration, renewal and retrieving SurfShark server configs (which seems to be updated every 30 mins or so). Next step is generating/updating OpenWRT configuration, still not sure if there's any benefit in having multiple peers. Maybe config.json should be extended with a 'preferred server' so only one is selected? Also you could do some neat filtering based on current load and other properties in the surfshark json response but i really need to brush up on my jq skills for that...


For those in the dark as to how to configure SurfShark WireGuard Configuration Files
Thanks to all the folks here who keep perfecting this project.

IMPORTANT UPDATE April 17, 2022 - Easter Day
For The Most Simple and Direct Evolution of All
The Collective Hard Work Done Here -
In other words TRULY Easy SurfShark WireGuard

Go Here People For SurfShark WireGurard ~ SSWG


Overview of nano's shortcuts

From the dummy file below: Go to the the very bottom of this file and add the following :
The keys and addresses used here are fictional and used only for illustrative purposes.

Set the server's network configuration by editing /etc/config/network to include following parts.

In the default install folder ( /wg/ ) after running script ( ) - you will find SurfShark Wireguard configuration files in the default installation folder /wg/ in the conf directory. In this example I am using - you can read the file - by running # cat - while in the conf directory. All configuration files are in /wg/conf directory - my file used here is


1) Set the wireguard server's network configuration by editing 
to include following parts.




2 - Open the file: nano /etc/config/network  - and go to the very bottom of the file
Here is how you configure the SurfShark WireGuard Interface and Two Peers
The Information is found in the example directly above.

config interface 'wg0'
        option proto 'wireguard'
        option private_key 'foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q='
        list addresses ''
        option mtu '1350'
        option dns ''

config wireguard_wg0
        option public_key '/llFOsnvj7GcXasKrojhZl6nRnnn4D8sRuDUKEdiZzM='
        option route_allowed_ips '1'
        list allowed_ips ''
        option persistent_keepalive '25'
        option description 'WG_1'
        option endpoint_host ''
        option endpoint_port '51820'

config wireguard_wg0
        option public_key 'cxti1XR6uW483xAioP3d1ZaoGSy+obY6WaE4fW1A6Nk='
        list allowed_ips ''
        option persistent_keepalive '25'
        option description 'WG_2'
        option route_allowed_ips '1'
        option endpoint_host ''
        option endpoint_port '51820'

Save and Exit 

3) Configure the OpenWRT firewall for your Surfshark WIRGUARD Client:

Special Thanks to trendy ( from the OpenWRT Forum ) for helping me with this elegant solution

The most simple, effective and efficient method to set up your firewall
for Surfshark WIREGUARD this is to add the 'wg0' network 
to the wan zone in the /etc/config/firewall configuration file

Edit /etc/config/firewall file and add the 'wg0' network as follows:

Open the file: nano /etc/config/firewall 

config zone
        option name 'wan'
        list network 'wan'
        list network 'wan6'
        list network 'wg0'  ## This is the line you need to add - and you are done
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'

Save and Exit 

Then issue from command line Step 4 below:

4 ) Apply changes

/etc/init.d/network reload
ifdown wg0
ifup wg0
/etc/init.d/firewall restart


# wg show  ## in order to check connection and data transfer rates

Dear patrickm,
Thanks for the script - should a cron job be set up with this script. BTW - your script registered / renewed keys just fine. Ran into a bit of an issue as it did not generate / retrieve SurfShark server configs.
I ran both of the commands below : and -f

Neither command produced the SurfShark server configs, but both registered the public key - and generated both wg.json and the token.json. Just reporting back

Any information about possible necessity of cron job - and information as to how to properly use your script will be greatly appreciated.


1 Like

What is the reason for adding a peer for I didn't do that and it seems to work fine for me but i've seen this in RuralRoots script as well. No idea if it has any purpose?

How do you guys take care of not leaking DNS requests? I think I need to setup a split DNS, so eligible clients on my LAN resolve remote hosts over VPN without losing access to local DNS.

Without any arguments my version of the script just registers or renews the public key. It's valid for 7 days, i've not yet confirmed the connection actually breaks if you don't renew in time. If it does you should run it in a cronjob at least once per week I guess. But my goal is to update openwrt wireguard config in place, run it maybe every ~6 hours to check for config changes, run it automatically when connection goes down etc.

For now to generate conf for all servers (which takes a while and you likely just need one), in my version of the script, run it with -g parameter.

Updated Script


From a clean OpenWRT image I followed the official OpenWRT guide to get the client wireguard baselined. Your choice may differ..
I deviated slightly and gave my WG_IF="vpn" the name WG_IF="SSWG" >> client

This baseline install is vanilla without luci YET! install the following. Since your are here: Create Surfshark wireguard connection on OpenWrt easily
We'll assume you've already hit the Git

opkg update
opkg install luci-proto-wireguard luci-app-wireguard qrencode curl jq
/etc/init.d/rpcd restart

optional: and after you get yazdan's configs mastered....This is a placeholder url that you may find handy that is easily overlooked.. winking at Paul :wink:

opkg vpn-policy-routing
/etc/init.d/rpcd restart


Log into your router: CHECK your "WG_IF "interface" doublechecking the copy/paste wiz/bang you did from the clean install of "Client". Look at your keys.
Now use your terminal to ssh into your router. I use WinSCP because Windows grants the cheat to visualize this and eventually make directories, files, text edits; without wondering what vi or nano keyboard command are for text editing. ¯(ツ)/¯ winking @ Paul again for weeks now ¯(ツ)/¯

Try looking in /root.. Once you find the keys from vanilla's install
step 2:
It's time to decide where you're; going to run your awesome RuralRoots Cron job from and... AND, edit that location into the "" file. Yup you heard me right Paul...Awesome! Speaking of Awesome don't neglect to get the code snippet he's posted. This code makes life fun!

My example is shown in the pics.. and crontab job below.. I buried yazdan's files in /etc/config/wireguard/
Notice line 26 of the current Git sh.

I've edited the file and left the config.json with only my user/pass.. that darnblamfrigglefracking lost cause "config_folder": "." thingy can stay "." OK! BECAUSE we are going to tell json to go to hello world with line 26 of the file. Why? because the Professor asked a good question. If you run this from Putty anywhere, Crontab defaults to /root, or six folders deep in WinSCP's Console: config.json errors are a bygone problem.

And make it happen your style. This means moving your files to a folder of your making and align it to placeholders in line 26, and Crontab.

BTW.. I've camped on this page for about 6 weeks now reading up/down/sideway/over/beyond, so apologies since I've given ya'll nicknames to your avatars. Professor aka directnupe you've been pleasantly persistent asking the hard questions. By that I means humble yet succinct. Paul aka RuralRoots. Bless you for making us think and learn and strive. I hope yazdan lives to plug your verbose mods.

If you're a smart feller, edit the crontab below to align with the directory you placed yazdan's edited files.. If you're a *art smeller and copied my example.. it's simply copy/paste from here.

cat << "EOF" >> /etc/crontabs/root
# Periodically reinstate Key duration
05 00 * * * /etc/config/wireguard/ -f -g >/etc/config/wireguard/wg-f.log 2>&1 # force registration and print to log midnight+5min
10 00 * * * /etc/config/wireguard/ -g >/etc/config/wireguard/wg-g.log 2>&1 # after force and print to log.  
05 12 * * * /etc/config/wireguard/ -f -g >/etc/config/wireguard/wg-f.log 2>&1 # force registration and print to log noon+5min
10 12 * * * /etc/config/wireguard/ -g >/etc/config/wireguard/wg-g.log 2>&1 # after force and print to log.
uci set system.@system[0].cronloglevel="5"
uci commit system
/etc/init.d/cron restart

Good Luck All
I trust one pic is enough newbie's of any age: Born Limited.