Skip to content

A self-hosted web IDE that lets you code from anywhere. Deploy it on your server and access your development environment from any browser.

License

Notifications You must be signed in to change notification settings

guneyural/nomad-ide

Nomad IDE

Portable IDE. Vibe Code Anywhere.

License: MIT Node.js pnpm Docker

A self-hosted web IDE that lets you code from anywhere — especially from your mobile device. Deploy it on your server and access your development environment from any browser.

Features

Code Editor

  • Monaco Editor — The same editor that powers VS Code
  • Multi-file tabs with unsaved changes indicator
  • Syntax highlighting for 20+ languages
  • Auto-save with Ctrl/Cmd+S

Terminal

  • Full PTY Terminal — Real terminal, not emulation
  • WebSocket-based real-time streaming
  • Clickable links in output
  • 256-color and truecolor support

Claude Code Integration

  • Native Claude CLI support built-in
  • Dedicated Claude terminal panel
  • Virtual keyboard for mobile devices
  • AI-powered coding assistance

Git Integration

  • Multi-repository support — Work with multiple git repos in one project
  • Stage, unstage, commit, push, and pull
  • Visual diff viewer with color-coded changes
  • Branch management and commit history
  • Undo last commit (soft reset)
  • GitHub token management for private repos

File Explorer

  • Tree-style navigation
  • Create, rename, and delete files/folders
  • File type icons
  • Smart filtering (hides node_modules, .git, etc.)

Security

  • Two-Factor Authentication — TOTP-based (Google Authenticator, Authy)
  • JWT with HttpOnly cookies
  • Account lockout after failed attempts
  • Rate limiting on auth endpoints
  • Path traversal protection

Mobile-First Design

  • Responsive layout for all screen sizes
  • Virtual keyboard for terminal input
  • Touch-friendly UI elements
  • Collapsible panels

Quick Start with Docker

Prerequisites

  • Docker and Docker Compose
  • A server with a public IP (or run locally)

Installation

  1. Clone the repository:
git clone https://github.com/guneyural/nomad-ide.git
cd nomad-ide
  1. Configure environment:
cp .env.example .env

# Generate a secure JWT secret
echo "JWT_SECRET=$(openssl rand -base64 32)" >> .env
  1. Start the application:
docker-compose up -d
  1. Access the IDE:
    • Open http://your-server-ip:3000
    • Complete initial setup (create admin account + enable 2FA)

Tech Stack

Frontend

  • Next.js 16 with Turbopack
  • React 19
  • Tailwind CSS for styling
  • Monaco Editor for code editing
  • xterm.js for terminal
  • Redux Toolkit + RTK Query

Backend

  • Express.js REST API
  • Socket.io for real-time communication
  • Prisma ORM with SQLite
  • node-pty for terminal sessions

Infrastructure

  • pnpm workspaces (monorepo)
  • TypeScript throughout
  • Docker for deployment

Project Structure

nomad-ide/
├── apps/
│   ├── web/                  # Next.js frontend
│   │   ├── src/
│   │   │   ├── app/          # App router pages
│   │   │   ├── components/   # React components
│   │   │   ├── hooks/        # Custom hooks
│   │   │   ├── lib/          # Utilities
│   │   │   └── store/        # Redux store
│   │   └── ...
│   │
│   └── server/               # Express backend
│       ├── src/
│       │   ├── routes/       # API routes
│       │   ├── services/     # Business logic
│       │   ├── middleware/   # Auth, validation
│       │   └── utils/        # Helpers
│       ├── prisma/           # Database schema
│       └── ...
│
├── packages/
│   └── shared/               # Shared types & utils
│
├── docker-compose.yml
├── Dockerfile
└── README.md

Configuration

Environment Variables

Variable Description Required Default
JWT_SECRET Secret for JWT signing Yes
DATABASE_URL SQLite database path No file:./nomad-ide.db
PORT Backend server port No 4000
CORS_ORIGIN Frontend URL for CORS No http://localhost:3000
COOKIE_SECURE Set to false for HTTP (see below) No true in production
PROJECTS_DIR Base projects directory No ~/projects

⚠️ Important: HTTP vs HTTPS

By default, cookies are set with Secure flag in production, which only works over HTTPS. If you're running without HTTPS (e.g., http://your-ip:3000), you must set:

COOKIE_SECURE=false

