Skip to content

Run obhttpd with slowcgi to Host C++ Program On FreeBSD

click to large: obhttpd+slowcgi on FreeBSD to Host c++ program
obhttpd+slowcgi on FreeBSD to Host c++ program

About obhttpd and slowcgi

obhttpd (OpenBSD Httpd): https://man.openbsd.org/httpd.8

slowcgi: https://man.openbd.org/slowcgi.8

Configure obhttpd

/usr/local/etc/obhttpd.conf:

chroot  "/www"
ext_addr="*"

server "yourdomain" {
        listen on $ext_addr port 80
        root "/webroot"

        location "/cgi-bin/*.fcgi" {
                fastcgi socket "/run/slowcgi.socket"
                root "/"
        }
}

Create chroot environment:

mkdir -p /www/{webroot,cgi-bin,logs,run}
chown -R www:www /www
service obhttpd restart

You can run obhttpd -d -v to make the log to stdout to test.

Put the html and other static files into /www/webroot, and make the owner to be www.

Run slowcgi

Because the chroot is set to /www and the slowcgi socket at location is set to /run/slowcgi.socket, the slowcgi socket passed to slowcgi command will be /www/run/slowcgi.socket.

Then run slowcgi now:

slowcgi -d -p /www -s /www/run/slowcgi.socket

-d means debug and not daemonize, so the error will be viewed on console immediately. Remove this arg to run in background! The default slowcgi user is www if you doesn't set it.

Now, both obhttpd and slowcgi should be working.

C++ Code

// hello.cpp

#include <iostream>
#include <string>
#include <sstream>

using namespace std::string_literals;

class Page {
private:
        const std::string header = "Content-Type: text/html\r\n\r\n";
        std::string title;
        std::string content;
        std::stringstream buffer;
public:
        Page(const std::string & title, const std::string & content):
                title(title), content(content)
        {
                this->init();
        }
        void init() {
                buffer << header;
                buffer << 
R"...(<!DOCTYPE HTML>
<html>
<head>
        <title>)..."s + title + R"...(</title>
</head>
<body>
<center>
        <h1>)..."s + title + R"...(</h1>
        <p>)..."s + content + R"...(</p>
</center>
</body>
</html>
)...";
        }
        void display() {
                std::cout << buffer.str() << std::endl;
        }
        ~Page() {
                std::cout << "<!-- page loaded normally -->\n" << std::flush;
        }
};

int main() {
        Page xjail("xjail", "Hello, C++! (xjail.tiv.cc/posts)");
        xjail.display();
}

Then, Compile your c++ code to the fcgi program:

clang++ hello.cpp -stdlib=libc++ -std=c++17 -o /www/cgi-bin/hello.fcgi
chown www /www/cgi-bin/hello.fcgi

Speed Up C++ Code Compiling

Use clang modulemap to speed up c++ code compiling.

cp /usr/src/contrib/libc++/include/module.modulemap /usr/include/c++/v1/

Then, replace all include lines in c++ code with a single "import std;"!

clang++ -fmodules-ts -fmodules -stdlib=libc++ -std=c++17 hello.cpp -o /www/cgi-bin/hello.fcgi
chown www /www/cgi-bin/hello.fcgi

You can write some shell script to make it easy to compile!

Configure C++ environment in chroot

Your program or any other executable scripts need to copy the dependencies to chroot environment.

cd /www/cgi-bin/
ldd ./hello.fcgi 
  ./hello.fcgi:
        libc++.so.1 => /usr/lib/libc++.so.1 (0x800250000)
        libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x80031f000)
        libm.so.5 => /lib/libm.so.5 (0x800342000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800372000)
        libc.so.7 => /lib/libc.so.7 (0x800388000)

Now, copy them into chroot. Additionally you need to copy /libexec/ld-elf.so.*

mkdir -p /www/usr/lib
cp /usr/lib/libc++.so.1 /www/usr/lib

mkdir /www/lib
cd /lib/
cp libcxxrt.so.1 libm.so.5 libgcc_s.so.1 libc.so.7 /www/lib/

mkdir /www/libexec
cp /libexec/ld-elf.so.1 /www/libexec/

chown -R www:www /www

Now, Everything is Done!

Visit the web page with web browser

Open your web browser, and visit 127.0.0.1/cgi-bin/hello.fcgi

 

Trackbacks

No Trackbacks

Comments

Display comments as Linear | Threaded

No comments

Add Comment

E-Mail addresses will not be displayed and will only be used for E-Mail notifications.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Form options

Submitted comments will be subject to moderation before being displayed.