@onnimonni dotfiles. I'm full stack developer but I mainly work on devops and backend. These are my configs. This is personal backup for myself but hopefully you find it useful too.
Big thanks for @anttiviljami for years of guidance. I hope someday I will learn to play vimgolf but until then I will need these cheats.
- Custom keyboard mappings with karabiner-elements
- This includes my own keyboard layout based on Dvorak ( I implemented small tweaks for finnish language ).
# Install Xcode Command line tools to get git
xcode-select --install
# Clone the dotfiles and run the installation script
git clone https://github.com/onnimonni/dotfiles ~/.dotfiles
~/.dotfiles/.install.sh
# Then create age key with secure enclave
mkdir -p ~/.config/sops/age/
age-plugin-se keygen --access-control none -o ~/.config/sops/age/secure-enclave-key.txtlocal-user.nix is gitignored — each machine has its own copy. Generate one:
~/.dotfiles/scripts/generate-local-user.shOr copy the template manually:
cp ~/.dotfiles/local-user.nix.example ~/.dotfiles/local-user.nix
$EDITOR ~/.dotfiles/local-user.nixThe fields:
{
hostname = "Your-Mac-Hostname"; # from: scutil --get LocalHostName
username = "yourusername"; # from: whoami
fullName = "Your Name"; # from: id -F
email = "you@example.com";
# Optional: enables the Mac Studio share tunnel (see "Sharing the Mac Studio" below).
shareMacDomain = null;
}Then rebuild:
sudo darwin-rebuild switch --flake ~/.dotfilesThis flake always exports Onnis-MacBook-Pro and Onnis-Mac-Studio.
local-user.nix selects the default host for convenience but does not hide the other one.
This command updates flake dependencies, nix, brew and duckdb extensions:
$ update-all
- Create new ssh key in Secretive
- Copy the public key into
~/.ssh/secretive.pub - Add it into Github as new SSH key both as signing key and authentication key
You can create a new API key to use Gemini from command line here: https://aistudio.google.com/app/apikey
echo 'export GEMINI_API_KEY="XXXXXX"' >> ~/.secrets.fish# This only works in fish shell
$ update-dotfiles
If you get following messages:
warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels' does not exist, ignoring
You can fix them by running:
sudo nix-channel --update nixosRestart it by running (source):
launchctl kickstart -k gui/$(id -u)/org.pqrs.service.agent.karabiner_console_user_serverSet shareMacDomain = "<your-zone>" in local-user.nix and the Mac Studio
becomes reachable at:
| Service | Public hostname | Local backend |
|---|---|---|
| SSH | ssh-mac.<DOMAIN> |
127.0.0.1:22 |
| VNC | vnc-mac.<DOMAIN> |
127.0.0.1:5900 |
| Eternal Terminal | et-mac.<DOMAIN> |
127.0.0.1:2022 |
Outbound-only — no port forwarding, no public SSH/VNC/ET exposure. Two locks:
Cloudflare Access (email OTP today, WebAuthn once Touch ID is enrolled) + SSH
keys from github.com/<your-handle>.keys.
shareMacDomain lives in gitignored local-user.nix so the zone never lands
in the public repo. Hostnames are intentionally single-level so they fit under
Cloudflare Free's *.<DOMAIN> Universal SSL cert.
One-time setup on the client Mac:
# Add to ~/.dotfiles/local-user.nix on the client:
# shareMacDomain = "<your-zone>";
sudo darwin-rebuild switch --flake ~/.dotfiles # installs cloudflared + et + ssh config
# Pre-authenticate so the first remote-network attempt doesn't need a browser.
# Each hostname has its own cached Access token (~24h):
cloudflared access login ssh-mac.<DOMAIN>
cloudflared access login vnc-mac.<DOMAIN>
cloudflared access login et-mac.<DOMAIN>
ssh mac-studio echo hello # smoke testDaily use (from anywhere — café Wi-Fi, hotel, phone tether, all the same):
# Shell over SSH (plain, no session persistence)
ssh mac-studio
# Shell over Eternal Terminal (survives network drops + sleep — like mosh but TCP)
et-mac-studio
# et-mac-studio is a generated wrapper: it boots a one-shot
# `cloudflared access tcp` listener for the ET data leg, ssh-bootstraps
# via cloudflared access ssh, then exec's `et`. Foreground subprocesses,
# no launchd.
# Files (works because ssh mac-studio works)
scp mac-studio:~/Projects/foo/bar.txt ./
rsync -avz mac-studio:~/Projects/foo/ ./foo/
sftp mac-studio
# GUI via Screen Sharing — needs two terminals:
# terminal 1: open the TCP tunnel
cloudflared access tcp --hostname vnc-mac.<DOMAIN> --url localhost:5900
# terminal 2 (or Finder ⌘K): connect VNC to the local end
open vnc://localhost:5900 # VNC password is what you set in Sharing prefsWhen the Access session expires, the next ssh mac-studio / et-mac-studio
re-opens a browser for email OTP; click through and it's good for another
session window.
If ssh mac-studio says cloudflared: command not found, the client hasn't
rebuilt with shareMacDomain set yet — re-run sudo darwin-rebuild switch --flake ~/.dotfiles.
| Command | What it does |
|---|---|
ssh mac-studio |
Shell on the Mac Studio. ProxyCommand is the cloudflared tunnel; auth is your Secretive key. |
et-mac-studio |
Same shell, but over Eternal Terminal — resumes after network drops/sleep. Best with tmux/zellij on the far side for full session persistence. |
scp mac-studio:foo ./ |
File copy. Same path, same auth. |
cloudflared access login <host> |
Refresh the Access session (browser flow). Cached at ~/.cloudflared/<host>-…-token. |
cloudflared access tcp --hostname vnc-mac.<DOMAIN> --url localhost:5900 |
Open a local TCP socket that proxies through the tunnel — for VNC, databases, anything TCP. |
cloudflared tunnel info mac-studio (on the Mac Studio) |
Show tunnel health and active connections. |
cloudflared tunnel login # browser → pick your zone
cloudflared tunnel create mac-studio # writes ~/.cloudflared/<UUID>.json
sudo install -m 600 -o root -g wheel \
~/.cloudflared/<UUID>.json /etc/cloudflared/mac-studio.json
cloudflared tunnel route dns mac-studio ssh-mac.<DOMAIN>
cloudflared tunnel route dns mac-studio vnc-mac.<DOMAIN>
cloudflared tunnel route dns mac-studio et-mac.<DOMAIN>
# add shareMacDomain = "<your-zone>"; into local-user.nix
sudo darwin-rebuild switch --flake ~/.dotfiles
# System Settings → Sharing → Remote Login = On (Only these users → onnimonni)
# System Settings → Sharing → Screen Sharing = On + strong VNC passwordone.dash.cloudflare.com → Access controls → Applications → Add → Self-hosted:
- Public hostname: subdomain
ssh-mac, domain<your-zone>. Session 24h. - Policy: Allow your email.
- Repeat for
vnc-mac.<DOMAIN>andet-mac.<DOMAIN>.
Universal SSL on Free covers *.<DOMAIN> only (one level) — keep the names
single-level.
Currently MFA is relaxed to "email OTP only". To upgrade to WebAuthn:
- Access controls → Access settings → Manage your App Launcher → add Allow policy for your email. Save.
- Browse to
https://<your-team>.cloudflareaccess.com, log in, Account → Setup MFA → enroll Touch ID (Passkey) on every Mac + a hardware key as backup. - Back in Access settings → re-tick Apply global MFA settings by default.
After step 3, future sessions will prompt for Touch ID in the browser too.
sudo launchctl print system/com.cloudflare.cloudflared | head -5 # state = running
sudo launchctl print system/com.mistertea.etserver | head -5 # state = running
sudo tail -5 /var/log/cloudflared.log # 4 connections registered
sudo tail -5 /var/log/etserver.log # etserver listening on 2022
ssh onnimonni@127.0.0.1 echo ok # local sshd reachableLost a key or laptop — Zero Trust → Access controls → Applications → pause or block the policy. Tunnel stops authenticating in seconds, no router access required.
Swift app that dynamically tints the macOS menu bar based on window content below it. Captures a color strip via ScreenCaptureKit, composites it onto the wallpaper top edge, and sets it as desktop image. macOS vibrancy then naturally samples the modified wallpaper.
# Build & install
apps/MenuBarChameleon/build.sh
# Run
open ~/Applications/MenuBarChameleon.appRequires Screen Recording permission. Uses Apple Development signing identity for stable TCC.
Githits and context7 MCP are configured for Claude and Codex via nix-darwin modules.
Codex Playwright MCP is re-added on nix-darwin rebuild via codex mcp add playwright -- npx @playwright/mcp@latest --headless.
Codex itself is installed via Homebrew cask.
~/.codex/config.toml is generated as writable file so Codex can persist its own model prefs.
Interactive shell sessions auto-handoff into fish.
Non-interactive shell entry via the login shell falls back to bash.
claude, codex, gemini, and opencode are wrapped via nix so they launch under bash with SHELL=/bin/bash instead of inheriting fish.
consult-llm is installed via nix and configured on activation to use gemini-cli and codex-cli backends.
Use these dotfiles as you want to. Sharing is caring!
