diff options
25 files changed, 178 insertions, 100 deletions
diff --git a/doc/quickstart.html b/doc/quickstart.html index 4b369eb..974c4b5 100644 --- a/doc/quickstart.html +++ b/doc/quickstart.html @@ -25,16 +25,16 @@ <a href="//skarnet.org/software/s6-networking/">s6-networking</a> installed alongside tipidee. </li> <li> Prepare your document root for every virtual domain you aim to serve. -For instance, if your documents are in <tt>/home/www</tt> and you need to +For instance, if your documents are in <tt>/home/www/docs</tt> and you need to serve the <tt>example.com</tt> and <tt>example.org</tt> domains, create -<tt>/home/www/example.com</tt> and <tt>/home/www/example.org</tt> directories, +<tt>/home/www/docs/example.com</tt> and <tt>/home/www/docs/example.org</tt> directories, they will be the document roots for the <tt>example.com</tt> and <tt>example.org</tt> virtual sites respectively. </li> <li> Symlink these canonical directories to all the <em>host:port</em> combinations you want them to be available on. If you want <tt>example.com</tt> and <tt>example.org</tt> to be both available on ports 80 and 443, then symlink <tt>example.com</tt> to <tt>example.com:80</tt> and <tt>example.com:443</tt> -in the <tt>/home/www</tt> directory, and do the same with <tt>example.org</tt>. </li> +in the <tt>/home/www/docs</tt> directory, and do the same with <tt>example.org</tt>. </li> <li> Compile a default configuration for tipidee: <tt>:> /etc/tipidee.conf && tipidee-config</tt>. <ul> @@ -103,5 +103,37 @@ your service manager scripts. </li> containing service files to run tipidee under various service managers. </p> +<div id="faq"> +<h2> Frequently asked questions </h2> +</div> + +<h3> I want my web server to listen to more than one address. Do I need +to do all that for every address I have? </h3> + +<p> + Not necessarily: you could listen to <tt>0.0.0.0</tt> for IPv4, and +<tt>::</tt> for IPv6. But if you don't want your server to listen to +<em>all</em> the addresses on your machine, then yes, you will have +to run one process per address:port tuple. +</p> + +<p> + It's okay though: every listening process is very small. The skarnet.org +server has two network cards and runs a web server on both of them, on +IPv4 and IPv6, over HTTP and HTTPS, which makes 8 services. Plus one +<a href="//skarnet.org/software/s6/s6-log.html">s6-log</a> logger process +for each of these services. Plus a supervisor for every service and every +logger — for a whooping total of 64 long-running processes just for +its web server functionality; and it's still not even noticeable, the +amount of resources it consumes is negligible. So, don't worry about it. +</p> + +<p> + Note that this allows you to run different instances of +<a href="tipideed.html">tipideed</a> with different configurations, if +you need it. Use the <tt>-f</tt> option to specify a different config +file for <a href="tipideed.html">tipideed</a>. +</p> + </body> </html> diff --git a/etc/tipidee.conf b/etc/tipidee.conf deleted file mode 100644 index cbbfac6..0000000 --- a/etc/tipidee.conf +++ /dev/null @@ -1,61 +0,0 @@ -# tipideed verbosity (overridden by the -v option). -# 0 is quiet, 1 is normal, 2+ is verbose. -# global verbosity 1 - -# tipideed will exit if the client does not send a new request -# after N milliseconds. -# 0 means no timeout. -# global read_timeout 0 - -# tipideed will drop the connection if the client -# does not read answers for N milliseconds. -# 0 means no timeout. -# global write_timeout 0 - -# tipideed will answer 504 ("Gateway Timeout") if a CGI program -# (including NPH) does not complete in N milliseconds. -# 0 means no timeout. -# global cgi_timeout 0 - -# tipideed will refuse to serve POST requests if the client- -# provided data is larger than N bytes. -# global max_request_body_length 8192 - -# tipideed will answer 502 ("Bad Gateway") if a CGI script's answer -# is larger than N bytes. (does not apply to NPH scripts) -# global max_cgi_body_length 4194304 - -# When the requested URL is a directory, tipideed will serve the first -# existing file in this list. (Useful e.g. if you have an index.cgi program.) -# global index_file index.html - -# You can define your own Content-Type mappings by file extension. -# The default mappings should work well for most servers. -# content-type text/html .html .htm - - -# The domain to which the next directives apply. -# You need one domain directive for each of the domains you serve, -# domain example.com - -# If a CGI script under the current domain starts with this prefix, -# it will be considered a NPH script (non-parsable headers). -# nph-prefix nph- - -# If uncommented: every file under that directory will be considered -# a CGI script. -# cgi /cgi-bin/ - -# You can also declare that individual files are CGI scripts. -# cgi /index.cgi - -# If uncommented: every CGI script under that directory will be considered NPH. -# nph /cgi-bin/nph/ - -# You can also declare that individual scripts are NPH. -# nph /cgi-bin/basic.cgi - -# You can override the default Content-Type for individual files, -# no matter what extension they have. -# file-type /source/document.html text/plain - diff --git a/examples/s6-rc/httpd-6-log/run b/examples/s6-rc/httpd-6-log/run index 50d7448..5889b3e 100755 --- a/examples/s6-rc/httpd-6-log/run +++ b/examples/s6-rc/httpd-6-log/run @@ -2,4 +2,4 @@ s6-setuidgid wwwlog exec -c -s6-log -d3 t s1000000 n20 /var/log/httpd-46 +s6-log -d3 t s1000000 n20 /var/log/httpd-6 diff --git a/examples/s6/httpd-4/log/notification-fd b/examples/s6/httpd-4/log/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6/httpd-4/log/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6/httpd-4/log/run b/examples/s6/httpd-4/log/run new file mode 100755 index 0000000..51897c7 --- /dev/null +++ b/examples/s6/httpd-4/log/run @@ -0,0 +1,5 @@ +#!/bin/execlineb -S1 + +s6-setuidgid wwwlog +exec -c +s6-log -d3 t s1000000 n20 /var/log/httpd-4 diff --git a/examples/s6/httpd-4/notification-fd b/examples/s6/httpd-4/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6/httpd-4/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6/httpd-4/run b/examples/s6/httpd-4/run new file mode 100755 index 0000000..190392f --- /dev/null +++ b/examples/s6/httpd-4/run @@ -0,0 +1,10 @@ +#!/bin/execlineb -P + +fdmove -c 2 1 +backtick -E ip { pipeline { s6-dnsip4 example.com } head -n 1 } +s6-envuidgid www +cd /home/www +fdmove 1 3 +s6-tcpserver4 -v2 -1 -U -c 512 -- $ip 80 +s6-tcpserver-access -lexample.com -- +tipideed -v2 -- diff --git a/examples/s6/httpd-6/log/notification-fd b/examples/s6/httpd-6/log/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6/httpd-6/log/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6/httpd-6/log/run b/examples/s6/httpd-6/log/run new file mode 100755 index 0000000..5889b3e --- /dev/null +++ b/examples/s6/httpd-6/log/run @@ -0,0 +1,5 @@ +#!/bin/execlineb -S1 + +s6-setuidgid wwwlog +exec -c +s6-log -d3 t s1000000 n20 /var/log/httpd-6 diff --git a/examples/s6/httpd-6/notification-fd b/examples/s6/httpd-6/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6/httpd-6/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6/httpd-6/run b/examples/s6/httpd-6/run new file mode 100755 index 0000000..ae4dbba --- /dev/null +++ b/examples/s6/httpd-6/run @@ -0,0 +1,10 @@ +#!/bin/execlineb -P + +fdmove -c 2 1 +backtick -E ip { pipeline { s6-dnsip6 example.com } head -n 1 } +s6-envuidgid www +cd /home/www +fdmove 1 3 +s6-tcpserver6 -v2 -1 -U -c 512 -- $ip 80 +s6-tcpserver-access -lexample.com -- +tipideed -v2 -- diff --git a/examples/s6/httpsd-4/log/notification-fd b/examples/s6/httpsd-4/log/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6/httpsd-4/log/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6/httpsd-4/log/run b/examples/s6/httpsd-4/log/run new file mode 100755 index 0000000..770d831 --- /dev/null +++ b/examples/s6/httpsd-4/log/run @@ -0,0 +1,5 @@ +#!/bin/execlineb -S1 + +s6-setuidgid wwwlog +exec -c +s6-log -d3 t s1000000 n20 /var/log/httpsd-4 diff --git a/examples/s6/httpsd-4/notification-fd b/examples/s6/httpsd-4/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6/httpsd-4/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6/httpsd-4/run b/examples/s6/httpsd-4/run new file mode 100755 index 0000000..54be026 --- /dev/null +++ b/examples/s6/httpsd-4/run @@ -0,0 +1,11 @@ +#!/bin/execlineb -P + +fdmove -c 2 1 +backtick -E ip { pipeline { s6-dnsip4 example.com } head -n 1 } +s6-envuidgid www +export KEYFILE /etc/ssl/acme/private/example.com/key.pem +export CERTFILE /etc/ssl/acme/example.com/cert.pem +cd /home/www +fdmove 1 3 +s6-tlsserver -v -4 -1 -U -c 512 -K 30000 -- $ip 443 +tipideed -v2 -- diff --git a/examples/s6/httpsd-6/log/notification-fd b/examples/s6/httpsd-6/log/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6/httpsd-6/log/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6/httpsd-6/log/run b/examples/s6/httpsd-6/log/run new file mode 100755 index 0000000..a8281ad --- /dev/null +++ b/examples/s6/httpsd-6/log/run @@ -0,0 +1,5 @@ +#!/bin/execlineb -S1 + +s6-setuidgid wwwlog +exec -c +s6-log -d3 t s1000000 n20 /var/log/httpsd-6 diff --git a/examples/s6/httpsd-6/notification-fd b/examples/s6/httpsd-6/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6/httpsd-6/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6/httpsd-6/run b/examples/s6/httpsd-6/run new file mode 100755 index 0000000..652a354 --- /dev/null +++ b/examples/s6/httpsd-6/run @@ -0,0 +1,11 @@ +#!/bin/execlineb -P + +fdmove -c 2 1 +backtick -E ip { pipeline { s6-dnsip6 example.com } head -n 1 } +s6-envuidgid www +export KEYFILE /etc/ssl/acme/private/example.com/key.pem +export CERTFILE /etc/ssl/acme/example.com/cert.pem +cd /home/www +fdmove 1 3 +s6-tlsserver -v -6 -1 -U -c 512 -K 30000 -- $ip 443 +tipideed -v2 -- diff --git a/examples/tipidee.conf b/examples/tipidee.conf index f75a9cc..705b88c 100644 --- a/examples/tipidee.conf +++ b/examples/tipidee.conf @@ -1,41 +1,79 @@ -### Global definitions +### Global definitions. -# After 1 minute without a new request, exit -global read_timeout 60000 +# tipideed verbosity (overridden by the -v option). +# 0 is quiet, 1 is normal, 2+ is verbose. +# global verbosity 1 -# If the client fails to read a response for 1 minute, exit -global write_timeout 60000 +# tipideed will exit if the client does not send a new request +# after N milliseconds. +# 0 means no timeout. +# global read_timeout 0 -# If a CGI script takes more than 10s to run, kill it and respond 504 instead -global cgi_timeout 10000 +# tipideed will drop the connection if sending a response has +# not completed after N milliseconds. +# 0 means no timeout. +# global write_timeout 0 -# Serve .ini and .cfg files as plain text -content-type text/plain .ini .cfg +# tipideed will answer 504 ("Gateway Timeout") if a CGI program +# (including NPH) does not complete in N milliseconds. +# 0 means no timeout. +# global cgi_timeout 0 +# tipideed will refuse to serve POST requests if the client-provided +# data is larger than N bytes. +# global max_request_body_length 8192 -### Definitions for the example.com virtual domain -domain example.com +# tipideed will answer 502 ("Bad Gateway") if a CGI script's answer +# is larger than N bytes. (does not apply to NPH scripts) +# global max_cgi_body_length 4194304 -# CGI scripts called nph-foobar are considered non-parsed-headers -nph-prefix nph- +# When the requested URL is a directory, tipideed will serve the first +# existing file in this list. (Useful e.g. if you have an index.cgi program.) +# global index_file index.html -# CGI scripts live under /cgi-bin -cgi /cgi-bin/ +# You can define your own Content-Type mappings by file extension. +# The default mappings should work well for most servers. +# content-type text/html .html .htm -# Serve http://example.com/README as plain text -file-type /README text/plain + +### Definitions for the example.com domain +# domain example.com + +# If a CGI script under the current domain starts with this prefix, +# it will be considered a NPH script (non-parsable headers). +# nph-prefix nph- + +# If uncommented: every file under that directory will be considered +# a CGI script. +# cgi /cgi-bin/ + +# You can also declare that individual files are CGI scripts. +# cgi /index.cgi + +# If uncommented: every CGI script under that directory will be considered NPH. +# nph /cgi-bin/nph/ + +# You can also declare that individual scripts are NPH. +# nph /cgi-bin/basic.cgi + +# You can override the default Content-Type for individual files, +# no matter what extension they have. +# file-type /README text/plain # Redirect http://example.com/rickroll to a fan favorite video. # Make it temporary to avoid revealing the trick in the client. -redirect /rickroll 307 https://www.youtube.com/watch?v=dQw4w9WgXcQ +# redirect /rickroll 307 https://www.youtube.com/watch?v=dQw4w9WgXcQ # Permanently redirect http://example.com/community/foobar... requests # to https://example.org/foobar... -redirect /community/ 308 https://example.org +# redirect /community/ 308 https://example.org + +### Definitions for the example.org domain +# domain example.org -### Definitions for the example.org virtual domain -domain example.org +# example.org has the same NPH prefix +# nph-prefix nph- -nph-prefix nph- -cgi /cgi-bin/ +# example.org hosts CGI scripts in /cgi-bin as well +# cgi /cgi-bin/ diff --git a/src/config/lexparse.c b/src/config/lexparse.c index a7ed5b2..da9d7f5 100644 --- a/src/config/lexparse.c +++ b/src/config/lexparse.c @@ -99,7 +99,7 @@ static inline void parse_global (char const *s, size_t const *word, size_t n, md { .name = "verbosity", .key = "G:verbosity", .type = 0 }, { .name = "write_timeout", .key = "G:write_timeout", .type = 0 } } ; - struct globalkey_s *gl ; + struct globalkey_s const *gl ; if (n < 2) strerr_dief8x(1, "too ", "few", " arguments to directive ", "global", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; gl = bsearch(s + word[0], globalkeys, sizeof(globalkeys)/sizeof(struct globalkey_s), sizeof(struct globalkey_s), &globalkey_cmp) ; @@ -194,7 +194,7 @@ static inline void parse_redirect (char const *s, size_t const *word, size_t n, static void parse_bitattr (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, unsigned int bit, int set) { - static char const *attr[3][2] = { { "noncgi", "cgi" }, { "nonnph", "nph", }, { "noauth", "basic-auth" } } ; + static char const *const attr[3][2] = { { "noncgi", "cgi" }, { "nonnph", "nph", }, { "noauth", "basic-auth" } } ; uint8_t mask = (uint8_t)0x01 << bit ; if (n != 1) strerr_dief8x(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", attr[bit][set], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; diff --git a/src/config/tipidee-config-internal.h b/src/config/tipidee-config-internal.h index e274f94..154c6ff 100644 --- a/src/config/tipidee-config-internal.h +++ b/src/config/tipidee-config-internal.h @@ -35,8 +35,6 @@ extern struct global_s g ; extern void confnode_start (confnode *, char const *, size_t, uint32_t) ; extern void confnode_add (confnode *, char const *, size_t) ; -#define confnode_adds(node, s) confnode_add(node, (s), strlen(s)) -#define confnode_add0(node) confnode_add((node), "", 1) /* conftree */ diff --git a/src/config/tipidee-config-preprocess.c b/src/config/tipidee-config-preprocess.c index 6ac4812..03b54f1 100644 --- a/src/config/tipidee-config-preprocess.c +++ b/src/config/tipidee-config-preprocess.c @@ -206,9 +206,11 @@ static void includefromhere (char const *file) switch (cmd) { case 2 : + if (namesa.s[d] & 2) + strerr_dief5x(3, "in ", namesa.s + d + 1, " line ", linefmt, ": extra !included: directive") ; if (!strcmp(sa.s + sastart, "unique")) namesa.s[d] |= 3 ; else if (!strcmp(sa.s + sastart, "multiple")) namesa.s[d] |= 2 ; - else strerr_dief6x(3, "in ", namesa.s + d + 1, " line ", linefmt, "invalid !included: argument: ", sa.s + sastart) ; + else strerr_dief6x(3, "in ", namesa.s + d + 1, " line ", linefmt, ": invalid !included: argument: ", sa.s + sastart) ; break ; case 1 : case 0 : diff --git a/src/config/tipidee-config.c b/src/config/tipidee-config.c index be13e39..36b1c03 100644 --- a/src/config/tipidee-config.c +++ b/src/config/tipidee-config.c @@ -52,11 +52,6 @@ static inline void conf_output (char const *ofile, unsigned int omode) memcpy(otmp + olen, ":XXXXXX", 8) ; fdw = mkstemp(otmp) ; if (fdw == -1) strerr_diefu3sys(111, "open ", otmp, " for writing") ; - if (coe(fdw) == -1) - { - unlink_void(otmp) ; - strerr_diefu2sys(111, "coe ", otmp) ; - } if (!cdbmake_start(&cm, fdw)) { unlink_void(otmp) ; @@ -77,7 +72,7 @@ static inline void conf_output (char const *ofile, unsigned int omode) unlink_void(otmp) ; strerr_diefu2sys(111, "fsync ", otmp) ; } - if (fchmod(fdw, omode & 0755) == -1) + if (fchmod(fdw, omode & 0777) == -1) { unlink_void(otmp) ; strerr_diefu2sys(111, "fchmod ", otmp) ; diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c index 118f33a..f71be9f 100644 --- a/src/tipideed/tipideed.c +++ b/src/tipideed/tipideed.c @@ -30,6 +30,7 @@ #define dieusage() strerr_dieusage(100, USAGE) #define dienomem() strerr_diefu1sys(111, "stralloc_catb") +#define MAX_LOCALREDIRS 32 #define ARGV_MAX 128 struct global_s g = GLOBAL_ZERO ; @@ -367,6 +368,7 @@ int main (int argc, char const *const *argv, char const *const *envp) tipidee_rql rql = TIPIDEE_RQL_ZERO ; tipidee_headers hdr ; int e ; + unsigned int localredirs = 0 ; char const *x ; size_t content_length ; tipidee_transfercoding tcoding = TIPIDEE_TRANSFERCODING_UNKNOWN ; @@ -509,7 +511,9 @@ int main (int argc, char const *const *argv, char const *const *envp) /* And serve the resource. The loop is in case of CGI local-redirection. */ - while (serve(&rql, docroot, hostlen + 1 + g.localportlen, uribuf, &hdr, bodysa.s, bodysa.len)) ; + while (serve(&rql, docroot, hostlen + 1 + g.localportlen, uribuf, &hdr, bodysa.s, bodysa.len)) + if (localredirs++ >= MAX_LOCALREDIRS) + die502x(&rql, 1, "too many local redirections - possible loop involving path ", rql.uri.path) ; } } log_and_exit(0) ; |