As discussed before, I think it's a very astute plan to have hm2 generate a virtual host for it's own main hosting site, and append that file onto the virtual host configuration.

Another issue I discovered while finishing up the import code, is that if the sites already exist , and have virtual hosts configured outside of hostmaster 2, we will end up creating duplicate virtual hosts and possibly breaking apache.

I think the only way to fix this properly will involve a command line install script, that can parse the apache configuration, see if the changes have already be made that we want to make, and add the entry / remove any additional virtual hosts that have been defined.

This script would likely need root privileges, and could also be used to set up the server user accounts and the like. To automate the installation.

It need not be written in php, infact, i think a shell script would probably be a safer solution. Hell, it could even be a autoconf/Makefile, if we really wanna go to that level. I'd only consider a makefile because it would be easier to integrate with package management software.

I'd need to do some research into driving install.php from the command line without a single existing drupal site, perhaps by creating a very small / simple bootstrap db dump. I don't know yet.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

adrian’s picture

Version: » 5.x-0.1-alpha1

Well. I realized people must have needed to parse apache config files with php :

Here's a php licensed PEAR class :
http://pear.php.net/package/Config

and i've attached a simple gpl licensed class for php. i found it on phpclasses, which is a terrible site and i won't force other people to sign up for it.

Using proc_open, we can even have the user enter their root password as part of a hosting setup / provision setup script.

This is related to http://drupal.org/node/273295

adrian’s picture

FileSize
5.44 KB
adrian’s picture

Title: Devise method for importing existing sites, without the chance of clashing with existing virtual hosts. » Manage httpd.conf to avoid clashing hostnames and as a sanity check on configuration.

better title.

anarcat’s picture

I don't think we should parse httpd.conf. It's not that the file format is that complex in itself, it's that there's a lot of corner cases to cover. We will have to work *very* hard to make sure we avoid an error that is basically an operator error (provisionning virtual hosts outside of hostmaster). Once hostmaster is on a server, it should rightly expect to have every domain available to itself.

Of course it should check if it's allowed to host certain domains, e.g. allowing yahoo.com to be hosted on hostmaster is probably a bad idea, but this is a matter of policy and outside the scope of this issue here.

So my opinion is that we can *check* if a hostname is already defined in the apache configuration files in a crude grep-style way, but going further than that is a waste of time.

anarcat’s picture

We could use `httpd -S` to check what hostnames are taken:

VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:*                    is a NameVirtualHost
         default server marvin.anarcat.ath.cx (/etc/apache2/sites-enabled/000-default:2)
         port * namevhost marvin.anarcat.ath.cx (/etc/apache2/sites-enabled/000-default:2)
         port * namevhost anarcat.ath.cx (/etc/apache2/sites-enabled/0_anarcat.ath.cx.conf:1)
Syntax OK

The advantage is that this is the actual parsed configuration that's currently active. As a bonus, we check if we screwed up the config by declaring duplicate stuff or whatever.. ;)

adrian’s picture

Title: Manage httpd.conf to avoid clashing hostnames and as a sanity check on configuration. » Use httpd -S as a sanity check to make sure the config path is included.

This needs to be added to hosting setup, to make sure the server is picking up all the changes we make.

adrian’s picture

Status: Active » Postponed

Here's a regular expression to extract this info :

preg_match_all('+port (\d*)\ namevhost\ ([\w\.]*)\ \((.*):\d+\)$+', $output, $matches);

We have several problems with this however ..

A) its different between different distros. Debian has /usr/sbin/apache2 instead of httpd
B) The binary is unlikely to be in the path of our script user, since sbin is usually only in the root user's path on redhat based systems
C) There are permission issues relating to this, as the script user will need to be able to sudo the binary in most cases.

marking this as postponed for now, until we have a cleaner way to solve this.

anarcat’s picture

a) we should make that customizable per webserver, just like apachectl is
b) we could lookup a few paths in the verification of the webserver (/usr/s?bin/(apache|httpd)2?)
c) same as apachectl again: it (the above + -S) needs to be added to sudo