Otherwise, authentication will fail after login (cookies won't be saved by the browser).

Deployment

Using Docker Compose (Recommended)

docker-compose up -d

Data is persisted in the ./data directory. Projects are mounted from ~/projects.

Using Docker Run

If you prefer docker run instead of docker-compose:

# 1. Create data directory and generate JWT secret
mkdir -p ~/nomad-ide-data
openssl rand -base64 32 > ~/nomad-ide-data/jwt-secret.txt
chmod 600 ~/nomad-ide-data/jwt-secret.txt

# 2. Create the projects directory with correct permissions
sudo mkdir -p /home/nomad
sudo chown -R 1001:1001 /home/nomad

# 3. Pull and run the container
docker run -d \
  --name nomad-ide \
  -p 3005:3000 \
  -p 3006:4000 \
  -v ~/nomad-ide-data:/app/data \
  -v /home/nomad:/home/nomad \
  -e JWT_SECRET="$(cat ~/nomad-ide-data/jwt-secret.txt)" \
  -e COOKIE_SECURE=false \
  --restart unless-stopped \
  guneyural0/nomad-ide:latest

Then access the IDE at http://your-server-ip:3005

📁 Volume Mounts Explained:

  • -v ~/nomad-ide-data:/app/data — Database and app data (persists between updates)
  • -v /home/nomad:/home/nomad — Projects directory (your code files)

⚠️ Important: Permissions

The container runs as user nomad (uid 1001). You must set correct ownership on the projects directory:

sudo chown -R 1001:1001 /home/nomad

Without this, you'll get "Permission denied" errors when running npm install, git, or Claude CLI.

🔌 Port Mapping:

  • Frontend: External port 3005 → Container port 3000
  • Backend/WebSocket: External port 3006 → Container port 4000

The frontend automatically connects to backend on frontend_port + 1. So if you use -p 8080:3000 -p 8081:4000, access via http://your-ip:8080.

🔑 Environment Variables:

  • JWT_SECRET — Required. Keep this consistent across container updates to preserve sessions.
  • COOKIE_SECURE=false — Required for HTTP. Remove this if using HTTPS.

Reverse Proxy with Nginx

For HTTPS support, use a reverse proxy:

server {
    listen 443 ssl http2;
    server_name ide.yourdomain.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # Frontend
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # Backend API
    location /api {
        proxy_pass http://localhost:4000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # WebSocket
    location /socket.io {
        proxy_pass http://localhost:4000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

Reverse Proxy with Caddy

ide.yourdomain.com {
    reverse_proxy /api/* localhost:4000
    reverse_proxy /socket.io/* localhost:4000
    reverse_proxy * localhost:3000
}

Using Claude Code

  1. Open a project in Nomad IDE
  2. Go to Settings (gear icon) and enter your Anthropic API key
  3. Click the Claude tab in the bottom panel
  4. Start coding with AI assistance

Note: Your API key is stored securely and never leaves your server.

The Claude terminal includes a virtual keyboard for mobile devices.

Security Features

Feature Description
2FA (TOTP) Google Authenticator, Authy compatible
JWT + HttpOnly Cookies Secure session management
Account Lockout 15 min lockout after 5 failed attempts
Rate Limiting 10 requests per 15 min on auth
Path Traversal Protection Can't access files outside project
Security Headers Helmet.js middleware
Non-root Docker User Runs as unprivileged user

Troubleshooting

"Permission denied" errors in terminal

npm error EACCES: permission denied

Cause: The /home/nomad directory has wrong ownership.

Solution:

sudo chown -R 1001:1001 /home/nomad

"Failed to connect to terminal server"

Cause: WebSocket can't connect to backend.

Solution: Make sure you're mapping both ports:

-p FRONTEND_PORT:3000 -p BACKEND_PORT:4000

Backend port must be FRONTEND_PORT + 1. Example: -p 3005:3000 -p 3006:4000

Login works but immediately logs out (401 errors)

Cause: Secure cookies over HTTP.

Solution: Add -e COOKIE_SECURE=false to your docker run command.

"execvp(3) failed" in terminal

Cause: Shell not found (old Docker image).

Solution: Pull the latest image:

docker pull guneyural0/nomad-ide:latest

Claude CLI shows "execvp failed"

Cause: Old Docker image.

Solution:

  1. Pull latest image: docker pull guneyural0/nomad-ide:latest
  2. Restart the container

Files not visible in IDE

Cause: Directory not mounted into container.

Solution: Add volume mount: -v /path/on/host:/path/in/container

Database reset after container update

Cause: Database file name mismatch.

Solution: The database is stored at /app/data/nomad-ide.db. Make sure your volume mount points to /app/data:

-v ~/nomad-ide-data:/app/data

Updating Nomad IDE

# 1. Stop and remove old container
docker stop nomad-ide && docker rm nomad-ide

# 2. Pull latest image
docker pull guneyural0/nomad-ide:latest

# 3. Run with same volume mounts (data persists)
docker run -d \
  --name nomad-ide \
  -p 3005:3000 \
  -p 3006:4000 \
  -v ~/nomad-ide-data:/app/data \
  -v /home/nomad:/home/nomad \
  -e JWT_SECRET="your-same-jwt-secret" \
  -e COOKIE_SECURE=false \
  --restart unless-stopped \
  guneyural0/nomad-ide:latest

Keep JWT_SECRET the same to preserve user sessions.

Contributing

Contributions are welcome! Here's how to get started:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run pnpm build to ensure everything compiles
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

License

MIT License — see LICENSE for details.


Built for developers who code on the go.

About

A self-hosted web IDE that lets you code from anywhere. Deploy it on your server and access your development environment from any browser.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages