#!/usr/bin/python3 -u import sys, os import subprocess import argparse import platform import shutil import pathlib import distro import pwd import getpass import re #import pymysql.cursors #pymysql.install_as_MySQLdb pyv=platform.python_version_tuple() if pyv[0]!='3': print('Need python 3 for execute this script') sys.exit(1) parser = argparse.ArgumentParser(description='Script for create a flask site.') parser.add_argument('--domain', help='The domain where is the site', required=True) parser.add_argument('--home_user', help='The name of the new user', required=True) parser.add_argument('--git_url', help='Url for download the last tag of app, can be used for update app', required=True) parser.add_argument('--user', help='The name of the domain user', required=True) parser.add_argument('--dependencies', help='The dependencies of the flask app separated by commas', required=True) parser.add_argument('--app_flask', help='The string type app:app for load in gunicorn', required=True) #parser.add_argument('--port', help='The port of the gunicorn application', required=True) parser.add_argument('--path', help='The path of the flask install') args = parser.parse_args() linux_distro=distro.id() home_user=args.home_user if home_user.find('/', -1)==-1: print("Error: you need backslash in home_user option") exit(1) user=args.user apache_cmd='apache2' apachectl='apache2ctl' if linux_distro!='debian' and linux_distro!='ubuntu': apache_cmd='httpd' apachectl='apachectl' if linux_distro=='rocky' or linux_distro=='fedora': apache_group='apache' if linux_distro=='arch': apache_group='http' system_user=getpass.getuser() if os.path.isdir(home_user): print("Cleaning %s directory" % home_user) if subprocess.call("sudo su %s -s /bin/bash -c 'rm -f -r %s'" % (user, home_user), shell=True) > 0: print('Error: cannot clean directory {}'.format(home_user)) sys.exit(1) """ if linux_distro=='debian' or linux_distro=='ubuntu': #libapache2-mod-wsgi-py3/ if subprocess.call("sudo apt-get update && sudo apt-get upgrade && sudo apt-get install libapache2-mod-wsgi-py3", shell=True) > 0: print('Error: cannot install mod_wsgi for apache') sys.exit(1) """ print("Creating virtualenv for the flask app...") if subprocess.call("sudo su %s -s /bin/bash -c 'mkdir -p %s && python3 -m venv %s/venv'" % (user, home_user, home_user), shell=True) > 0: print('Error: cannot install python virtualenv in {}'.format(home_user)) sys.exit(1) dependencies=args.dependencies if subprocess.call("sudo su %s -s /bin/bash -c '%s/venv/bin/pip install %s flask gunicorn'" % (user, home_user, dependencies.replace(',', ' ')), shell=True) > 0: print('Error: cannot install python virtualenv dependencies in {}'.format(home_user)) sys.exit(1) num_proc=str(os.cpu_count()*2+1) name=os.path.basename(home_user[:-1]).strip() #port=int(args.port) if not re.match('\w+:\w+', args.app_flask): print('Error: define the app_flask with app:app format') sys.exit(1) path='/' if args.path: if args.path.find('/', -1)==-1: print("Error: you need backslash in path option") exit(1) path=args.path[:-1] full_path=args.path if path=='': path='/' print("Creating the service for flask app with gunicorn...") with open('./%s-%s.service' % (args.domain, name), 'w') as f: f.write("# Save it in /etc/systemd/system/%s-%s.service\n" % (args.domain, name)) f.write("[Unit]\n") f.write("Description=App %s\n" % name) f.write("After=syslog.target\n") f.write("After=network.target\n") f.write("[Service]\n") f.write("Type=simple\n") f.write("User=%s\n" % user) f.write("Group=%s\n" % user) f.write("WorkingDirectory=%s/app\n" % home_user) f.write("ExecStart=%svenv/bin/gunicorn -w%s -b unix:%sgunicorn.sock --timeout 300 --error-logfile %s%s-error.log --access-logfile %s%s-access.log --reload %s\n" % (home_user, num_proc, home_user, home_user, name, home_user, name, args.app_flask)) f.write("Restart=always\n") f.write("Environment=USER=%s HOME=/home/%s\n" % (user, user)) f.write("[Install]\n") f.write("WantedBy=multi-user.target\n") print("Downloading application using git...") if subprocess.call('sudo cp ./%s-%s.service /etc/systemd/system' % (args.domain, name), shell=True) > 0: print('Error: cannot install app service in systemd...') sys.exit(1) if subprocess.call("sudo su %s -s /bin/bash -c 'git clone %s %sapp && cd %sapp && export GTAG=$(git describe --tags `git rev-list --tags --max-count=1`) && git checkout $GTAG -b latest-$GTAG'" % (user, args.git_url, home_user, home_user), shell=True) > 0: print('Error: cannot download git packages in {}app'.format(home_user)) sys.exit(1) if path=='/': base_name_file='{}-001-{}.conf'.format(args.domain, name) else: base_name_file='{}-000-{}.conf'.format(args.domain, name) name_file='/home/{}/{}'.format(system_user, base_name_file) with open(name_file, 'w') as f: f.write("ProxyPreserveHost On\n") f.write("ProxyRequests Off\n") f.write("\n" % path) #ProxyPass unix:/home/root/flask_rest/flaskrest.sock|http://127.0.0.1/ f.write("ProxyPass unix:%sgunicorn.sock|http://127.0.0.1%s\n" % (home_user, full_path)) f.write("ProxyPassReverse unix:%sgunicorn.sock|http://127.0.0.1%s\n" % (home_user, full_path)) if path!='/': f.write("RequestHeader set SCRIPT_NAME %s\n" % path) f.write("RequestHeader set X-Forwarded-Proto http\n") f.write("RequestHeader set X-Forwarded-Prefix %s\n" % path) f.write("\n") if path=='/': f.write("\n") f.write("ProxyPass !\n") f.write("\n") print('Updating apache configuration for flask outside of htdocs...') if subprocess.call('sudo mv {} /etc/{}/vhosts.d/extra && sudo chown root:root /etc/{}/vhosts.d/extra/{}'.format(name_file, apache_cmd, apache_cmd, base_name_file), shell=True) > 0: print('Error') sys.exit(1) print("Preparing apache for use gunicorn...") if linux_distro=='debian' or linux_distro=='ubuntu': if subprocess.call('sudo a2enmod proxy_http', shell=True) > 0: print("Error: cannot enable proxy_http in apache in debian/ubuntu distro") sys.exit(1) service=args.domain+'-'+name if subprocess.call("sudo systemctl enable %s && sudo systemctl start %s && sudo systemctl restart %s" % (service, service, apache_cmd), shell=True) > 0: print("Error: cannot update and restart apache") sys.exit(1) print("Flask app install successfully!")