Skip to content

baremetalphp/go-appserver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

20 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ BareMetalPHP App Server

High-performance Go + PHP worker bridge for the BareMetalPHP framework

Go Version License Build Status PHP BareMetalPHP Go

A lightning-fast Go application server that runs BareMetalPHP via a persistent pool of PHP workers β€” similar to FrankenPHP and RoadRunner, but lightweight, transparent, and tailored for your framework.


✨ Features

  • ⚑ Persistent PHP workers β€” no cold boots
  • 🧡 Fast + slow worker pools with request classification
  • πŸ“ Static file serving (Go handles assets before PHP)
  • πŸ”₯ Hot Reload (automatic worker restart on PHP file changes)
  • 🧩 Config file support (go_appserver.json)
  • πŸ›  Automatic project root detection
  • 🚦 Graceful worker recycling (timeouts + max request count)
  • πŸ”’ Binary protocol between Go and PHP workers

πŸ“¦ Installation

1. Initialize a Go module

go mod init my-app

2. Install dependencies

go get github.com/google/uuid
go get github.com/fsnotify/fsnotify

3. Place the app server code

Expected directory layout:

my-app/
β”œβ”€β”€ go.mod
β”œβ”€β”€ cmd/
β”‚   └── server/
β”‚       β”œβ”€β”€ main.go
β”‚       └── config.go
β”œβ”€β”€ server/
β”‚   β”œβ”€β”€ worker.go
β”‚   β”œβ”€β”€ pool.go
β”‚   └── server.go
β”œβ”€β”€ php/
β”‚   β”œβ”€β”€ worker.php
β”‚   β”œβ”€β”€ bridge.php
β”‚   └── bootstrap_app.php
β”œβ”€β”€ routes/
β”‚   └── web.php
└── public/

4. Add the configuration file:

go_appserver.json


βš™οΈ Configuration (go_appserver.json)

{
  "fast_workers": 4,
  "slow_workers": 2,
  "hot_reload": true,
  "request_timeout_ms": 10000,
  "max_requests_per_worker": 1000,
  "static": [
    { "prefix": "/assets/", "dir": "public/assets" },
    { "prefix": "/css/",    "dir": "public/css" },
    { "prefix": "/js/",     "dir": "public/js" }
  ]
}

If the file is missing, defaults are automatically applied.


▢️ Running the Server

From project root:

go run ./cmd/server

Important:
Do not run go run cmd/server/main.go β€” Go will ignore config.go and break the build.
Instead run the whole package:
go run ./cmd/server

Server will start on:

http://localhost:8080

🧩 How It Works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Go HTTP Host β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”œβ”€β–Ί tryServeStatic() β†’ serves /assets/, /css/, /js/ directly
       β”‚
       └─► BuildPayload() β†’ JSON message β†’ WorkerPool
               β”‚
               β–Ό
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚ PHP Worker (hot)   β”‚   ← Boots BareMetalPHP ONCE
      β”‚ handle_bridge_req  β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
               β–Ό
      JSON response β†’ Go β†’ Browser

Go = router + static host + supervisor
PHP = long-running application kernel


πŸ”₯ Hot Reload (Dev Mode)

Enable via config:

{ "hot_reload": true }

or environment variable:

export GO_PHP_HOT_RELOAD=1

Hot reload watches for changes in:

  • php/
  • routes/

When a file changes β†’ workers marked dead β†’ automatically restarted on next request.


πŸ“ Example Project Structure

my-app/
β”œβ”€β”€ cmd/server
β”‚   β”œβ”€β”€ main.go
β”‚   └── config.go
β”œβ”€β”€ server
β”‚   β”œβ”€β”€ worker.go
β”‚   β”œβ”€β”€ pool.go
β”‚   └── server.go
β”œβ”€β”€ php
β”‚   β”œβ”€β”€ bootstrap_app.php
β”‚   β”œβ”€β”€ bridge.php
β”‚   └── worker.php
β”œβ”€β”€ routes
β”‚   └── web.php
β”œβ”€β”€ public
β”‚   └── index.html
└── go_appserver.json

πŸ› Troubleshooting

❌ Error: undefined: StaticRule or undefined: loadConfig

You're running:

go run cmd/server/main.go

Correct:

go run ./cmd/server

Go ignores files in the package if you run a single file.


❌ Error: write |1: broken pipe

This means:

  • Worker crashed
  • Worker hit max request limit
  • Hot reload replaced workers

The pool recovers automatically.


❌ Static files not served

Check:

  • Your prefix routes
  • public/ exists
  • go_appserver.json has correct directory names
  • No directory traversal (../) errors

πŸš€ Production Configuration Example

{
  "fast_workers": 12,
  "slow_workers": 4,
  "hot_reload": false,
  "request_timeout_ms": 30000,
  "max_requests_per_worker": 5000,
  "static": [
    { "prefix": "/",        "dir": "public" },
    { "prefix": "/assets/", "dir": "public/assets" }
  ]
}

🧭 Roadmap

  • WebSocket support
  • HTTP/2 + QUIC
  • Native TLS termination
  • Worker dashboard + metrics endpoint
  • Fiber-style async adapters
  • Zero-downtime worker rotation

πŸ“„ License

MIT License.
You can do whatever you want with this code :)

About

PHP App Server implementation in Golang

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors