Synopsis
This is the documentation for the create-website script I’ve created. The results of passing the -h parameter print out the following help:
SYNOPSIS:
create-website -u USER -w WEBSITE [-s|-f|-d|-h|-i <ip>]
DESCRIPTION:
Creates a new web site for a new user on the system. This
includes creating the user, the FTP account, the Database and
the virtual host
USER is the username of the owner of the web site. If the
account name doesn’t exist it will be created. Must be a valid
UNIX and MySQL username
WEBSITE is the url of the site to be created. Must be a FQDN,
should not include the www prefix. Preferably should be lower-
case.
-s Allow SSH based logins for the user [default = false]
-f Allow FTP based logins for the user [default = false]
-d Create a database for the user [default = false]
-i The IP the virtual host will listen on, by default the IP of eth0
-h Show this help message
That should be pretty self explanatory.
Configuration and execution
This script needs root privileges to run, so it is important that only root is able to edit the script. The script is stored in /usr/sbin/create-website.
This script does pull in a configuration file from /etc/.create-website. This file should be owned by root and chmodded to 400 (only readable by root). The contents of that configuration file should be something like:
<?php
$config = array(
‘mysql_username’ => ‘builder’,
‘mysql_password’ => ‘some_password’,
‘mysql_host’ => ‘localhost’
);
?>
This MySQL account need full privileges in order to be allowed to create accounts and give out the correct privileges itself.
Log rotation configurations are put into place that will rotate the access.log and error.log on a weekly basis, keeping 52 weeks of log files for each web site.
Files this script potentially touches:
Files Trigger
/etc/passwd Creating User
/etc/groups Creating User
/etc/shadow Creating User
/etc/apache2/sites-available/$website Creating Website
/etc/apache2/sites-enabled/$website Creating Website
/etc/logrotate.d/apache2_$website Creating Website
/etc/vsftpd.user_list When user is granted FTP access
/etc/ssh/sshd_config When user is granted SSH access
/home/$user/$website/ Directory where public facing web content resides
/home/$user/log/www/$website Directory where Apache log files reside
Note that this script has made specifically for the Ubuntu server with all the software installed where apt-get installs them by default. This script will need tweaking if used on a different set up.
#!/usr/bin/php
<?php
/**
* Create Website
*
* Entirely in house, very system dependent. Works on an Ubuntu installation with Apache and Mysql at pretty much default preferences.
* If you're moving this to a new server you will very likely have to re-write parts of it (paths etc)
*
* @license Public Domain
* @author Sid Karunaratne
*/
error_reporting(0);
// Options: user, website, has_ssh, has_ftp, has_db
$opts = getopt('u:w:sfdhi:');
$user = $opts['u'];
$website = $opts['w'];
$ip = array_key_exists('i',$opts) ? $opts['i'] : get_ip();
$has_ssh = (bool) array_key_exists('s',$opts);
$has_ftp = (bool) array_key_exists('f',$opts);
$has_db = (bool) array_key_exists('d',$opts);
$help = (bool) array_key_exists('h',$opts);
$err = fopen('php://stderr','w');
$out = fopen('php://stdout','w');
$db = null;
if ($help || (!$user || !$website))
{
display_help();
exit;
}
if (posix_getuid() !== 0)
{
_err('I need to be run as root');
exit(1);
}
if (site_exists($website))
{
_err('The website already exists, if you want to add more users to control this site you are going to have to do it manually');
exit(1);
}
# Check with the user we are doing the right thing
_err("About to create the account $user with the website $website with the virtual host listening on $ip");
$str = $has_ssh ? '' : 'NOT ';
_err($str. "allowing SSH login");
$str = $has_ftp ? '' : 'NOT ';
_err($str. "allowing FTP login");
$str = $has_db ? '' : 'NOT ';
_err($str. "creating a database");
_err("Press y/n to confirm action: ", false);
if (!in_array(_in(), array('y', 'Y', 'yes', 'true')))
{
_err('Exiting');
exit(1);
}
require('/etc/.create-website');
connect_db();
if (!user_exists($user))
{
_out("User '$user' does not exist and will be created");
`adduser --gecos "" $user`;
}
if ($has_ssh && !user_has_ssh($user))
{
_out("User '$user' is being given SSH access");
`echo 'AllowUsers $user' >> /etc/ssh/sshd_config`;
}
if ($has_ftp && !user_has_ftp($user))
{
_out("User '$user' is being given chrooted FTP access");
`echo $user >> /etc/vsftpd.user_list`;
}
if ($has_db)
{
# Create DB
global $db;
_out("Database being created (or already exists), user being created and access to database being given");
$mysql_password = prompt_silent("Please enter a MySQL password: ");
$db_name = str_replace('.', '_', $website);
mysql_query("CREATE DATABASE IF NOT EXISTS `$db_name`");
mysql_query("CREATE USER '$user'@'%' IDENTIFIED BY '".mysql_real_escape_string($mysql_password)."'");
mysql_query("GRANT USAGE ON * . * TO '$user'@'%' IDENTIFIED BY '".mysql_real_escape_string($mysql_password)."'");
mysql_query("GRANT ALL PRIVILEGES ON `$db_name` . * TO '$user'@'%'");
mysql_query("FLUSH PRIVILEGES");
}
_out("Virtual host for $website is being created");
# Create vhost
mkdir("/home/$user/$website", 0755, true);
chown("/home/$user/$website", $user);
chgrp("/home/$user/$website", $user);
mkdir("/home/$user/log/www/$website", 0755, true);
chown("/home/$user/log/www/$website", $user);
chgrp("/home/$user/log/www/$website", $user);
$vhost = "<VirtualHost {$ip}:80>
ServerAdmin [email protected]
DocumentRoot /home/$user/$website
ServerName $website
ServerAlias www.$website
ErrorLog /home/$user/log/www/$website/error.log
CustomLog /home/$user/log/www/$website/access.log combined
</VirtualHost>";
file_put_contents("/etc/apache2/sites-available/$website", $vhost);
symlink("/etc/apache2/sites-available/$website", "/etc/apache2/sites-enabled/$website");
_out("Configuration for the logrotation are being put in place");
# Adding logrotate
$logrotate = "/home/$user/log/www/$website/*.log {
weekly
missingok
rotate 52
compress
notifempty
copytruncate
}
";
file_put_contents("/etc/logrotate.d/apache2_{$user}_{$website}", $logrotate);
_err("Services are being reloaded for the changes to take effect");
`service apache2 reload`;
`service vsftpd reload`;
`service ssh reload`;
/**************************
/* HERE ARE THE FUNCTION THAT YOU SHOULDN'T NEED TO TOUCH
**************************/
function user_exists($user)
{
$users = file('/etc/passwd', FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
foreach ($users as $line)
{
$components = explode(':', $line);
if ($components[0] === $user)
return true;
}
return false;
}
function site_exists($website)
{
return file_exists("/etc/apache2/sites-enabled/$website");
}
function user_has_ssh($user)
{
$config = file('/etc/ssh/sshd_config', FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
foreach ($config as $line)
{
if (strncasecmp($line, 'AllowUsers', 10) === 0)
if (in_array($user, explode(' ', $line)))
return true;
}
return false;
}
function user_has_ftp($user)
{
$users = file('/etc/vsftpd.user_list', FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
foreach ($users as $line)
{
if ($line === $user)
return true;
}
return false;
}
function connect_db()
{
global $db;
global $config;
$db = mysql_connect($config['mysql_host'], $config['mysql_username'], $config['mysql_password']);
mysql_select_db('mysql', $db);
echo mysql_error();
}
function display_help()
{
$help = "
SYNOPSIS:
create-website -u USER -w WEBSITE [-s|-f|-d|-h|-i <ip>]
DESCRIPTION:
Creates a new web site for a new user on the system. This
ncludes creating the user, the FTP account, the Database and
the virtual host
USER is the username of the owner of the web site. If the
account name doesn't exist it will be created. Must be a valid
UNIX and MySQL username
WEBSITE is the url of the site to be created. Must be a FQDN,
should not include the www prefix. Preferably should be lower-
case.
-s Allow SSH based logins for the user [default = false]
-f Allow FTP based logins for the user [default = false]
-d Create a database for the user [default = false]
-i The IP the virtual host will listen on, by default the IP of eth0
-h Show this help message";
_err($help);
}
/**
* Interactively prompts for input without echoing to the terminal.
* Requires a bash shell and won't work with safe_mode settings (Uses `shell_exec`)
* from: http://www.sitepoint.com/blogs/2009/05/01/interactive-cli-password-prompt-in-php/
*/
function prompt_silent($prompt = "Enter Password:")
{
$command = "/usr/bin/env bash -c 'echo OK'";
if (rtrim(shell_exec($command)) !== 'OK')
{
trigger_error("Can't invoke bash");
return;
}
$command = "/usr/bin/env bash -c 'read -s -p \"" . addslashes($prompt) . "\" mypassword && echo \$mypassword'";
$password = rtrim(shell_exec($command));
_out('');
return $password;
}
function get_ip()
{
return substr(`ifconfig | grep 'addr:' | head -n1 | awk '{print $2}' | sed 's/addr://'`, 0, -1);
}
function _err($msg, $nl=true) { global $err; if($nl) $msg.=PHP_EOL; fwrite($err, $msg); }
function _out($msg) { global $out; fwrite($out, $msg . PHP_EOL); }
function _in() { return trim(fgets(STDIN)); }
?>