Security

Your keys stay on this Mac.

This page explains how Kule protects your servers, keys and connections. The short version is right below.

Last updated: October 14, 2026
  • No server of our ownEvery connection is made directly from this Mac.
  • One key per serverEach server has its own SSH key, kept in Keychain.
  • The host key is pinnedIf it changes, Kule stops the connection.
  • Signed and notarizedBoth the app and its updates arrive signed.

Every connection from this Mac

Kule has no server of its own. It connects to your servers, the Dokploy panel, GitHub and Cloudflare directly from this Mac. Since there is no server we run in between, your keys, tokens and server details never reach us.

These connections are made by the app’s core, written in Rust. The interface you see can’t reach the internet on its own: the content security policy allows only the app’s own files and the core.

Keys and tokens in Keychain

Secrets are kept in the macOS Keychain, under the com.getkule.app service. Kule generates a separate ed25519 key for each server; one server’s key doesn’t open another server.

SSH keysOne ed25519 key per servermacOS Keychain
Panel credentialsThe Dokploy API key, the password of the admin account Kule createdmacOS Keychain
GitHubToken obtained through the device flowmacOS Keychain
CloudflareThe cf CLI’s own session; Kule doesn’t read it~/Library/Preferences/cloudflare
Server list and event historyContains no secrets~/Library/Application Support/com.getkule.app

The interface never sees secrets

SSH keys and tokens go from Keychain only to the core, never to the interface. The screen shows only what you ask to see: the panel’s admin password, when you choose "Şifreyi göster" (Show password); the recovery kit’s passphrase, once, while the kit is being created.

The first connection and the root password

The root password you type when adding a new server is used only for the first connection. During that connection Kule adds the server’s own key to the authorized_keys file, puts the key in Keychain and verifies that key login works. The password is kept only in memory, wiped after use and never written anywhere. If a step fails, nothing is left behind in Keychain.

On the first connection, Kule takes the server’s identity, its host key fingerprint, and pins it. On every later connection it accepts only that identity. If the identity changes, it stops the connection and warns you.

Protections set up on the server

The first step of setup hardens the server. The firewall (ufw) allows only the SSH, 80 and 443 ports. fail2ban blocks addresses that keep trying wrong logins. Automatic security updates are turned on, and if there is no swap space, 2 GB of swap is added.

Password SSH login is turned off; root can log in only with a key. Kule doesn’t stop at writing the setting: it reads the setting the server actually applies with sshd -T. If password login is still on, setup stops there.

If you turn on the firewall later from the Sunucular (Servers) screen, Kule first sets up a safety timer on the server: a job that will turn the firewall off again after two minutes. Once the firewall is on, it tries to get in with a new SSH connection. If it can, it cancels the timer; if it can’t, the firewall turns itself off within two minutes. A wrong rule won’t lock you out of your server.

The Sunucular screen reads the security state in a single SSH round and changes nothing: firewall, open ports, fail2ban, password login and automatic updates. Docker opens the ports it publishes to the outside by going around ufw; so if the panel is reachable on port 3000, Kule shows it with the warning "Panel portu 3000 dışarı açık" (Panel port 3000 is open to the outside).

Recovery kit

So that you can still get into your servers if this Mac is lost or breaks, Kule prepares a recovery kit. The kit is a second SSH key; that key is authorized on each of your servers.

The key is saved as a PDF in your Downloads folder, together with your server list and their identities. The key in the PDF is encrypted with a passphrase (OpenSSH format, bcrypt and AES-256). The passphrase is not in the PDF: Kule shows it on screen once and doesn’t write it to disk. Write it down somewhere; without the passphrase the kit won’t open.

GitHub and Cloudflare

You connect to GitHub with the device flow: Kule shows a code and you approve on github.com. No server is needed for this, and the token stays in Keychain.

Kule asks for the repo read:user scope. GitHub’s OAuth apps have no scope that is just enough to read private repos; reading a private repo and adding a deploy key and webhook need repo. Kule adds a read-only deploy key to each repo; the platform pulls the code with that key and can’t write to the repo.

You connect to Cloudflare with Cloudflare’s official cf command-line tool. Login uses a device code, and you approve in the browser. cf keeps the session itself; Kule only runs cf commands and never sees the token. If Node isn’t on this Mac, Kule downloads it from nodejs.org and verifies it against the official SHASUMS256 list.

Signing and updates

Kule is signed with a Developer ID and passes Apple’s notarization check. Before opening the app, macOS verifies who it comes from and that it hasn’t been changed since.

Kule checks for a new version through cdn.getkule.com shortly after it opens, or when you choose Güncellemeleri Denetle… (Check for Updates) in the Kule menu. Every update is signed; Kule verifies the signature with the public key inside the app and doesn’t install an update that doesn’t match. When it finds a new version, it asks you before installing it.

Found a vulnerability?

If you think you’ve found a security issue in Kule, write to hey@getkule.com. If you include how we can reproduce it and which version you saw it in, we can move quickly.

If you write to us before sharing the details anywhere public, we gain time to get the fix to users.