RAMP is a deterministic local development stack manager for Windows x64. It orchestrates Apache, MySQL, and PHP through a formally defined state machine — no race conditions, no orphaned processes, no partial config writes.
Replace XAMPP or Laragon with something you can read, audit, and trust.
- Deterministic — every state transition is explicit:
STATE + EVENT → NEW STATE + SIDE EFFECTS - Safe — every service runs inside a Windows Job Object; killing RAMP kills the entire process tree, no zombies
- Observable — all transitions logged; events are replayable for debugging
- Fast — sub-second UI, Apache ready in ≤ 3 s, MySQL ready in ≤ 5 s
- Self-provisioning — generates
httpd.conf,my.ini,php.ini, and initialises the MySQL data directory on first run - System tray — lives quietly in the tray; full egui status window on demand
- Crash recovery — automatic restart with exponential backoff (1 s → 2 s → 4 s → 8 s → Error)
| Requirement | Notes |
|---|---|
| Windows 10/11 x64 | Only supported platform |
| Apache HTTP Server 2.4 (Win64, VS17) | From Apache Lounge |
| MySQL 9.x Community (ZIP) | ZIP archive, not installer |
| PHP 8.x Thread Safe (ZIP) | TS x64 ZIP — required for PHP-CGI FastCGI |
| Visual C++ Redistributable 2022 x64 | Required by Apache Lounge builds |
Grab ramp.exe from the latest release and place it at:
C:\ramp\ramp.exe
Extract the Apache ZIP so that httpd.exe ends up at:
C:\ramp\apache\bin\httpd.exe
Extract the MySQL ZIP so that mysqld.exe ends up at:
C:\ramp\mysql\bin\mysqld.exe
Extract the PHP ZIP so that php-cgi.exe ends up at:
C:\ramp\php\php-cgi.exe
The final layout should look like:
C:\ramp\
ramp.exe
apache\
bin\httpd.exe
modules\
...
mysql\
bin\mysqld.exe
lib\
share\
...
php\
php-cgi.exe
ext\
...
Run vc_redist.x64.exe if you haven't already.
Double-click ramp.exe. On first launch RAMP will:
- Generate
ramp.toml(ports 80 + 3306 + 9000) - Create
apache\conf\httpd.conf,apache\htdocs\index.php,mysql\my.ini,php\php.ini - Run
mysqld --initialize-insecure(~10–20 s, once only) - Show the system tray icon and status window
Click Start All to bring up all three services. Apache will be at http://127.0.0.1/, MySQL at 127.0.0.1:3306 (root, no password), and PHP-CGI will be listening on 127.0.0.1:9000 (FastCGI, proxied from Apache).
Edit C:\ramp\ramp.toml to change ports:
install_dir = "C:\\ramp"
[apache]
port = 80
[mysql]
port = 3306
[php]
port = 9000RAMP validates the entire file before accepting it — an invalid config is rejected completely and the last valid config is preserved. After editing, restart the affected service from the UI.
httpd.conf,my.ini, andphp.iniare generated once and never overwritten — edit them freely for custom virtual hosts, extensions, etc.
RAMP is a single binary built around a pure reducer:
STATE + EVENT → NEW STATE + SIDE EFFECTS
| Layer | File | Role |
|---|---|---|
| Types | state.rs |
AppState, ServiceState machine, all constants |
| Events | events.rs |
Event enum (11 variants) + SideEffect enum |
| Logic | reducer.rs |
Pure function — no I/O, fully unit-tested |
| I/O | executor.rs |
Translates SideEffects into process ops and threads |
| Processes | process.rs |
Windows Job Object spawn/kill |
| Health | health.rs |
Apache HTTP + MySQL TCP + PHP TCP readiness and health checks |
| Config | config.rs |
ramp.toml load/validate + atomic write |
| Paths | paths.rs |
Install-dir contract, traversal rejection, symlink rejection |
| Log | logger.rs |
Bounded ring buffer (1 000 lines) |
| Apache conf | apache_conf.rs |
Generate httpd.conf with PHP FastCGI proxy |
| MySQL conf | mysql_conf.rs |
Generate my.ini, initialize data dir |
| PHP conf | php_conf.rs |
Generate php.ini for PHP-CGI |
| Tray | tray.rs |
Windows system tray |
| UI | ui.rs |
egui status window |
Stopped ──START──► Starting ──PROCESS_READY──► Running
│ │
PROCESS_EXIT PROCESS_EXIT
│ │
└──────────► Crashed ◄──────┘
│
AUTO_RETRY (×4, backoff)
│
Starting
│
(max retries exceeded)
│
Error
Any state ──FATAL_ERROR──► Error
Running ──STOP──► Stopping ──PROCESS_EXIT──► Stopped
Every service spawns inside a dedicated Windows Job Object with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE. Dropping the job handle terminates the entire process tree — Apache child workers, MySQL threads, everything — with no orphans.
If AssignProcessToJobObject fails the service transitions directly to Error and never starts.
| Service | Check | Pass condition | Interval | Fail threshold |
|---|---|---|---|---|
| Apache | HTTP GET 127.0.0.1:port/ |
200–399 + Server: Apache |
2 s | 3 consecutive |
| MySQL | TCP connect + 4-byte greeting | Handshake starts | 2 s | 3 consecutive |
| PHP | TCP connect to FastCGI port | Connection succeeds | 2 s | 3 consecutive |
Three consecutive failures trigger HEALTH_CHECK_FAIL, which kills the service and schedules a retry.
# Prerequisites: Rust stable toolchain (rustup.rs), MSVC build tools
git clone https://github.com/rbenzing/ramp.git
cd ramp
cargo build --release
# Binary at target\release\ramp.exeRun the test suite:
cargo test
cargo clippy -- -D warnings
cargo fmt -- --check- Services bind to
127.0.0.1only — no external exposure by default - All binary paths are absolute and validated against the install directory — no PATH-based execution
- Environment variables are sanitised before spawning child processes
- Config writes are atomic (
temp → fsync → rename) — a crash during write cannot corrupt the config - Symlinks are rejected for the config directory, binaries, and data directory
- MySQL is initialised with
--initialize-insecure(no root password) — suitable for local development only
RAMP is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License v3.0.