openconnect-toggle is a small macOS helper script that makes it easy to:
- connect to and control OpenConnect VPN sessions;
- work with a simple server setup where the client only has:
- the server CA certificate,
- a username,
- and a password.
You can:
- run the script in CLI mode from Terminal,
- run it with a double-click in Finder (as a
.commandfile) from any directory, - optionally view status and control connections via the excellent SwiftBar GUI in the macOS menu bar.
For a quick initial setup it is recommended to:
- save your CA certificate in X.509 format under the name
ca.crt, - put
ca.crtnext to the script.
However, this is not required: during interactive setup you can instead paste an absolute path to your existing certificate file without renaming it.
-
Single toggle command:
openconnect-toggle <username>- If VPN is disconnected → connect as
<username>. - If VPN is connected for that user → disconnect.
- If VPN is connected for another user → disconnect and connect as
<username>.
- If VPN is disconnected → connect as
-
Status output:
- shows
VPN connected for username@server.orVPN disconnected., - prints active VPN interface (e.g.
utun0) and tunnel IP (e.g.10.x.x.x).
- shows
-
SwiftBar integration (optional, guided interactively):
- menu bar icon showing connection status (🔒 / 🔓),
- per-user toggle menu items,
- an
Add user…item, - auto-starts SwiftBar after integration (if possible).
-
Touch ID for sudo (optional):
- can add
auth sufficient pam_tid.soat the top of/etc/pam.d/sudo, - remembers if this script added the line (
TOUCHID_ADDED=1), -uninstallcan roll it back if the config is still present.
- can add
-
Secure credentials:
- VPN passwords are stored only in Keychain (as generic password items),
- keyed by
account = <username>,service = openconnect:<server>.
-
Centralized config & CA:
- config and CA live in:
~/Library/Application Support/openconnect-toggle/
- SwiftBar plugin directory contains only the plugin script, not config or certs. The plugin script is exactly the same original script but with different name, it uses the same shared config.
- config and CA live in:
-
Reset & uninstall helpers:
-reset: remove config + Keychain entries for known users (saved in the config).-uninstall: everything-resetdoes, plus optional cleanup of SwiftBar plugin, logs, SwiftBar app, and PAM Touch ID changes.
⚠️ This script is intended for advanced users. It touches PAM (optionally) and usessudo. Read carefully before using in security-critical environments.
- macOS (recent versions with SwiftBar support).
- Homebrew (recommended) for installing:
openconnectswiftbar(optional, for the menu bar GUI)
Install OpenConnect:
brew install openconnect
Optional: install SwiftBar:
brew install --cask swiftbar
git clone https://github.com/<your-username>/openconnect-toggle.git
cd openconnect-toggle
chmod +x openconnect-toggle.command
You can:
- run it directly from the repository directory, or
- copy/move
openconnect-toggle.commandanywhere you like (for example,~/binor your Desktop for double-click usage).
Run the script without arguments from Terminal or just double-click it:
./openconnect-toggle.command
On first run, it will guide you through:
-
VPN server hostname
Example:vpn.example.com. -
Path to CA certificate file
-
Default:
ca.crt. -
If you just press Enter, it will look for
ca.crtnext to the script. -
If you provide a relative path (for example,
certs/ca.crt), it is treated as relative to the script directory, not the current working directory. An absolute path will work as it is. -
The certificate is copied into:
~/Library/Application Support/openconnect-toggle/.crt
and the filename is stored in the config as
CA_FILE.
-
-
First VPN user
- The script will ask for a username.
- It will then ask for the corresponding password and store it in Keychain as:
account = <username>service = openconnect:<server>
-
Optional: enable Touch ID for sudo
-
The script may offer to enable Touch ID for
sudoby inserting:auth sufficient pam_tid.so
at the top of
/etc/pam.d/sudo. -
If you accept:
- the script records that it added this line (
TOUCHID_ADDED=1in config), -uninstallwill later be able to remove it.
- the script records that it added this line (
-
If you decline:
- it records
TOUCHID_DENIED=1and will not ask again, - you can reset this behavior by removing the config (for example, with
-reset).
- it records
-
-
Optional: SwiftBar integration
- The script can set up a SwiftBar plugin:
-
if SwiftBar is not installed, it can install it via Homebrew (if available),
-
you will be asked for the SwiftBar plugins directory, default:
~/Library/Application Support/SwiftBar/plugins
-
the script then copies itself into that directory as:
openconnect-toggle.1m.sh
and marks it executable with
chmod +x. -
if SwiftBar is not running, the script will try to start it:
open -a "SwiftBar"
-
- The script can set up a SwiftBar plugin:
After initial setup, running the script without arguments in Terminal will:
- show the current VPN status (connected/disconnected, interface and IP),
- without re-running the setup (unless the config is deleted).
The script uses the following locations:
-
Config directory
~/Library/Application Support/openconnect-toggle/ -
Config file
~/Library/Application Support/openconnect-toggle/openconnect-toggle.cfg -
CA certificate copy
~/Library/Application Support/openconnect-toggle/<your-ca-file-name>.crt -
Log file
~/Library/Logs/openconnect-toggle.log -
PID file for the
openconnectprocess~/.openconnect.pid
Passwords are never stored in the config file — only in Keychain.
Example config (simplified):
SERVER=vpn.example.com
CA_FILE=ca.crt
TOUCHID_DENIED='0'
TOUCHID_ADDED='1'
SWIFTBAR_INSTALLED='1'
SWIFTBAR_DENIED='0'
SWIFTBAR_PLUGIN_PATH='/Users/you/Library/Application Support/SwiftBar/plugins/openconnect-toggle.1m.sh'
CURRENT_USER='youruser'
USER_youruser='1'
USER_someoneelse='1'
./openconnect-toggle.command
Interactive terminal:
-
if configured, prints something like:
VPN connected for username@server. Interface: utun3 VPN IP: 10.x.x.xor:
VPN disconnected. Interface: none VPN IP: none -
if not configured yet, this triggers the interactive setup.
./openconnect-toggle.command <username>
Behavior:
-
If VPN is disconnected:
- ensures a password for
<username>exists in Keychain (prompts if missing), - starts
openconnectin background with:--protocol=anyconnect--user=<username>--cafile=<CA_PATH>--background--pid-file=~/.openconnect.pid
- prints status.
- ensures a password for
-
If VPN is connected:
- sends
INTto theopenconnectprocess referenced by~/.openconnect.pid
(falling back tokillall openconnectif needed), - clears
CURRENT_USERin the config, - prints
VPN disconnected.and interface/IP info.
- sends
./openconnect-toggle.command adduser
- Must be run in an interactive terminal.
- Prompts for a new username.
- If needed, prompts for the password and stores it in Keychain.
- Marks the user in the config as
USER_<username>=1.
If SwiftBar integration is enabled, the plugin script is created as:
~/Library/Application Support/SwiftBar/plugins/openconnect-toggle.1m.sh
SwiftBar periodically runs this script without arguments, which triggers the SwiftBar status mode:
-
menu bar icon:
- 🔒 = connected
- 🔓 = disconnected
-
status entries:
Status: connected/Status: disconnectedInterface: utunX/Interface: noneVPN IP: 10.x.x.x/VPN IP: none
-
user-related actions:
-
one menu item per configured user:
Toggle VPN (user1) Toggle VPN (user2) ...each of them runs:
openconnect-toggle.command <user> -
an
Add user...menu item that launches Terminal and runs:openconnect-toggle.command adduser
-
CLI usage and SwiftBar usage share the same config and Keychain entries and can be used side by side.
When you allow the script to enable Touch ID, it:
-
inserts at the top of
/etc/pam.d/sudo:auth sufficient pam_tid.so -
records
TOUCHID_ADDED=1in the config.
This allows you to confirm sudo operations with Touch ID (on supported Mac hardware).
- This affects all
sudoinvocations on your system, not just this script. - If you later run
./openconnect-toggle.command -uninstallwhile the config still exists, the script can detectTOUCHID_ADDED=1and offer to remove the line again.
If you delete the config (manually or via -reset), the script will no longer know whether it added the pam_tid.so line, and you will have to edit /etc/pam.d/sudo manually if you want to revert it.
By default, sudo behaves as usual (password or Touch ID, depending on your system).
If you want to reduce password prompts for this script’s actions only, you can add a sudoers rule.
⚠️ Be careful with sudoers. A broken sudoers file can lock you out ofsudo.
Always edit viasudo visudoand make sure you know what you’re doing.
Example: allow your user to run openconnect, kill, and killall without a password:
-
Run:
sudo visudo -
Add a line (adjust
yourusernameand paths as necessary):yourusername ALL=(root) NOPASSWD: /usr/local/bin/openconnect, /opt/homebrew/bin/openconnect, /bin/kill, /usr/bin/killall
Paths depend on your Homebrew prefix (for example, /opt/homebrew/bin/openconnect on Apple Silicon).
This is entirely optional.
./openconnect-toggle.command -reset
This will:
-
load the config (if present),
-
remove Keychain entries for all known users:
account = <username>service = openconnect:<server>
-
delete the entire config directory:
~/Library/Application Support/openconnect-toggle/
Important:
-reset deletes the configuration file, which also stores whether PAM settings were modified (TOUCHID_ADDED=1).
After -reset, the script no longer knows whether it added pam_tid.so to /etc/pam.d/sudo, so if you later run -uninstall, it will not be able to automatically revert PAM changes. In that case, you must edit /etc/pam.d/sudo manually if you want to remove the Touch ID line.
./openconnect-toggle.command -uninstall
Interactive only (must be run in a real terminal).
It will:
- behave like
-reset(remove config + Keychain entries for known users), - and additionally ask if you want to:
-
remove the SwiftBar plugin (if
SWIFTBAR_PLUGIN_PATHis known), -
remove the log file:
~/Library/Logs/openconnect-toggle.log -
uninstall SwiftBar via Homebrew (if present),
-
remove
pam_tid.sofrom/etc/pam.d/sudo, but only if:TOUCHID_ADDED=1is in the config, and- the
pam_tid.soline is found in the file.
-
It does not:
- delete the script file
openconnect-toggle.command, - delete your original CA certificate file (the one you used during setup).
The project consists of a single script file:
openconnect-toggle.command
If you modify it:
- try to preserve backward compatibility of the config format,
- be especially careful with changes related to PAM and
sudo.
This project is licensed under the GNU General Public License v3.0 (GPLv3) or later.
See the LICENSE file or the official text at:
https://www.gnu.org/licenses/gpl-3.0.en.html