Complete Phone-to-Laptop Terminal Mirroring Setup Guide

What This Solution Provides

This guide establishes a development workflow that enables you to switch between your Mac and iPhone while maintaining terminal session continuity. Using Tailscale for secure networking, Zellij for terminal multiplexing, and Terminus as an iOS SSH client, you can start work on your laptop and continue from your phone without losing context or progress.

Key advantages include network independence (functions across WiFi, cellular, and different locations), synchronized terminal sessions, persistence through network interruptions, and encrypted device-to-device communication. This setup is useful for monitoring long-running processes, making quick code changes remotely, or maintaining development workflow flexibility.

The following steps will walk you through the complete configuration process.

Prerequisites

  • Mac with macOS (any recent version)
  • iPhone with iOS 13+
  • Basic familiarity with terminal/command line
  • Admin access on your Mac

Part 1: Tailscale Setup (VPN Mesh Network)

Step 1: Create Tailscale Account

  1. Visit tailscale.com
  2. Click "Get started for free"
  3. Sign up using Google, GitHub, Microsoft, or email
  4. Choose the free personal plan (100 devices, plenty for personal use)

Step 2: Install Tailscale on Mac

  1. Download Tailscale for macOS from tailscale.com/download
  2. Open the downloaded .pkg file and follow the installer
  3. Launch Tailscale from Applications or menu bar
  4. Click "Log in" and authenticate with your Tailscale account
  5. Grant necessary permissions when prompted
  6. Note your Mac's Tailscale IP (shown in the Tailscale menu) - typically 100.x.x.x

Step 3: Install Tailscale on iPhone

  1. Download "Tailscale" from the App Store
  2. Open the app and tap "Log in"
  3. Authenticate with the same Tailscale account
  4. Enable the VPN when prompted
  5. Grant VPN permissions to iOS

Step 4: Verify Connection

  1. On your Mac, open Tailscale and note your iPhone's IP
  2. In Terminal on Mac, ping your iPhone: ping [iPhone-IP]
  3. You should see successful ping responses
  4. Both devices should now appear in your Tailscale admin console

Part 2: SSH Configuration on Mac

Step 5: Enable SSH on Mac

  1. Open System Preferences → Sharing (or System Settings → General → Sharing on newer macOS)
  2. Check "Remote Login"
  3. Set access to "Only these users" and add your user account
  4. Note the SSH connection info shown (usually your username@hostname)

Step 6: Configure SSH for Security

  1. Create/edit SSH config:
sudo nano /etc/ssh/sshd_config
  1. Add or modify these lines for better security:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
  1. Restart SSH service:
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load /System/Library/LaunchDaemons/ssh.plist

Part 3: Zellij Installation and Configuration

Step 7: Install Zellij on Mac

  1. Install using Homebrew (install Homebrew first if needed):
# Install Homebrew if you don't have it
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install Zellij
brew install zellij
  1. Verify installation:
zellij --version

Step 8: Configure Zellij

  1. Create Zellij config directory:
mkdir -p ~/.config/zellij
  1. Create a basic config file:
# Zellij will create a default config on first run, but you can create one manually:
touch ~/.config/zellij/config.kdl
  1. Optional: Add custom configuration to ~/.config/zellij/config.kdl:
// Example customizations
keybinds {
    normal {
        bind "Ctrl a" { SwitchToMode "tmux"; }
    }
}

// Set default shell
default_shell "zsh"

// Theme
theme "catppuccin-mocha"  // or "default", "gruvbox", etc.

Part 4: Terminus Setup and SSH Keys

Step 9: Install Terminus on iPhone

  1. Download "Terminus" from the App Store (by Christian Selig)
  2. Open the app and complete initial setup

Step 10: Generate SSH Key on iPhone

  1. In Terminus, tap the "⚙️" settings icon
  2. Go to "Keys"
  3. Tap "+" to create a new key
  4. Choose "Generate new key pair"
  5. Name it (e.g., "Mac Connection")
  6. Choose RSA 4096 or Ed25519 (recommended)
  7. Set a passphrase for security
  8. Tap "Generate"