adrian’s picture

Status: Postponed » Needs work

Actually..

i found out that apachectl and apache2ctl have the same flags.

So we don't have to configure an additional binary.
ALSO, i found :

notroot@ubuntu:~$ sudo apache2ctl -V
Server version: Apache/2.2.9 (Ubuntu)
Server built:   Sep 19 2008 13:43:21
Server's Module Magic Number: 20051115:15
Server loaded:  APR 1.2.12, APR-Util 1.2.12
Compiled using: APR 1.2.12, APR-Util 1.2.12
Architecture:   32-bit
Server MPM:     Prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT=""
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="/var/run/apache2/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="/etc/apache2/mime.types"
 -D SERVER_CONFIG_FILE="/etc/apache2/apache2.conf"

m+-D SERVER_CONFIG_FILE=(.*)?$+' extracts the apache configuration file.

anarcat’s picture

So apache.conf is not all: it may Include another file or a directory which then would include Aegir. That's how the INSTALL.txt tells people to setup Aegir anyways, and I think it's proper from a packaging point of view.

Basically, the apache.conf would be a start, then you need to parse each file for Include and recursively parse those to find your final include.

Anonymous’s picture

Title: Use httpd -S as a sanity check to make sure the config path is included. » Use httpd -S / apache2ctl configtest as a sanity check before restarting

Renaming, made #747384: Add apache2ctl configtest check before ever restarting apache a duplicate of this, they are pretty much after the same thing.

We'll need to handle nginx etc as well if we ever do this.

omega8cc’s picture

For NginX it is a matter of good init script. We are using it already in Barracuda, so it always runs configtest before running reload. Furthermore, even without this configtest, NginX will ignore reload command completely if there are any fatal errors. Of course it will fail to start when admin will try to force restart, but at least we know that Aegir will not be able to take down the NginX web server. This init script is Debian/Ubuntu compatible, but I don't think we can include it in the Aegir docs/hints. Anyway, we are safe by default with vanilla NginX install because we are using safe reload init command, and not restart.

ergonlogic’s picture

Version: 5.x-0.1-alpha1 » 6.x-2.x-dev
Category: task » feature

Is this still relevant? I don't recall seeing any recent problems caused by errors in Apache conf files... Still, this seems like it would be pretty easy to implement. We'd certainly want it if we undertook anything like #1217302: Add functionality to change Apache VirtualHost definitions from UI

anarcat’s picture

It is just good practice, so yes, this is still relevant. we should probably rollback the task if the config check fails.

ergonlogic’s picture

Status: Needs work » Needs review
FileSize
1.04 KB

The attached patch appears to work for the base apache service.

ergonlogic’s picture

Here it is for the rest of the http services. I haven't tested on Nginx, but I believe '-t' is the proper option to do a configtest.

Since we use $this within the function, we can't make this static as we do with apache_restart_cmd().

omega8cc’s picture

Status: Needs review » Needs work

This doesn't work for Nginx, since the -t works only with Nginx binary and not with the init script. Note that you don't really need to use any specific command other then typical service nginx reload because it will not reload the config and will show the config error when the reload fails. That is the difference between reload and restart in Nginx.

v251a:~# /usr/sbin/nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
v251a:~#
v251a:~# service nginx -t
Usage: /etc/init.d/nginx {start|stop|restart|force-reload|status|configtest|quietupgrade|terminate}
v251a:~# service nginx configtest
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
v251a:~#

Note however that configtest may not be available since it depends on the init script provided by particular distro, so calling Nginx binary with -t flag is the most reliable method. IMO.

ergonlogic’s picture

Status: Needs work » Needs review
FileSize
4.86 KB

Fixed extra ')', and now trying to find the nginx binary.

anarcat’s picture

I don't like manually parsing the PATH at all: if nginx is in the PATH, iterating over the PATH is useless, as we should just be able to call "nginx" directly (without an absolute path).

