Last active
September 2, 2020 23:04
-
-
Save MLutt/58afbcc587fadb976089356bb235cfc6 to your computer and use it in GitHub Desktop.
Drupal multisite creator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import shutil | |
import subprocess | |
import mysql.connector | |
import string | |
import random | |
def promptInput(text: str, default: str) -> str: | |
prompt = f"{text} [{default}]" if default is not None else text | |
prompt += ": " | |
temp = input(prompt) | |
if temp == "": | |
return default | |
else: | |
return temp | |
def promptList(text: str) -> list: | |
print(text) | |
print("You can end input with a blank line!") | |
temp = [] | |
tmp = input("Enter the next entry: ") | |
while tmp != "": | |
temp.append(tmp) | |
tmp = input("Enter the next entry: ") | |
return temp | |
def get_random_string(length: int) -> str: | |
letters = string.ascii_letters | |
return ''.join(random.choice(letters) for i in range(length)) | |
if __name__ == "__main__": | |
print("Please note - this script is optimized for NerdGautica's standard environment (defaults) on a Debian-based system.") | |
print("This script will take care of the following tasks:") | |
print("-> Creating the site directory") | |
print("-> Creating and setting the private file storage") | |
print("-> Creating a MySQL user and corresponding database") | |
print("-> Setting trusted host patterns") | |
print("-> Configuring and restarting apache2 (without SSL)") | |
print("-> Generating an SSL certificate and setting up a redirect via certbot") | |
print("\nPlease provide any details as they are requested. Note that input is always case-sensitive!\n") | |
rootDir = promptInput("Please provide the drupal root directory", "/var/www/DrupalBase") | |
siteName = promptInput("Please provide the site's (Sub-)Domain", None) | |
siteAlias = promptList("Please provide site aliases") | |
privateFiles = promptInput("Please provide the private file storage path (it must not be accessible via web!)", f"/var/www/privateFileStorage/{siteName}") | |
apacheConfigPath = promptInput("Please insert the path to the apache sites-enabled configuration", f"/etc/apache2/sites-enabled/{siteName}.conf") | |
user = promptInput("Please provide the username of the web server", "www-data") | |
siteSpecificModules = promptInput("Allow site-specific modules? - y/n", "n") == "y" | |
grantOption = promptInput("Give database grant option to the site user? yes/no", "no") == "yes" | |
print("\nPlease provide the database details for the website") | |
MySQLDetails = { | |
"ServerHost": promptInput("Please insert the hostname/IP of the database server", "127.0.0.1"), | |
"ServerPort": int(promptInput("Please insert the port of the database server", "3306")), | |
"DBAdminUser": promptInput("Please insert the username of the DBAdmin to use", "root"), | |
"DBAdminPassword": promptInput("Please insert the password of the DBAdmin to use", None), | |
"User": promptInput("User name for the new site", siteName.replace(".", "_").replace("-","_")), | |
"Password": promptInput("Please provide the password for the site user", get_random_string(40)), | |
"Host": promptInput("Please insert the hostname/IP of the server hosting the site", "localhost"), | |
"Database": promptInput("Please insert the name of the database the site has access to. It will be created if necessary.", "DRUPALCLUSTER") | |
} | |
if not promptInput("\nPlease check your provided details - is everything ok? yes/no", "no") == "yes": | |
exit(5) | |
apacheConfig = [ | |
"<VirtualHost *:80>", | |
f" ServerName {siteName}", | |
f" ServerAlias {' '.join(siteAlias)}", | |
f" DocumentRoot {rootDir}", | |
f" <Directory \"{rootDir}\">", | |
" AllowOverride All", | |
" </Directory>", | |
"</VirtualHost>" | |
] | |
apacheConfig = "\n".join(apacheConfig) | |
if os.path.exists(f"{rootDir}/sites/{siteName}"): | |
print("Site directory found - skipping creation") | |
else: | |
print(f"Creating site directory at {rootDir}/sites/{siteName}") | |
os.mkdir(f"{rootDir}/sites/{siteName}") | |
print("Copying default configuration files to the new site's directory") | |
shutil.copyfile(f"{rootDir}/sites/default/default.settings.php", f"{rootDir}/sites/{siteName}/settings.php") | |
print("Setting trusted host configuration") | |
with open(f"{rootDir}/sites/{siteName}/settings.php", "a") as config: | |
config.write("$settings['trusted_host_patterns'] = [") | |
escaped = '\\.'.join(siteName.split('.')) | |
config.write(f"'^{escaped}$',") | |
for x in siteAlias: | |
escaped = '\\.'.join(x.split('.')) | |
config.write(f"'^{escaped}$',") | |
config.write("];") | |
print("Creating and setting private files directory") | |
config.write(f"$settings['file_private_path'] = '{privateFiles}';") | |
if not os.path.exists(privateFiles): | |
os.makedirs(privateFiles) | |
subprocess.call(["chown", f"{user}:{user}", privateFiles]) | |
if siteSpecificModules: | |
os.mkdir(f"{rootDir}/sites/{siteName}/modules") | |
if not os.path.exists(f"{rootDir}/sites/sites.php"): | |
print("sites.php not found, copying default") | |
shutil.copyfile(f"{rootDir}/sites/example.sites.php",f"{rootDir}/sites/sites.php") | |
print("Appending newly created site to configuration") | |
with open(f"{rootDir}/sites/sites.php", "a") as sitesConfiguration: | |
sitesConfiguration.write(f"$sites['{siteName}'] = '{siteName}';") | |
print("Changing ownership of the site directory to the web server") | |
subprocess.call(["chown", "--recursive", f"{user}:{user}", f"{rootDir}/sites/{siteName}"]) | |
print("Please check the apache configuration for mistakes:\n") | |
print(apacheConfig) | |
if promptInput("\nInsert 'yes' to continue", "no") != "yes": | |
exit(7) | |
print("Readying MySQL") | |
connection = mysql.connector.connect( | |
host=MySQLDetails["ServerHost"], | |
port=MySQLDetails["ServerPort"], | |
user=MySQLDetails["DBAdminUser"], | |
password=MySQLDetails["DBAdminPassword"] | |
) | |
print("Creating MySQL User and Database") | |
connection.cursor().execute(f"CREATE DATABASE IF NOT EXISTS {MySQLDetails['Database']}") | |
connection.cursor().execute(f"CREATE USER IF NOT EXISTS '{MySQLDetails['User']}'@'{MySQLDetails['Host']}' IDENTIFIED BY '{MySQLDetails['Password']}'") | |
grantString = f"GRANT ALL PRIVILEGES ON {MySQLDetails['Database']}.* TO '{MySQLDetails['User']}'@'{MySQLDetails['Host']}'" | |
if grantOption: | |
grantString += " WITH GRANT OPTION" | |
connection.cursor().execute(grantString) | |
connection.cursor().execute("FLUSH PRIVILEGES") | |
print("DB Configuration done") | |
connection.close() | |
print("Writing apache configuration") | |
with open(apacheConfigPath, "w") as configFile: | |
configFile.write(apacheConfig) | |
print("Restarting apache") | |
subprocess.call(["service", "apache2", "restart"]) | |
print("Enabling SSL") | |
subprocess.call(["certbot", "-d", ",".join([siteName] + siteAlias), "--redirect"]) | |
print("Everything done - you will need the following details for the initial site configuration:") | |
print(f"MySQL User -> {MySQLDetails['User']}") | |
print(f"MySQL Password -> {MySQLDetails['Password']}") | |
print(f"MySQL Database -> {MySQLDetails['Database']}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment