Skip to content

Instantly share code, notes, and snippets.

@MLutt
Last active September 2, 2020 23:04
Show Gist options
  • Save MLutt/58afbcc587fadb976089356bb235cfc6 to your computer and use it in GitHub Desktop.
Save MLutt/58afbcc587fadb976089356bb235cfc6 to your computer and use it in GitHub Desktop.
Drupal multisite creator
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