Skip to content

Instantly share code, notes, and snippets.

@johnoscott
Last active November 24, 2025 07:55
Show Gist options
  • Select an option

  • Save johnoscott/f5d5110ddec85cb04729fe8ef982eeb8 to your computer and use it in GitHub Desktop.

Select an option

Save johnoscott/f5d5110ddec85cb04729fe8ef982eeb8 to your computer and use it in GitHub Desktop.
Syncthing MacBook client setup script
#!/bin/bash
# Add a folder to Syncthing sync
# Usage: ./add-sync-folder.sh /path/to/folder [folder-id]
set -e
if [ -z "$1" ]; then
echo "Usage: $0 /path/to/folder [folder-id]"
echo "Example: $0 ~/Developer/my-project"
exit 1
fi
# Expand path
FOLDER_PATH=$(cd "$1" 2>/dev/null && pwd || echo "$1")
if [ ! -d "$FOLDER_PATH" ]; then
echo "Error: Directory does not exist: $FOLDER_PATH"
exit 1
fi
# Generate folder ID from path if not provided
if [ -z "$2" ]; then
FOLDER_ID=$(basename "$FOLDER_PATH" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
else
FOLDER_ID="$2"
fi
FOLDER_LABEL=$(basename "$FOLDER_PATH")
# Server device ID
SERVER_DEVICE_ID="MN3ITLN-KOKU2QK-WDLYF6W-WDSDUU3-PALUU3L-Q32FOGP-RKW2YKO-E6KKMQK"
# Get API key
CONFIG_PATH="$HOME/Library/Application Support/Syncthing/config.xml"
API_KEY=$(grep -o '<apikey>[^<]*' "$CONFIG_PATH" | sed 's/<apikey>//')
if [ -z "$API_KEY" ]; then
echo "Error: Could not find Syncthing API key"
exit 1
fi
echo "Adding folder to Syncthing..."
echo " Path: $FOLDER_PATH"
echo " ID: $FOLDER_ID"
echo " Label: $FOLDER_LABEL"
# Add folder
curl -s -X POST -H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"id\": \"$FOLDER_ID\",
\"label\": \"$FOLDER_LABEL\",
\"path\": \"$FOLDER_PATH\",
\"type\": \"sendreceive\",
\"devices\": [
{\"deviceID\": \"$SERVER_DEVICE_ID\"}
],
\"rescanIntervalS\": 60,
\"fsWatcherEnabled\": true,
\"fsWatcherDelayS\": 1,
\"ignorePerms\": false,
\"autoNormalize\": true
}" \
http://127.0.0.1:8384/rest/config/folders
echo ""
echo "✅ Folder added successfully!"
echo ""
echo "Folder ID: $FOLDER_ID"
echo ""
echo "Next: Add this folder on the home server and other devices using the same folder ID."
.PHONY: download-scripts add-folder
GIST_URL = https://gist.githubusercontent.com/johnoscott/f5d5110ddec85cb04729fe8ef982eeb8/raw
download-scripts:
curl -sL $(GIST_URL)/setup-macbook-client.sh -o setup-macbook-client.sh
curl -sL $(GIST_URL)/add-sync-folder.sh -o add-sync-folder.sh
chmod +x setup-macbook-client.sh add-sync-folder.sh
@echo "Scripts downloaded"
add-folder:
ifndef FOLDER
$(error FOLDER is required. Usage: make add-folder FOLDER=~/Developer/my-project)
endif
./add-sync-folder.sh $(FOLDER)
#!/bin/bash
# Syncthing MacBook Client Setup Script
# This script installs and configures Syncthing on a MacBook
set -e
# Configuration - UPDATE THESE VALUES
SERVER_DEVICE_ID="MN3ITLN-KOKU2QK-WDLYF6W-WDSDUU3-PALUU3L-Q32FOGP-RKW2YKO-E6KKMQK"
SERVER_IP="192.168.86.57"
FOLDER_ID="dev-projects"
FOLDER_PATH="$HOME/SyncedProjects"
echo "=== Syncthing MacBook Client Setup ==="
echo ""
# Install Homebrew if not present
if ! command -v brew &> /dev/null; then
echo "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Add Homebrew to PATH for Apple Silicon
if [[ $(uname -m) == "arm64" ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
fi
# Install Syncthing
echo "Installing Syncthing..."
brew install syncthing
# Determine syncthing path based on architecture
if [[ $(uname -m) == "arm64" ]]; then
SYNCTHING_PATH="/opt/homebrew/bin/syncthing"
else
SYNCTHING_PATH="/usr/local/bin/syncthing"
fi
# Create LaunchAgent
echo "Creating LaunchAgent for auto-start..."
mkdir -p ~/Library/LaunchAgents
cat > ~/Library/LaunchAgents/com.syncthing.syncthing.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.syncthing.syncthing</string>
<key>ProgramArguments</key>
<array>
<string>${SYNCTHING_PATH}</string>
<string>serve</string>
<string>--no-browser</string>
<string>--no-restart</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>ProcessType</key>
<string>Background</string>
<key>LowPriorityBackgroundIO</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/syncthing.log</string>
<key>StandardErrorPath</key>
<string>/tmp/syncthing-error.log</string>
</dict>
</plist>
EOF
# Start Syncthing service
echo "Starting Syncthing service..."
launchctl load ~/Library/LaunchAgents/com.syncthing.syncthing.plist
# Wait for config to initialize
echo "Waiting for Syncthing to initialize..."
sleep 5
# Get device ID (using new CLI syntax for v2.x)
DEVICE_ID=$($SYNCTHING_PATH cli show system | grep myID | cut -d'"' -f4)
echo ""
echo "=== This MacBook's Device ID ==="
echo "$DEVICE_ID"
echo ""
# Get API key
CONFIG_PATH="$HOME/Library/Application Support/Syncthing/config.xml"
API_KEY=$(grep -o '<apikey>[^<]*' "$CONFIG_PATH" | sed 's/<apikey>//')
# Create sync folder
echo "Creating sync folder at $FOLDER_PATH..."
mkdir -p "$FOLDER_PATH"
# Add home server as remote device
echo "Adding home server as remote device..."
curl -s -X POST -H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"deviceID\": \"$SERVER_DEVICE_ID\",
\"name\": \"HomeServer\",
\"addresses\": [\"tcp://$SERVER_IP:22000\"],
\"compression\": \"metadata\",
\"introducer\": false,
\"paused\": false
}" \
http://127.0.0.1:8384/rest/config/devices
# Add sync folder
echo "Configuring sync folder..."
curl -s -X POST -H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"id\": \"$FOLDER_ID\",
\"label\": \"Development Projects\",
\"path\": \"$FOLDER_PATH\",
\"type\": \"sendreceive\",
\"devices\": [
{\"deviceID\": \"$SERVER_DEVICE_ID\"}
],
\"rescanIntervalS\": 60,
\"fsWatcherEnabled\": true,
\"fsWatcherDelayS\": 1,
\"ignorePerms\": false,
\"autoNormalize\": true
}" \
http://127.0.0.1:8384/rest/config/folders
# Create .stignore file
echo "Creating .stignore file..."
cat > "$FOLDER_PATH/.stignore" << 'EOF'
// Ignore OS files
.DS_Store
Thumbs.db
// Ignore common development artifacts
node_modules
.next
dist
build
target
*.pyc
__pycache__
.pytest_cache
.venv
venv
.env.local
// Ignore IDE settings (optional - remove if you want these synced)
// .idea
// .vscode
// Ignore temporary files
*.tmp
*.swp
*~
EOF
# Restart to apply config
echo "Restarting Syncthing to apply configuration..."
launchctl unload ~/Library/LaunchAgents/com.syncthing.syncthing.plist
launchctl load ~/Library/LaunchAgents/com.syncthing.syncthing.plist
echo ""
echo "=== Setup Complete ==="
echo ""
echo "MacBook Device ID: $DEVICE_ID"
echo "Sync Folder: $FOLDER_PATH"
echo "Web UI: http://127.0.0.1:8384"
echo ""
echo "IMPORTANT: You need to add this device on the home server!"
echo "Run the following on the Proxmox container (pct exec 201):"
echo ""
echo "Add device and folder share using the Web UI at http://$SERVER_IP:8384"
echo "Or use the API to add this device ID: $DEVICE_ID"
echo ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment