From 89835e3c86e467a0750f10589cf29aec0d8d327c Mon Sep 17 00:00:00 2001 From: Mo8it Date: Tue, 3 May 2022 19:02:39 +0200 Subject: [PATCH] Add Python scripts --- scripts/logged_server_setup.py | 94 ++++++++++++++++++++++++++++++++++ scripts/root_update.py | 23 +++++++++ scripts/server_setup.py | 22 ++++++++ scripts/shared.py | 55 ++++++++++++++++++++ scripts/user_update.py | 28 ++++++++++ 5 files changed, 222 insertions(+) create mode 100644 scripts/logged_server_setup.py create mode 100644 scripts/root_update.py create mode 100644 scripts/server_setup.py create mode 100644 scripts/shared.py create mode 100644 scripts/user_update.py diff --git a/scripts/logged_server_setup.py b/scripts/logged_server_setup.py new file mode 100644 index 0000000..b8ba0a6 --- /dev/null +++ b/scripts/logged_server_setup.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 + +import sys +from pathlib import Path + +script_dir = Path(__file__).parent.absolute() + +sys.path.insert(0, str(script_dir)) + +from shared import install_latest_pipx, local_bin, poetry_install_latest, run, step + +logs_dir = Path("/var/log/advlabdb/") + +step("Update system packages") +run("sudo apt update") +run("sudo apt dist-upgrade") + +step("Remove unused packages") +run("sudo apt autoremove") + +step("Install needed system packages") +run("sudo apt install python3 python3-pip python3-venv ufw nginx systemd -y") + +step("Install optional system packages") +run("sudo apt install htop") + +step("Setup firewall") +run("sudo ufw default allow outgoing") +run("sudo ufw default deny incoming") +run("sudo ufw allow ssh") +run("sudo ufw allow http/tcp") +# TODO: Setup https +# run("sudo ufw allow https/tcp") +run("sudo ufw enable") +run("sudo ufw status") + +step("Enable Gunicorn") +gunicorn_service_file = script_dir / "gunicorn.service" +run(f"sudo cp -v {gunicorn_service_file} /etc/systemd/system/") +run("sudo systemctl enable gunicorn") + +step("Setup Nginx") +for dir_appendix in ("available", "enabled"): + run(f"sudo rm -v /etc/nginx/sites-{dir_appendix}/default") + +nginx_conf_file = script_dir / "advlabdb.conf" +run(f"sudo cp -v {nginx_conf_file} /etc/nginx/sites-available/") +run("sudo ln -v -s /etc/nginx/sites-available/advlabdb.conf /etc/nginx/sites-enabled/") +run("sudo systemctl enable nginx") + +step("Install pipx") +install_latest_pipx() + +pipx_bin = local_bin / "pipx" + +step("Install Poetry") +run(f"{pipx_bin} install poetry") +# Place virtual environments in the root directory of the project +# The virtual environment will then be found in /home/admin/advlabdb/.venv +poetry_bin = local_bin / "poetry" +run(f"{poetry_bin} config virtualenvs.in-project true") + +step("Install Certbot") +run(f"{pipx_bin} install certbot") +run(f"{pipx_bin} inject certbot certbot-nginx") + +step("Setup Certbot") +certbot_bin = local_bin / "certbot" +run(f"sudo {certbot_bin} --nginx") +run( + f"echo \"0 0,12 * * * root python3 -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo {certbot_bin} renew -q\" | sudo tee -a /etc/crontab" +) + +step("Setup update cron jobs") + +user_update_script = script_dir / "user_update.py" +user_update_log = logs_dir / "user_update.log" + +root_update_script = script_dir / "root_update.py" +root_update_log = logs_dir / "root_update.log" + +# Every Sunday at 04:00 +run(f'echo "0 4 * * 0 admin python3 {user_update_script} &>> {user_update_log}" | sudo tee -a /etc/crontab') +# Every Sunday at 04:15 +run(f'echo "15 4 * * 0 root python3 {root_update_script} &>> {root_update_log}" | sudo tee -a /etc/crontab') + +step("Install latest Poetry packages") +poetry_install_latest(script_dir) + +step("Deactivate the 'root' user") +run("sudo passwd -l root") + +step("Reboot") +run("sudo reboot") diff --git a/scripts/root_update.py b/scripts/root_update.py new file mode 100644 index 0000000..46bd8c3 --- /dev/null +++ b/scripts/root_update.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 + +import sys +from datetime import datetime +from pathlib import Path + +script_dir = Path(__file__).parent.absolute() + +sys.path.insert(0, str(script_dir)) + +from shared import box, run, spaced_hl + +spaced_hl() + +dt = datetime.now().strftime("%d.%m.%Y %H:%M:%S") + +box(dt, "Update on") + +box("Update system packages") +run("sudo apt update") +run("sudo apt upgrade -y") + +run("sudo reboot") diff --git a/scripts/server_setup.py b/scripts/server_setup.py new file mode 100644 index 0000000..51faa93 --- /dev/null +++ b/scripts/server_setup.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +import sys +from pathlib import Path + +script_dir = Path(__file__).parent.absolute() + +sys.path.insert(0, str(script_dir)) + +from shared import run + +logs_dir = Path("/var/log/advlabdb/") + +# Create logs directory +run(f"sudo mkdir -v -p {logs_dir}") +run(f"sudo chown -R admin:admin {logs_dir}") + +logged_server_setup_script = script_dir / "logged_server_setup.py" +log_file = logs_dir / "server_setup.log" + +# Start actual server setup script with logging +run(f"python3 -u {logged_server_setup_script} | tee {log_file}") diff --git a/scripts/shared.py b/scripts/shared.py new file mode 100644 index 0000000..7684ba3 --- /dev/null +++ b/scripts/shared.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +import subprocess +from getpass import getpass +from pathlib import Path + +local_bin = Path("/home/admin/.local/bin/") + + +def run(command, **kwargs): + return subprocess.run(command, shell=True, **kwargs) + + +def box(message, context=None): + text_line = "| " + + if context is not None: + text_line += context + ": " + + text_line += message + " |" + + separator = "=" * len(text_line) + + print() + print(separator) + print(text_line) + print(separator) + print() + + +def step(message): + continue_message = "-> Press ENTER to continue or Ctrl+C to interrupt the script <-" + upper_separator = "_" * len(continue_message) + + print() + print(upper_separator) + + box(message, "Next step") + + print(continue_message) + getpass("") + print() + + +def install_latest_pipx(): + run("pip install --user --upgrade pipx") + + +def poetry_install_latest(script_dir): + poetry_bin = local_bin / "poetry" + run(f"{poetry_bin} install", cwd=script_dir / "..") + + +def spaced_hl(): + print("\n\n___________________\n\n") diff --git a/scripts/user_update.py b/scripts/user_update.py new file mode 100644 index 0000000..08f9a5b --- /dev/null +++ b/scripts/user_update.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import sys +from pathlib import Path + +script_dir = Path(__file__).parent.absolute() + +sys.path.insert(0, str(script_dir)) + +from shared import box, install_latest_pipx, local_bin, poetry_install_latest, spaced_hl + +spaced_hl() + +dt = datetime.now().strftime("%d.%m.%Y %H:%M:%S") + +box(dt, "Update on") + +box("Upgrade pipx") +install_latest_pipx() + +box("Upgrade pipx packages") +pipx_bin = local_bin / "pipx" +run(f"{pipx_bin} upgrade-all --include-injected") + +# TODO: Backup + +box("Install latest Poetry packages") +poetry_install_latest(script_dir)