Your local apps, through a private door.
Portico is a native macOS menu-bar app for giving web services reachable from your Mac stable, private HTTPS addresses on a Tailscale tailnet.
It creates an independent Portal for each service. A Portal keeps its own Tailscale identity and URL, so you can share a durable private address without putting the service on the public internet or routing it through your Mac's existing Tailscale node.
- Stable HTTPS URLs for services running on the Mac, such as
http://127.0.0.1:8787becominghttps://hermes.<tailnet>.ts.net. - Multiple independent Portals, each with an immutable Portal Name and a Tailscale-assigned identity.
- Local App destinations on the Mac and Remote App destinations reachable over the Mac's normal network.
- Browser authentication for each Portal, without asking you to manage auth keys.
- A menu-bar control and focused management window for daily work.
- Clear, separate state for the desired state, Tailscale connection, and destination reachability.
- Start, stop, repoint, copy, open, diagnose, and remove controls for each Portal.
The management window keeps the important facts together: the Portal's identity, assigned name, connection state, destination reachability, and private URL.
Creating a Portal starts with a detected Local App or an explicitly configured Local App or Remote App destination.
The screenshots use example data from the native UI test fixture; they do not represent a released build or a live tailnet.
The menu-bar popover is the everyday control surface: check Portal state, open a private URL, or jump to settings, diagnostics, and the full management window without leaving the menu bar.
- Choose a destination. Select a detected Local App or enter a Local App or Remote App destination.
- Create a Portal. Choose a durable Portal Name and complete browser authentication for its independent Tailscale node.
- Use the private URL. Copy or open the Portal URL from the menu bar or management window wherever your tailnet can reach it.
Access remains governed by your Tailscale tailnet policy. Portico provides the private doorway; it does not add a second application-level authorization layer.
Portico is in active development. The latest release is
v0.0.2.
The repository is the source of truth for the current executable, helper, and
MVP behavior.
You will need:
- A Mac running macOS 14 or later.
- A Tailscale tailnet with MagicDNS and HTTPS certificates enabled.
- A web service reachable from the Mac.
Portico is a selected working name and has not yet been legally cleared.
Prerequisites:
- Xcode 26.3 selected with
xcode-select - Go 1.26.5
- XcodeGen (
brew install xcodegen)
Generate the local Xcode project, build, and launch:
./Scripts/generate-xcode-project.sh
xcodebuild \
-project Portico.xcodeproj \
-scheme Portico \
-destination 'platform=macOS' \
-derivedDataPath .build/xcode \
build
open .build/xcode/Build/Products/Debug/Portico.appRun the Swift unit tests, native UI tests, and Go helper tests:
bundle install
bundle exec fastlane mac test
(cd helper && go build ./cmd/portico-helper && go test ./...)For the generated-project check and local app smoke test, see the scripts in
Scripts/.
Each release is a universal macOS 14+ application. The helper is built for arm64 and x86_64, embedded in Portico.app, signed before the app, and distributed in one notarized DMG. The direct download and Homebrew cask use that same DMG; Portico does not check for, download, or install updates itself. Homebrew users can install or update it with:
brew install --cask chrisbanes/tap/porticoThe Publish release workflow is the only publishing path. It runs the
Fastlane mac release lane and must be dispatched from main manually with a
0.x.y version. It always releases main's current commit. Before it creates a
public GitHub Release or changes the tap, the workflow runs the Swift and Go
suites, builds, signs, notarizes, staples, mounts, and verifies the exact DMG.
It then verifies the uploaded draft asset and audits the generated cask before
publishing the normal GitHub Release. It clean-installs the cask before
committing its version, URL, and SHA-256 to chrisbanes/homebrew-tap; a retry
for the same version and main commit resumes a release whose tap update did
not complete.
Keep these repository secrets outside the repository. The public-release
environment still protects the manual publishing job:
APPLE_SIGNING_CERTIFICATE_BASE64APPLE_SIGNING_CERTIFICATE_PASSWORDAPPLE_NOTARY_KEY_BASE64APPLE_NOTARY_KEY_IDAPPLE_NOTARY_ISSUER_IDHOMEBREW_TAP_TOKEN— an expiring fine-grained token with Contents write access only tochrisbanes/homebrew-tap
The Fastlane mac build lane can create the same credentialed release material
locally without publishing it:
bundle install
APPLE_NOTARY_KEY_BASE64="$(base64 < /path/to/AuthKey_….p8)" \
APPLE_NOTARY_KEY_ID=… \
APPLE_NOTARY_ISSUER_ID=… \
bundle exec fastlane mac build version:0.1.0Keep the Developer ID certificate and App Store Connect team API key outside the repository. Before configuring credentials, the universal helper build can be verified locally with:
./Scripts/verify-universal-helper.sh


