WiredAlter-Term
Repository: https://github.com/buildplan/WiredAlter-Term
Project Overview
WiredAlter-Term is a containerized, web-based terminal interface designed to provide a persistent, portable, and customizable command-line environment accessible via a browser. Built on Node.js 24 and Debian 13 (Trixie), it leverages xterm.js and node-pty for terminal emulation while maintaining a persistent backend state.
The core design philosophy emphasizes portability (running on any host without permission conflicts) and persistence (separating user configuration from the ephemeral container runtime).
System Architecture
1. The “Seed and Link” Persistence Strategy
To resolve the conflict between ephemeral container filesystems and the need for persistent user configurations (dotfiles), the application employs a custom “Seed and Link” logic during startup (src/index.js):
- Detection: The application checks a mounted host volume (
/data) for existing configuration files. - Seeding: If specific files (e.g.,
.bashrc,starship.toml) are missing from the volume, the application copies “Factory Defaults” (baked into the container image at/usr/local/share/smart-term) to the volume. - Linking: The application forcefully removes the container’s local configuration directories and replaces them with symbolic links pointing to the
/datavolume.
This ensures that user customizations survive container restarts, while the system remains self-healing if configuration files are corrupted or deleted.
2. Dynamic Permission Mapping
To enable Docker-in-Docker control without privilege escalation issues, the entrypoint script (src/entrypoint.sh) dynamically detects the Group ID (GID) of the host’s Docker socket (/var/run/docker.sock). It creates a corresponding group inside the container and adds the node user to it at runtime, ensuring seamless communication with the host Docker daemon.
3. Security Layer
The application implements a custom authentication middleware using:
- Express-Session & FileStore: Sessions are persisted to disk (
/data/sessions), preventing user logout during container restarts. - Rate Limiting: A brute-force protection mechanism locks out login attempts for 15 minutes after 5 failed PIN entries.
- Asset Whitelisting: Static assets (CSS, Fonts, JS) are served via a whitelist to ensure the login page remains accessible while protecting the socket connection.
Installation & Deployment
Prerequisites
- Docker and Docker Compose installed on the host machine.
- (Optional) A reverse proxy (Nginx/Traefik/Cloudflare Tunnel) if exposing to the public internet.
Quick Start
- Clone the Repository:
git clone https://github.com/buildplan/WiredAlter-Term.git
cd WiredAlter-Term
- Deploy via Docker Compose: The default configuration exposes the terminal on port
3939.
docker compose up -d --build
- Access: Navigate to
http://localhost:3939(or your server IP).- Default PIN:
123456(Change this immediately in production).
- Default PIN:
Configuration
Configuration is managed via Environment Variables in docker-compose.yml.
| Variable | Default | Description |
|---|---|---|
PIN | 123456 | The numeric passcode required to access the terminal. |
SESSION_SECRET | (Default string) | A random string used to sign session cookies. Must be changed. |
PORT | 3939 | The internal port the Node.js application listens on. |
NODE_ENV | production | Set to production for performance optimization. |
Example docker-compose.yml
services:
wiredalter-term:
build: .
image: wiredalter-term
container_name: wiredalter-term
restart: unless-stopped
ports:
- "3939:3939"
volumes:
# Persistent storage for configs, keys, and history
- ./data:/data
# Socket mapping for Docker-in-Docker control
- /var/run/docker.sock:/var/run/docker.sock
environment:
- PIN=882299
- SESSION_SECRET=ChangeThisToARandomString123!
- NODE_ENV=production
Data Persistence & Storage
All persistent data is stored in the ./data directory on the host machine. The container symlinks internal paths to this directory.
| Feature | Container Path | Host Path | Notes |
|---|---|---|---|
| General Storage | ~/storage | ./data/storage | Use this folder for persistent downloads/scripts. |
| SSH Keys | ~/.ssh | ./data/.ssh | Keys generated here persist across rebuilds. |
| Shell Config | ~/.bashrc | ./data/.bashrc | Stores aliases and env vars. |
| Shell History | ~/.bash_history | ./data/.bash_history | Preserves command history. |
| Prompt Config | ~/.config/ | ./data/.config/ | Stores starship.toml. |
| Fonts | (Internal) | ./data/fonts/ | Holds the .ttf file served to the frontend. |
Customization Guide
1. Changing the Font
The terminal uses a Nerd Font to render icons correctly. To change the font (e.g., to FiraCode or JetBrains Mono):
- Download a Nerd Font compatible
.ttffile. - Rename the file to
font.ttf. - Replace the existing file at
./data/fonts/font.ttfon the host. - Perform a “Hard Refresh” in the browser (
Ctrl+F5) to clear the font cache.
2. Customizing the Prompt
The prompt is powered by Starship.
- Locate
./data/.config/starship.tomlon the host. - Edit the file to modify colors, symbols, or module behavior.
- Restart the container (
docker compose restart) or reload the shell to apply changes.
3. Factory Reset
If configuration files become corrupted or usability is lost:
- Stop the container:
docker compose down. - Delete the specific configuration file from the host’s
./datadirectory (e.g.,rm data/.config/starship.toml). - Start the container:
docker compose up -d. - The system will detect the missing file and auto-restore the factory default version.
Troubleshooting
“Docker permission denied” inside the terminal
Cause: The container cannot access the host’s Docker socket due to a Group ID mismatch. Solution: Ensure /var/run/docker.sock is mounted in docker-compose.yml. Check container logs (docker logs wiredalter-term) to confirm the entrypoint script successfully detected the GID:
🔌 Detected Host Docker GID: 999
Changes to starship.toml keep reverting
Cause: Starship defaults to a built-in preset if it detects a syntax error in the configuration file. Solution:
- Run
cat ~/.config/starship.tomlinside the terminal to verify your changes exist on disk. - If the file exists but the prompt looks like the default, check the file for syntax errors (missing quotes, unclosed brackets).
npm install fails during local development
Cause: The node-pty dependency requires C++ compilation tools (python3, make, g++) which may not be present on the host machine. Solution: Do not run npm install on the host. Allow the Dockerfile to handle installation during the build process, as it includes the necessary build toolchain.