ajwdev / mod_wasm

mod_wasm is an extension module for the Apache HTTP Server (httpd) that enables the usage of WebAssembly (Wasm). This module will allow to execute certain tasks in the backend in a very efficient and secure way.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

mod_wasm

mod_wasm is an Apache Server (httpd) extension module able to run and serve WebAssembly binaries as endpoints.

It was unveiled at the ApacheCon North America on Oct 3rd, 2022 (see the slides). In addition, a full-detailed article can be found at VMware's Wasm Labs page.

✅ Features

mod_wasm can be useful in the different scenarios:

  • Run existing applications from a variety of languages without modification.
  • Execute untrusted third-party code in a secure environment without using containers.
  • The Wasm capabilities model allows to enable/disable capabilites per HTTP request.

▶️ Quick Demo

  1. Run the container:
docker run -p 8080:8080 projects.registry.vmware.com/wasmlabs/containers/httpd-mod-wasm:latest
  1. Open browser at: http://localhost:8080/wasm-module-endpoint

More details about the 'PrettyFy' WebApp Demo below.

📔 Contents

🔭 Overview

The mod_wasm project is composed by two different libraries:

  • mod_wasm.so (written in C) acts as the extension module for the Apache Server (httpd).
  • libwasm_runtime.so (written in Rust) offers a very high-level C-API to manage WebAssembly modules via Wasmtime.

alt Architecture

New Directives

To setup and manage WebAssembly binaries, mod_wasm offers new directives to the httpd.conf configuration file:

Directive Description
WasmRoot Set the root directory for Wasm modules.
WasmModule Set the Wasm module file name.
WasmDir Pre-open a host directory for the Wasm context.
WasmMapDir Pre-open a host directory for the Wasm context and mount into a given directory.
WasmArg Set an argument to be passed to the Wasm module context.
WasmEnv Set an environment variable to be passed to the Wasm module context.
WasmEnableCGI Enable/Disable CGI emulation mode for HTTP requests.

Workflow

mod_wasm plays a role in two different stages of the Apache Server workflow:

  1. The different WasmXXX directives are read from httpd.conf during the boot up sequence. Once the configuration if fully processed, mod_wasm requests to the Wasm runtime to start loading the Wasm binaries. This is by far the most expensive operation and that is why it is executed only once during the Apache boot up sequence. When completed, the Apache Sever is ready to response to incoming HTTP requests.
  2. For each HTTP request, mod_wasm builds the WASI context for the already-loaded Wasm binary. Next, the Wasm module is instantiated and the entry point is executed. The stdout from the Wasm module is redirected to the HTTP response, and the stderr is appended to Apache Server's trace (usually at <httpd_dir>/dist/logs/error_log).

mod_wasm also offers the ability to build a specific execution context per HTTP request. When setting up WasmEnableCGI On, mod_wasm will pass HTTP headers as environtment variables to the Wasm module (they will be prefixed as HTTP_). In addition, URL parameters are also passed in the environment variable QUERY_STRING.

alt Workflow

⭐ 'PrettyFy' WebApp Demo

The 'PrettyFy' demo is a simple one-script, Python-based WebApp (see Examples).

🕹️ Examples

This repo cointains several pre-built WebAssembly examples to play with.

Feel free to explore, modify and crash them!

🏗️ Building mod_wasm in your environment

Prerequisites

  • Apache Portable Runtime Project (apr)
  • Apache Portable Runtime Utility Library (aprutil)
  • Apache HTTP Server (development headers)
  • Rust
  • C compiler
  • pkg-config
  • libtool

For example, in an Ubuntu environment, you can install all dependencies by running:

apt install make pkg-config libtool-bin cargo libapr1-dev libaprutil1-dev apache2-dev

Also, cbindgen is needed to generate the C bindings from Rust:

cargo install cbindgen

Building

make build

After the build is complete, you can find the module and an example Apache configuration file under the dist directory:

$ tree dist
dist
|-- conf
|   `-- httpd.conf
`-- modules
    `-- mod_wasm.so

Now, you can load this module in your Apache installation.

📦 Building the container image

This repository contains all you need to build a local container image

Prerequisites

To build the container you will need docker, or podman with the docker alias enabled.

For convenience we've organized the build commands in a Makefile, so you can use make if you prefer.

Build

You can build this image like so:

make container-image

Building a dev image

The dev image will include all examples, along with additional tools required for future development. If you want to benchmark and compare running a python script via cgi vs via mod_wasm you will need to build this image.

make dev-image

⚠️ Troubleshooting

Cannot load modules/mod_wasm.so into server

This is a common error related to LD_LIBRARY_PATH:

$ httpd
httpd: Syntax error on line XXX of <...>/httpd/dist/conf/httpd.conf:
Cannot load modules/mod_wasm.so into server: libwasm_runtime.so: cannot open shared object file: No such file or directory

Apache is loading modules/mod_wasm.so but during the process it cannot find libwasm_runtime.so. Either run Apache with LD_LIBRARY_PATH pointing to the directory where libwasm_runtime.so is located, or copy libwasm_runtime.so to a directory such as /usr/lib.

🐛 Debugging

To get detailed debugging information about the Wasm execution, run the Apache Server with the following environment variables:

  • WASMTIME_BACKTRACE_DETAILS=1
  • RUST_BACKTRACE=full

Also, it is recommended to run Apache in debug mode (-X option), this means only one process, only one worker, and without detaching from the terminal.

WASMTIME_BACKTRACE_DETAILS=1 RUST_BACKTRACE=full ./httpd -X

About

mod_wasm is an extension module for the Apache HTTP Server (httpd) that enables the usage of WebAssembly (Wasm). This module will allow to execute certain tasks in the backend in a very efficient and secure way.

License:Apache License 2.0


Languages

Language:Rust 47.4%Language:C 43.5%Language:Dockerfile 4.6%Language:Shell 2.9%Language:Makefile 1.4%Language:HTML 0.2%