Skip to main content

Local Setup

Optional

You don't need a local setup. Everything works server side, browser based desktop, VS Code, and SSH from any device. This page covers optional local editing with automatic sync to the server.

Step 1: Connect via SSH

The server listens on port 3434. Connect with:

ssh -p 3434 abc@<server-ip>
# → Enter your SUDO_PASSWORD

Replace <server-ip> with your server's IP address.

Skip repeated password prompts (optional)

If you connect frequently, you can make SSH reuse a single authenticated connection so you only enter your password once every 16 hours. Add this at the top of ~/.ssh/config:

Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 16h

Then create the directory it needs:

mkdir -p ~/.ssh/sockets
chmod 700 ~/.ssh/sockets

How it works: When you first run ssh -p 3434 abc@<server-ip>, you enter your password as usual. SSH keeps that connection open in the background. Every subsequent ssh, scp, or rsync to the same server rides the existing connection with no password prompt for up to 16 hours.

note

If rsync fails with a connection error, it may be because the multiplexed SSH connection has timed out. Run ssh -O exit abc@<server-ip> to close the old connection, then connect again normally. Rsync will work.

:::

Step 2: Global .gitignore (safety net)

Prevents IDE config files from being committed to any Git repo:

touch ~/.gitignore_global

cat >> ~/.gitignore_global << 'EOF'
# VS Code
.vscode/
*.code-workspace

# General IDE
.idea/
.DS_Store
*.swp
*.swo
*~
EOF

git config --global core.excludesfile ~/.gitignore_global

Step 3: Install the Run on Save extension

code --install-extension emeraldwalk.runonsave

Step 4: Create a workspace file

This file maps your local project to the server. Keep it outside your project folder so it's never committed to Git.

Create ~/Documents/Workspaces/cloud-dev.code-workspace:

{
"folders": [
{
"name": "my-project",
"path": "/Users/<your-username>/Code/my-project"
}
],
"settings": {
"files.autoSave": "onFocusChange",
"emeraldwalk.runonsave": {
"commands": [
{
"match": ".*",
"cmd": "rsync -avz --delete -e 'ssh -p 3434' /Users/<your-username>/Code/my-project/ abc@<server-ip>:/projects/my-project/"
}
]
}
}
}

Replace:

  • <your-username>: your system username
  • <server-ip>: your server's IP address
  • my-project: your project folder name (both in the local path and on /projects/)
  • Adjust the local path (/Users/.../Code/ or /home/.../Code/) to match where your project lives

How it works:

  • You edit files in your local folder normally
  • When you click away from a file, VS Code autosaves → Run on Save fires rsync
  • rsync compares your entire local project against the server copy
  • Only changed files are transferred (incremental, not the whole project each time)
  • --delete means: if you deleted a file locally, it's deleted on the server too
Trailing slash matters

rsync /path/my-project/ (with trailing slash) copies the contents of the directory. rsync /path/my-project (no trailing slash) copies the directory itself. The workspace config uses a trailing slash on the source. Get this wrong and you'll get /projects/my-project/my-project/ on the server.

Why onFocusChange and not afterDelay

  • afterDelay saves every second you pause typing → hundreds of rsync calls per minute → server gets hammered
  • onFocusChange saves only when you click away from the editor (to terminal, another tab, browser) → one upload per editing session per file → clean

Why rsync instead of scp

  • scp only uploads files: deletions are lost. You'd have to manually clean up the server
  • rsync --delete gives you a true mirror: create, edit, delete locally → reflected on the server
  • rsync sends only changed blocks, not entire files: faster for large files
  • rsync scans the full project on every run: for typical projects this takes under a second

Step 5: Open the workspace

Instead of File → Open Folder, use:

  • Double click cloud-dev.code-workspace in your file manager
  • Or File → Open Workspace from File... in VS Code