Conventional software configuration is backwards.
If you want an HTTP server to listen on port 80 and serve some directory full of files, you tell the service to bind to port 80 and pass it the path of the files to serve:
$ http-server --port 80 --files /srv/www
Serving `/srv/www` via HTTP on port 80.
This is backwards. Let's call this kind of configuration "internal configuration", because it's configuration that happens inside programs.
Instead, processes should declare a namespace of resources that they consume or produce:
$ mount http-server /http
Mounted `http-server` instance at `/http`.
$ tree /http
/http
/socket
/listen
/imports
/files
After mounting, resources would be mapped as you see fit, from outside the process, without having to stop or reconfigure the service:
$ listen 80 /http/socket/listen
Connections to port 80 are being forwarded to socket `/http/socket/listen`.
$ export /srv/www /http/imports/files
Filesystem `/srv/www` exported to `/http/imports/files`.
Let's call this "external configuration", because it's configuration that happens outside programs.
External configuration has a number of benefits:
-
Uniformity. Consistent configuration. Configure using system tools, not binary-specific flags and configuration files. System tools can be featureful, well documented, and universal.
-
Security. Processes have no permissions that they aren't specifically granted. Processes cannot "ask" for permissions.
-
Dynamic reconfiguration. Processes can be reconfigured on the fly.
-
Faster development. Internal configuration requires developers of each program to supply options for binding ports, consuming filesystem trees, exporting filesystem trees, and dynamic reconfiguration. With external configuration, developers export resources, and configuration and consumption of those resources is handled externally.