Furthermore, if "nginx reload" works, why do we mess around with the init.d? If we would skip using the init.d, we would avoid the code duplication created by the patch in #20, which i dislike a little. Same for apache, actually: let's just call apache2ctl directly please.

omega8cc’s picture

Nginx does require init script. There is no such thing as "nginx reload" -- it is "service nginx reload" which is "/etc/init.d/nginx reload" effectively. That said, I don't see any need for extra check for Nginx, since "service nginx reload" runs that check -- but of course you will not notice that it failed to reload when there is no config check in provision.

anarcat’s picture

Well, I don't know about the different versions of nginx, but here there *is* such a thing as nginx reload: it's

anarcat@marcos:provision$ nginx -h
nginx version: nginx/1.2.1
Usage: nginx [-?hvVtq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
[...]
  -s signal     : send signal to a master process: stop, quit, reopen, reload

So I assume that this:

nginx -s reload

will do the right thing.

Also, the idea behind this feature request is to rollback in provision if we introduce a syntax error, instead of creating a configuration file that could crash the webserver on reboot or keep it from reloading properly until there's a manual intervention.

omega8cc’s picture

Right, we can call binary for reload with "nginx -s reload" and it still checks the config syntax, so we don't need to rely on the init script -- but note that then we kind of "enforce policy" if we ignore init script. But in this case it is not a problem to me.

So, we can check the syntax with "nginx -t" and if there is an error, revert the task and use "nginx -s reload" for config update.

Note that we have introduced that paths discovery (if I recall this correctly) to support OS X installs. Or maybe we just followed the way the path discovery was done for Apache, not sure, but before we will drop this, maybe we should ask folks using OS X if calling just nginx directly works -- and then maybe modify PATH in the aegir cron entry, if needed.

omega8cc’s picture

However, we will break things on upgrades, until the server admin will modify /etc/sudoers entry.

anarcat’s picture

I think it's fine to break the upgrade path for 2.x, it's the right time.

If we'd like to not impose policy, we'd need to allow users to set specific "test" and "reload" commands, something which we are not doing right now either: we are just autodetecting, not allowing customization, if I understand properly.

As for path discovery: I just don't get it, I think. :) Really, why do we need to iterate manually through $PATH? Isn't that what "exec" does?

omega8cc’s picture

It has been added to make it work when Nginx is installed from sources in a path which is not listed in PATH in the aegir cron entry, like /usr/local/bin/nginx or /usr/local/sbin/nginx and to support config reloads with and without init script on various systems. Here is relevant issue: #1259098: nginx HTTP service should support different restart commands plus #1303088: wrong nginx restart script detection code

anarcat’s picture

Status: Needs review » Needs work

right i see. let me clarify what i mean.

+++ b/http/Provision/Service/http/nginx.phpundefined
@@ -137,6 +137,38 @@ class Provision_Service_http_nginx extends Provision_Service_http_public {
+    foreach (explode(':', $_SERVER['PATH']) as $path) {
+      $options[] = "$path/nginx";
+    }

this is useless.

+++ b/http/Provision/Service/http/nginx.phpundefined
@@ -137,6 +137,38 @@ class Provision_Service_http_nginx extends Provision_Service_http_public {
+    $options[] = '/usr/sbin/nginx';
+    $options[] = '/usr/local/sbin/nginx';
+    $options[] = '/usr/local/bin/nginx';

this may not be, but I would expect people to modify their PATH to the same effect... but i'm ready to concede this may be expecting too much.... maybe we should set the PATH in the crontab instead?

ergonlogic’s picture

Status: Needs work » Needs review

The last few comments strike me as out-of-scope for this issue. However we do it, it seems to me that the sanity check should be consistent with the way the restart command itself is determined. I'm tempted to commit this, and start a follow-up issue to continue the discussion about changing how we set the nginx commands.

anarcat’s picture

i feel this should be pushed to 3.x.

ergonlogic’s picture

Version: 6.x-2.x-dev » 7.x-3.x-dev
Status: Needs review » Needs work