Deploy Open Terminal on macOS with Tailscale HTTPS
Overview
This guide explains how to run Open WebUI’s Open Terminal on a MacBook, publish it privately over HTTPS with Tailscale Serve, and configure it to start automatically with macOS.
Open Terminal provides AI agents with a dedicated environment for executing commands, managing files, and running code through an API. It is designed to be controlled by an AI assistant rather than used as a conventional browser-based terminal.
Tailscale Serve provides a Tailscale-managed HTTPS endpoint that is accessible only to devices on the same tailnet. It should not be confused with Tailscale Funnel, which publishes a service to the public internet.
Prerequisites
Before beginning, ensure the following requirements are met:
- A MacBook with Tailscale installed and connected
- Access to the target Tailscale tailnet
- Open Terminal installed under the current macOS user
- A working Open Terminal configuration file
- Open WebUI, if Open Terminal will be used by an AI model
- Administrative access to Open WebUI’s terminal connection settings
- A Tailscale HTTPS certificate-enabled tailnet name
Confirm the Open Terminal executable path:
1
command -v open-terminal
The deployment documented here used:
1
/Users/collensaunders/.local/bin/open-terminal
Important: If
command -v open-terminalreturns a different path, use that path in the LaunchAgent configuration.
Architecture
The resulting connection path is:
1
2
3
4
5
6
7
8
9
Open WebUI
|
| HTTPS over the Tailscale tailnet
v
Tailscale Serve on the MacBook
|
| Local HTTP connection
v
Open Terminal
TLS terminates at Tailscale Serve. Open Terminal can therefore listen on a local HTTP port while Tailscale supplies the trusted HTTPS endpoint.
Procedure
Step 1: Verify the Open Terminal configuration
The deployment used the following configuration path:
1
/Users/collensaunders/.config/open-terminal/config.toml
Confirm that the file exists:
1
2
3
test -f /Users/collensaunders/.config/open-terminal/config.toml \
&& echo "Configuration found" \
|| echo "Configuration not found"
Protect the configuration file because it may contain authentication credentials:
1
chmod 600 /Users/collensaunders/.config/open-terminal/config.toml
Step 2: Start Open Terminal manually
Start Open Terminal with the configured TOML file:
1
2
/Users/collensaunders/.local/bin/open-terminal run \
--config /Users/collensaunders/.config/open-terminal/config.toml
Leave this terminal window open during the initial test.
Expected result: Open Terminal starts without an immediate configuration or port-binding error.
If the command fails, verify:
- The executable path
- The configuration path
- File permissions
- The configured listening port
- Whether another process already uses the port
Once manual operation is confirmed, stop the process with Ctrl+C.
Step 3: Test the service locally
Restart Open Terminal and test its configured port from another Terminal window.
For example, if the service is listening on port 3000:
1
curl -v http://127.0.0.1:3000/
An HTTP response confirms that the service is reachable locally. Depending on the endpoint and authentication settings, the response may be a success, authentication error, or API response.
Note: A
401 Unauthorizedresponse can still confirm network connectivity. It means the service answered but requires valid authentication.
Step 4: Publish the service with Tailscale Serve
For an Open Terminal service listening on local port 3000, configure Tailscale Serve:
1
tailscale serve --bg 3000
The equivalent explicit command is:
1
tailscale serve --bg https / http://127.0.0.1:3000
The --bg option saves the Serve configuration so it remains active after the Terminal window is closed [1].
Review the resulting configuration:
1
tailscale serve status
Tailscale should display the HTTPS URL assigned to the MacBook and the local backend receiving proxied requests.
Expected result:
1
2
3
https://macbook-name.tailnet-name.ts.net
|
+-- / proxy http://127.0.0.1:3000
The exact hostname depends on the MacBook’s Tailscale machine name and tailnet DNS name.
Step 5: Test the Tailscale HTTPS endpoint
From another device connected to the same tailnet, open the HTTPS URL displayed by:
1
tailscale serve status
The endpoint can also be tested with curl:
1
curl -v https://macbook-name.tailnet-name.ts.net/
Replace the example hostname with the URL returned by Tailscale Serve.
Expected result: The request reaches Open Terminal through a valid Tailscale-managed HTTPS connection.
Important: Tailscale Serve is private to the tailnet by default. Do not enable Tailscale Funnel unless Open Terminal is intentionally meant to be reachable from the public internet [1].
Step 6: Create the macOS LaunchAgent
Create the log directory:
1
mkdir -p /Users/collensaunders/Library/Logs/open-terminal
Create the LaunchAgent:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
cat > /Users/collensaunders/Library/LaunchAgents/com.openwebui.open-terminal.plist <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.openwebui.open-terminal</string>
<key>ProgramArguments</key>
<array>
<string>/Users/collensaunders/.local/bin/open-terminal</string>
<string>run</string>
<string>--config</string>
<string>/Users/collensaunders/.config/open-terminal/config.toml</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>ThrottleInterval</key>
<integer>10</integer>
<key>StandardOutPath</key>
<string>/Users/collensaunders/Library/Logs/open-terminal/stdout.log</string>
<key>StandardErrorPath</key>
<string>/Users/collensaunders/Library/Logs/open-terminal/stderr.log</string>
</dict>
</plist>
EOF
Validate the property list:
1
plutil -lint /Users/collensaunders/Library/LaunchAgents/com.openwebui.open-terminal.plist
Expected result:
1
/Users/collensaunders/Library/LaunchAgents/com.openwebui.open-terminal.plist: OK
Step 7: Load the LaunchAgent
Load the service for the current user:
1
2
3
launchctl bootstrap \
gui/$(id -u) \
/Users/collensaunders/Library/LaunchAgents/com.openwebui.open-terminal.plist
Enable and start it:
1
2
launchctl enable gui/$(id -u)/com.openwebui.open-terminal
launchctl kickstart -k gui/$(id -u)/com.openwebui.open-terminal
Check its status:
1
launchctl print gui/$(id -u)/com.openwebui.open-terminal
Confirm that the process is running:
1
pgrep -af open-terminal
Review the logs:
1
tail -n 100 /Users/collensaunders/Library/Logs/open-terminal/stdout.log
1
tail -n 100 /Users/collensaunders/Library/Logs/open-terminal/stderr.log
Step 8: Configure Open WebUI
In Open WebUI:
- Open the administrator or user connection settings.
- Locate the Open Terminal integration.
- Add the HTTPS URL displayed by
tailscale serve status. - Enter the authentication credentials configured for Open Terminal.
- Save the connection.
- Select the terminal in a chat that supports Open Terminal.
- Ensure the model uses native function calling.
- Ask the model to perform a basic test:
1
Use the selected terminal to execute: pwd
Expected result: The model invokes Open Terminal and returns the terminal’s working directory.
Validation
Complete the following checks after deployment.
Confirm the LaunchAgent is running
1
launchctl print gui/$(id -u)/com.openwebui.open-terminal
Confirm Open Terminal is listening
1
pgrep -af open-terminal
If the configured port is 3000, check it with:
1
lsof -nP -iTCP:3000 -sTCP:LISTEN
Confirm Tailscale Serve is active
1
tailscale serve status
Confirm HTTPS access from another tailnet device
1
curl -v https://macbook-name.tailnet-name.ts.net/
Use the actual hostname returned by tailscale serve status.
Confirm Open WebUI can execute a command
Ask the model:
1
Use the selected terminal to execute: whoami
The returned user should match the macOS account running the LaunchAgent.
Confirm startup after a reboot
Restart the MacBook, sign in, and run:
1
launchctl print gui/$(id -u)/com.openwebui.open-terminal
Then retest the Tailscale HTTPS URL and execute another command from Open WebUI.
Troubleshooting
Open Terminal does not start
Check the error log:
1
tail -n 100 /Users/collensaunders/Library/Logs/open-terminal/stderr.log
Common causes include:
- An incorrect executable path
- A missing configuration file
- Invalid TOML syntax
- Incorrect file permissions
- A port already in use
- A dependency unavailable in the LaunchAgent environment
Run the exact command from ProgramArguments manually to expose startup errors:
1
2
/Users/collensaunders/.local/bin/open-terminal run \
--config /Users/collensaunders/.config/open-terminal/config.toml
LaunchAgent configuration changes are not applied
Unload the existing job:
1
2
3
launchctl bootout \
gui/$(id -u) \
/Users/collensaunders/Library/LaunchAgents/com.openwebui.open-terminal.plist
Validate the file:
1
plutil -lint /Users/collensaunders/Library/LaunchAgents/com.openwebui.open-terminal.plist
Load it again:
1
2
3
launchctl bootstrap \
gui/$(id -u) \
/Users/collensaunders/Library/LaunchAgents/com.openwebui.open-terminal.plist
Tailscale HTTPS URL does not respond
Check the Serve configuration:
1
tailscale serve status
Test Open Terminal locally:
1
curl -v http://127.0.0.1:3000/
If the local request fails, troubleshoot Open Terminal before Tailscale. If the local request succeeds but the HTTPS request fails, check:
- Tailscale is connected on both devices
- Both devices are authorized on the tailnet
- Tailnet ACLs or grants allow access
- MagicDNS and HTTPS are enabled
- Tailscale Serve points to the correct local port
Open WebUI reports that the terminal server was not found
If Open WebUI displays an error such as:
1
Terminal server 'URL' not found
verify that the saved Open Terminal connection still exists and that the chat is not referencing a stale terminal-server record.
Delete and recreate the Open Terminal connection if necessary, then start a new chat and select the newly created terminal.
File browsing works, but command execution fails
The Open WebUI browser interface may be able to reach Open Terminal even when the Open WebUI backend cannot. A successful browser-side connection is therefore not sufficient to prove end-to-end connectivity [1].
Test the Tailscale URL from the same host or container running the Open WebUI backend.
If Open WebUI runs in Docker:
- Open a shell in the Open WebUI container.
- Run
curlagainst the Tailscale HTTPS URL. - Confirm DNS resolution, TLS negotiation, and HTTP connectivity.
- Verify that the container can route traffic through the host’s Tailscale connection.
The backend must be able to reach the configured terminal URL for model-driven command execution to work [1].
Authentication fails
Verify that:
- Open WebUI uses the same credentials configured in Open Terminal.
- The API key or token contains no accidental spaces.
- The credential was not copied with surrounding quotation marks.
- Open Terminal was restarted after its configuration changed.
- The Open WebUI connection was saved after updating the credential.
Do not disable authentication merely to work around a connectivity problem.
Service Management
Restart Open Terminal
1
launchctl kickstart -k gui/$(id -u)/com.openwebui.open-terminal
Stop Open Terminal
1
launchctl kill SIGTERM gui/$(id -u)/com.openwebui.open-terminal
Because KeepAlive is enabled, launchd may restart the process automatically.
Disable automatic startup
1
launchctl disable gui/$(id -u)/com.openwebui.open-terminal
1
2
3
launchctl bootout \
gui/$(id -u) \
/Users/collensaunders/Library/LaunchAgents/com.openwebui.open-terminal.plist
Remove the Tailscale Serve configuration
1
tailscale serve reset
Warning:
tailscale serve resetremoves the device’s complete Serve configuration, including unrelated Serve routes configured on the same MacBook.
Security Considerations
- Use Tailscale Serve rather than Funnel to keep Open Terminal private to the tailnet.
- Require Open Terminal authentication even when access is restricted by Tailscale.
- Store configuration files with restrictive permissions such as
600. - Do not commit API keys or configuration files containing credentials to Git.
- Restrict access using Tailscale ACLs or grants.
- Remember that Open Terminal allows AI agents to execute commands and access files under the macOS user account running the service.
- Run the service under a dedicated, minimally privileged account when broader access is unnecessary.
- Review Open Terminal and Open WebUI logs for unexpected command execution.
- Do not run Open Terminal as
rootunless a documented administrative requirement exists.