Maxdaemon Framework
Maxdaemon is a file-based web application server framework. It comprises a fast, lightweighted HTTP server with three kinds of CGI interfaces, a run-time system with showcase applications, a web server manager with a web browser surface to manage files, content, design and applications, a web server platform, as well as a development, test, integration, distribution and production environment.
- Maxdaemon HTTP Server with three kinds of CGI interfaces
- Web Application Server Runtime System and showcase Applications
- Webserver Manager with Web Browser Surface
- Webserver Platform (Perl with CPAN modules, Apache, SSL, Mariadb, ..)
- Development, Test, Integration and Production Environment (Git, RPM, ..)
The framework can be configured for various purposes, such as connecting Maxdaemon hosts over a network, and is specifically designed as a development and production environment for web applications written in Perl, as the HTTP server and the WebServer library are implemented in Perl, too.
Manual Scope
This manual is an overview of the use of Maxdaemon with Maxscape. It is neither comprehensive nor is it complete. You'll find the general Maxdaemon manual at Maxdaemon.org.
HTTP Server
An HTTP daemon is an interesting program. With the client/server network model a client computer sends a request to a server host that then returns a response back to the client. Graphical web browser clients and HTTP servers serving HTML documents, that is what we call the world wide web.
A client request has a protocol scheme (http, https, ..), points to a location on the server's file system and consists of request headers, request method (get, post, ..), form or multi-part data, the CGI (Common Gateway Interface) query string a.s.o.
Uniform Resource Locator: <scheme>://<FQDN>:<Port>/<file path><path info>?<query string>
A server response is generated by the means of the request parameters and the MIME type of the location that is pointed to by the file path. If the file path is a text, HTML, CSS, Javascript, image, audio, video, etc. file, this file is send back to the client.
In case of a request for an executable program, the HTTP daemon executes that CGI program, passing the parameters via the CGI interface, and then returns the dynamically generated content back to the client.
The generic concept of the CGI interface allows the HTTPD to communicate with application processes via program call parameters, environment variables and the interprocess communication using Unix Domain and TCP/IP sockets.
CGI, SCGI and DCGI Interfaces
The HTTP server implements three kinds of CGI interfaces for interprocess communication between the HTTP daemons and the application processes. The actual used CGI interface is transparent to the application code, because it uses the same client side of the CGI protocol.
CGI Interface
The CGI interface implements a fork/exec/pipe mechanism. An application program is executed once and the output is send to back to the HTTPD's client. The application program can be coded in any language and the HTTP server doesn't have to be restarted after application code changes.
CGI programs located anywhere below the document root directory are executed by the HTTPD without any further configuration. Well, the disadvantage of this interface is that it is simply to slow for big applications.
SCGI Interface
Applications using the SCGI interface are running within process daemons.
The CGI's fork/exec mechanism is replaced by daemon that communicates with
the HTTPD via Unix Domain or TCP/IP sockets. This has the advantage, that
applications coded in an interpreter language, don't have to be recompiled
and that database connections don't have to be (re)established on each request.
To use the SCGI interface place an SCGI script below the server's document root
and configure it with an 'AddScript' directive in the server's configuration file.
The usage is similar to that of FastCGI. The application process is launched
by the HTTP daemon on request.
# Configuration file: /maxdaemon/server/<app server>/etc/maxdaemon<-version>.conf
=================================================================================
...
# TCP/IP port 8092 or UNIX domain socket name with 3 preforked SCGI workers.
AddScript scgi-script $MaxdaemonHome/server/<app server>/htdocs/app.scgi 8092 3
...
# Exemplary SCGI script: /maxdaemon/server/<app server>/htdocs/app.scgi
=======================================================================
...
my $Process = Maxdaemon::Process->new ();
my $SCGI_Interface = Maxdaemon::Daemon::SCGI_Client->new;
...
while (my $Client = $SCGI_Interface->accept)
{
print $Process->execute;
}
DCGI Interface
Via the DCGI interface applications can directly be integrated within the HTTPD.
This is similar to mod_perl with Apache, but without a Perl/C adapter, since the
HTTPD is written in Perl. Because the inter-process communication between the
daemon and the CGI application is dropped, the DCGI interface is pretty fast.
A disadvantage is that if the application fails the daemon fails, too.
To integrate an application module, you can directly place an entry function or method
call in the 'executeViaDCGI_Interface' method of the 'Maxdaemon::Daemon::HTTPD'
class, though this is only recommended for applications that are part of the standard
distribution.
A next place is the 'Main' method of the 'Maxdaemon::Module::Main' class. Within
this method the runtime objects ($Process, $Page, $CGI, $User, ...) are already
defined and can directly be used within application modules. This is only recommended
for applications that are part of the standard distribution, because future distributions
will override the 'Maxdaemon::Module::Main' class file.
The best way is to use the generic module plug-in mechanism. The plug-in mechanism
looks for the presence of a 'ServerApplication.pm' file in the 'lib' directory of the
application server and then calls the function named 'ServerApplication' of the
'Maxdaemon::<AppServer>' class, where <AppServer> is the name of the
application server, defined in the configuration file.
Because the daemon creates the same environment as with CGI scripts, CGI applications
works with DCGI like with the CGI interface.
# Application module: /maxscape/server/<AppServer>/lib/ServerApplication.pm:
=============================================================================
package Maxdaemon::<AppServer>;
use strict;
sub ServerApplication {
my ($HTTPD, $Request, $Connection, $Configuration) = @_;
return Maxdaemon::<AppServer>->new->MyApp ($HTTPD, $Request, $Client, $Configuration);
}
sub new {
my $class = shift;
my %parameter = @_;
my $this = {};
bless $this, $class;
...
return $this;
}
sub MyApp {
my $this = shift;
my ($HTTPD, $Request, $Connection, $Configuration) = @_;
...
return ($Content, $Header); # scalar and hash references
}
...
Configuration and Operation Modes
The HTTP daemon can be configured to run in various modes and supports quite a lot of features.
Content and applications are stored on a standardized file system structure following Unix
conventions. Each application server has its own indepandant directory tree. An application server
consists of one ore more processes communicating with the HTTP server via the CGI interfaces.
The HTTP server needs to be configured to run the process scripts.
The configuration files are Apache style and to configure the server, as well as application code.
The main HTTPD configuration files are located below '~/etc'.
The configuration file version is used to reflect the various network configuration
possibilities. For example does '~/etc/maxdaemon.conf'
configure the HTTPD to listen to the IP 127.0.0.1 on ports 8000 (HTTP) and 8001 (HTTPS).
For more information see: Maxdaemon Configuration.
You can eighter use the 'sp' (set project) script to set the environment
or pass the configuration as parameters to the Maxdaemon start/stop script.
Use the 'sp' script to permanetly set up the configuration file version and the
shell environment, e.g.:
# Use the configuration file: $MAXDAEMON_HOME/etc/maxdaemon-fqdn.conf: > sp -c fqdn > maxdaemon -vv restart
SSL Certificates Creation for Maxdaemon
To set up a name-based virtual SSL host, the required SSL certificates needs to be
created. See the 'certificate' man pages, the 'certificate' HTML online manual
and the SSL Certificates Creation chapter. for details.
Here is an example with two name-based virtual hosts. The 'createAppServer' shell copies the 'Template'
server's certificates by default, so you'll get a warning from Firefox: "The certificate is not valid for
the name <virtual host name>.").
The creation of several name based SSL hosts is a bit tricky, as you have to define
the complete list (subjectAltName) of all virtual hosts running on your server.
'subjectAltName' is the list of all virtual site names in the form of e.g.
'URI:w1.local.net,URI:w2.local.net,URI:w3.local.net'.
Example to create a certificate for a single host (even here use the '-a' option): > certificate -w Example -a URI:example.local.net example.local.net Example with two name-based virtual hosts: > certificate -w <unique server name 1> -a "URI:<virtual host name 1>,URI:<virtual host name 2>" -s 00 <virtual host name 1> > certificate -w <unique server name 2> -a "URI:<virtual host name 1>,URI:<virtual host name 2>" -s 01 <virtual host name 2> Creation of certificates for the HTTPD, the 'Test' and the 'Template' servers: > certificate -a <subjectAltName> -s 00 <your host name> > certificate -w Test -a <subjectAltName> -s 01 <Test's virtual name> > certificate -w Template -a <subjectAltName> -s 02 <Template's virtual name>
Debug Messages, Access and Error Logs
Maxdaemon provides extensive debugging options to follow the program execution flow.
The printed package name and the line number of a debug message can be used to
find the corresponding source file and the surrounding code snippet. Thus it is
easy to find and to make changes to the code. Debug messages are enabled by passing
debug options to the 'maxdaemon' start script and are printed to STDERR, until the
'-l' option is provided.
You can use the Tcsh alias 'de' to watch the error and 'da' to watch the access logs,
defined in the 'maxdaemon.conf' files. Access logs are formated similar to the Apache
style.
You can easily use this facility to print your own debug messages by adding them to the
message hashes and call the related log functions. See the man pages or the on-line manual for more details.
> maxdaemon -vv -sl restart # turns on debug messages on STDERR > maxdaemon -vv -sl -l restart # turns on debug messages on the related error log > de # Tcsh alias to watch the error logs Reload Maxdaemon configuration: /opt/maxdaemon/daemon/etc/maxdaemon-maxdaemon.local.net.conf. Restarting Maxdaemon... <Launch-->> <maxdaemon.pl: 119> Daemon launched.................: /opt/maxdaemon/daemon/sbin/maxdaemon.pl <Configuratio: 129> Computer hostname (FQDN, IP)....: maxdaemon.local.net, 192.168.0.2. <HTTPD.pm : 145> Listening to name or IP.........: http://maxdaemon.local.net:80/ <HTTPD.pm :2711> Set daemon GID to...............: maxdaemon (8002). <HTTPD.pm :2728> Set daemon UID to...............: maxdaemon (8002). > maxdaemon -vv -sl restart > da # Tcsh alias to watch the access logs ==> /opt/maxdaemon/daemon/var/logs/maxdaemon-access.log <== 192.168.0.1 - - [09/Apr/2018:19:08:51 +0000] "GET / HTTP/1.1" 200 168953 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0"
However what you do, there are not enough debug messages for all situations. So, you might want to use the shortcut 'pe ("");' instead of the more verbose 'print STDERR ("");' statement.
Web Sockets
WebSockets are a very interesting technology, because a server can push messages onto a client
without prior request. WebSocket clients can receive server messages, instead of polling
the server for replies. The server processes have to keep track of the client's sockets. This
suggests an event driven model.
Maxdaemon's web socket support is new and experimental (set $::WEB_SOCKETS_SUPPORT=1 in
'Globals.pm' to enable). Notably, the process and connection management is basic and there
is only a DCGI implementation, because SCGI scripts can't be upgraded to WebSockets, by now.
So far, the HTTPD simply forks itself, and the child process keeps track of the connection.
If in the application server's 'ServerApplication.pm' file the function 'WebSocketCallback'
is defined, then this function is executed within the WebSocket loop. Only text messages
are implemented.
Here's the 'WebSocketCallback' of the MaxChat server that implements a little experimental
WebSocket chat. The function writes a received message to a file and sends
an 'ALRM' signal to other chat processes, which in return sends that message to their
WebSocket clients. Its just a rough beginning...
File: $::MAXDAEMON_HOME/server/WebSocket/lib/ServerApplication.pm
==================================================================
sub WebSocketCallback {
my $On = shift;
my $WebSocket = shift;
my $ClientMessage = shift;
...
my $WebChat = Maxdaemon::WebSocket->new();
if ($On eq 'OnMessage') {
...
} elsif ($On eq 'OnSignal') {
...
} elsif ($On eq 'OnClose') {
...
} elsif ($On eq 'OnTimeout') {
...
}
return $ServerMessage;
}
Chat Mode
The 'Chat Mode' is merely an example how to implement a specific communication protocol. To communicate in 'Chat Mode', Maxdaemon needs to be installed on both ends. The 'minclient' script in interactive mode can then be used to send SSL encrypted messages to the other side, which can then be watch via the daemon's error log. Obviously this isn't very comfortable, but just a beginning and quite secure, because of the end to end SSL encryption. Sent and received messages should be placed in one window and a usable send message input shell should be provided.
Compatibility with Apache/FastCGI
If applications follow a few rules, it is no issue to run them with Maxdaemon, as well as with the Apache. So, you can develop and test with Maxdaemon and run your production server with an Apache/FastCGI configuration.
Runtime System
Normally, the runtime system comprises two HTTP daemon processes, one listening for HTTP and one for HTTPS requests and several application processes, depending on the configuration of the installation. The daemon and the applications processes communicate mainly via the CGI, DCGI or SCGI interfaces with each other. You can run as many HTTPDs as you like in parallel provided they are assigned to different ports or Ethernet interfaces.
Start/Restart/Stop Scripts
In the '/sbin' folder you'll find the Maxdaemon start/stop scripts. To turn on the debug mode use the '-vv' option, e.g. to find out on which IP and port the daemon is running. Provide the '-sl' option also, to easily find the corresponding lines in the source file.
To setup a wanted configuration, namely the Perl installation and the configuration files, the 'sp' shell script is quite useful to quickly set the environment.
> sp -p OSperl -c 127.0.0.1-8000-8001 # Perl installation of the OS > maxdaemon -vv start > maxdaemon stop > exit > sp -p optperl -c max # Perl installation below '/opt' > maxdaemon -vvvvv -sl restart > maxdaemon stop > exit > sp -p maxperl -c max # Perl installation below '/opt/maxdaemon' > maxdaemon restart
Maxdaemon Configuration
Maxdaemon can be configured to run in various modes. The main configuration
files are located below the '~/etc' directory and include the application server
configuration files, which are places in their '~/server/<app server>etc'
folders. Some configuration options are directly defined in the Perl modules
(e.g. Globals.pm).
Configuration files have a version to distinguish the modes. You can either pass
a configuration file directly to the daemon with the '-c' option or you can use the 'sp (set project)'
script to set a wanted shell environment. The 'sp' shell script is meant to be adapted
by you to set wanted shell environments.
# Set the environment to the Perl installation provided by the OS. > sp -p OSperl # Start/stop the server. > maxdaemon -vv restart <Launch-->> Daemon launched.................: /opt/maxdaemon/daemon/sbin/maxdaemon.pl Listening to name or IP.........: http://127.0.0.1:8000/ <Launch-->> Daemon launched.................: /opt/maxdaemon/daemon/sbin/maxdaemon.pl Listening to name or IP.........: https://127.0.0.1:8001/ > maxdaemon stop # Exit the environment. > exit # use '/etc/maxdaemon-fqdn.conf' > sp -c fqdn > maxdaemon -vv restart <Launch-->> Daemon launched.................: /opt/maxdaemon/daemon/sbin/maxdaemon.pl Listening to name or IP.........: http://www.local.net:8000/ <Launch-->> Daemon launched.................: /opt/maxdaemon/daemon/sbin/maxdaemon.pl Listening to name or IP.........: https://www.local.net:8001/
The default configuration file is 'maxdaemon.conf' configures the HTTPD to listen to the IP address '127.0.0.1'
and the the ports 8000 (HTTP) and 8001 (HTTPS). The directives are shortly described
within the file.
The name-based version 'maxdaemon-fqdn.conf
configures the daemon to listen to the FQDNs of the computer's first Ethernet
interface, on port 8000 for HTTP and on port 8001 for HTTPS requests. If you set
the ports to 80/443 you must execute the start script from the UNIX root account.
The daemon can also be configured to listen to other Ethernet interfaces by
passing the IP to the maxdaemon start script (-n, -i, -b options).
# File: \$MAXDAEMON_HOME/etc/maxdaemon-<configuration file version>.conf ======================================================================= > me # tcsh alias for 'cd \$MAXDAEMON_HOME/etc' > vi maxdaemon-<configuration file version>.conf ... HostName - HostName is the HTTP address to listen to. AppServerName - Unique application server name NameVirtualHost - One entry for each virtual host VirtualHost - Virtual host name with port. ServerName - Virtual Host name. Port - Port to listen to. HTTPPort - Port for HTTP requests. SSLPort - Port for HTTPS requests. AddScript - SCGI process with Port/socket User - User under which Maxdaemon runs Group - Group under which Maxdaemon runs ... include - Includes an application server configuration file ...
Application Server
The unique 'AppServerName' denotes the complete set of entities (content, modules, files, virtual host name, database instances, etc.) belonging to that server. They live in a standardized directory tree containing all directories and files unique to that application (documents, scripts, access, error logs, PID files, ..).
The files of an application server are generally located below the '~/server' folder (see Server and Application Directory Structure) and have a unified directory structure.
<installation folder>/maxdaemon/daemon/server/MyApp bin - Scripts. cgi-bin - CGI scripts. etc - Configuration files. htdocs - 'DocumentRoot' folder (e.g. scripts). lib - Libraries. man - man pages. tables - Database tables. var - Files that changedes (e.g. logs).
The Perl code of web applications are best executed within separate application processes. The application server daemons communicate with the HTTP deaemons via their CGI interface using fork/exec, resp. TCP/IP or UNIX domain sockets. So, an application server implements the generic functionality to provide the basic objects and fuctions to execute the application code and to operate the server.
Application Server Creation
To create/remove an application directory tree the 'createAppServer' shell script is provided. The script takes the 'Template' server as a template, therefore you can change the 'Template' app server to generate your desired requirements and design.
> createAppServer create <AppServerName> <VirtualHostName> <HTTP port> <HTTPS port> # Example (creates an application server below '~/server/Example'): > createAppServer create Example example.local.net 80 443
Follow the instructions printed by the script. After this, the newly created app should be accessible via a browser. The most important files and folders are:
# App server configuration file: ~/server/<AppServerName>/etc/maxdaemon-<version>.conf # CGI script: ~/server/<AppServerName>/htdocs/www.cgi # SCGI script: ~/server/<AppServerName>/htdocs/www.scgi # Index page template: ~/server/<AppServerName>/htdocs/www.phtml # App server Perl modules: ~/server/<AppServerName>/lib/ServerApplication.pm # App server default index element: ~/server/<AppServerName>/htdocs/element/Index.phtml # Page tempate elements folder: ~/server/<AppServerName>/htdocs/template/
If properly configured, the app process should display a short description on how to work with your newly created app. You can display this description also via the 'Template' app, of course.
Application Server Configuration
The configuration files (maxdaemon-<version>.conf) of an application process are located below the application's 'etc' folder. The <version> must match the <version> of the main configuration file. Use the directives to configure the application process:
- VirtualHost - Virtual host name with port.
- ServerName - Virtual host name (FQDN).
- Port, HTTPPort and SSLPort - Must be the HTTPD's values.
- AddScript - SCGI process directive.
- ...
The application process configuration file must be included in the main HTTPD's
configuration file and the 'NameVirtualHost' directives have to be added, one for each
'VirtualHost' server. Note, that the 'NameVirtualHost' directives in the main HTTPD
configuration file must match the 'VirtualHost' directives in the application's
configuration file.
Note also, that a <virtual host name> is a FQDN (Full Qualified Domain Name,
e.g. www.example.com) that cannot just be invented, but must be configured
by the network configuration, either Intranet locally (e.g. (/etc/hosts, hostname,
domainname) or with an Internet service provider on the Internet.
To configure an application process edit its configuration file and set the directives
to the wanted values. Also, add the required directives to the main configuration file.
# Use the web surface or the following shell commands: > ms # Tcsh alias for 'cd $MAXDAEMON_HOME/server' > cd <AppServerName>/etc > vi maxdaemon<-version>.conf # File: ~/server/Example/etc/maxdaemon<-version>.conf ==================================================== <VirtualHost www.example.com:8000> ... VirtualHostName www.example.com:8000 ServerName www.example.com AppServerName Example SSL 0 ... </VirtualHost> ... <VirtualHost www.example.com:8001> ... VirtualHostName www.example.com:8001 ServerName www.example.com AppServerName Example SSL 1 ... </VirtualHost> > me # Tcsh alias for 'cd $MAXDAEMON_HOME/etc' > vi maxdaemon<-version>.conf # File: ~/etc/maxdaemon<-version>.conf ==================================================== ... NameVirtualHost www.example.com:8000 NameVirtualHost www.example.com:8001 ... include $MaxdaemonHome/server/Example/etc/maxdaemon<-version>.conf ...
SCGI scripts must be configured with an 'AddScript' directive. Make sure that the ports are unique.
# File: $MAXDAEMON_HOME/server/<virtual host name>/etc/maxdaemon-<version>.conf =============================================================================== ... # Add a SCGI interface handler to configure a SCGI application process. # Arguments are the 'port' and the number of process workers. AddScript scgi-script $MaxdaemonHome/server/<AppServerName>/htdocs/app.scgi 8089 3 ...
If configured properly, application processes are easily accessible via the web surface. Simply click on the scripts you want to run.
Appliction Server Start/Stop
Note, that the <virtual host name> must be configured by the network (see chapter 'Local Name-based Virtual Hosts').
> sp -p maxperl -c max > maxdaemon -vv restart <Launch-->> <maxdaemon.pl: 119> Daemon launched.................: /opt/maxdaemon/daemon/sbin/maxdaemon.pl <Configuratio: 129> Computer hostname (FQDN, IP)....: maxdaemon.local.net, 192.168.0.2. ...
To see the newly created process running, you might want to use the web surface. Go to the application process's document root and a click on the CGI resp. SCGI script. This will start the (SCGI) process, if all is configured properly.
Application Daemon Scripts
Application daemon scripts containing the process main loop are best placed below the application server's 'DocumentRoot' folder.
> ms # Tcsh alias for 'cd $MAXDAEMON_HOME/server'
> cd <AppServerName>/htdocs
> vi <script name>.scgi
# File: ~/server/<AppServerName>/htdocs/<script name>.scgi
========================================================================
...
my $SCGI_Interface = Maxdaemon::Daemon::SCGI_Client->new ();
...
while (my $Client = $SCGI_Interface->accept)
{
my $Content = 'Hello world';
print "Content-type: text/html$::CRLF$::CRLF" . $Content;
}
To make scripts generic and reusable encapsulate them in something like the 'Maxscape::Process' container class, then CGI/FCGI/SCGI scripts look quite similar, and need to be changed only once in a blue moon. Though an $App->run() method implementing all CGI interfaces is elegant, it is not really necessary, thereby avoiding unwanted dependencies.
# CGI, FastCGI script example:
...
while($FCGI_Request->Accept() >= 0)
{
$Request = Maxscape::HTTP::Request->new();
$Response = $Process->execute($Request);
print $Response->HeaderAsString, $Response->Content;
$Process->postProcess();
$Process->cleanup();
}
...
If you want to integrate an existing script, you might want to start the development with the CGI interface and then change later to SCGI. You need to tweak your script to the Maxdaemon environment. E.g. exchange '#!/usr/bin/perl' with '#!/opt/maxdaemon/daemon/bin/perl' or '#!/usr/bin/env perl'.
Addressing Application Objects and Functions
The are several ways to map URIs (Uniform Recource Identifier) to control the behaviour of applications. The location of a script placed below the process document root (htdocs) is the path relative to that document root. Special applications functions can then be addressed via the CGI's QUERY_STRING, the PATH_INFO and other variables (e.g. HTTP headers):
URL: ==== scheme net address port process script path info query string hash tag -------+------------------+---------------+----------+----------------------+-------- https://www.local.net:8080/user/index.scgi/Page.phtml?Element=foo&Action=bar#foobar HTTP request and request header: ================================ GET /user/index.scgi/Page.phtml?Element=foo&Action=bar#foobar HTTP/1.1 Content-Type: text/html Connection: keep-alive Host: www.local.net:8080 User-Agent: Minclient ...
Application Programming and Content Generation
To separate source code and (HTML) text is always a good idea for several reasons,
though it is sometimes not completely possible. If a piece of text becomes big, then
it is definitely a candidate for being stored outside the source code, where it can
be reused, also. Separation of content and source code introduces the possibility to
distinguish between different content types and storage locations, as well as the
definition of categories, pages, templates and elements.
A very nice feature of Perl is that variables and function/method calls can
be embedded within an (HTML) text. You can even store this text in a database,
fetch it at runtime and then execute it on the fly. So, unless you want to
restrict the access rights to runtime objects, you don't need an additional
parser to embed software in strings, text files or database fields.
This allows to define a 'parse' content/MIME type (.phtml), say an (HTML) text
with embedded software that can be stored e.g. in a text file and then be
red and evaluated at runtime. In return, this greatly helps to separate content
from templates and the application code to better fit to the different views
of content authors, designers and programmers.
In the example below, the '$Page' object is used to insert page elements into the
HTML template, thereby abstracting where these elements are actually stored.
Variables are passed to the template as members of the '$Page' object, via the
'$Var' hash or can be imported into the programs name space.
Note, that application methods within Maxdaemon return content and HTTP headers as
string and hash references and do not directly write to STDOUT or sockets.
The file based page, template, element system used by the web surface is quite simple and there
to avoid the dependency on a (content) database, introduced by Maxscape.
# HTML page with embedded Perl example:
=======================================
<!DOCTYPE html>
<html>
<head>
@{[ $Page->Element (Name => 'Head', Type => 'parse') ]}
<title>$Page->{Variables}->{Title}</title>
</head>
<body>
@{[ $Page->Element (Name => 'Body', Type => 'parse'
Variables => {
RootLink => $Var->{RootLink},
LoginLink => $Var->{LoginLink},
},)
]}
</body>
</html>
There is a second class (Maxdaemon::PageByPathInfo) that generates a Page from a file pointed to by the PATH_INFO environment variable, where '$ENV{PATH_INFO}' is the file path. Because Perl variables can be pushed onto the evaluation name space, these variables can be embedded by their name into an Perl parsed HTML text. Note, that this class is in a beta state.
# Application module: ===================== ... my $Page = Maxdaemon::PageByPathInfo->new; ... $Page->embedVariables (Action => 'action', Object => 'object'); ... # File: Example.phtml ===================== # Use pushed variables in Perl parsed '*.phtml' files by their name. E.g.: <html> ... An $Object may have an $Action! ... </html>
For each page, pointed to by the path info variable, a callback function can be defined in the 'ServerApplication.pm' file, which is then called by the $Page object, automatically. '$$p{Name}' is the file name of a page without extension (phtml).
# File: $MAXDAEMON_HOME/server/<AppServer>/lib/ServerApplication.pm:
====================================================================
package Maxdaemon::<AppServer>;
...
sub PageContextCallback
{
my ($Page, $p) = @_;
if ($$p{Name} eq 'Example') {
my $RefreshTime = 60;
my $Counter = $Page->QueryString ('Counter');
$Page->embedVariables (
LifeStreamURL => "$RefreshTime; url=/page.scgi/Frame.phtml?Counter=$Counter",);
}
return '';
}
...
See the Maxdaemon Index Server below the '/server/Maxdaemon' folder and the '/index.scgi' script, as a example.
Runtime Objects - Using Maxdaemon Classes in Apps
The runtime system provides several objects that can be used within applications. E.g.:
- Configuration - Server Configuration.
- SCGI - SCGI Interface.
- Page - Container for content related data.
- CGI - Client side of the CGI interface.
- Form - HTML forms.
- User - User related data.
- DirectoryTree - File system management.
- ...
The classes are an excerpt of the Maxscape classes essential to implement the daemon, the web surface and the Maxdaemon applications. You'll find a complete list in the online man pages.
Below, the code of an example script is shown, how to use these classes in application scripts. It simply displays the file 'showEnv.phtml', which prints the script's environment. If, for example, the file name is replaced by a CGI variable, say 'Path', an arbitrary file can be displayed (href="?Path=/arbitraryFile.phtml").
# File: $MAXDAEMON_HOME/server/Template/htdocs/showEnv.scgi
========================================================================
...
my $SCGI_Interface = Maxdaemon::Daemon::SCGI_Client->new ();
...
while (my $Client = $SCGI_Interface->accept)
{
my $CGI = Maxdaemon::CGI->new ();
my $Page = Maxdaemon::Page->new (CGI => $CGI);
my $RequestURI = $CGI->RequestURI;
my $ServerName = $CGI->ServerName;
my $DocumentRoot = $CGI->DocumentRoot;
my $absoluteFilePath = $DocumentRoot . $RequestURI;
my $DirectoryTree = Maxdaemon::DirectoryTree->new (DocumentRoot => $DocumentRoot,);
my ($Content, $FileLinesNumber) = $DirectoryTree->printFile (FileName => '/showEnv.phtml');
my $Content = $Page->parseText ($Content); # $Content contains text with embedded Perl code
print "Content-type: text/html$::CRLF" . $::CRLF . $Content;
}
The 'showEnv.scgi' script is not configured by default. Note, that you might want to remove the 'showEnv.(s)cgi' scripts altogether, because they show the CGI environment.
Callback Function Plug-In
It is easy to integrate callback functions into the daemon. By default the 'rewriteURI_Callback' and the 'sendFileCallback' can be configured via the configuration file (/etc/maxdaemon.conf). With the first you can manipulate a request URI, while the second is called before a response is sent to a client, thus giving the possibility to manipulate the generated content.
# File $MAXDAEMON_HOME/server/<AppServer>/etc/maxdaemon.conf
=============================================================
...
rewriteURI_Callback Maxdaemon::Module::Main::rewriteURI_Callback
...
# File $MAXDAEMON_HOME/lib/Maxdaemon/Module/Main.pm
===================================================
...
sub rewriteURI_Callback {
my ($Request, $ServerName, $VirtualHostName, $AppServerName) = @_;
my $RequestURI = $Request->{RequestURI};
my $relativePath = $Request->{relativePath};
my $QueryString = $Request->{QueryString};
my $MimeType = $Request->{MimeType};
if ($Request->{FileExtension} eq 'phtml')
{
# e.g. /manual/Index.phtml to /?Action=show+file&Path=/manual/Index.phtml
my $UserDir = ($relativePath =~ //user// ? "/user/" : /);
$RequestURI =~ s/^(${UserDir}manual$::SL.*)/?Action=show+file&Path=$1/;
$MimeType = 'application/x-httpd-dcgi';
$relativePath = $UserDir;
$QueryString = "Action=show file&Path=$1";
$QueryString =~ s/?/&/;
}
$Request->{RequestURI} = $RequestURI;
$Request->{relativePath} = $relativePath;
$Request->{QueryString} = $QueryString;
$Request->{MimeType} = $MimeType;
return $Request;
}
...
Control Daemon
The control daemon is an example for the use of Maxdaemon as a general purpose daemon with a special communication protocol. Here the 'SystemControlCallback' function implements a simple database user authentification. The 'ServerSocketTimeout' directive can be used to periodically execute a 'ServerSocketTimeoutCallback' function.
# File: $MAXDAEMON_HOME/server/ControlDaemon/etc/maxdaemon-<version>.conf
# 1: only message, 2: full HTTP server
SystemControlDaemon 1
SystemControlCallback Maxdaemon::Module::ControlDaemon::ControlCallback
# ServerSocketTimeout and ServerSocketTimeoutCallback
# ServerSocketTimeout 10.0
# ServerSocketTimeoutCallback Maxdaemon::Module::ControlDaemon::ServerSocketTimeoutCallback
...
# File: $MAXDAEMON_HOME/lib/Maxdaemon/Module/ControlDaemon.pm
...
sub ControlCallback {
my ($HTTPD, $Request, $Client) = @_;
my $AppServerName = $HTTPD->{Configuration}->getValue ('AppServerName');
if (!defined ($Cursor)) {
$DB->registerDatabase ($AppServerName);
$Cursor = $DB->connectAppDatabase ($AppServerName);
if (!$Cursor) {
logError ('ControlDaemon.connect', "AppServerName ($AppServerName)");
}
}
...
}
...
In the '/sbin' folder you'll find the maxcontrol start/stop script. See the maxcontrol online man page.
- maxcontrol start | restart | stop
- man maxcontrol
To install the Control Daemon download 'maxdaemon-ControlDaemon-1.0.0-distribution.tgz' and untar that file in the Maxdaemon 'root' folder. Note, that you need a database and the DBI/DBD package to use this daemon for database authentification.
Database Authentication Daemon
To authenticate users stored in a database table instead of in a file, set the 'AuthBasicProvider' to 'ControlDaemon', and define the 'Database Name', 'Host', 'User', 'Password' variables via the '%Databases' hash (in 'DatabaseConfiguration.pm'):
# File: $MAXDAEMON_HOME/server/ControlDaemon/etc/maxdaemon.conf:
...
<Directory /user/>
# Check if a user has logged in.
checkUserAuthorization 1
# Basic authorization
AuthType Basic
# Browser basic authorization prompt
AuthName Maxdaemon HTTPS server login:
# Get password from ControlDaemon.
AuthBasicProvider ControlDaemon
...
<Directory>
...
# File: $MAXDAEMON_HOME/lib/SiteLocal/DatabaseConfiguration.pm:
...
sub configureDatabase {
my $DatabaseProduct = 'mysql';
my %Databases = (
'MaxAgent' =>
{
Name => 'Maxdaemon', Host => 'localhost', User => 'Maxdaemon', Password => 'MyPW',
},
'ControlDaemon' =>
{
Name => 'Maxdaemon', Host => 'localhost', User => 'Maxdaemon', Password => 'MyPW',
},
);
return ($DatabaseProduct, \%Databases);
}
...
The control daemon then looks up the database, as defined by the 'configureDatabase' function in the 'SiteLocal::DatabaseConfiguration' package. Of course, the database must be configured beforehand, see Maxdaemon-utf8.sql.
# MySQL database example;
> su - mysql
mysql> mysql -p -uroot
mysql> create database Maxdaemon;
mysql> connect mysql;
# create MySQL user
mysql> insert into user (Host,User,Password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Reload_priv,Shutdown_priv,Process_priv,File_priv,Grant_priv,References_priv,Index_priv,Alter_priv,Show_db_priv,Super_priv,Create_tmp_table_priv,Lock_tables_priv,Execute_priv,Repl_slave_priv,Repl_client_priv,Create_view_priv,Show_view_priv,Create_routine_priv,Alter_routine_priv,Create_user_priv,Event_priv,Trigger_priv,Create_tablespace_priv) values ('localhost','Maxdaemon',password('MyPW'),'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y' );
# Create MySQL db
mysql> insert into db (host,db,user,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Grant_priv,References_priv,Index_priv,Alter_priv) values ('localhost','Maxdaemon','Maxdaemon','Y', 'Y', 'Y', 'Y', 'N', 'N', 'N', 'N', 'N', 'N');
mysql>quit
> mh # Tcsh alias for 'cd $MAXDAEMON_HOME'
# create database tables
> cat server/ControlDaemon/tables/Maxdaemon-utf8.sql | mysql -uroot -p
> mysqladmin -udba -p reload
Maxdeamon Applications
Web sites and services are implemented with Maxdaemon application servers. An application server consists of one ore more process daemons connected to the HTTP server via the configured CGI interface. A Maxdaemon installation includes several default applications (Maxdaemon (Webserver Manager), Test, Template, ControlDaemon, etc.).
Webserver Browser Surface to communicate with Remote Hosts
Maxdaemon includes a file system management server with which you can administer
the server's, as well as the remote host's file system with a web browser.
Although this surface is not a content management system, it can be used to edit a web site's
content and the server software. It can be configured to grant access to any file of
a (remote) host without a login shell. Of course, permissions can be restricted and
are controlled via various parameters like UNIX user/group, node permissions, surface
configuration, user name and actions. To access files outside the 'DocumentRoot',
simply add a symbolic link at the wanted location.
Features and Functionality
The surface works quite similar to a file explorer. There are some differences due to the HTTP client server model and the HTML/CGI implementation style. Working on local and remote hosts is transparent and the in-build features differ. Although it is not a content management system, it can be used to edit files on (remote) hosts, web sites, as well as the web server's software and content, indeed. The main file system management functions are provided:
- display - Respond requests.
- edit - Edit files by (MIME) type
- new - Create files and folders
- change - Change files
- copy - Copy files
- move - Rename and move nodes
- remove - Delete nodes
- upload - Upload files
- search - Search for strings
Directory Tree Document Root
The 'DocumentRoot' of the web surface server's directory tree is set to the home folder of a Maxdaemon installation ('<installation directory>/maxdaemon/daemon'), which is actually a folder link to a special Maxdaemon version (e.g. 1.0.0). Therefore any file of the daemon and the installed application servers ('/server') can directly be displayed/edited. In the following the '/' refers to this folder ($MAXDAEMON_HOME). The symbolic link '/root' leads to the installation directory ($MAXDAEMON_ROOT), where merely local host specific parts, like the UNIX user home, are placed.
Display Files And Execute Scripts
The surface default page displays the server's file system below whatever the 'DocumentRoot' is set to. Click on folder hyperlinks to traverse the server's directory tree. Click on file links to display, listen to and view the file content or to run server side application scripts. The action that is performed by the server is mainly determined by the surface/HTTPD configuration, the file's MIME type, the surface user, the HTTP headers and CGI variables. For example, clicking a script of type 'application/x-httpd-cgi' will execute it via the CGI interface of the HTTP daemon.
Create, Edit and Change Files
It is easy to add static content the to the server. Simply go to the wanted folder of
the document tree, click 'edit' and enter the file name. Choose an appropriate file
extension, because it determines the file handling at runtime. To edit files with the
surface makes only sense with human readable file content, and only the very basic
file system operations are implemented, so far. Creation of symbolic links to include
files or folders outside the document tree, and changing file owner/group/permission
are not supported.
The effort to implement/integrate applications depends on their complexity, of course.
In the simplest case just put a CGI script within the directory tree or the 'cgi-bin'
folder and then click on it.
The editing functions are implemented with HTML form <textarea> tags, which are quite flexible in nature. You like WYSIWYG? Simply add one of these nice Javascript editors. I wonder if there is one that supports mixing of multiple languages like Perl and HTML. Anyway, to edit (HTML source) text via the surface often makes sense, but with scripts I mostly prefer the Vi editor. There are a few caveats when editing HTML with a <textarea> form tag. Namely, that the &*;'s are replaced by Firefox, and that a <textarea> tag in a <textarea> form field crashes the form. For more, see the 'Maxdaemon::DirectoryTree::escapeTextAreaBug' method.
To ease HTML form handling, the surface page header can be hidden (☰) to make more space and the button bar can be fixed to a position to minimize nasty form field scrolling. By using the browser's text search function, one can work quite rapidly, although the 'textarea' form field scrolls on top of the page, when changes are submitted.
Copy, Move and Delete
To copy, move or delete files go to the file's source folder, select the source file via the radio button, enter the destination path and submit the wanted action. The destination path name follows UNIX conventions. So, '../' points to the parent directory.
Upload Files
Go to the desired folder, click the (ugly default) 'upload' button to upload a file to the remote server. Note, that the file permission will be '-rw-r-----'. Uploads are only allowed to registered members, by default.
Search for Strings
One of the crucial aspects of any software project is to know resp. to find the (storage)
places of project entities and the speed to possibly change them. In the simplest case
you are searching for a short string in a bunch of files and maybe databases.
Maxdaemon has two solutions to this challenge. Firstly, since in '/Manifest.txt'
all files of the server are listed, the 'gp' script just 'grep's these files for the
string and lists the matching file names and lines. Secondly, as Git is used to track the
development, Git's search function is utilized.
Configuration Modes and Files
The surface and the HTTP daemon have various configuration modes and options. Have a look at the following files for more information on configuration directives of the surface:
- • $MAXDAEMON_HOME/etc/DirectoryTree.conf
- • $MAXDAEMON_HOME/etc/maxdaemon<-version>.conf
For example, if you want to edit/change a file with a MIME type not listed so far, add a new 'AddEditMimeType' directive in '/etc/DirectoryTree.conf'.
Adapting the Surface
To change or add points to the pulldown menu, edit the file '$MAXDAEMON_HOME/page/element/PulldownMenu.phtml'. List your application servers in '$MAXDAEMON_HOME/page/AppSitesMenu.phtml' for fast access.
Themes, Look and Feel
The basic surface version is implemented useing only HTML/CSS/CGI and does't depend on Javascript libraries, what is good for portabillity reasons over times. Well, the form widgets doesn't look that nice. Fortunatly, is it quite easy to change to other themes by integrating one of these nice user interface Javascript libraries (e.g. jQuery-UI). By now, there are two default themes resp. button style to choose via the menu (☰) and you can change the look and feel by tweaking the CSS style sheets under the '$MAXDAEMON_HOME/css' folder to add more themes on your own.
Web Surface User Accounts
To be able to log into the Maxdaemon web surface, you need to create a Maxdaemon web surface user account:
> createUserLogin create <user id>
Note, that all registered users have access and can change any files within the scope of the UNIX user and groups under which Maxdaemon is running!
CGI Interfaces
The surface can be executed via all three CGI interfaces of the HTTP daemon. To run the surface via the CGI, respectively the SCGI interface, simply click on the '/www.cgi' resp. the '/www.scgi' scripts in the '/', resp. the '/user' folders. Clicking the '/user/www.(s)cgi' script will pop up a login form for registered users (basic authentication).
Template Application Server
The distribution contains a 'Template' application server, which is used as a template for application server creation with the 'createAppServer' shell script. The script creates the general directory structure and copies essential files. To tailor server creation to your requirements, add resp. change the files and directories and adapt the 'createAppServer' script accordingly. See the 'Template' server running.
Test Server
The distribution also contains a 'Test' application server to get accustomed to Maxdaemon and to start programming right away. Have a look at the Work Flow Examples.
Manual Server
The 'Manual Server' is at the beginning of a decent manual. Note, that this server is a special case, in that the SCGI script is '~/index.scgi' and that the configuration files are located below '~/etc'.
MaxChat Server
The 'MaxChat Server' is a prototype of a 'WebSocket' chat. If you are interessted to work on that chat, let me know. You can download the Chat via the download page.
LifeStream Server
The 'LifeStream Server' is a prototype of a life stream application using jQuery and Ajax. If you are interessted to work on that life stream prototype, let me know. You can download the life stream app via the download page.
Maxscape Application Servers
The Maxscape Application Servers, including the Content Database Administration Server, normaly running in an Apache/FastCGI configuration are doing fine with Maxdaemon's DCGI, CGI and SCGI interfaces.
Development and Integration Environment
To develop a program is not always an easy task. First and all above, you need to have the full control over your source code, content and data, and you have to understand the subject, of course. This tends to become more difficult when projects gets bigger and when the number of people involved, increases. Anyway, there are some simple rules to ease the process concerning (web) programming:
- Have a complete list of all project files and data and have search functions to easily find and change them. Good choices are CVS or even better its offspring Git.
- Have some kind of a version management mechanism to restore previous versions.
- Try to have only one version of each entity (file, text, object, function, etc).
- Minimize the code and reuse as much as you can..
- Keep anything as simple as possible, because the easy things are hard to do.
- Minimize the effort to make any kind of changes to the system.
- Separate generic from application specific parts.
- Separate text, templates and source code.
- Have well defined interfaces between components and part systems.
- Write wrapper functions around external interfaces.
- Choose the appropriate tools to accomplish special tasks.
Maintainability of a code base greatly depends on the speed with which changing environments can be incorporated, and therefore how fast code changes can be accomplished.
According to Perl's motto "There's more than one way to do it." and the three principal virtues of a Perl programmer (laziness, impatience and hubris), Maxdaemon relies on the good old UNIX tools (sh, vi, make, grep, find, xterm, git, rpm, ..), some shell scripts (makefile, gp, certificate, createAppServer, etc.), Firefox and the Maxdaemon web surface.
Web Server Platform
To run a web server a basic system (web server platform) is required. Namely the operating system (OS, e.g. Linux), an HTTP daemon (e.g. Apache), a programming language (e.g. Perl), an encryption component (e.g. Openssl) and most possibly a database (e.g. Mysql, Mariadb, Oracle).
- Operating System
- Open SSL Build
- Perl Interpreter and CPAN Build
- Apache Build
- (Rational) Database
- Content Tracker (CMS)
Operating System Setup
The Maxdaemon Framework is developed and tested only under Ubuntu, so far. A portation to another UNIX should be possible with little changes. A Windows port might need quite a bit of work.
Best is to use the tools provided by the OS. Otherwise you have to build the required parts by yourself. Several helpful components can be installed by the update mechanism of the OS, e.g. for Ubuntu:
apt-get update apt-get upgrade apt-get -y install analog aptitude autoconf bison cmake curl cvs Expat ffmpeg \ g++ git iptables libaio-dev libav-tools libjpeg62-dev libncurses5-dev libpng12-dev \ libtool libxpm-dev libxvidcore4 libfaac0 locate lynx man-db net-tools nmap rcconf \ rpm tcsh vim whois zlib1g-dev
Webserver Platform Build
To ease the build of components on your own, the RPM (Red Hat Package Manager) is used. All conmonents should be installed below the '/opt' folder. Therefore a RPM repository is provided, which contains the RPM spec and RPM source files. The RPM source files (Apache, Perl, ..) are not changed at all and provided for convenience, only. Maybe there are newer versions at their official download sites.
To install the RPM folders download 'Maxscape-Platform-Build-RPM-Repository.tgz' and untar that file in the Maxdaemon 'root' ($MAXDAEMON_ROOT) folder. Then follow the instructions in the 'README.txt' file.
> su - root > ln -s $MAXDAEMON_ROOT/rpmbuild rpmbuild > mr # tcsh alias for 'cd $MAXDAEMON_ROOT' > tar zxvf <download directory>/Maxscape-Platform-Build-RPM-Repository.tgz > cd rpmbuild > cat README.txt
The build is developed and tested under Ubuntu (14, 16). The goal would be to adapt the SPEC files to work on any possible OS. Therefore the RPM repository is published under the LGPL (GNU LESSER GENERAL PUBLIC LICENSE). Please send us your modifications and enhancements, so that we can publish them.
Open SSL Build
Though the OS Openssl installation can most probably be used for HTTPS communication, it might be not sufficient to build Perl with an encryption source code filter. If your OS also doesn't provide the Openssl include C header files, you should build your own Openssl installations (/opt/ssl/<Openssl version>):
> rsp # alias for 'cd $MAXDAEMON_ROOT/rpmbuild/SPECS' # For Filter::Crypto (which doesn't compile correctly with openssl-1.1.0g) > rpmbuild -ba -vv openssl-1.0.2n.spec # For Apache, NetSSLeay, SSL certificates, .. > rpmbuild -ba -vv openssl-1.1.0g.spec > rpmbuild -bi -vv openssl-1.1.0g.spec
To incorporate the Openssl installation in your Maxdaemon directory tree, simply copy the files to the $MAXDAEMON_ROOT/ssl/ folder and adapt the 'sp' script accordingly.
Perl Interpreter and CPAN Build
There are several reasons that you might want to build your own Perl interpreter.
For example, to install the latest Perl release, to install an extended set of CPAN
modules or to incorporate special features, like source code filters to encrypt the
Perl sources e.g. for production systems to hide e.g. passwords.
To build an own Perl Interpreter set the build environment with the 'sp' script
and execute the perl-5.26.1.spec file, which builds and installs several CPAN
modules (FCGI, libwww-perl, Data::Dumper, GD, Plack, Mojolicious, ..). Edit the
Perl spec file to add more or to remove not wanted packages.
Maxdaemon itself only requires the Net-SSLeay (HTTPS communication), the Filter-Crypto (Perl source code encryption) and possibly the DBI/DBD (database interface) packages.
To experiment with the Perl build, Perl's 'Policy.sh' and 'config.sh' files are good places. See the spec file for the use of this feature with RPM.
# set the build environment (SSL_ROOT, APACHE_ROOT, ..) > sp -p optperl > cd $MAXDAEMON_ROOT/rpmbuild/SPECS > vi perl-5.26.1.spec > rpmbuild -ba -vv perl-5.26.1.spec
If you like to include your Perl version within the Maxdaemon directory tree, simply copy the related files using the makefile (cd /opt/maxdaemon; make copy-perl-opt-to-maxdaemon) and set the PERL5LIB accordingly (best use the 'sp -p maxperl' script).
Perl Source Code Encryption (Filter-Crypto Package)
For production servers it is wise to encrypt the Perl sources to hide, for example, the passwords from unwanted viewers. Basically, two Perl versions are installed, one with which Perl source files can be encrypted ('/opt/perl/5.26.1-crypt_file-decrypt') and one only with the decrypt function (/opt/perl/'5.26.1'). You'll find the difference in '$RPM_SOURCE_DIR/maxdaemon-Perl-5.26.1-crypt_file-decrypt.tgz', after the build.
# Filter::Crypto pass phrase file is: # $RPM_SOURCE_DIR/CipherConfig.h # Perl executable to encrypt Perl source files is: # /opt/perl/5.26.1-crypt_file-decrypt/bin/perl-crypt_file-decrypt # Perl executable to only decrypt Perl source files is: # /opt/perl/5.26.1/bin/perl > man Filter::Crypto > ln -s /opt/perl/5.26.1-crypt_file-decrypt/bin/crypt_file /opt/maxdaemon/bin/crypt_file # Encrypt a Perl source with 'crypt_file' > crypt_file --in-place <Perl source file>
Apache Build
For heavy loaded production systems you might want to use Apache instead of the Maxdaemon HTTPD. The apache-2.4.29.spec RPM spec file will help you to build a prefork version with mod_ssl, mod_fcgi and mod_perl.
> sp -p optperl # Sets the build environment (SSL_ROOT, APACHE_ROOT, ..) > cd $MAXDAEMON_ROOT/rpmbuild/SPECS > vi apache-2.4.29.spec > rpmbuild -ba -vv apache-2.4.29.spec > rpmbuild -bi -vv apache-2.4.29.spec > rpmbuild -ba mod_perl-2.0.10.spec > rpmbuild -bi mod_perl-2.0.10.spec # Exchange the decrypt and thread-multi Perl versions, because I havn't been # able to build mod_perl with the static decrypt Perl installation cd /opt/perl rm -rf ./5.26.1-x86_64-linux-thread-multi mv 5.26.1 5.26.1-x86_64-linux-thread-multi mv 5.26.1-decrypt 5.26.1
Of course, you have to configure the apache configuration via the httpd.conf file (/opt/apache/2.4.29/conf/httpd.conf). Also, set the permissions of your (FCGI) scripts and the FCGI UNIX domain sockets (/opt/apache/2.4.29/logs/fcgidsock) correctly. Then you can start the Apache with the 'apachectl start|restart|stop' script.
(Rational) Database
To use a database the Perl database interface DBI/DBD packages have to be installed. If you like Oracle, Postgress or another database, the related DBD packages have to be installed, best by creating own RPM spec files and executing them instead of the MySQL DBD spec file, within the Perl 'perl-5.26.1.spec'.
Under Ubuntu a MySQL database is or can be installed, which easily can be used. Of course, the MySQL data directory needs to be initialized (mysql_install_db), the database users and instances needs to be created and the data models have to be defined (see the Database Authentication Daemon example).
Visit Maxscape.com for more details on how a (rational) database can enhance content management and web application server programming.
Content Tracker (CMS)
Content trackers like CVS and its more comfortable offspring Git are very useful tools. Therefore Git is used to track the Maxdaemon development. To install a local Git repository see the 'git-install.sh' script.
Server and Application Directory Structure
Maxdaemon provides a unified directory structure to ease web server management
and to share application modules between several applications, as well as with the
daemon software. Each folder has its own purpose and the directory tree is structured
according to UNIX conventions. So, configuration files are located in 'etc', executables
in 'bin', daemons in 'sbin' and modules below 'lib' folders.
Generally, all parts of an installation are located below the 'maxdaemon' root
directory. Exceptions are optional third party products like Apache, SSL and
databases, which are best located under the '/opt' folder. The directory structure
reflects the purposes of the parts and follows UNIX conventions (etc, bin, sbin, lib,
..).
<installation folder>/maxdaemon .git - Git content tracker repository. 1.0.0 - Maxdaemon version 1.0.0. bck - Backup folder. bin - General scripts. daemon - Link to the actual Maxdaemon version. etc - Environment and boot scripts. home - Maxdaemon UNIX user home. perl - Local Perl language interpreter. rpmbuild - RPM (Red Hat Package Manager) repository. templates - Useful templates. tmp - Temporary files. License.txt - Distribution License. makefile - Installation and backup makefile.
A basic installation consists of the 'root' tree and the 'home' sub-tree. The 'root' tree comprises the nodes local to the host, like the UNIX user, the backup directory and the folders containing special Maxdaemon versions. The 'daemon' symbolic link is used to point to the current Maxdaemon version and is referred to by 'home' ('~/'), because 'home' is the 'DocumentRoot' of the web surface server, even though this is a bit confusing. Note, that in this context '~/' does't mean the UNIX user home.
<installation folder>/maxdaemon/daemon bin - Management scripts. cgi-bin - CGI scripts. css - CSS style sheets. etc - Configuration files. javascript - Javascript scripts. lib - Modules and packages. man - Maxdaemon man pages. manual - HTML man pages. media - Images, audios and videos. page - Page templates and elements. root - Link to the root folder. sbin - Daemons and start scripts. server - Applications servers. user - Folder link for registered users. var - Log, temp, stat and pid files. index.scgi - Maxdaemon manual SCGI script. Manifest.txt - Maxdaemon manifest. www.cgi - Surface CGI script. www.scgi - Surface SCGI script.
All application servers are located below the '~/server' directory and have a similar
structure. Several Tcsh aliases are defined for quick navigation within the directory tree.
To come to know about the file system structure, simply browse through this server's
directory tree with the web surface. If you set the display style to 'Head',
a short summary of each node is shown. If you set the display depth ('Depth') high
enough, the whole server file system is displayed.
Content/Application Management
Because the web surface makes the basic file management functions accessible via a web browser, some kind of content management functionality is provided, but this can hardly be called a content management system. If you are interested in that area, have a look at Maxscape, which uses a (rational) database as the content/application repository, in addition to the server's file system. Storing web content and software in a database, opens up a whole new world of possibilities and adds the power of the SQL language and rational databases to content management and application programming.
Shell Tools
Besides the File System Management surface there are a few, nonetheless quite helpful little tools, namely the "makefile", "sp.sh", "gp.sh", "createAppServer.sh", "createUserLogin", "certificate.sh","makeManual.sh", "minclient.pl", the Tcsh aliases and the RPM spec files (see the online man pages), when working with a command line shell. Shell scripts are written to work with 'bash', but might work with other shells (e.g. 'sh', 'dash', ..), too.
Manifest or How To Find Text and Code Pieces
The complete list of all files is stored in 'Manifest.txt', which is used for several purposes. Firstly, it contains the headlines that are displayed by the web surface in 'Head' display mode. Secondly, it may contain the display and edit permissions for each file of the server. Add all your source files to the 'Manifest.txt' to take advantage of that feature. To configure it, the following variables must be the set:
# File: $MAXDAEMON_HOME/lib/Maxdaemon/Globals.pm $::USE_MANIFEST_PERMISSIONS = 1; # Use permissions defined in the 'Manifest.txt'. $::STRICT_MANIFEST_PERMISSIONS = 0; # Access denied for all nodes not defined in 'Manifest.txt'. # File: $MAXDAEMON_HOME/Manifest.txt ... # Example: Hide 'bin/certificate.sh'. bin/certificate.sh - Creates SSL certificates for name-based virtual server. - h ...
Strict permissions means that files not listed in '/Manifest.txt' are not accessible, altogether, if strict is not set, manifest permission are not applied to those files. Note, that the 'Manifest' permission feature is only experimental, so far.
Thirdly, '~/Manifest.txt' is used by the 'gp' shell command to find out where a piece of text or code is stored.
> gp '<search string>'
For example, imagine the situation that you want to change the string 'help' in all files and directory names to 'manual'. Well, first get a list of all files, feed an editor with that list, use the editor's search function to find the string, go through each file and change 'help' to 'manual' with the search/replace function of your editor. With Vim enter the following commands:
> gp -e help /maxdaemon/bin/certificate.sh /maxdaemon/../bin/gp.sh /maxdaemon/page/element/SurfaceIntroduction.html /maxdaemon/page/element/MaxdaemonOverview.html # copy above output, enter v (alias to vim) and paste. # Use Vim's search and replace functions to change 'help' to 'manual'. > v /maxdaemon/bin/certificate.sh /maxdaemon/../bin/gp.sh /maxdaemon/page/element/SurfaceIntroduction.html /maxdaemon/page/element/MaxdaemonOverview.html # 'mh' is a Tcsh alias for 'cd $MAXDAEMON_HOME'. > mh # 'f' is a Tcsh alias for 'find . -name <string>'. > f help ./help ./user/help # Change file, links, resp. folder names. > mv ./help ./manual > mv ./user/help ./user/manual
Alternatively, you can find a string with the search function of the web surface, also displaying the list of files, containing the searched string. Though in this case, it will take more time, because of the search/replace feature of Vi, but fine to get an overview.
Desktop, X-terms and Web Surface
While Vi or an equivalent editor is mostly the best tool to edit software, documents can often more easily be edited with a (HTML) text editor or a web browser's 'textarea' form field.
So, to efficiently work with Maxdaemon, arrange the computer desktop so that you have one virtual desktop for the X-terms e.g. to edit the programs and to (re)start the daemon and another desktop for the web browser tabs to display the developed pages and to edit content and embedded software.
Download, Installation and Configuation
Downloads
Downloads are available via the Maxscape downloads page.
Quick Glance Installation
To take a quick glance at Maxdaemon, you might want to install Maxdaemon under your UNIX user account. The makefile helps you to set your environment and gives you some installation hints, only.
# You'll need an account on a Unix host with tcsh, wget or curl, md5sum, tar, make, Perl # and a web browser for the installation and operation. Use Firefox for ease of use. # Downloaded the Maxdaemon distribution to your downloads directory (e.g.: ~/Downloads) # using a web browser or downloaded it via a terminal with e.g. curl. # Create an account at http://maxscape.com/ to get your credentials <UserId:Password>: > curl -ku <UserId:Password> https://maxscape.local.net/User/Downloads/maxdaemon-home-source-distribution-1.0.0.tar.gz --output ~/Downloads/maxdaemon-home-source-distribution-1.0.0.tar.gz # Check the md5sum: > md5sum ~/Downloads/maxdaemon-home-source-distribution-1.0.0.tar.gz # Change to the directory under which to install Maxdaemon (best: ~/): > cd # Untar the the distribution: > tar zxvf ~/Downloads/maxdaemon-home-source-distribution-1.0.0.tar.gz maxdaemon/ ... # Install, configure and start Maxdaemon. > cd maxdaemon/1.0.0 > make install_quick_glance Installing Maxdaemon for you. ... # Set the Maxdaemon shell environment, temporarily: > ./bin/sp # Start Maxdaemon (use options [-vv -sl] for debug mode): > maxdaemon start Starting Maxdaemon Application Server. ... # Open your browser and enter the location 'http://localhost:8000'. # Login to the web surface as 'Max' with the password '123456'. # Display access logs: > da ... 192.168.0.3 - - [10/Aug/2025:07:32:43 +0000] "GET / HTTP/1.1" 200 10380 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0" ... # Restart the server. > maxdaemon restart Restarting Maxdaemon Application Servers. ... # Stop the server. > maxdaemon stop ... # Change or remove the web surface password of 'Max'!
Now, enter 'http://127.0.0.1:8000/' in your browser, and the Maxdaemon surface should
show up. The SSL daemon has the address 'http://127.0.0.1:8001/'.
If your browser already has stored a certificate with the name '127.0.0.1' for the server
'127.0.0.1:8001', delete that certificate via the browser's Certificate Manager and use
another serial number, if '00' dosn't work.
Note, that when executing Maxdaemon as a 'non-root' user, you will not be able to use the default HTTP(S) ports (default HTTP port is 80, default HTTPS port is 443), because they are preserved for (change) root daemons. To run servers on TCP/IP port numbers below 1024 root permissions are required and you can't set up a name based virtual server.
Advanced Installation
To set up a fully fledged virtual name-based server might take some time. Firstly, you'll need to set up your operating system and to provide the required components, that are not part of your OS.
- Operating system set up.
- Setup host and domain names.
- Configure the network interface.
- Choose UNIX user account and groups.
- Choose installation directory.
- Untar Maxdaemon Tar file(s).
- Configure and start Maxdaemon.
To run a fully featured development or production server, an own UNIX account (maxdaemon:maxdaemon) is recommended, best placed in the '/opt' folder. Each application server has an own standardized directory structure located below the 'server' folder. Most configuration modes and options are configured by directives in configuration files (maxdaemon<-version>.conf) placed in the related 'etc' directories.
UNIX User Account and Groups
There are three kinds of UNIX user accounts under which Maxdaemon can be installed (supported by the makefile):
- Install under an own 'maxdaemon' account (recommended).
- Install as user 'root'.
- Install as a 'non-root' user.
Install Maxdaemon as User 'root'
Even if you want to execute Maxdaemon as user 'root', I recommend to install Maxdaemon under an own account. This way development can be done under the 'maxdaemon' user, while Maxdaemon can be started by the 'root' user, respectively by an '/etc/init.d/maxdaemon' script at boot time (see the '/opt/maxdaemon/etc/maxdaemon.etc.init.d.sh' example script). Set the 'User' and 'Group' entries in the '~/etc/maxdaemon.conf' file to the UID/GID names under which you want to run Maxdaemon.
Maxdaemon UNIX Account
If you have root permission, it is best to create an own UNIX account, say maxdaemon. Assuming that there is no user 'maxdaemon (UID=8002)' and no group 'maxdaemon (GID=8002)' on your computer so far (choose other user(UID)/group(GID), if you like), you need to create the 'maxdaemon' user and the 'maxdaemon' group. The makefile does not automate this, because I don't want to fiddle with your computer's '/etc/passwd' and '/etc/group' files. Also assuming that you have untared the distribution tar file under '/opt', enter the next lines.
If you use 'sudo', the following lines must be preceeded by it. To bypass 'sudo' enter 'sudo passwd root' and be a bit careful what you are doing. Provided that there are no UID/GID 8002/8002 on your computer, do:
> su - root > groupadd -g 8002 maxdaemon > useradd -u 8002 -s /bin/sh -d /opt/maxdaemon/home -g maxdaemon maxdaemon > passwd maxdaemon
Now, you can login to your newly created 'maxdaemon' account (su - maxdaemon).
Maxdaemon Installation Steps
I recommend to install Maxdaemon below the '/opt' directory. If this is not wanted or possible choose another. Go to that directory and untar the distribution file, then you will find the installation, below the maxdaemon directory.
> su - root > cd <Installation directory> # best '/opt' > tar zxvf <Download directory>/maxdaemon-root-1.0.0-distribution-<version>.tgz > su - maxdaemon > mr # tcsh alias for 'cd $MAXDAEMON_ROOT' > make info # prints some information about your installation > createUserLogin create <user name> > certificate -a URI:<FQDN> -s 00 <FQDN> # FQDN is given by 'hostname --fqdn' > sp -p OSperl -c fqdn > maxdaemon -vv start
Now, enter 'http://<FQDN>:8000/' in your browser, and the Maxdaemon surface should show up. The SSL daemon has the address 'http://<FQDN>:8001/'.
Because we have started Maxdaemon from our UNIX maxdaemon account, we'll get the error 'Set EGID/RGID: Operation' not permitted. To get ride of this warning, comment out the 'User' and 'Group' directives, in the configuration file (~/etc/maxdaemon-fqdn.conf).
If we start Maxdaemon from the UNIX root account, the HTTP(S) will run with the user/groups defined by the 'User' and 'Group' directives.
Shell Environment
To work with Maxdaemon from your UNIX root account the shell environment needs to be configured, which is defined in the global profile and tcshrc files. If you include them in your root account's '~/.profile' and '~/.tcshrc' resource files, the variables are then set when you login, automatically.
<Installation directory>/maxdaemon/etc/profile # Maxdaemon global profile <Installation directory>/maxdaemon/etc/tcshrc # Maxdaemon global tcshrc
At least define the 'MAXDAEMON_INSTALLATION_ROOT' variable in your '~/.profile'. Assuming that you have installed Maxdaemon under the '/opt' folder, add the following lines to your '~/.profile'. If you don't want to pollute your environment, only export the 'MAXDAEMON_INSTALLATION_ROOT' variable and use (maybe adapt) the 'sp' (set project) script, to set the environment.
# File: ~/.profile MAXDAEMON_INSTALLATION_ROOT=/opt/maxdaemon; export MAXDAEMON_INSTALLATION_ROOT; if [ -f $MAXDAEMON_INSTALLATION_ROOT/maxdaemon/etc/profile ]; then . $MAXDAEMON_INSTALLATION_ROOT/maxdaemonetc/profile else echo "Maxdaemon profile ($MAXDAEMON_INSTALLATION_ROOT/maxdaemon/etc/profile) not found!" fi tcsh if [ $? != 0 ]; then echo "You should install and use tcsh with Maxdaemon, in order to be able" echo "to use the Maxdaemon tcsh aliases." sh fi
The global profile ($MAXDAEMON_ROOT/etc/profile) defines the following shell environment variables and sets the PATH and MANPATH for Maxdaemon:
> env|grep MAX MAXDAEMON_INSTALLATION_ROOT=/opt/maxdaemon MAXDAEMON_NAME=maxdaemon MAXDAEMON_VERSION=1.0.0 MAXDAEMON_ROOT=$MAXDAEMON_INSTALLATION_ROOT/$MAXDAEMON_NAME MAXDAEMON_MANPATH_OS_ORIG= MAXDAEMON_HOME=$MAXDAEMON_ROOT/daemon MAXDAEMON_PATH_OS_ORIG=/usr/local/bin:/usr/bin:/bin: MAXDAEMON_TMP_DIR=/opt/maxdaemon/daemon/var/tmp MAXDAEMON_CONF_FILE_VERSION= > echo $PATH /opt/maxdaemon/daemon/bin:/opt/maxdaemon/daemon/sbin:/opt/maxdaemon/bin:/bin:/bin:/usr/local/bin:/usr/bin:/bin: > echo $MANPATH /opt/maxdaemon/daemon/man:
To control the various configuration modes the 'sp' (set project) shell script is provided. This script is meant to be adapted by you, to set your project's evironment.
# Uses the Perl installation ($MAXDAEMON_ROOT/perl) provided by Maxdaemon (only for Ubuntu!) # and the configuration file: '$MAXDAEMON_HOME/etc/maxdaemon-127.0.0.1-8000-8001.conf'. > sp -p maxperl -c 127.0.0.1-8000-8001 > ls -l /opt/maxdaemon/daemon/bin/perl lrwxrwxrwx ... /opt/maxdaemon/daemon/bin/perl -> /opt/maxdaemon/perl/5.26.1/bin/perl > wp # which project Project is......................: maxdaemon Environtment variables are......: Maxdaemon installation directory: /opt Maxdaemon name..................: maxdaemon Maxdaemon home..................: /opt/maxdaemon/maxdaemon/daemon Maxdaemon root..................: /opt/maxdaemon/maxdaemon Maxdaemon version...............: 1.0.0 Maxdaemon temporary folder......: /opt/maxdaemon/maxdaemon/daemon/var/tmp Maxdaemon configuration file....: /opt/maxdaemon/maxdaemon/daemon/etc/maxdaemon-127.0.0.1-8000-8001.conf. MAXDAEMON_INSTALLATION_ROOT.....: /opt/maxdaemon PERL_VERSION....................: 5.26.1 PERL_ROOT.......................: /opt/maxdaemon/perl/5.26.1 PERL_BIN........................: /opt/maxdaemon/perl/5.26.1/bin PERL5LIB........................: /opt/maxdaemon/perl/5.26.1/lib/5.26.1:/opt/maxdaemon/perl/5.26.1/lib/5.26.1/x86_64-linux:/opt/maxdaemon/perl/5.26.1/lib/site_perl/5.26.1:/opt/maxdaemon/perl/5.26.1/lib/site_perl/5.26.1/x86_64-linux SSL_VERSION.....................: 1.1.0g SSL_ROOT........................: /opt/maxdaemon/ssl/1.1.0g SSL_BIN.........................: /opt/maxdaemon/ssl/1.1.0g/bin APACHE_VERSION..................: 2.4.29 APACHE_ROOT.....................: /opt/apache/2.4.29 APACHE_BIN......................: /opt/apache/2.4.29/bin DATABASE_TYPE...................: mysql-maxscape MYSQL_VERSION...................: 5.5.39 MYSQL_ROOT......................: /opt/mysql/5.5.39/usr MYSQL_BIN.......................: /opt/mysql/5.5.39/usr/bin PATH............................: /opt/maxdaemon/daemon/bin:/opt/maxdaemon/daemon/sbin:/opt/maxdaemon/bin:/opt/maxdaemon/perl/5.26.1/bin:/opt/maxdaemon/ssl/1.1.0g/bin:/opt/apache/2.4.29/bin:/opt/mysql/5.5.39/usr/bin:/opt/mysql/5.5.39/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin MANPATH.........................: /opt/maxdaemon/daemon/man:/opt/maxdaemon/perl/5.26.1/man:/opt/maxdaemon/ssl/1.1.0g/man:/opt/apache/2.4.29/man:/opt/mysql/5.5.39/usr/share/man: LD_LIBRARY_PATH.................: /opt/maxdaemon/ssl/1.1.0g/lib Perl executable is..............: lrwxrwxrwx 1 root root 35 Apr 11 11:44 /opt/maxdaemon/daemon/bin/perl -> /opt/maxdaemon/perl/5.26.1/bin/perl
Network Prerequisites
An HTTP daemon requires some prerequisites to run properly. Namely, the IP address of the Ethernet/PPP interface and the host and domain names (FQDNs) under which you want to access the daemon. Various modes can be configured:
- Localhost (e.g. http://localhost:8000/, http://127.0.0.1:8000/).
- IP-based host (e.g. http://192.168.0.1:8000/).
- Name-based virtual host (e.g. https://www.local.net/).
Localhost
For development and test purposes you can configure the daemon to listen to the local loopback device, but the server cannot be reached via a network. This is the default configuration after installation (http://127.0.0.1:8000/).
IP-based Host
You can configure the Maxdaemon to listen to the IP address of your Ethernet/PPP interfaces. If the network is configured accordingly, the daemon is then accessible via the IP address. By the way, an HTTPD answering requests to an IP address is quite interesting, if the IP address is the dynamic address of the pppd (Point-to-Point Protocol Daemon) interface address. This enables end devices (e.g. mobil phones) to directly communicate with each other, provided they know their antagonist, maybe exchanged by a 'connect dynamic pppd IPs' switch server.
Name-based Virtual Hosts
To run a name-based virtual host daemon, the FQDNs (Full Qualified Domain Name) of all virtual hosts have to be configured by an Internet service provider or can be configured locally, for development and test purposes.. In both cases a 'hostname --fqdn' should yield a FQDN e.g.:
> hostname --fqdn www.local.net # example FQDN
In combination with the ports, this FQDN can then be used as the URL under which Maxdaemon and the web surface can be accessed, e.g.:
http://www.local.net:8000/ # HTTP requests https://www.local.net:8001/ # HTTPS requests
Host and Server Configuration
Host Name and IP Configuration
It is assumed, that the IP address of the host dev.local.net is 192.168.0.3, a second ethernet device with the IP 192.168.0.4 is configured with the host name dev.local.net. To set up a the host name and IP address do something like:
> su - root
> vi /etc/hosts # add IP and hostnames
192.168.0.3 dev.local.net dev
192.168.0.4 devdaemon.local.net devdaemon
> hostnamectl set-hostname dev # add hostname, changes /etc/hostname
# Shell session - temporarily
> ifconfig eth0 192.168.0.3 netmask 255.255.255.0 up
> ifconfig eth0:1 192.168.0.4 netmask 255.255.255.0 up # second Ethernet device
# Boot - permanent
> vi /etc/network/interfaces # Add the following lines:
iface eth0 inet static
address 192.168.0.3
netmask 255.255.255.0
# Add a second interface:
iface eth0:1 inet static
address 192.168.0.4
netmask 255.255.255.0
auto eth0 eth0:1
# Then restart the Ethernet interface:
> /sbin/ifdown eth0
> /sbin/ifup eth0
> /sbin/ifup eth0:1
# Show ethernet configuration
> ifconfig
eth0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.0.3 netmask 255.255.255.0 broadcast 192.168.0.255
ether 00:24:8c:95:47:3a txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0:1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.0.4 netmask 255.255.255.0 broadcast 192.168.0.255
ether 00:24:8c:95:47:3a txqueuelen 1000 (Ethernet)
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10>host>
loop txqueuelen 1000 (Local Loopback)
RX packets 24951 bytes 1518667 (1.5 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 24951 bytes 1518667 (1.5 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
# Maxscape configuration
> vi /maxscape/etc/httpd-2.4.29.conf # IP setup
Listen 192.168.0.3:80
Listen 192.168.0.3:2080
<IfModule ssl_module>
Listen 192.168.0.3:443
</IfModule>
# change the hostnames
> vi /maxscape/server/*/etc/httpd-2.4.29.conf
> vi /maxscape/etc/License # add entry
my %License = (
#>LICENSE_STRING
'dev.local.net/?%%?/192.168.0.3' =#> 'Max;3.00;2024;350;msql:mysql:oracle:;',
#>/LICENSE_STRING<
);
> vi /maxscape/server/WebServer/etc/maxscape.conf
<item key="Page.postOnLocalHost">https://dev.local.net:2080/User/www.fcg</item>
# edit max's management server's home page...
# Maxdaemon configuration
> vi $MAXDAEMON_INSTALLATION_ROOT/maxdaemon/etc/profile
HOST_NAME=`hostname`
DOMAIN_NAME=`domainname`
if [ "$HOST_NAME" = "dev" -a "$DOMAIN_NAME" = "local.net" ]; then
MAXDAEMON_HOST_IP=192.168.0.4
MAXDAEMON_HOST_NAME=devdaemon.local.net
fi
Local Name-based Virtual Hosts
For development and test purposes, FQDNs can easily be configured locally. To configure a FQDN locally, some lines in the '/etc/hosts' file might be enough. Maybe you need to configure the Ethernet device (e.g. with 'ifconfig eth0', '/sbin/ifdown eth0', '/sbin/ifup eth0', '/bin/domainname local.net', '/etc/rc.local', /etc/network/interfaces).
> vi /etc/hosts ... 192.168.0.1 www.local.net 192.168.0.1 www-2.local.net ... 192.168.0.2 maxdaemon.local.net 192.168.0.2 test.local.net 192.168.0.2 template.local.net ...
Note, that to run a name-based virtual host, the 'hostname' and the 'domainname' of the host must be set properly. For example:
# Set your Ethernet network interface IP to e.g. '192.168.0.1',
# if it isn't configured, already:
# Shell session - temporarily
> su - root
> ifconfig eth0 192.168.0.1 netmask 255.255.255.0 up
> ifconfig eth0:1 192.168.0.2 netmask 255.255.255.0 up # second Ethernet device
# Boot - permanent
> su - root
> vi /etc/network/interfaces
# Add the following lines:
iface eth0 inet static
address 192.168.0.1
netmask 255.255.255.0
auto eth0
# Maybe add a second interface:
# iface eth0:1 inet static
# address 192.168.0.2
# netmask 255.255.255.0
# auto eth0 eth0:1
# Then restart the Ethernet interface:
> /sbin/ifdown eth0
> /sbin/ifup eth0
> # /sbin/ifup eth0:1
> ifconfig
eth0 Link encap:Ethernet HWaddr 00:24:8c:95:22:68
inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
If eth0:1 is configured:
eth0:1 Link encap:Ethernet HWaddr 00:24:8c:95:22:68
inet addr:192.168.0.2 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
...
Define the server's domainname, if it isn't configured, already:
> domainname local.net
A good place for these commands at boot time is '/etc/rc.local':
> vi /etc/rc.local
# add the following lines:
/sbin/ifup eth0
/bin/domainname local.net
Now, define the FQDN's locally in '/etc/hosts':
> vi /etc/hosts
...
192.168.0.1 www.local.net
192.168.0.1 www1.local.net
...
192.168.0.1 wwwn.local.net
...
Running Maxdaemon as 'root' and at Boot Time
To start Maxdaemon as the 'root' user and at boot time, the Maxdaemon shell environment needs to be configured:
# File: ~/.profile ================== MAXDAEMON_INSTALLATION_ROOT=/opt/maxdaemon; export MAXDAEMON_INSTALLATION_ROOT;
There are several ways to do that, and there is a distinction between login and boot shells. To set the required enviroment for Maxdaemon to the root user login shell, you can either execute the Maxdaemon profile in your '~/.profile' or you can call the 'sp' script from the command line. The 'sp' command launches the 'tcsh' shell (if available), in order to make use of the Maxdaemon 'tcsh' aliases:
# Assumes a Perl installation below /opt/perl/<Perl version> > sp -p optperl -c fqdn > maxdaemon restart
To launch Maxdaemon at boot time see the example script: maxdaemon.etc.init.d.sh or man maxdaemon.etc.init.d.sh.
SSL Certificate Creation
The HTTPS protocol requires SSL certificates that must be known by the HTTP server. To create them, you can use the 'certificate' script.
# Maxdaemon SSL certificate directory: > certificate 127.0.0.1 > ls /maxdaemon/etc/ssl ca.crt ca.csr ca.key ca.key.crypt server.crt server.csr server.key server.key.crypt # Application server SSL certificate directory: > certificate -w <application server> 127.0.0.1 > ls /maxdaemon/server/<application server>/etc/ssl ca.crt ca.csr ca.key ca.key.crypt server.crt server.csr server.key server.key.crypt
The creation of several name based SSL hosts is a bit tricky, as you need to know the complete list of all virtual host names, beforehand. This list must then be passed to each call of the 'certificate' script, using the '-a <List of all virtual host names>' option.
To only create a SSL certificate for the Maxdaemon web surface, and if your virtual host name (FQDN) is 'www.local.net', enter (use another serial number, if '00' dosn't work):
> certificate -a URI:www.local.net -s 00 www.local.net # Or if you have no FQDN configured, e.g.: > certificate -a URI:127.0.0.1 -s 00 127.0.0.1 > certificate -a URI:192.168.0.1 -s 00 192.168.0.1 # Or do it by hand, if you don't want a name-based virtual SSL host: > cd <ssl folder> > openssl genrsa -des3 -out server.pass.key 1024 > openssl req -new -key server.pass.key -out server.csr > openssl rsa -in server.pass.key -out server.key > openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
To create the SSL certificates for the Maxdaemon web surface and the 'Test' and 'Template' application server examples, enter:
# maxdaemon.local.net - Maxdaemon's web surface FQDN # test.local.net - 'Test's virtual host name # template.local.net - 'Template's virtual host name # List of virtual hosts = "URI:maxdaemon.local.net,URI:test.local.net,URI:template.local.net" > certificate -a <List of virtual hosts> -s 00 maxdaemon.local.net > certificate -w Test -a <List of virtual hosts> -s <> 01 test.local.net > certificate -w Template -a <List of virtual hosts> -s 02 template.local.net
Don't be surprised, when you get a warning from Firefox that your certificate isn't trusted, because it is 'self-signed'. Some browsers refuses 'self-signed' certificates altogether. Self-signed simply means that the certificate isn't authorized by a third party. Buy a certificate to get ride of that warning.
Note, that you might have to delete your browser's Maxdaemon certificates (see browser preferences), if you reinstall Maxdaemon. Otherwise your browser might refuse to connect the Maxdaemon SSL server! Sometimes my firefox gets confused with its certificates, then I simply delete the '~/.mozilla/firefox/*.default' 'cert8.db' and 'cert_override.txt' files. Beware that this deletes all your certificates besides the default ones!
Work Flow Examples
Please note, that actual changes via the web surface are preserved for registered users by default. On production sites you might want to disable the public surface, altogether. Have in mind also, that the surface is meant to be an addition to shells and other tools, not a replacement. To (re)start/stop the server you definitely need a command line shell.
Static Content
Publishing static content is as simple as placing the related text and media files in an
application server's document tree. If you have files with MIME types not listed in the
global HTTPD MIME type configuration file ('~/etc/mime_types.conf'), it is mostly sufficient
to add them with an 'AddType' directive entry.
Lets exercise some examples. Assuming you are working on the 'Test' application server, traverse
to the Test server's 'DocumentRoot'.
Maybe, choose the 'Edit Layout' via the menu (☰), to hide the surface page header and to fix the
action button bar.
As a registerd user you would have logged in first, to be able to actually make changes.
Click the 'new file' button and enter a file name, whereby the file name extension determines, how
the file is rendered at runtime. An extension correlates to its MIME type, which then determines
the server's action.
Say, your file name is 'MyTest.txt'. Enter some text, click 'change' and then right-click the
base name of the shown file path and say 'Open Link in New Tab' (Firefox) to display the
your page in another browser tab (display tab). Alternatively, click on the menu symbol (☰)
to open another tab. Because the file extension is 'txt' the content is believed to be of MIME
type 'text/plain'. Therefore the server sends the following response:
HTTP/1.1 200 OK date: Sun, 1 Apr 2018 00:18:42 GMT server: Maxdaemon/1.0.0 content-type: text/plain; charset=utf-8; content-length: 22 last-modified: Sun, 1 Apr 2018 00:18:42 GMT connection: close Hallo, this is some text.
The server's response consists of the HTTP headers and the actually displayed page. Because the content type is 'text/plain', the browser just displays what you have written without rendering it.
For the next example, leave 'MyTest.txt' by clicking the 'htdocs' part of the shown file path,
which leads you back to Test's document root. Now, create a file with an 'html' extension,
say 'MyTest.html'. Maybe copy and paste the source code from elsewhere. If you need a
HTML tag template, you might want to use the HTML help via the '?' menu) to copy
and paste the desired tag.
To edit an existing file, press the 'edit' button and select the wanted file via the radio
widget. Edit the file and then press 'change' to store the changes. When working with big
files, select a text snipped that you can search for with the browser's search function,
before you press 'change' to leave out nasty page scrolling.
For not registered users changes are disabled, so I have copied and pasted the following
HTML code, which is based on the Holy Grail example from developer.mozilla.org, beforehand.
Best use Firefox for this example, as other browsers might need a '-webkit' in front of
some CSS properties.
By the way, writing HTML source code is easier than most laymen might think. Often is it simpler than using a WYSIWYG editor that tries to hide the difficulties and at least more flexible (see the experimental Maxdaemon::WYSIWYG class for using an WYSIWYG editor).
File: ~/server/Test/htdocs/MyTest.html:
=======================================
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Page Title</title>
</head>
<body>
<header>Header</header>
<main>
<nav>Navigation</nav>
<article>Article</article>
<aside>Aside</aside>
</main>
<footer>Footer</footer>
</body>
</html>
Click 'change' and display the result in another browser tab. The basic parts of a web page are shown. To make it look more nicely, we add a style sheet (place it in between the <head> tag):
<style type="text/css">
body {
margin: 0px;
padding: 0px;
font: 24px Helvetica;
background: #999999;
}
main {
min-height: 800px;
margin: 0px;
padding: 0px;
display: flex;
flex-flow: row;
}
main > article {
margin: 4px;
padding: 5px;
background: #dddd88;
flex: 3 1 60%;
order: 2;
}
main > nav {
margin: 4px 4px 4px 0px;
padding: 5px;
background: #ccccff;
flex: 1 6 20%;
order: 1;
}
main > aside {
margin: 4px 0px 4px 4px;
padding: 5px;
background: #ccccff;
flex: 1 6 20%;
order: 3;
}
header, footer {
display: block;
margin: 0px;
padding: 5px;
min-height: 100px;
background: #ffeebb;
}
/* Too narrow to support three columns */
@media all and (max-width: 640px) {
header, footer {
font: 16px Helvetica;
}
main {
font: 16px Helvetica;
flex-direction: column;
}
main > article, main > nav, main > aside {
margin: 4px 0px;
order: 0; /* Return to document order */
}
main > nav, main > aside, header, footer {
min-height: 50px;
max-height: 50px;
}
}
</style>
Reload the page in the display tab. Note, that this page is responsive, so when displayed on a screen with less than 640 pixel the order of the page parts and the font size adapt to the view port of the screen (shrink your browser window for a test).
Dynamic Content
Though the last example doesn't seem to be so static, the content is. So, for dynamic pages, we use CGI scripts to generate the content on the fly. The most simple Perl CGI script is shown below:
File: /server/Template/htdocs/hello.cgi ======================================= #!/opt/maxdaemon/daemon/bin/perl package main; use strict; my $CRLF = "\015\012"; my $Header = "Content-type: text/plain$::CRLF"; my $Content = 'Hello world.'; print $Header . $::CRLF . $Content; 1;
Copy this file with a command line shell in an Xterm or the surface.
Web surface: ============ Go to the '~/server/Template/htdocs' folder, click 'copy file', select 'hello.cgi' via the radio button, enter the destination path in the input field (/server/Test/htdocs/hello.cgi) and click 'copy file', again. Command line: ============= > su - maxdaemon > ms # tcsh alias for 'cd $MAXDAEMON_HOME/server' > cp -p Template/htdocs/hello.cgi Test/htdocs/MyTest.cgi > cd Test/htdocs > vi MyTest.cgi
After this, the surface displays an hyper link ('MyTest.cgi') below the '/server/Template/htdocs' folder. Click on it, to display 'Hello world.' and then edit the script. Take the author, copyright, a.s.o and the perlpod at the end of the file as a template for your data. You can later add the script's perlpod to the on-line man pages by adding two lines to '~/bin/makeManual.sh'.
Next, we want to combine the above HTML example with a CGI script. So, we create a new
file, say 'MyTest+HTML.cgi' by copying 'hello.cgi.
There are numerous ways to generate content within a CGI programming environment, indeed.
In a first attempt, we could copy the HTML text into the CGI script and make it
a Perl variable that we then print. Obviously, this is not a to good idea, because
the content (HTML text) and the application code (script) are mixed in the same file.
Instead, we better read the text from a file (e.g. 'MyTest+CSS.html') then we have
separate storage places for the content and the application script. In the example
below, the 'Maxdaemon::PageByPathInfo' class is used to do just that.
To adapt the code to the CGI environment, we have to consider under which application
server we like to run the script. Normally, because we are working on the 'Test'
application server, we have configured a name-based virtual host (e.g. 'test.local.net'),
beforehand. The address is then 'http://test.local.net/MyTest+HTML.cgi'.
For test purposes, we can run it also under the 'Maxdaemon' surface server via
the address 'http://maxdaemon.local.net/server/Test/htdocs/MyTest+HTML.cgi',
but then we need to tell the 'generatePage' method via the 'PageRoot' parameter where
to find the pages to be displayed.
Please note the call of the 'pe' (print to error log) function. It prints a
message to the error log file, which is either STDERR or the error log of the
related application server. For development you might also want to use the 'pd' resp. 'pdd'
functions (see: 'Globals' man page).
To watch the output, open a Xterm, restart the server and reload the page in the browser.
File: /server/Test/htdocs/MyTest+HTML.cgi
=========================================
#!/opt/maxdaemon/daemon/bin/perl
###############################################################################
package main;
use strict;
sub BEGIN {
# Tell Perl where to find Maxdaemon.
unshift(@INC, "$ENV{MAXDAEMON_HOME}/lib");
eval ("use Maxdaemon::Globals;");
Maxdaemon::Globals::checkProjectEnvironment(0);
}
use Maxdaemon::PageByPathInfo;
###############################################################################
my $DocumentRoot = $ENV{DOCUMENT_ROOT};
my $PageRoot = '';
if ($DocumentRoot eq "$::MAXDAEMON_HOME") {
$PageRoot = "$DocumentRoot/server/Test/htdocs";
}
elsif ($DocumentRoot eq "$::MAXDAEMON_HOME/server/Test/htdocs") {
# $PageRoot = '';
} else {
pe ("MyScript: DocumentRoot ($DocumentRoot) not found!");
}
pe ("MyScript: PageRoot=$PageRoot.");
my ($Content, $HTTP_Header, $Status) = Maxdaemon::PageByPathInfo->new->generatePage (
PageRoot => $PageRoot,
defaultPageName => '/MyTest+CSS.html',
);
print $$HTTP_Header . $$Content;
1;
__END__
###############################################################################
Tcsh Shell in a Xterm:
======================
> maxdaemon restart # print diagnostics to STDERR
or
> maxdaemon -l restart # print diagnostics to the server's error log
> de # tcsh alias to displays the error logs:
MyScript: PageRoot=/opt/maxdaemon/daemon/server/Test/htdocs.
> da # tcsh alias to displays the access logs:
==> /opt/maxdaemon/daemon/var/logs/maxdaemon-access.log <==
192.168.0.1 - - [04/Apr/2018:14:11:07 +0000] "GET /server/Test/htdocs/MyTest+HTML.cgi HTTP/1.1" 200 1735 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0"
Now, we fill our page with life by adding Perl code to the (HTML) text. Therefore
we create a file with the extension '.phtml' (Perl parsed HTML). So, copy 'MyTest.html'
to 'MyTest+CSS.phtml'.
There are several ways to embed Perl code within a text file. One is to read the file
into a string variable and let Perl's 'eval' function do the variable substitution
and the execution of the embedded function calls. Then the text has become a Perl
string that is evaluated by the Perl interpreter. An additional parser is then not
required, instead Perl is doing the job, and even better Perl's string evaluation
is pretty fast.
How the embedded variables are substituted and which methods are called is defined
by the (lexical) context in which the string is evaluated. This gives us the
possibility to pass variable values and objects from the script into the text.
Well, when we now execute the script by reloading the page we get an error, because
Perl believes that '@media' in the HTML text is an undeclared array. Therefore, we
need to escape characters special to the Perl interpreter (e.g. $, @) with a
backslash.
There are several possibilities to name, store and pass embedded variables. When
the string evaluation takes place in the scope of the 'Maxdaemon::PageByPathInfo'
class, we can define variables/objects as members of the '$Page' object.
To embed the '$CGI->Query ('Article')' method call within the document text, we
simply use a so called closure (@{[ <your function/method call> ]}).
Thank you Perl!
To make the page really dynamic, we also add a CGI interface object and use the
CGI query string to control the script behaviour.
File: /server/Test/htdocs/MyTest+CSS.phtml:
===========================================
...
<header>$Page->{Data}->{header}</header>
...
<article>@{[ $Page->{CGI}->Query ('Article') ]}</article>
...
<footer>$Page->{Data}->{Footer}</footer>
...
File: /server/Test/htdocs/MyTest+PHTML.cgi
==========================================
...
use Maxdaemon::PageByPathInfo;
use Maxdaemon::CGI;
...
my $Page = Maxdaemon::PageByPathInfo->new;
my $CGI = Maxdaemon::CGI->new;
$Page->{CGI} = $CGI;
$Page->{CGI}->Query ('Article')
|| ($Page->{CGI}->{Article} = "Append '?Article=DynamicArticle' to the location");
$Page->{Data}->{Header} = "Generated Page Header";
$Page->{Data}->{footer} = "Generated Page Footer";
my ($Content, $HTTP_Header, $Status) = $Page->generatePage (
PageRoot => $PageRoot,
defaultPageName => '/MyTest+CSS.phtml',
);
...
Browser location e.g.:
======================
http://maxdaemon.local.net/server/Test/htdocs/MyTest+PHTML.cgi?Article=DynamicArticle
or use the path info (e.g. PATH_INFO=/MyTest.phtml) to address a special page:
http://maxdaemon.local.net/server/Test/htdocs/MyTest+PHTML.cgi/MyTest+CSS.phtml?Article=Hello world
By now, we have created a basic tool kit to implement dynamic pages. The layout
is defined by the (responsive) style sheet and separated from the (HTML) content. By
embedding Perl variables and method calls within the document, the (HTML/CSS) text is
(greatly) separated from the CGI script code, also. So, we can think in terms of a
(dynamic) text with an embedded API instead of pondering about a program that outputs
the text.
The next steps are to turn 'MyTest.cgi' into a SCGI, maybe a DCGI and/or a FCGI (for Apache)
script to optimize the execution speed and to implement an application, of course.
For a more elaborated example, have a look at the '~/server/Test/htdocs/www.cgi' CGI and the '~/server/Test/htdocs/www.scgi' SCGI scripts (e.g.: http://test.local.net/).
Each part of the page is now stored in an own file, so these parts can easily be reused
by other pages. Candidates that might be reused are located below the 'template' and parts
that contains real content below the 'element' folders.
File: ~/server/Test/htdocs/www.phtml:
====================================
<!DOCTYPE html>
<html>
<head>
@{[ $Page->Template (Name => 'DocumentHeader', Type => 'parse') ]}
</head>
<body>
<header>
@{[ $Page->Template (Name => 'PageHeader', Type => 'parse') ]}
</header>
<main>
<nav>
@{[ $Page->Template (Name => 'PageNavigation', Type => 'parse') ]}
</nav>
<article>
@{[ $Page->Element (Name => 'Index', Type => 'parse') ]}
</article>
<aside>
@{[ $Page->Template (Name => 'PageAside', Type => 'parse') ]}
</aside>
</main>
<footer>
@{[ $Page->Template (Name => 'PageFooter', Type => 'parse') ]}
</footer>
</body>
</html>
File: ~/server/Test/htdocs/template/DocumentHeader.phtml:
========================================================
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Test Page</title>
<link href="$Page->{Data}->{FolderPrefix}/css/www.css" rel="stylesheet" type="text/css"/>
<script src="$Page->{Data}->{FolderPrefix}/javascript/Maxscape/Typewriter.js" type="text/javascript"></script>
<script src="$Page->{Data}->{FolderPrefix}/javascript/Maxscape/Clock.js" type="text/javascript"></script>
File: ~/server/Test/htdocs/template/PageHeader.phtml:
====================================================
<table id="PageHeaderTable" width="100%" summary="Header Table" cellpadding="0" cellspacing="0">
<tr>
<td style="padding: 10px 10px 0px 0px; height: 80px;" align="left" valign="bottom">
<a id="PageHeaderTableText" href="/www.scgi">$Page->{Data}->{Header}</a>
</td>
<td align="right" valign="top">
</td>
</tr>
</table>
File: ~/server/Test/htdocs/template/PageNavigation.phtml:
========================================================
Navigation
File: ~/server/Test/htdocs/element/Index.phtml:
=============================================
<h2>Test CGI Script</h2>
...
File: ~/server/Test/htdocs/template/PageAside.phtml:
===================================================
<canvas id="canvas" width="150" height="150"></canvas>
<script type="text/javascript">
window.requestAnimationFrame (clock);
</script>
File: ~/server/Test/htdocs/template/PageFooter.phtml:
===================================================
$Page->{Data}->{Footer}
Application Module Plug-in
Normally, a main script is not a good place for application modules, which should better be placed e.g. in the 'ServerApplication.pm' file that is imported, if it exists. So, if an appliction server is created with the 'createAppServer' script, the file '~/server/<app server name>/lib/ServerApplication.pm' contains a package (Maxdaemon::<app server name>) that can be used as a starting point to implement an applications.
The 'PageContextCallback' method is used to push variables into the name space of pages and page elements/templates, so that they can be embedded in '*.phtml' files by their name (see Maxdaemon::PageByPathInfo, also).
File: ~/server/<app server name>/lib/ServerApplication.pm:
=========================================================
sub PageContextCallback {
my $Page = shift;
my $p = shift;
$Page->embedVariables (
VariableName => 'variable name',
);
return '';
}
Use a variable in '*.phtml' files by name:
==========================================
<html>
...
Simply use a variable by the $VariableName.
...
</html>
Third Party Products
Maxdaemon uses the following third party products:
| Product | Authors | License |
|---|---|---|
| Perl | Larry Wall and the Perl community | Perl Artistic |
| Openssl | The OpenSSL Project Authors | The License |
| Cwd | Perl 5 porters (Maintained by Ken Williams) | Perl Artistic |
| Data::Dumper | Gurusamy Sarathy | Perl Artistic |
| Digest::MD5 | Gisle Aas, Neil Winton and RSA Data Security, Inc. | Perl Artistic |
| Encode | Dan Kogai | Perl Artistic |
| Fcntl | ? | ? |
| File::Basename | ? | ? |
| File::Copy | Aaron Sherman and Charles Baile | Perl Artistic |
| Filter::Crypto | Steve Hay | Perl Artistic or GPL |
| Getopt::Long | Johan Vromans | Perl Artistic or GPL |
| IO::Socket | Graham Barr, Lincoln Stein and the Perl Porters | Perl Artistic |
| IO::Socket::INET6 | Graham Barr, Rafael Martinez Torres, Shlomi Fish and Euro6IX project. | Perl Artistic |
| IO::Socket::UNIX | Graham Barr | Perl Artistic |
| MIME::Base64 | Gisle Aas | Perl Artistic |
| Net::Domain | Graham Barr, David Sundstrom and Steve Hay | Perl Artistic |
| Net::hostent | Tom Christiansen | ? |
| Net::SSLeay | Sampo Kellomaeki, Florian Ragwitz and Mike McCauley | Perl Artistic 2.0 |
| Pod::Usage | Marek Rouchal and Brad Appleton | ? |
| POSIX | ? | ? |
| RPM | Marc Ewing, Jeff Johnson, Erik Troan Red Hat | ? |
| Socket | Perl 5 Porters and Paul Evans | ? |
| Time::HiRes | Douglas E. Wegscheid, Jarkko Hietaniemi and Andrew Main | Perl Artistic |
The Maxdaemon distribution also contains the following software packages that are used in example and test applications or just for convenience:
| Product | Authors | License |
|---|---|---|
| Apache | Apache Software Foundation | Apache License |
| Apache::LogFormat::Compiler | Masahiro Nagano | Perl Artistic |
| HTTP::Entity::Parser | Masahiro Nagano and Tokuhiro Matsuno | Perl Artistic |
| bareword::filehandles | Dagfinn Ilmari Mannsåker | Perl Artistic |
| Catalyst::Runtime | Perl Artistic | |
| CGI | Lincoln D. Stein and others | ? |
| CGI::Fast | Lincoln D. Stein | Perl Artistic |
| CGI::Simple | ? | ? |
| CGI::Struct | Matthew Fuller | Perl Artistic |
| Class::Data::Inheritable | Damian Conway, Michael G Schwern and Tony Bowden | Perl Artistic |
| Class::Load | Shawn M Moore | Perl Artistic |
| Class::Inspector | Adam Kennedy | Perl Artistic |
| Class::Method::Modifiers | Shawn M Moore | Perl Artistic |
| Clone | Ray Finch | Perl Artistic |
| Cookie::Baker | Masahiro Nagano | Perl Artistic |
| Data::Dump | Gisle Aas and Gurusamy Sarathy | Perl Artistic |
| Data::Dumper::Concise | Matt S. Trout and Arthur Axel | Perl Artistic |
| Data::OptList | Ricardo Signes | Perl Artistic |
| Dancer | Alexis Sukrieh | Perl Artistic |
| DBI/DBD | Tim Bunce | Perl Artistic |
| DBD::mysql | Patrick Galbraith, Michiel Beijen and others | Perl Artistic |
| Devel::GlobalDestruction | Yuval Kogman, Florian Ragwitz, Jesse Luehrs, Peter Rabbitson, Arthur Axel, 'fREW' Schmidt, Elizabeth Mattijsen and Greham Knop | Perl Artistic |
| Devel::StackTrace | Dave Rolsky | Perl Artistic 2.0 |
| Devel::StackTrace::AsHTML | Tatsuhiko Miyagawa and Shawn M Moore | Perl Artistic |
| Devel::Hide | Adriano R. Ferreira | Perl Artistic |
| Encode::Locale | Gisle Aas | Perl Artistic |
| ExtUtils::Config | Ken Williams and Leon Timmermans | Perl Artistic |
| ExtUtils::Helpers | Ken Williams and Leon Timmermans | Perl Artistic |
| ExtUtils::InstallPaths | Ken Williams and Leon Timmermans | Perl Artistic |
| FCGI | Open Market, Inc. | Free |
| FCGI::ProcManager | James E Jurach Jr and Gareth Kirwan | GNU Lesser General Public License |
| File::Remove | Shlomi Fish | Perl Artistic |
| Filesys::Notify::Simple | Tatsuhiko Miyagawa | Perl Artistic |
| File::Listing | Gisle Aas | Perl Artistic |
| File::ShareDir | Adam Kennedy | Perl Artistic |
| GD | Lincoln D. Stein | Perl Artistic |
| gitweb | Kay Sievers, Christian Gierke | GPLv2 |
| Hash::Merge | by David Golden, Ricardo Signes, Adam Kennedy and Contributors | Perl Artistic |
| Hash::MultiValue | Tatsuhiko Miyagawa, Aristotle Pagaltzis and Hans Dieter Pearcey | Perl Artistic |
| HTML::Parser | Gisle Aas and Michael A. Chase | Perl Artistic |
| HTTP::Cookies | Gisle Aas | Perl Artistic |
| HTTP::Body | Christian Hansen, Sebastian Riedel, Christian Walde and Torsten Raudssus | Perl Artistic |
| HTTP::Daemon | Gisle Aas | Perl Artistic |
| HTTP::Negotiate | Gisle Aas | Perl Artistic |
| HTTP::Request::AsCGI | Christian Hansen, Hans Dieter Pearcey | Perl Artistic |
| HTTP::Server::Simple | Jesse Vincent, Marcus Ramberg, Sam Vilain | Perl Artistic |
| HTTP::Server::Simple::PSGI | Tokuhiro Matsuno, Kazuhiro Osawa and Tatsuhiko Miyagawa | Perl Artistic |
| HTTP::Headers::Fast | Tatsuhiko Miyagawa | Perl Artistic |
| HTTP::Message | Gisle Aas | Perl Artistic |
| HTTP::Date | Gisle Aas | Perl Artistic |
| inc::latest | David Golden and Eric Wilhelm | Apache License 2.0 |
| indirect | Vincent Pit | Perl Artistic |
| IO | ? | ? |
| IO::Socket::IP | Paul Evans | ? |
| IO::Socket::SSL | Marko Asplund, Peter Behroozi and Steffen Ullrich | Perl Artistic |
| IPC::Signal | Roderick Schertler | ? |
| IPC::Shareable | Benjamin Sugars | ? |
| jQuery | Sebastian Senf and jQuery Foundation | MIT & GPL |
| JSON | Makamaka Hannyaharamitu and Marc Lehmann | Perl Artistic |
| JSON::MaybeXS | Matt S. Trout | Perl Artistic |
| jQuery-ui | jQuery Foundation and contributors | See LICENSE.txt file |
| List::MoreUtils | Tassilo von Parseval and by Jens Rehsack | Perl Artistic |
| LWP::MediaTypes | Gisle Aas | Perl Artistic |
| LWP::Protocol::https | Gisle Aas | Perl Artistic |
| LWP (libwww) | Gisle Aas and Martijn Koster | Perl Artistic |
| libgd | See COPYING file | See COPYING file |
| MIME::Types | Mark Overmeer | Perl Artistic |
| mod_perl | ? | Apache License |
| Module::Runtime | Andrew Main | Perl Artistic |
| Module::Build | Ken Williams | Perl Artistic |
| Module::Install | Adam Kennedy, Audrey Tang and Brian Ingerson | Perl Artistic |
| Module::ScanDeps | Audrey Tang and Steffen Mueller | Perl Artistic |
| Module::Install::ExtraTests | Ricardo Signes | Perl Artistic |
| Module::Install::AuthorTests | Ricardo Signes | Perl Artistic |
| Moo | Matt S. Trout | Perl Artistic |
| Mojolicious | Sebastian Riedel and others | Perl Artistic |
| MooseX::Getopt | Stevan Little | Perl Artistic |
| MRO::Compat | Brandon L. Black | Perl Artistic |
| Mysql | ? | GPL 2 or Commercial license by Oracle |
| Module::Build::Tiny | Leon Timmermans and David Golden | Perl Artistic |
| namespace::autoclean | Florian Ragwitz | Perl Artistic |
| namespace::clean | Robert 'phaylon' Sedlacek, Florian Ragwitz, Jesse Luehrs, Peter Rabbitson and Father Chrysostomos | Perl Artistic |
| Net::HTTP | Gisle Aas | Perl Artistic |
| Net::Server | Paul Seamons | Perl Artistic |
| Net::Server::HTTP | Paul Seamons | Perl Artistic |
| Parallel::Prefork | ß | ? |
| Server::Starter | Kazuho Oku | Perl Artistic |
| Path::Class | Ken Williams | Perl Artistic |
| Plack | Tatsuhiko Miyagawa, Tokuhiro Matsuno, Jesse Luehrs, Tomas Doran and Graham Knop | Perl Artistic |
| POSIX::strftime::Compiler | Masahiro Nagano | Perl Artistic |
| PSGI | Tatsuhiko Miyagawa | Creative Commons license by-sa |
| Role::Tiny | Matt S. Trout | Perl Artistic |
| Server::Starter | Kazuho Oku | Perl Artistic |
| Starlet | Kazuho Oku, Miyagawa, Kazeburo and Tomohiro Takezawa | Perl Artistic |
| Starman | Tatsuhiko Miyagawa | Perl Artistic |
| Safe::Isa | Matt S. Trout | Perl Artistic |
| Stream::Buffered | Tatsuhiko Miyagawa | Perl Artistic |
| Sub::Quote | Matt S. Trout | Perl Artistic |
| Syntax::Keyword::Gather | Arthur Axel, "fREW" Schmidt and Damian Conway | Perl Artistic |
| Test::Requires | Tokuhiro Matsuno | Perl Artistic |
| Test::Most | ? | ? |
| Test::SharedFork | Tokuhiro Matsuno | Perl Artistic |
| Test::TCP | Tokuhiro Matsuno | Perl Artistic |
| Test::NoWarnings | Fergal Daly and Adam Kennedy | Perl Artistic |
| Test::YAML | Ingy döt Net | Perl Artistic |
| Try::Tiny | Yuval Kogman and Jesse Luehrs | MIT (X11) License |
| Socket6 | ? | ? |
| strictures | Matt S. Trout | Perl Artistic |
| Sub::Exporter::Progressive | Arthur Axel | Perl Artistic |
| Task::Weaken | Adam Kennedy | Perl Artistic |
| TermReadKey | Kenneth Albanowsk, Kenneth Albanowski, Jonathan Stowe and others | Perl Artistic |
| Test::RequiresInternet | Mark Allen | Perl Artistic |
| Test::Fatal | Ricardo Signes | Perl Artistic |
| Text::SimpleTable | Sebastian Riedel and Marcus Ramberg | Perl Artistic |
| Time::ParseDate | David Muir Sharnoff and Google Inc. | Free |
| URI | Gisle Aas, Tim Bunce, Roy Fielding and Martijn Koster | Perl Artistic |
| warnings::illegalproto | Arthur Axel "fREW" Schmidt | Perl Artistic |
| Web::Simple | Matt S. Trout | Perl Artistic |
| WWW::Form::UrlEncoded | Masahiro Nagano | Perl Artistic |
| WWW::RobotRules | Gisle Aas and Martijn Koster | Perl Artistic |
| XML::Dumper | Mike Wong | Perl Artistic |
| XML::Parser | Larry Wall, Clark Cooper and Matt Sergeant | |
| YAML | Ingy döt Net | Perl Artistic |
| YAML::Tiny | Adam Kennedy | Perl Artistic |
Limitations
Maxdaemon is developed and tested under Ubuntu Linux, but should run under other Unix derivations
with minor changes, too. There is no Windows version, so far. Please note, that the Maxdaemon
HTTPD is published for the first time and has never been used or tested by anybody else than
myself. So, at this point in time, I recommend to use an Apache/FastCGI or another configuration
on mission critical production sites as the main HTTP daemon. For more limitations have a look
at the 'To Do' list.
Also note, that this manual page is a draft. It is neither comprehensive nor is it complete,
and there is only this Denglish version, so far. Nevertheless the code mostly speaks for
itself and there are quite a few useful comments and hints in the code.
Bugs
- I am sure that there are quite a few. It would be nice, if you tell me about them.
- Error log messages of apps are in some situations written to main error log.
- In a few situations, the server isn't stopped properly. Use the 'killall perl ' or 'kill -9 <process ids>' commands.
To Do
- Portation to other operating systems than Ubuntu.
- Speed optimization.
- Configuration directives needs to be documented, decently.
- Configuration error handling needs to be worked out.
- The configuration structure hash should be made global (shm?).
- A real reload for maxdaemon restart, instead off killing.
- An automatic restart of SCGI processes after changes.
- Application process management should be evolved.
- An own logger daemon would be nice.
- Server seek mode for audio and video files (Maybe solved).
- Add Transfer-encoding handling.
- Add more generic 'WebSocket' support.
- Manifest permissions should be worked out.
- Adapt sources for all databases supported by DBI/DBD.
- DBD packages for other databases than Mysql.
- Add the user id cash to the control daemon.
- StatusMessage doesn't only belong to the Maxdaemon::Request class.
- Read the SSL encrypted key file instead of 'server.key'.
- Allow configuration file encrytion.
- SCGI client/server communication protocol optimization..
- SCGI client modules in other languages (PHP, C, Java, ..).
- SCGI keep-alive mode (reuse sockets to clients, instead of re-connect).
- Restart SCGI scripts on change.
- Javascript Editor for 'textarea' form fields.
- SSL/TLS handling should be worked out.
- Either the network code should be reviewed or/and exchanged IO::Socket::*.
- IPv6 support should be added (see above to do).
- Unicode handling should be worked out.
- Web Sockets HTTPS and process management required.
- Concurrent development extension for the web surface.
- Enhance set of web surface MIME type icons.
- Web surface handling (e.g. select Javascript handlers).
- Add WYSIWYGP code editor to web surface form <textarea> tag.
- A 'lock file' mechanism for concurrent editing via the web surface.
- Set up a real development server.
- Speed up the 'gp' script by using git.
- A decent manual.
- Don't show select buttons for non editable mime types..
- Solve the 'MH-todo:' comments in the sources.
- A lot more that can be done (see Limitations) ...
Copyright and License
The Maxdaemon 1.0.0 distribution is licensed under the terms of the: Maxdaemon Copyright and License.
Authors
Maxdaemon is written by Max (Dipl.-Ing Ernst Robert Maximilian Heinzelmann). The implementation is inspired by the Perl man pages, many modules of the Perl CPAN archives (CGI, FCGI, Socket, Socket::IO, Net::SSLeay, Filter::Crypto, DBD/DBI, LWP, ..), SelfHTML, Webmin, Mojolicious, the Apache HTTPD, FastCGI, Mysql and many other sources.
The program code includes ideas from the work of Larry Wall, Steven E. Brenner Tim Bunce, Gisle Aas, Lincoln Stein, Gurusamy Sarathy, Sampo Kellomaeki, Florian Ragwitz, Mike McCauley, Paul Evans, Steve Hay, Kellomaeki, Johan Vromans, Werner Bosse, Jamie Cameron, Sebastian Riedel, the Perl 5 Porters, the 'lwp' authors, the CPAN, the Apache, Mozilla, OpenSSL developers, Linus and the Linux people, just to name a few.
History
I began to write the predessor of Maxdaemon on 2000-01-02 from scratch, to have a control daemon for Maxscape's user authorization, process control and Licenses, what was quite fast achieved. Because the idea of replacing the Apache by an HTTPD written in Perl is so tempting, I redesigned this control daemon to perform as an HTTP daemon for Maxscape in 2014. Only in August 2017 I touched upon it again, to implement a more generic HTTPD that also supports name-based virtual SSL hosts, Unicode utf-8, a replacement for FastCGI and to develop and integrate Maxscape's file management web surface.
Table of Content
- Maxdaemon
- Audience and Scope
- Web Application Server Framework
- A Web Application Server for Perl Developer
- HTTP(S) Daemon
- Abstract
- Maxdaemon HTTPD
- HTTPD Installation
- HTTPD Configuration
- CGI, SCGI and DCGI Interfaces
- SSL Certificates Creation for Maxdaemon
- Debug Messages, Access and Error Logs
- Chat Mode
- Web Sockets
- Compatibility with Apache/FastCGI
- Why an HTTPD in Perl?
- Application Server Runtime System
- Start/Restart/Stop Maxdaemon
- Maxdaemon Configuration
- Application Server
- Application Server Creation
- Application Server Configuration
- Start an Appliction Server
- Application Server Scripts
- Addressing Application Functions
- Application Programming and Content Generation
- Runtime Objects - Using Maxdaemon Classes in Apps
- Callback Function Plug-In
- Control Daemon
- Database Authentication Daemon
- Maxdeamon Applications
- Web Surface to Manage the Server File System
- Features and Functionality
- Directory Tree Document Root
- Display Files and Execute Scripts
- Create, Edit and Change Files
- Copy, Move and Delete
- Upload Files
- Search for Strings
- Configuration Modes and Files
- Adapting the Surface
- Themes, Look and Feel
- Create Web Surface User Account
- CGI Interfaces
- Template Application Server
- Test Server
- Manual Server
- MaxChat Server
- LifeStream Server
- Maxscape Application Server
- Development and Integration Environment
- Web Server Platform
- Operating System Setup
- Webserver Platform Build
- Open SSL Build
- Perl Interpreter Build with RPM
- Perl Source Code Encryption
- Apache Build
- (Rational) Database
- Content Tracker
- Server and Application Directory Structure
- Content Management
- Shell Tools
- Manifest or How To Find Text and Code Pieces
- Desktop, X-terms and Web Surface
- Download, Installation and Configuration
- Downloads
- Quick Glance Installation
- 'Non-root' User
- Advanced Installation
- Choose UNIX User Account and Groups
- Install Maxdaemon as User 'root'
- UNIX Account
- Maxdaemon Installation Steps
- Shell Environment
- SSL Certificate Creation
- Host and Server Configuration
- Running Maxdaemon as 'root' and at Boot Time
- Programs, Scripts and Modules Man Pages
- Work Flow Examples
- Third Party Products
- Limitations
- Bugs
- To Do
- Copyright And License
- Authors
- History
| next ∙ previous ∙ Top ∙ Join ∙ Contact | © Maxscape |
