SOcket Activator/Deactivator: like inetd but not really
 
 
Go to file
Val Packett 18d215374b Update readme 2022-10-03 02:06:04 +03:00
.clang-format clang-format 2017-01-29 15:13:19 +03:00
.clang-tidy Add clang-tidy config 2018-11-11 18:44:02 +03:00
.gitignore initial commit 2017-01-02 21:19:20 +03:00
CODE_OF_CONDUCT.md initial commit 2017-01-02 21:19:20 +03:00
README.md Update readme 2022-10-03 02:06:04 +03:00
UNLICENSE initial commit 2017-01-02 21:19:20 +03:00
config.ru initial commit 2017-01-02 21:19:20 +03:00
soad.c flags warnings stuff 2017-04-29 16:05:31 +03:00
test_server.rb initial commit 2017-01-02 21:19:20 +03:00

README.md

soad: SOcket Activator/Deactivator unlicense

A simple modern tool for running web applications on demand and stopping them after a period of inactivity.

Back in the day, web apps used something like CGI or inetd, where one request got one UNIX process that would, well, process it — and quit. This meant that your whole app would be loaded and unloaded once per request, which is especially slow when you use big frameworks written in scripting languages. But it also meant that when no requests were being processed, no resources (such as RAM) were held. Of course, these days no one cares about not holding resources and this approach is completely dead OH WAIT NO IT'S THE COOL NEW THING.

But what I want to do is to run many rarely used services on a VPS with low RAM. Modern web app servers are designed to run on a socket until you stop them. So what if I want to stop inactive services?

Installation

Should work on any modern UNIX-like system.

$ cc -O2 -fPIE -pie -fstack-protector-all -lpthread -o soad soad.c

And put soad where you keep your binaries.

Usage

First, your web server needs to support socket activation. Either by explicitly specifying a file descriptor via something like an fd://3 argument, or by using the tiny metadata protocol from systemd — the LISTEN_PID, LISTEN_FDS and LISTEN_FDNAMES environment variables.

It also needs to shut down gracefully on a signal (SIGTERM is sent by default, customize by passing the signal number as -S/--shutdown-signal).

Some libraries and apps for that:

(You can implement your own in 5 minutes, all you need to do is create a socket object from a file descriptor. See test_server.rb for a tiny example.)

Now, to run your app on a UNIX domain socket, something like this:

$ soad -s /var/run/myapp.sock -t 240 -- bundle exec --keep-file-descriptors puma -b unix:/var/run/myapp.sock
$ soad -s /var/run/pyapp.sock -t 240 -- gunicorn app:app
$ soad -s /var/run/pyapp.sock -t 240 -- uwsgi --master --hook-master-start "unix_signal:15 gracefully_kill_them_all" --wsgi-file app.py --callable app --lazy-apps

The -t/--time-until-stop argument is the number of seconds the app will be allowed to run without any activity. (Activity is determined by incoming socket connections, so basically the number of seconds since the last incoming request.)

Point your reverse proxy to that socket and enjoy.

Contributing

Please feel free to submit pull requests!

By participating in this project you agree to follow the Contributor Code of Conduct and to release your contributions under the Unlicense.

Please run clang static analysis when testing your changes, something like that:

$ scan-build14 clang14 -Weverything -Wthread-safety -fsanitize=address -lpthread -o soad soad.c

And use clang-format to format the code.

License

This is free and unencumbered software released into the public domain.
For more information, please refer to the UNLICENSE file or unlicense.org.