Step 11: Copy Public Key to Mac

  1. In Terminus, tap your new key
  2. Tap "Export Public Key"
  3. Copy the public key text
  4. Send it to yourself via email/messages, or use AirDrop
  5. On your Mac, add the key to authorized keys:
# Create .ssh directory if it doesn't exist
mkdir -p ~/.ssh
chmod 700 ~/.ssh

# Add the public key (replace with your actual public key)
echo "your-public-key-here" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Part 5: Connection Setup

Step 12: Configure SSH Connection in Terminus

  1. In Terminus, tap "+" to add a new host
  2. Fill in the details:
    • Host: Your Mac's Tailscale IP (e.g., 100.64.0.2) or MagicDNS name
    • Port: 22
    • Username: Your Mac username
    • Key: Select the key you generated
  3. Save the connection

Step 13: Test SSH Connection

  1. Tap your saved connection in Terminus
  2. Enter your SSH key passphrase
  3. You should connect successfully to your Mac's terminal

Part 6: Using the Setup

Step 14: Start a Zellij Session on Mac

  1. Navigate to your project directory:
cd ~/your-project-folder
  1. Start a named Zellij session:
zellij -s work-session
  1. Your session is now running with the name "work-session"

Step 15: Connect from iPhone

  1. Open Terminus and connect to your Mac
  2. List available Zellij sessions:
zellij list-sessions
  1. Attach to your session:
zellij attach work-session
  1. You now have the same session mirrored on both devices in real-time!

Part 7: Workflow Tips and Optimizations

Useful Zellij Commands

# Create new named session
zellij -s project-name

# List all sessions
zellij list-sessions

# Attach to session
zellij attach session-name

# Kill session
zellij kill-session session-name

# Create new pane (while in session)
Ctrl+p + n

# Switch between panes
Ctrl+p + arrow keys

Create SSH Shortcuts (Optional)

Add to your Mac's ~/.ssh/config:

Host mac-tailscale
    HostName 100.x.x.x  # Your Mac's Tailscale IP
    User yourusername
    IdentityFile ~/.ssh/id_rsa
    ServerAliveInterval 60

iOS Shortcuts (Optional)

  1. Create an iOS Shortcut that opens Terminus and runs:
zellij attach work || zellij -s work

Troubleshooting

Connection Issues

  • Can't ping between devices: Check Tailscale is running on both devices
  • SSH connection refused: Verify Remote Login is enabled in Mac System Preferences
  • Key authentication failed: Double-check the public key was added correctly to ~/.ssh/authorized_keys

Zellij Issues

  • Session not found: Use zellij list-sessions to see available sessions
  • Permission denied: Check file permissions on SSH keys and config files
  • Commands not working: Default Zellij prefix is Ctrl+p, not Ctrl+b (tmux)

Network Issues

  • Slow connection: Try direct IP instead of MagicDNS
  • Frequent disconnects: Add ServerAliveInterval 60 to SSH config
  • Can't connect on cellular: Restart Tailscale app on iPhone

Security Notes

  • Always use SSH keys, never passwords for remote access
  • Keep your SSH keys secure and use passphrases
  • Regularly update Tailscale and Terminus
  • Consider using hardware security keys for Tailscale login
  • Monitor your Tailscale admin console for unauthorized devices

Next Steps

Once you have this working:

  • Set up dotfiles syncing for consistent shell environment
  • Configure Zellij layouts for different project types
  • Add development tools that work well in terminal (htop, git, your preferred editors)
  • Consider setting up port forwarding for accessing local web servers from your phone's browser
Loading comments...
You've successfully subscribed to The Cloud Codex
Great! Next, complete checkout to get full access to all premium content.
Error! Could not sign up. invalid link.
Welcome back! You've successfully signed in.
Error! Could not sign in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.