A modular web framework for C, inspired by kernel modules. Dynamically upload and compile C code at runtime to build REST APIs, WebSocket services, and more. Includes support for JSON (Jansson), SQLite, OpenSSL, and streaming large data efficiently.
See the codeNote:
This project is currently a proof of concept and represents the bare minimum viable product (MVP).
It is not designed for production use, and there may be bugs, limitations, or incomplete features.
Use at your own discretion.
Alert: Rework in progress. The “web framework” direction isn’t a good fit for C because HTML/templates add too much complexity. I’m refocusing this on compute-first modules where C is a better fit.
Welcome to c-web-modules, a C plugin host for CPU bound web workloads. Inspired by kernel modules and AWS Lambda, this project lets you upload C code directly to the server, compile it at runtime, and hot-swap the logic without restarting the host.
For more detailed information, please refer to the official documentation.
c-web-modules is focused on compute + streaming, not traditional frontend work. It is designed for workloads where you want C-level performance and low-latency streaming.
/jobs APIs./jobs/ws and expose durable status via /jobs/:uuid.The production environment uses TLS for encrypting, by default it expects there to be a server.crt and server.key which can be generated by using this command:
openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365 -nodes
Modules register routes with method + path. Paths must be unique across modules and can use regex.
Modules register WebSocket handlers and keep connections alive across hot-swaps.
Modules register jobs and the server triggers them via /jobs/*.
module_hash for provenance.Jobs deploy the same way as HTTP/WS modules: upload a C module to /mgnt. A single module can define routes, WebSockets, and jobs at the same time.
/jobs/* is a protected namespace owned by the server. Modules cannot register routes under /jobs/.
POST /jobs - Trigger a job with { "module": "mod", "job": "name", "payload": { ... } }GET /jobs/:uuid - Job status, including module_hashPOST /jobs/:uuid/cancel - Cancel a jobGET /jobs?state=running - List jobs by stateWS /jobs/ws?id=:uuid&since_event_id=456job_events and supports replay from since_event_id.CWEB_ADMIN_KEY to require an admin key for /mgnt, /jobs, and /jobs/ws.X-API-Key: <key> or Authorization: Bearer <key>.127.0.0.1 are allowed without a key./jobs HTTP API with UUIDs, status, cancel, and list.module_t.jobs[]) and triggered by name..so for provenance in job status./jobs/ws with id and since_event_id query params.jobs(
id INTEGER PRIMARY KEY,
module_name TEXT,
job_name TEXT,
state TEXT,
module_hash TEXT,
created_at INTEGER,
updated_at INTEGER,
payload_json TEXT,
result_json TEXT,
error_text TEXT
)
job_events(
id INTEGER PRIMARY KEY,
job_id INTEGER,
ts INTEGER,
type TEXT,
data_json TEXT
)
Currently supported external libraries:
Deploying code to the server is simple and can be done in multiple ways, depending on your workflow.
curlAt its core, deploying code to the server involves sending a POST request with the C file attached. Here’s an example using curl:
curl -X POST -F "code=@path/to/yourcode.c" http://localhost:8080/mgnt
The script handles:
curl../cweb deploy path/to/yourcode.c
You can deploy multiple modules in one go using a configuration file. By default, the script looks for a file named routes.ini.
Example routes.ini file:
server_url=http://localhost:8080/mgnt
[modules]
example1.c
example2.c
When using the .ini files you run: ./cweb deploy
For Windows there currently only is a very primitve deploy.bat script:
.\deploy.bat file.c
The server needs to be specified inside the .bat file, default is: http://localhost:8080/mgnt
Error messages are forwarded back to you over http.
Note:
MacOS support is not guaranteed!
The project depends on:
# Debian
sudo apt-get install libssl-dev
sudo apt-get install libsqlite3-dev
sudo apt-get install libjansson-dev
# Arch
sudo pacman -S openssl
sudo pacman -S sqlite
sudo pacman -S jansson
# Bug with archlinux and fanitizser, ref: https://github.com/joexbayer/c-web-modules/issues/12
sudo sysctl vm.mmap_rnd_bits=30
# MacOS
brew install openssl@3
brew install sqlite
brew install jansson
Run make to compile and make run to start the server.
make
make run
--module-dir <path> (or -m <path>): Store compiled modules and routes.dat in a specific directory. Defaults to modules.--purge-modules (or -P): Delete compiled .so modules on shutdown. Off by default.docker-compose up --build
Unlike Apache modules and ISAPI extensions, which are tightly integrated into the server and require configuration changes followed by a server restart or reload, c-web-modules offers runtime flexibility.
Key Differences:
Dynamic Deployment:
c-web-modules allows you to upload raw C code directly to the server, which compiles and integrates it into the running application without restarts. Neither Apache modules nor ISAPI extensions support this level of runtime modification.
Module Isolation:
Each module in c-web-modules is independently managed, minimizing the risk of crashing the entire server.
WebSocket Updates:
WebSocket handlers can be updated at runtime without breaking existing connections, a feature not typically available in Apache modules or ISAPI.
This makes c-web-modules suitable for rapid experimentation and modular design, especially in scenarios requiring frequent updates without disrupting service.
83 commits
C
97.3%
Shell
1.3%
Makefile
1.1%
A modular web framework for C, inspired by kernel modules. Dynamically upload and compile C code at runtime to build REST APIs, WebSocket services, and more. Includes support for JSON (Jansson), SQLite, OpenSSL, and streaming large data efficiently.
See the codeNote:
This project is currently a proof of concept and represents the bare minimum viable product (MVP).
It is not designed for production use, and there may be bugs, limitations, or incomplete features.
Use at your own discretion.
Alert: Rework in progress. The “web framework” direction isn’t a good fit for C because HTML/templates add too much complexity. I’m refocusing this on compute-first modules where C is a better fit.
Welcome to c-web-modules, a C plugin host for CPU bound web workloads. Inspired by kernel modules and AWS Lambda, this project lets you upload C code directly to the server, compile it at runtime, and hot-swap the logic without restarting the host.
For more detailed information, please refer to the official documentation.
c-web-modules is focused on compute + streaming, not traditional frontend work. It is designed for workloads where you want C-level performance and low-latency streaming.
/jobs APIs./jobs/ws and expose durable status via /jobs/:uuid.The production environment uses TLS for encrypting, by default it expects there to be a server.crt and server.key which can be generated by using this command:
openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365 -nodes
Modules register routes with method + path. Paths must be unique across modules and can use regex.
Modules register WebSocket handlers and keep connections alive across hot-swaps.
Modules register jobs and the server triggers them via /jobs/*.
module_hash for provenance.Jobs deploy the same way as HTTP/WS modules: upload a C module to /mgnt. A single module can define routes, WebSockets, and jobs at the same time.
/jobs/* is a protected namespace owned by the server. Modules cannot register routes under /jobs/.
POST /jobs - Trigger a job with { "module": "mod", "job": "name", "payload": { ... } }GET /jobs/:uuid - Job status, including module_hashPOST /jobs/:uuid/cancel - Cancel a jobGET /jobs?state=running - List jobs by stateWS /jobs/ws?id=:uuid&since_event_id=456job_events and supports replay from since_event_id.CWEB_ADMIN_KEY to require an admin key for /mgnt, /jobs, and /jobs/ws.X-API-Key: <key> or Authorization: Bearer <key>.127.0.0.1 are allowed without a key./jobs HTTP API with UUIDs, status, cancel, and list.module_t.jobs[]) and triggered by name..so for provenance in job status./jobs/ws with id and since_event_id query params.jobs(
id INTEGER PRIMARY KEY,
module_name TEXT,
job_name TEXT,
state TEXT,
module_hash TEXT,
created_at INTEGER,
updated_at INTEGER,
payload_json TEXT,
result_json TEXT,
error_text TEXT
)
job_events(
id INTEGER PRIMARY KEY,
job_id INTEGER,
ts INTEGER,
type TEXT,
data_json TEXT
)
Currently supported external libraries:
Deploying code to the server is simple and can be done in multiple ways, depending on your workflow.
curlAt its core, deploying code to the server involves sending a POST request with the C file attached. Here’s an example using curl:
curl -X POST -F "code=@path/to/yourcode.c" http://localhost:8080/mgnt
The script handles:
curl../cweb deploy path/to/yourcode.c
You can deploy multiple modules in one go using a configuration file. By default, the script looks for a file named routes.ini.
Example routes.ini file:
server_url=http://localhost:8080/mgnt
[modules]
example1.c
example2.c
When using the .ini files you run: ./cweb deploy
For Windows there currently only is a very primitve deploy.bat script:
.\deploy.bat file.c
The server needs to be specified inside the .bat file, default is: http://localhost:8080/mgnt
Error messages are forwarded back to you over http.
Note:
MacOS support is not guaranteed!
The project depends on:
# Debian
sudo apt-get install libssl-dev
sudo apt-get install libsqlite3-dev
sudo apt-get install libjansson-dev
# Arch
sudo pacman -S openssl
sudo pacman -S sqlite
sudo pacman -S jansson
# Bug with archlinux and fanitizser, ref: https://github.com/joexbayer/c-web-modules/issues/12
sudo sysctl vm.mmap_rnd_bits=30
# MacOS
brew install openssl@3
brew install sqlite
brew install jansson
Run make to compile and make run to start the server.
make
make run
--module-dir <path> (or -m <path>): Store compiled modules and routes.dat in a specific directory. Defaults to modules.--purge-modules (or -P): Delete compiled .so modules on shutdown. Off by default.docker-compose up --build
Unlike Apache modules and ISAPI extensions, which are tightly integrated into the server and require configuration changes followed by a server restart or reload, c-web-modules offers runtime flexibility.
Key Differences:
Dynamic Deployment:
c-web-modules allows you to upload raw C code directly to the server, which compiles and integrates it into the running application without restarts. Neither Apache modules nor ISAPI extensions support this level of runtime modification.
Module Isolation:
Each module in c-web-modules is independently managed, minimizing the risk of crashing the entire server.
WebSocket Updates:
WebSocket handlers can be updated at runtime without breaking existing connections, a feature not typically available in Apache modules or ISAPI.
This makes c-web-modules suitable for rapid experimentation and modular design, especially in scenarios requiring frequent updates without disrupting service.
83 commits
C
97.3%
Shell
1.3%
Makefile
1.1%