Control your devices for the Tailscale Mullvad VPN add-on with a Discord bot.
Hosted with Cloudflare Workers.
- Why not?
- The mobile app for Tailscale didn't really have a way to add / remove devices to the Mullvad VPN add-on, and we were too lazy to have to log in to the Tailscale dashboard.
This project assumes the following:
- You have
pnpminstalled (install here) - You have a Cloudflare account (registering one is free!)
- You have a Tailscale account (registering one is free!)
- You have a subscription for the Tailscale Mullvad VPN add-on
/mullvad-add device:<device>: Adds a device from your tailnet to the Tailscale Mullvad VPN add-on. The device names and IP addresses have autocomplete./mullvad-remove device:<device>: Removes a device from your tailnet to Tailscale Mullvad VPN add-on. The device names and IP addresses have autocomplete./mullvad-list: Lists all devices which have themullvadnode attribute.
- Rename the
.dev.vars.examplefile to.dev.vars. - Run the
pnpm installcommand on your terminal to install dependencies.
Create a Discord application in the Discord Developer Portal.
- Copy the Application ID and Public Key values in the General Information tab.
- Fill in the
DISCORD_APPLICATION_IDandDISCORD_PUBLIC_KEYenvironment variables accordingly in the.dev.varsfile. - Copy the token value in the Bot tab.
- Fill in the
DISCORD_TOKENenvironment variable with the token value in the.dev.varsfile.
Go to your Tailscale dashboard, click on the Settings tab, and navigate to OAuth clients.
- Click on the "Generate OAuth client..." button.
- Optional, but recommended: add a description. This will distinguish it among the other OAuth clients you might have already created.
- The bot requires Read and Write permissions for Policy File in order to make changes to your Access Controls file, so select those.
- We only need the "Client secret" part. Paste the value for the
TAILSCALE_CLIENT_SECRETenvironment variable in the.dev.varsfile.
We need to create a Cloudflare KV namespace. This will be used to cache the Tailscale API token, so we don't hit a ratelimit.
To do that, use the following instructions:
- Log in to your Cloudflare account by running the
pnpm wrangler logincommand in your terminal. - Afterwards, run the
pnpm wrangler kv namespace create <namespace>command in your terminal. - Specify a unique name. For example, something like
tailscale-kv. (pnpm wrangler kv namespace create tailscale-kv) - Copy the
kv_namespacescodeblock that thewrangler kvcommand returned, and replace the existingkv_namespacesproperty in thewrangler.jsoncfile.
Invite the bot by either:
- going your application's page in Discord Developer Portal, navigating to the "Installation" tab and copying the "Install Link" URL
- or using the following link:
https://discord.com/oauth2/authorize?client_id=<your bot's client ID>, and replacing<your bot's client ID>with theDISCORD_APPLICATION_IDenvironment variable in the.dev.varsfile.
- Optional, but highly recommended: fill in the
DISCORD_GUILD_IDenvironment value in the.dev.varsfile with the ID of your, preferably, private Discord server to restrict commands to only run in said server. - Run the
pnpm registercommand in your terminal to sync your bot's slash commands against the Discord API.
By default, the commands are public, meaning anyone can execute them.
If you don't want this behavior, go to your server -> Settings -> Integrations, then find your application. There, you'll find an overview of the permissions for commands. Modify this as you wish. (for example, restricting commands to a specific user/role)
- Run the
pnpm wrangler bulk .dev.varscommand in your terminal to create secrets to your Cloudflare Worker. - Wrangler might prompt you about the following message:
There doesn't seem to be a Worker called "mullvadcord". Do you want to create a new Worker with that name and add secrets to it?. Just click Enter / respond with the "Y" key on your keyboard. - This will create a Cloudflare Worker with the name
mullvadcord, and add secrets from the.dev.varsfile. If you want to change the name of your Worker, edit thenameproperty in thewrangler.jsoncfile.
- Run the
pnpm pushcommand in your terminal. This might take a couple of seconds. - You should see a URL like
https://mullvadcord.chloe.workers.dev. - Go to your application's page in the Discord Developer Portal, and paste the full
.workers.devURL that thepnpm pushcommand returned in the "Interactions Endpoint URL" input field.
That's it! Your bot is now up and running.
This repository is licensed under the MIT license.
ยฉ 2025 Sapphic Angels.