GNU MyServer is a powerful web server designed, to be easily executed on a personal computer by the average computer user. It is based on multi-threaded architecture, which makes it extremely scalable and usable in large scale sites, as well as in small networks. It has built-in supports for the HTTP, HTTPS and FTP protocols. Support for dynamic pages is made available trough CGI, ISAPI, WinCGI, SCGI and FastCGI protocols.
The MyServer configuration is done using three different XML files:
These files can exist in different locations, they are looked in the following order:
It is possible to specify a different directory where looks for
configuration files by the --cfgdir
argument to the myserver
process. In case a path is specified, then the configuration files
are looked exclusively in this directory.
Plugins are allowed to install new handlers to read the configuration
from other sources. It is done changing the value of the variables
server.vhost_handler
and server.server.mime_handler
,
respectively to use a different handler for the virtual hosts and for
the MIME types. If no value is specified then the value xml
is used.
CGI scripts can get the server administrator e-mail and show them to
the user (through the SERVER_ADMIN environment variable).
It is defined trought the server.admin
variable, that can be
set in the global configuration file or for virtual host.
There can be need for the server to save temporary files as a form of
inter-process communication.
It is possible to configure the directory where temporary files are
stored trought the server.temp_directory
variable inside the
main configuration file.
Operations on disk are much slower than read or write directly from
the primary memory. To solve this problem under GNU/Linux you can
think about use virtual memory instead of a persistent storage device
to store files.
It can be done, by the root user, as:
# mount -t tmpfs -o size=256m tmpfs /tmp/tmpfs
The previous command mount a portion of memory, 256M, on the
/tmp/tmpfs and it can be used as a normal file system.
At this point, server.temp_directory
shall be set to
/tmp/tmpfs to benefit from it.
Files saved on the primary memory are not persistent between reboots,
introducing another level of security as temporary data will not be
saved on the server.
Protocols like FTP or HTTP/1.1 support keep-alive connections, in
other words the connection is kept alive between requests to avoid a
different connection to the server on every request.
MyServer performances are not affected by the number of active
connections but if they are not controlled, they can reach the maximum
number of allowed connections without give the possibility to new
connections that really want to request a resource to be
estabilished.
Active connections are closed after a fixed amount of time has passed
without any activity.
The amount of time, before an inactive connection is closed, is
configured trought the server.connection_timeout
value defined
in the global configuration file. This value is specified in
seconds.
Virtual hosts is a method to link more than a domain name to the same machine, even if they refer to the same network interface. Virtual hosts are supported by the HTTP and HTTPS protocols.
For example http://mypc.net is different from http://sub.mypc.net. Virtual hosts are defined in the file virtualhosts.xml. A sample virtual hosts configuration file looks like:
<VHOSTS> <VHOST> <NAME>Every connection</NAME> <PORT>80</PORT> <IP>192.168.0.0/24</IP> <PROTOCOL>HTTP</PROTOCOL> <DOCROOT>web</DOCROOT> <SYSROOT>system</SYSROOT> <HOST>foo.bar.com</HOST> <ACCESSLOG>logs/myServer.log</ACCESSLOG> <WARNINGLOG>logs/myServer.err</WARNINGLOG> <ALLOW_CGI>NO</ALLOW_CGI> </VHOST> </VHOSTS>
Log files can have extra options:
<ACCESSLOG type="combined">logs/myServerHTTP.log</ACCESSLOG>
With this option, the logs will have two extra fields: HTTP Referrer and HTTP User Agent. Using cycle="yes" you will enable log cycler on the log file. When a log file with cycling enabled reaches the max size for log files it will write its content to a new file and recreate the original file. By default cycled log files uses the gzip compression to save space, if you don't want to use gzip specify cycle_gzip="no". Here is an example of a FTP virtual host:
<VHOSTS> <VHOST> <NAME>Ftp connection</NAME> <PORT>21</PORT> <IP>127.0.0.1/32</IP> <PROTOCOL>FTP</PROTOCOL> <DOCROOT>web</DOCROOT> <SYSROOT>system</SYSROOT> <HOST>ftp.foo.bar.com</HOST> <ACCESSLOG>logs/myServer.log</ACCESSLOG> <WARNINGLOG>logs/myServer.err</WARNINGLOG> </VHOST> </VHOSTS>
Tags semantics are identical with first example. Although FTP is used for public file sharing, restrictions may be imposed using security file.
It is possible to specify a throttling rate for the connection by the
connection.throttling
value. It can be specified in any
configuration file, at a global level, in the virtual host definition
and in the local security file.
Its value is specified in bytes/second.
The following line, for example, set the maximum transfer rate to 1 KByte/second:
<DEFINE name="connection.throttling" value="1024"/>
To improve performances, the server can use a cache of connections,
this value can be configured trough the server global variable
server.connections_pool.size
. If it is not specified, a
default value of 100 is used. Increase this value if more connections
can be active at the same time. Another effect of using a connections
cache is a less defragmented memory.
It may be necessary to register an entire location with a single
handler and it is done trought LOCATION
.
Any other element passed after the location will be part of the
PATH_INFO
variable.
<LOCATION path="foo/bar" mime="text/html" handler="CGI" param="/usr/local/bin/handler" />
In the previous example, the CGI process /usr/local/bin/handler
is used to manage any request to the location foo/bar, this
location includes for example: foo/bar, foo/bar/baz,
foo/bar/a/file, everything that follows foo/bar will be
part of PATH_INFO
.
MyServer gives you the option to enable or disable HTTP methods
command for each virtual host. It can be done trought the
http.COMMAND.allow
variable.
For example, the HTTP TRACE command can be disabled using:
<DEFINE name="http.trace.allow" value="NO" />
MIME types are used to specify the type of information a resource transmitted to or from the server contains. Some standard MIME types are already defined in the MIMEtypes.xml file. Using the same syntax you can define new MIME types or modify existing ones. For each MIME type it is possible to specify how the server will handle the files and which actions take before it can be sent to the client.
In this example two MIME types are defined:
<MIME mime="text/html" handler="SEND" param=""> <EXTENSION value="html"/> <FILTER value="gzip"/> </MIME> <MIME mime="text/html" handler="CGI" param="/usr/bin/perl" selfExecuted="NO"> <EXTENSION value="pl"/> <DEFINE name="http.error.file.404" value="404.html"/> </MIME>
The former defines to send any file with a .html
extension as
it is, in case it is supported by the client then the file content is
compressed using the gzip.
The latter specifies that every file with a pl
extension are
handled by the /usr/bin/perl CGI and the new process standard
output is redirected to the client. In addition, it defines which
resource use when a 404 HTTP file not found error happens.
Every MIME type is made of:
extension
items can be specified for the same MIME type.
param
.
<FILTER>
defines a filter for the MIME type. The data will
pass through the filter before being sent to the user.
In the example above, the data would be sent gzipped to the user.
It is possible to specify multiple filters for the same MIME type,
they will be applied in the specified order.
<DEFINE>
It defines a new value for a variable, take a look
here Security files for more details on the <DEFINE>
element.
The same MIME type can have several extensions, you will need to
specify a different <EXTENSION>
element for each extension.
These are valid HTTP handlers:
param
. This is not a real proxy, there is not caching and
message is forwarded as it is without any change.
It is possible to match the file name against a regular expression instead of specifying only its extension.
It is done using the PATH
directive in the following way:
<?xml version ="1.0"?> <MIME mime="text/html" handler="SEND" param=""> <PATH regex="/foo/bar/.*" /> </MIME>
The PATH
regular expressions are checked before the file
extension, in the order they are specified in the configuration file.
MyServer offers the feature to follow symlinks where they are supported. You can configure MyServer to follow symbolic links specifying this line in the myserver.xml file.
<DEFINE name="symlinks.follow" value="YES" />
By default MyServer doesn't follow symbolic links.
It is possible to use different handlers to determine the file MIME type. Additional handlers can be supported by external plugins.
The definition of external handlers can be done per vhost or globally
in the main configuration file changing the value of the variable
mime.handler
.
<DEFINE name="mime.handler" value="mime_magic" />
Under POSIX it is possible to change the MyServer process user identifier and group identifier after it has bound the necessary ports (only the root user can bind ports < 1024).
To specify a different process user id (PID), you must specify it in the myserver.xml file as:
<DEFINE name="server.uid" value="UID" />
Differently, to change the process group id (GID), the configuration line to use is:
<DEFINE name="server.gid" value="GID" />
When one of these features is used, MyServer will not use the auto-reboot because it will not be possible to get back old permissions.
It is possible to run CGI processes using a different uid/gid. It can be done defining the “cgi.uid” and “cgi.gid” values in a configuration file. It can be specified at any configuration level.
These directives can be used in a security file to force the execution of the new process with both uid and gid to 1000.
<DEFINE name="cgi.uid" value="1000" /> <DEFINE name="cgi.gid" value="1000" />
It is also possible to specify a new root directory location using the cgi.chroot attribute:
<DEFINE name="cgi.chroot" value="/some/where" />
In a POSIX environment the fork
syscall is used to execute new
processes. It clones the caller process keeping any open file or
connection in the child process too. To avoid this problem a fork
server is present in MyServer.
The communication between the MyServer process and the
fork server is done trought a socket. When MyServer wants to execute
a new process two connections are opened to the fork server, for
the stdin and stdout streams, and the fork server will fork itself and
execute the process using these connections as its I/O streams.
It is not configurable in any configuration file as the MyServer process is forked to create it before any file or connection is active.
It is enabled passing the -f
switch to the myserver process.
If the MyServer main process is configured to change its uid/gid after its initialization, it is the only way to spawn new processes with uid/gid different than the MyServer process.
By default, FastCGI and SCGI servers are lazily initialized by
MyServer on the first request to a resource that is handled trought
these protocols. In this case MyServer will initialize it using a random TCP port.
There may be cases where a different configuration is needed and it is
done using the PROCESS_SERVER
directive inside the
myserver.xml file.
A PROCESS_SERVER
entry makes it possible to access a specific
FastCGI/SCGI configuration inside MIME types by its name.
<!-- Inside myserver.xml. --> <DEFINE name="server.process_servers"> <DEFINE server="/opt/bin/fastcgi_server" domain="fastcgi" host="localhost" port="2010" local="yes" uid="1000" chroot="/chroot" gid="1000"/> </DEFINE>
In the previous example the FastCGI server
/opt/bin/fastcgi_server
is created. The domain
must be
"fastcgi" or "scgi", depending on the specific protocol to use.
local
specifies if the server is handled by myserver or it is
already running; in the former case, myserver will simply access and
use it.
If the server is not local then the server
is a simple label
that can be used by a MIME type trought param
to access it.
It is possible to specify a different uid/gid for the local server
process and don't maintain the original myserver process privileges.
It can be done using the uid
and gid
elements.
Also, it is possible to use a different root directory, mapping the
/ path to what is specied in the chroot
attribute.
Any file lookup can't go upper what is specied in the chroot. Pay
attention that any path specified in server
must be relative to
the new chroot.
The following code, declare an already running FastCGI server and
registers it on the fcgi
extension:
<DEFINE name="process_servers.list"> <DEFINE server="a_remote_server" domain="fastcgi" host="foo" port="2010" local="no"/> </DEFINE> <!-- Inside MIMEtypes.xml. --> <MIME mime="text/html" handler="RUNFASTCGI" param="a_remote_server"> <EXTENSION value="fcgi"/> </MIME>
The X-Sendfile directive can be used by FastCGI servers to instruct the web server to ignore any content but send the file specified in the X-Sendfile header. It is much faster to transfer static contents and avoid an additional step from the FastCGI server to the web server.
Since the FastCGI X-Sendfile can ask any file to be accessed
statically, this feature is not considered safe you must force it
manually, in can be done on a virtual hosts basis.
It is done trough the fastcgi.sendfile.allow
variable, to
enable X-Sendfile set its value to YES
.
It is possible to change almost any configuration for a single directory or a single resource trough the .security.xml. This file can be placed in any web directory and it will overwrite default configuration values. If the .security.xml file is not found in the directory where the requested resource is, then MyServer will look in the parents directory until the file is found. If .security.xml is not present in the virtual host root directory then the default one which is present in the system directory will be used.
Usually consider the first valid value found in this order:
Some values are not configurable in any .security.xml file and they are took directly from the Virtual host configuration and in some cases directly from the global configuration file.
In MyServer there are two different steps involved in the logging phase: user authentication and validation.
In the first step a permission mask is found given the username:password pair, no other information are used in this phase. In the second phase this value is refined using more information. The two phases are completely separated and it is possible to use different sources for any of them.
The .security.xml can be used for both phases and by default it is.
The anonymous user is matched inside MyServer with the “Guest” username and an empty password.
The name for the security file can be changed trought the
security.filename
variable.
The maximum allowed size for a security file can be limited by the
security.max_size
variable, by default there is no limit.
Both security.filename
and security.max_size
can be
defined in the global configuration file or differently for every
virtual host.
The information used for the first phase of logging is a simple list of USER elements. Any permission is configured by an attribute, if the attribute value is equal to “YES” then the permission is granted.
The permissions that MyServer considers are:
In the following example we enable an anonymous user to access resources in READ/EXECUTE/BROWSE mode, DELETE and WRITE are both denied.
<SECURITY> <USER name="Guest" password="" READ="YES" EXECUTE="YES" BROWSE="YES" DELETE="NO" WRITE="NO"/> </SECURITY>
As no other information beside username:password is used, this first phase is the same for any protocol supported by MyServer.
To improve security it is possible to use in place of the clear-text
password a crypted version of it. It is done using the
algorithm
variable. It specifies the function F to apply to
the client specified password before compare it with the
password
value.
<SECURITY> <USER name="admin" password="8ee0f7b66d1ab05714573fc556fbd7ff" algorithm="md5" READ="YES" EXECUTE="YES" BROWSE="YES" DELETE="NO" WRITE="NO"/> </SECURITY>
If the HTTP digest authorization scheme is used, it is not possible to use any password hash but the original clear-text password. The only exception to this rule is to specify the A1 part in the Digest scheme.
It is computed by the function: MD5 (username:realm:password).
<DEFINE name="http.auth" value="digest" /> <USER name="user" algorithm="a1" password="c2deada0bcb64f99e65be0d33bb92d54" READ="YES" EXECUTE="YES" BROWSE="YES" WRITE="NO"/>
The realm value used by MyServer is the virtual host name, including
the port number, i.e. localhost:8080
.
The A1 password can be computed using the following shell command, be
sure to use the right user, realm and password values.
printf "%s:%s:%s" user realm password | md5sum
To allow the .security.xml re-use, the FTP “Anonymous” user is mapped internally by MyServer to the “Guest” user.
The second phase allows to define some rules that can overload the settings specified in the authorization phase.
The default validator used by MyServer is the .security.xml file.
The XML validation phase reads the tag contained in the order that they are specified. It works almost in the same way a programming language does, but differently the XML validator doesn't allow a loop structure, this is required to terminate the parsing in a finite time.
The XML validation is done using four commands:
The CONDITION
block allows to evaluate a condition and in case
it is satisfied then the inner XML is evaluated too, in case it is not
satisfied then the inner code is not considered. It works like the
if
statement usually present in any programming language but
offering less syntactical freedom.
Here it is showed a simple use of CONDITION
:
<CONDITION name="auth.user" value="Guest"> ... </CONDITION>
The inner XML code, omitted for clarity, is evaluated only when the
auth.user
variable is equals to the value "Guest".
It may be necessary to specify the other case, evaluate the inner
block every time the condition is not satisfied. It is done using the
not
attribute:
<CONDITION name="auth.user" value="Guest" not="yes"> ... </CONDITION>
In this case, the inner block is evaluated every time the
auth.user
is different than "Guest".
It is possible to match a value against a regular expression, in this case you will need to declare it explicitly.
<CONDITION name="auth.user" value="admin.*" regex="yes" not="yes"> ... </CONDITION>
The DEFINE
block is used to specify a value for a variable that
later can be accessed by the server.
This is the way to specify variables that it is possible to specify in
the security file (not all variables are allowed to be defined here),
overloading the value specified in the virtual host or in the server
global configuration.
The syntax for the DEFINE
command is:
<DEFINE name="http.error.file.404" value="404.html"/>
In the previous example the HTTP 404 error page was replaced with a customized HTML page.
As the same configuration file can be used by different contexts, as
a web host or a FTP site, any variable has meaning only in its
original environment, define http.error.file.404
in a FTP site
will not have any effect.
The PERMISSION
element has the same syntax used in the first
authorization phase, the only difference is that username and password
are not specified.
<PERMISSION READ="NO" EXECUTE="NO" BROWSE="NO" DELETE="NO" WRITE="NO">
The previous example denies any access to the resource, replacing any value found previously.
The RETURN
element allows to exit immediately from the XML flow
without consider any other command specified in the file.
It has an additional attribute value
that must be set to the
value ALLOW
to keep the previous found attribute mask.
To immediately return from the XML file and at the same time deny any access, without care of the previous found permission mask, you must do:
<RETURN value="DENY" />
Differently, to return from the flow keeping the found permission mask there is need to do like:
<RETURN value="ALLOW" />
Pay attention, if at the same time you want to change the permissions
then you will need to specify them explicitly by the PERMISSION
command.
It is possible to specify a page when a HTTP error happens using the option:
<DEFINE name="http.use_error_file" value="YES" />
So, if you set the value to NO
, like in the line below,
<DEFINE name="http.use_error_file" value="NO" />
If an error page is not used MyServer will (by default) just send a header to your browser with the error code. It is possible to include a HTTP body in the error page, using:
<DEFINE name="http.error_body" value="YES" />
When a resource mapped to a local directory is requested, MyServer shows its content like an usual file manager does.
In the myserver.xml main configuration or in the virtualhosts.xml file, it is possible to set a list of default file names to use instead of the directory content.
Default file names are defined using a list called
http.default_file
and they are checked in the specified order
until one is found. If the file can't be found in the directory then
the directory content is listed.
<DEFINE name="http.default_file"> <DEFINE value="default.html"/> <DEFINE value="default.htm"/> <DEFINE value="index.html"/> <DEFINE value="index.htm"/> </DEFINE>
The previous lines define the order of files that are checked by the web server when a directory is requested. For example, given the previous configuration and a request to the http://foo/bar/ resource, where bar/ is mapped to a local directory, the server will look for these files in order:
http://foo/bar/default.htm http://foo/bar/index.htm http://foo/bar/default.html http://foo/bar/index.html
If that resources don't exist then the content of bar/ is listed.
When the directory content is listed, by default MyServer shows the
file name, last modified time and file size. This default bahaviour
can be changed redefining the http.dir.format
value.
It can be redefined in the local security file, in the virtual host or in the global server configuration. Its value is a formatting string, columns are showed in the same order that they are specified.
For example, the %f%s
value displays the file name followed
by its size, while %f%t
displays the file name and its last
modified time.
You can change the layout of the directory browsing page. The line below, in myserver.xml, points to the CSS file used to configure the layout for the browsing directory pages:
<DEFINE name="http.dir.css" value="/sys/css/browsestyle.css" />
It is possible to ignore some files to be listed from the final
output. It is done using the http.dir.ignore
regular
expression that can be specified at any level.
Pay attention, this directive does not change the file visibility, so a direct request to the entries that are part of the mask will have the same effect as if this directive is not specified.
In the following example, the file hidden is not included in the directory listing.
<DEFINE name="http.dir.ignore" value="hidden" />
The data encryption is used to protect the data that is sent between the client and the server. There are two types of algorithm: symmetric and asymmetric data encryption algorithms. The difference between the two types of algorithm is that for the symmetric algorithms the same key is used both for encryption and decryption. These algorithms are not used by servers with a potentially large number of clients because the data captured can be decrypted by any client that know the key and because the key needs to be distribute in a safe manner not distributing it on a large network like Internet. The asymmetric algorithms work in a different way, the data encrypted with a key can be decrypted only with the other key and vice-versa. Anyone know the public key but only the owner knows the private one. In this way the key owner do not have to distribute the key only to know clients but he can distributes it to a large scale network.
A certificate is needed to certify your identity through a CA (Certification Authority). You can use a certificate without register it to third party CA, it is called self-signed certificate. You can find all the necessary tools to create certificates in the GNU TLS command line tools. Look here for more information: http://www.gnu.org/software/gnutls/.
To generate a private key/self signed certificate couple you will need to execute these two commands:
certtool --generate-privkey --outfile cert.key certtool --generate-self-signed --load-privkey cert.key \ --outfile cert.pem
To configure certificates in MyServer you have to put the two files:
cert.key
, cert.pem
in the MyServer certificates
directory.
To configure a HTTPS host that will use the created certificate, add the following lines in the virtualhosts.xml file:
<VHOST> <NAME>Every connection</NAME> <PORT>443</PORT> <SSL_PRIVATEKEY>certificates/cert.key</SSL_PRIVATEKEY> <SSL_CERTIFICATE>certificates/cert.pem</SSL_CERTIFICATE> <PROTOCOL>HTTPS</PROTOCOL> <DOCROOT>web</DOCROOT> <SYSROOT>system</SYSROOT> <ACCESSLOG>logs/myServer.log</ACCESSLOG> <WARNINGLOG>logs/myServer.err</WARNINGLOG> </VHOST>
Take a look at the see Virtual hosts documentation to get more information about other tags.
The MyServer's log management system was designed to support logging over different targets. At the moment, these targets are made out of files, sockets and, of course, consoles. Each target, must be referred through its location string. In addition, it is possible to provide a list of filters (e.g. the Gzip filter) to improve the logging capabilities.
This section will introduce you to the use of the log management features.
A location string can be provided as an URI; the basic schema is in
the form protocol://resource
. protocol
can be chosen
between
console
file
socket
resource
can be either a valid filename or an hostname according
to its protocol
. The console
protocol, can take as its
resource
argument, either stdout
or stderr
.
socket://192.168.1.18:12345
file:///var/log/myserver/MyServerHTTP.log
Note the extra '/' needed to refer an absolute path.
console://stderr
You can set the MyServer's main log location through the switch
--loglocation=protocol://resource
where the --loglocation
argument is a valid location string.
Each virtual host needs two main log targets, one for the access
messages and the other one for the error messages, whose entries in the
configuration file, are respectively ACCESSLOG
and
WARNINGLOG
. Each of these targets, can in turn write its
messages over different streams. To tell MyServer about all that, you
can edit the virtualhosts.xml file, and apply the information
found in this section, to each VHOST
entry of that file. As we
can see in the following example, the ACCESSLOG
root entry for
the accesses log configuration, contains some STREAM
nodes, and
each STREAM
contains two attributes, the mandatory
location
and the optional cycle
. A STREAM
node, can
also contain optional FILTER
sub-nodes, one for each filter that
we want to add to the STREAM
.
<ACCESSLOG type="combined"> <STREAM cycle="1048576"> <FILTER>gzip</FILTER> </STREAM> <STREAM /> </ACCESSLOG>
Above we have two streams attached to the ACCESSLOG
entry. The
first one, is a file. This file will grow up to 1048576 bytes, over that
limit it will be cycled. Also, this target will take advantage of the
gzip compression, since it will write to the file through the gzip
filter. The second one is the standard error stream over the console.
The next example, shows instead the WARNINGLOG
entry. In that
example, we still have two streams where warning messages will be
sent. The first one is a socket, while the second one is a file that
will grow with no limit over its size. No filters will be applied to
that stream. Note that if we don't specify the cycle
attribute,
it is assumed to be zero by default, which means to never cycle the
STREAM
.
<WARNINGLOG> <STREAM /> <STREAM /> </WARNINGLOG>
If a wrong filter is specified, its relative STREAM
will not
be added.
It is possible to set color attributes for the text written over the console. In this way, messages can look different according to the logging level which they belong to. For example, you may wish to write error messages with a red text over a black background, info messages with a white text over a black background and warning messages with a yellow text over a black background. You can easily tell MyServer about that information by editing the myserver.xml configuration file and adding the following code:
<DEFINE name="log_color.info_fg" value="white"> <DEFINE name="log_color.info_bg" value="black"> <DEFINE name="log_color.warning_fg" value="yellow"> <DEFINE name="log_color.warning_bg" value="black"> <DEFINE name="log_color.error_fg" value="red"> <DEFINE name="log_color.error_bg" value="black">
Allowed values for colors are black
, red
, green
,
yellow
, blue
, magenta
, cyan
and
white
. The two common suffixes fg
and bg
represent
respectively the foreground attribute and the background one, while the
three prefixes, info
, warning
and error
represent
kinds of logging messages managed by MyServer.
If the console colours information is missing or it is partially
provided, MyServer will use default values.