From d4ebe6894e0e95048c03259725312562c3214fb6 Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Wed, 16 Aug 2023 13:47:49 +1000 Subject: [PATCH] main: Initial flask server --- README.md | 28 +++++++++- install.sh | 53 +++++++++++++++---- main.py | 130 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 4 ++ 4 files changed, 203 insertions(+), 12 deletions(-) create mode 100644 main.py create mode 100644 requirements.txt diff --git a/README.md b/README.md index 105c362..426b3c8 100644 --- a/README.md +++ b/README.md @@ -1 +1,27 @@ -# hnshosting-wp +# HNSHosting Wordpress +This is split into two parts. +There is the master server which is the server that will be used to manage the worker servers. +Then there is the worker server which is the server that will be used to host the wordpress site. + +This is done to make it easier to manage multiple wordpress sites on multiple servers. + +## Master server install + +Install prerequisites: + +``` +chmod +x install.sh +./install.sh +``` + +This will create the service to run the master server. + + +## Worker server install + +Install prerequisites: + +``` +chmod +x install.sh +./install.sh +``` \ No newline at end of file diff --git a/install.sh b/install.sh index 154f5f1..16a289a 100644 --- a/install.sh +++ b/install.sh @@ -1,18 +1,49 @@ #!/bin/bash # Initial install for all prerequisites for the project. -# This makes it quicker to get each site up and running. # Update the system sudo apt update && sudo apt upgrade -y -# Install Docker -sudo apt install apt-transport-https ca-certificates curl software-properties-common -y -curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg -echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null -sudo apt update -apt-cache policy docker-ce -sudo apt install docker-ce -y -sudo apt install docker-compose -y +# Install python prerequisites +python3 -m pip install -r requirements.txt -# Install NGINX -sudo apt install nginx -y \ No newline at end of file +# Create a service to run the python web server + +# Flask app directory and file +APP_DIR=$(pwd) +APP_FILE=main.py + +# Name for your systemd service +SERVICE_NAME=HNSHosting-Main + +# Create a user and group to run the service + +SERVICE_USER=hnshosting +SERVICE_GROUP=hnshosting + +sudo groupadd $SERVICE_GROUP +sudo useradd -g $SERVICE_GROUP $SERVICE_USER + +# Create a systemd service unit file +echo "[Unit] +Description=HNSHosting Main Service +After=network.target + +[Service] +User=$SERVICE_USER +Group=$SERVICE_GROUP +WorkingDirectory=$APP_DIR +ExecStart=/usr/bin/python3 $APP_DIR/$APP_FILE +Restart=always + +[Install] +WantedBy=multi-user.target" | sudo tee /etc/systemd/system/$SERVICE_NAME.service + +# Reload systemd to pick up the new unit file +sudo systemctl daemon-reload + +# Enable and start the service +sudo systemctl enable $SERVICE_NAME +sudo systemctl start $SERVICE_NAME + +echo "Service created and started." diff --git a/main.py b/main.py new file mode 100644 index 0000000..6446735 --- /dev/null +++ b/main.py @@ -0,0 +1,130 @@ +from flask import Flask, request, jsonify +import dotenv +import os + +dotenv.load_dotenv() + + +app = Flask(__name__) + +# API add license key (requires API key in header) +@app.route('/add-licence', methods=['POST']) +def add_license(): + # Get API header + api_key = request.headers.get('key') + if api_key != os.getenv('LICENCE-API'): + return jsonify({'error': 'Invalid API key', 'success': 'false'}) + + # Generate licence key + licence_key = os.urandom(16).hex() + + # Add license key to file + key_file = open('licence_key.txt', 'a') + key_file.write(licence_key + '\n') + key_file.close() + + return jsonify({'success': "true", 'licence_key': licence_key}) + + +@app.route('/new-site', methods=['POST']) +def new_site(): + domain=request.args.get('domain') + # Get API header + api_key = request.headers.get('key') + + # Verify both API key and domain exist + if api_key == None or domain == None: + return jsonify({'error': 'Invalid API key or domain', 'success': 'false'}) + + # Check if API key is a valid site key + if api_key not in open('licence_key.txt', 'r').read(): + return jsonify({'error': 'Invalid API key', 'success': 'false'}) + + # Check if domain already exists + if site_exists(domain): + return jsonify({'error': 'Domain already exists', 'success': 'false'}) + + + # Add domain to file + sites_file = open('sites.txt', 'a') + sites_file.write(domain + '\n') + sites_file.close() + + # Use key + key_file = open('licence_key.txt', 'r') + lines = key_file.readlines() + key_file.close() + key_file = open('licence_key.txt', 'w') + for line in lines: + if line.strip("\n") != api_key: + key_file.write(line) + key_file.close() + + + return jsonify({'success': 'true', 'domain': domain, 'status': "creating"}) + +# Add worker +@app.route('/add-worker', methods=['POST']) +def add_worker(): + worker=request.args.get('worker') + # Get API header + api_key = request.headers.get('key') + if api_key == None or worker == None: + return jsonify({'error': 'Invalid API key or worker', 'success': 'false'}) + if api_key != os.getenv('WORKER_KEY'): + return jsonify({'error': 'Invalid API key', 'success': 'false'}) + + # Check worker file + try: + workers_file = open('workers.txt', 'r') + except FileNotFoundError: + workers_file = open('workers.txt', 'w') + workers_file.close() + workers_file = open('workers.txt', 'r') + + # Check if worker already exists + if worker in workers_file.read(): + return jsonify({'error': 'Worker already exists', 'success': 'false'}) + + workers_file.close() + + # Add worker to file + workers_file = open('workers.txt', 'a') + workers_file.write(worker + '\n') + workers_file.close() + return jsonify({'success': 'true', 'worker': worker, 'status': "ready to join"}) + + +def get_sites_count(): + # If file doesn't exist, create it + try: + sites_file = open('sites.txt', 'r') + except FileNotFoundError: + sites_file = open('sites.txt', 'w') + sites_file.close() + sites_file = open('sites.txt', 'r') + num=len(sites_file.readlines()) + sites_file.close() + # Return number of lines in file + return num + +def site_exists(domain): + # If file doesn't exist, create it + try: + sites_file = open('sites.txt', 'r') + except FileNotFoundError: + sites_file = open('sites.txt', 'w') + sites_file.close() + sites_file = open('sites.txt', 'r') + + contains_site = False + # Check if domain is in file + if domain in sites_file.read(): + contains_site = True + sites_file.close() + return contains_site + + +# Start the server +if __name__ == '__main__': + app.run(debug=False, port=5000) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..01ad091 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +python-dotenv +requests +flask +jsonify \ No newline at end of file