From 8108c0c1aacf416c710fa017939a4ca28d2c629a Mon Sep 17 00:00:00 2001 From: Lukas Schaefer Date: Sun, 11 Jan 2026 22:19:23 -0500 Subject: [PATCH] Move Dockerfile from dockerWebsite repo and create docker-compose files Signed-off-by: Lukas Schaefer --- .github/FUNDING.yml | 15 ---- .github/dependabot.yml | 11 --- Dockerfile | 37 ++++++++ docker-compose.prod.yaml | 45 ++++++++++ docker-compose.yaml | 50 +++++++++++ html/config.json.template | 2 - html/include/functions.php | 2 +- python/database.py | 38 +++------ python/requirements.txt | 2 + python/restart.py | 168 +++++++++++++++++++++++-------------- start.sh | 9 ++ 11 files changed, 258 insertions(+), 121 deletions(-) delete mode 100644 .github/FUNDING.yml delete mode 100644 .github/dependabot.yml create mode 100644 Dockerfile create mode 100644 docker-compose.prod.yaml create mode 100644 docker-compose.yaml delete mode 100755 html/config.json.template create mode 100755 python/requirements.txt create mode 100644 start.sh diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index decdded..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,15 +0,0 @@ -# These are supported funding model platforms - -github: lukasdotcom # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -polar: # Replace with a single Polar username -buy_me_a_coffee: # Replace with a single Buy Me a Coffee username -thanks_dev: # Replace with a single thanks.dev username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 34aab5d..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,11 +0,0 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - -version: 2 -updates: - - package-ecosystem: "composer" # See documentation for possible values - directory: "/html/" # Location of package manifests - schedule: - interval: "daily" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..58506a7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +FROM ubuntu:latest +ARG TARGETPLATFORM +ENV DEBIAN_FRONTEND noninteractive +ENV TZ America/Detroit +# Used to install all the required software +RUN apt update +RUN apt install -y apache2 --no-install-recommends +RUN apt install -y mariadb-server +RUN apt install -y php --no-install-recommends +RUN apt install -y php-json php-mysql php-curl php-zip --no-install-recommends +RUN apt install -y python3 --no-install-recommends +RUN apt install -y python3-pip --no-install-recommends +RUN apt install -y python3-requests --no-install-recommends +RUN apt install -y curl --no-install-recommends +# Clean apt cache +RUN apt clean +RUN rm -rf /var/lib/apt/lists/* +# Clones the website +WORKDIR "/var/www/" +RUN rm -r html +COPY html/ html/ +COPY python/ python/ +WORKDIR "/var/www/python" +RUN pip3 install --break-system-packages -r requirements.txt +WORKDIR "/var/www/html" +# Gives apache the right settings +# COPY 000-default.conf /etc/apache2/sites-available/000-default.conf +# COPY apache2.conf /etc/apache2/apache2.conf +RUN a2enmod rewrite +COPY start.sh /start.sh +RUN chmod +x /start.sh +CMD ["/start.sh"] + +# Adds a healthcheck +HEALTHCHECK --timeout=5s CMD curl --fail http://localhost || exit 1 + +EXPOSE 80 diff --git a/docker-compose.prod.yaml b/docker-compose.prod.yaml new file mode 100644 index 0000000..66a4847 --- /dev/null +++ b/docker-compose.prod.yaml @@ -0,0 +1,45 @@ +version: "3.8" + +services: + website: + networks: + - default + - caddy_website + container_name: website + build: . + pull_policy: build + restart: unless-stopped + depends_on: + - db + environment: + # Defaults are specified in restart.py + - DATABASE_USERNAME=${DATABASE_USERNAME} # Username and password are also the default admin credentials + - DATABASE_PASSWORD=${MARIADB_PASSWORD} + - DATABASE_NAME=website + - DATABASE_HOST=website-db + - DATABASE_PORT=3306 + - WEBSITE_DEVELOPER=false + - MATOMO_DOMAIN=${MATOMO_DOMAIN} + - MATOMO_SITE_ID=${MATOMO_SITE_ID} + - TURNSTILE_SECRET=${TURNSTILE_SECRET} + - TURNSTILE_SITEKEY=${TURNSTILE_SITEKEY} + - TMDB_API_KEY=${TMDB_API_KEY} + db: + networks: + - default + image: mariadb:latest + container_name: website-db + restart: unless-stopped + volumes: + - /pool/website:/var/lib/mysql + environment: + - MARIADB_RANDOM_ROOT_PASSWORD=true + - MARIADB_DATABASE=website + - MARIADB_USER=${DATABASE_USERNAME} + - MARIADB_PASSWORD=${MARIADB_PASSWORD} + - MARIADB_PORT=3306 + +networks: + caddy_website: + external: true + default: diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..ec3cd4a --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,50 @@ +version: "3.8" + +services: + website: + networks: + - default + container_name: website-dev + build: . + pull_policy: build + restart: unless-stopped + depends_on: + - db + ports: + - "80:80" + volumes: + - ./html:/var/www/html + - ./python:/var/www/python + environment: + # Defaults are specified in restart.py + - DATABASE_USERNAME=${DATABASE_USERNAME:-admin} + - DATABASE_PASSWORD=password + - DATABASE_NAME=website + - DATABASE_HOST=website-db-dev + - DATABASE_PORT=3306 + - WEBSITE_DEVELOPER=true + - MATOMO_DOMAIN=${MATOMO_DOMAIN:-} + - MATOMO_SITE_ID=${MATOMO_SITE_ID:-1} + - TURNSTILE_SECRET=${TURNSTILE_SECRET:-} + - TURNSTILE_SITEKEY=${TURNSTILE_SITEKEY:-} + - TMDB_API_KEY=${TMDB_API_KEY:-} + db: + networks: + - default + image: mariadb:latest + container_name: website-db-dev + restart: unless-stopped + volumes: + - db_data:/var/lib/mysql + environment: + - MARIADB_RANDOM_ROOT_PASSWORD=true + - MARIADB_DATABASE=website + - MARIADB_USER=${DATABASE_USERNAME:-admin} + - MARIADB_PASSWORD=password + - MARIADB_PORT=3306 + +networks: + default: + +volumes: + db_data: diff --git a/html/config.json.template b/html/config.json.template deleted file mode 100755 index acf7287..0000000 --- a/html/config.json.template +++ /dev/null @@ -1,2 +0,0 @@ -#REMOVE LINE 1 WHEN DONE - please fill out all details for the json file as a config and rename to config.json -{ "api": "youtube api key", "database": { "username": "", "name": "", "password": "", "backupLocation": Where the backups should be stored, "backupLength" : how long the backups should be stored }, "developer": true/false Reminder that there should be no quotation marks(This should be a boolean), "throttle":the amount of login requests allowed per time period, "throttleTime":The number of seconds allowed for the throttle time period, "fanStart" : Tells the pi when to start the fan, "fanStop": Tells the pi when to stop the fan, "turnstileSecret": A cloudflare turnstile key for login security, "turnstileClient" : A cloudflare turnstile key for login security, "TMDBApiKey": Api Key for themoviedb.org} \ No newline at end of file diff --git a/html/include/functions.php b/html/include/functions.php index 230997b..4afe981 100755 --- a/html/include/functions.php +++ b/html/include/functions.php @@ -82,12 +82,12 @@ function sanitize($value) # Used to sanitize a value very strictly } function dbConnect() { // Is used to connect to the database - $SERVERLOCATION = "localhost"; if (!file_exists($_SERVER["DOCUMENT_ROOT"] . "/config.json")) { exit(); } $jsonInfo = file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/config.json"); $jsonData = json_decode($jsonInfo, true); + $SERVERLOCATION = $jsonData["database"]["host"]; $DATA_USERNAME = $jsonData["database"]["username"]; $DATABASENAME = $jsonData["database"]["name"]; $PASSWORD = $jsonData["database"]["password"]; diff --git a/python/database.py b/python/database.py index e9e9583..a854a3c 100755 --- a/python/database.py +++ b/python/database.py @@ -2,7 +2,6 @@ import mysql.connector as mysql import os import json -import time def readFile( @@ -33,32 +32,13 @@ def connect(database=""): ) if not database: database = dbInfo["database"]["name"] - try: - db = mysql.connect( - host="localhost", - passwd=dbInfo["database"]["password"], - user=dbInfo["database"]["username"], - database=database, - ) - except: # Used to automatically create the user and database - path = __file__[: __file__.rindex("/") + 1] - with open(path + "fix.sql") as f: - text = f.read() - text = text.replace("{username}", dbInfo["database"]["username"]) - text = text.replace("{password}", dbInfo["database"]["password"]) - text = text.replace("{database}", dbInfo["database"]["name"]) - with open(path + "fix2.sql", "w") as f: - f.write(text) - os.system(f"mysql < {path}fix2.sql") - os.remove(path + "fix2.sql") - print("Created the user for the database", time.time()) - db = mysql.connect( - host="localhost", - passwd=dbInfo["database"]["password"], - user=dbInfo["database"]["username"], - database=database, - ) - appendValue("log", ["9", "Created the user for the database", str(time.time())]) + db = mysql.connect( + host=dbInfo["database"]["host"], + password=dbInfo["database"]["password"], + user=dbInfo["database"]["username"], + database=database, + port=dbInfo["database"]["port"], + ) cursor = db.cursor() return db, cursor @@ -118,11 +98,13 @@ def backUp(fileName): password = dbInfo["database"]["password"] database = dbInfo["database"]["name"] location = dbInfo["database"]["backupLocation"] + host = dbInfo["database"]["host"] + port = dbInfo["database"]["port"] locationdata = f"{location}/{fileName}" if not os.path.exists(location): os.system(f"mkdir {location}") os.system( - f"mysqldump -u {username} --password={password} --result-file={locationdata} {database}" + f"mysqldump -u {username} --host={host} --port={port} --password={password} --result-file={locationdata} {database}" ) diff --git a/python/requirements.txt b/python/requirements.txt new file mode 100755 index 0000000..705df36 --- /dev/null +++ b/python/requirements.txt @@ -0,0 +1,2 @@ +mysql-connector-python +requests \ No newline at end of file diff --git a/python/restart.py b/python/restart.py index 72c1a54..c247f32 100755 --- a/python/restart.py +++ b/python/restart.py @@ -10,23 +10,34 @@ import datetime import sys import glob import string + whitelist = set(string.ascii_letters + string.digits + "/" + "@" + "." + "-" + "_") -def sanitize(txt): # Is a very simple sanitizer that allows all ascii_letters numbers and the / and @ - if type(txt) == type(1) or type(txt) == type(True): # Makes sure that if it is an int or a bool it will not be sanitized because that is not neccessary. + +def sanitize( + txt, +): # Is a very simple sanitizer that allows all ascii_letters numbers and the / and @ + if type(txt) == type(1) or type(txt) == type( + True + ): # Makes sure that if it is an int or a bool it will not be sanitized because that is not neccessary. return txt else: - return ''.join([ch for ch in txt if ch in whitelist]) + return "".join([ch for ch in txt if ch in whitelist]) + def error(e): - return "".join(traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__)) + return "".join( + traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__) + ) -def temp(): # Returns the temprature of the RPI +def temp(): # Returns the temprature of the RPI return readFile("/sys/class/thermal/thermal_zone0/temp") / 1000 -def writeFile(location, info, permission=True): # Will write info in json format to a file +def writeFile( + location, info, permission=True +): # Will write info in json format to a file with open(location, "w") as f: json.dump(info, f) if permission: @@ -38,6 +49,7 @@ def readFile(location): with open(location) as f: return json.load(f) + try: # Looks at the configuration at understands the config try: @@ -47,34 +59,39 @@ try: os.system("chown -R root:root " + configFilePath) configFilePath = configFilePath + "config.json" # Will find the location where the config should be located. - location = __file__[: __file__.rindex("/python/restart.py") + 1] + "html/" + location = __file__[: __file__.rindex("/python/restart.py") + 1] + "html" # Creates config with the enviromental variables - if os.getenv("WEBSITE_DEVELOPER", "false") == "true": - developmentMachine = True - else: - developmentMachine = False + developmentMachine = os.getenv("WEBSITE_DEVELOPER", "false") == "true" # This stores a list for the default config envConfiguration = [ - [["passwordOptions", "cost"], int(os.getenv("PASSWORD_ROUNDS", '10'))], + [["passwordOptions", "cost"], int(os.getenv("PASSWORD_ROUNDS", "10"))], [["mail", "server"], os.getenv("MAIL_SMTP_SERVER", "smtp.sendgrid.net")], [["mail", "username"], os.getenv("MAIL_USERNAME", "apikey")], [["mail", "password"], os.getenv("MAIL_PASSWORD", "none")], [["mail", "port"], int(os.getenv("MAIL_SMTP_PORT", "587"))], - [["database", "username"], os.getenv("WEBSITE_USER", "admin")], - [["database", "name"], os.getenv("WEBSITE_DATABASE_TABLE", "website")], - [["database", "password"], os.getenv("WEBSITE_PASSWORD", "password")], - [["database", "backupLocation"], os.getenv("WEBSITE_BACKUP_LOCATION", "/backup")], - [["database", "backupLength"], int(os.getenv("WEBSITE_BACKUP_LENGTH", "604800"))], + [["database", "username"], os.getenv("DATABASE_USERNAME", "admin")], + [["database", "name"], os.getenv("DATABASE_NAME", "website")], + [["database", "password"], os.getenv("DATABASE_PASSWORD", "password")], + [["database", "host"], os.getenv("DATABASE_HOST", "localhost")], + [["database", "port"], int(os.getenv("DATABASE_PORT", "3306"))], + [ + ["database", "backupLocation"], + os.getenv("WEBSITE_BACKUP_LOCATION", "/backup"), + ], + [ + ["database", "backupLength"], + int(os.getenv("WEBSITE_BACKUP_LENGTH", "604800")), + ], [["developer"], developmentMachine], [["throttle"], int(os.getenv("WEBSITE_THROTTLE", "5"))], - [["throttleTime"], int(os.getenv("WEBSITE_THROTTLE_TIME", '30'))], - [["fanStart"], int(os.getenv("WEBSITE_FAN_START", '43'))], - [["fanStop"], int(os.getenv("WEBSITE_FAN_STOP", '35'))], - [["matomoDomain"], os.getenv("MATOMO_DOMAIN", 'example.com')], - [["matomoSiteId"], int(os.getenv("MATOMO_SITE_ID", '1'))], - [["turnstileSecret"], os.getenv("TURNSTILE_SECRET", '')], - [["turnstileSitekey"], os.getenv("TURNSTILE_SITEKEY", '')], - [["TMDBApiKey"], os.getenv("TMDB_API_KEY", '')], + [["throttleTime"], int(os.getenv("WEBSITE_THROTTLE_TIME", "30"))], + [["fanStart"], int(os.getenv("WEBSITE_FAN_START", "43"))], + [["fanStop"], int(os.getenv("WEBSITE_FAN_STOP", "35"))], + [["matomoDomain"], os.getenv("MATOMO_DOMAIN", "example.com")], + [["matomoSiteId"], int(os.getenv("MATOMO_SITE_ID", "1"))], + [["turnstileSecret"], os.getenv("TURNSTILE_SECRET", "")], + [["turnstileSitekey"], os.getenv("TURNSTILE_SITEKEY", "")], + [["TMDBApiKey"], os.getenv("TMDB_API_KEY", "")], ] if os.path.exists(location + "/config.json"): configuration = readFile(location + "/config.json") @@ -99,11 +116,13 @@ try: # Checks if the key value pair exists or if it has to be created and the enviromental variable value has to be used if x[0][0] in configuration: if x[0][1] in configuration[x[0][0]]: - configuration[x[0][0]][x[0][1]] = sanitize(configuration[x[0][0]][x[0][1]]) + configuration[x[0][0]][x[0][1]] = sanitize( + configuration[x[0][0]][x[0][1]] + ) else: configuration[x[0][0]][x[0][1]] = sanitize(x[1]) else: - configuration[x[0][0]] = {x[0][1] : sanitize(x[1])} + configuration[x[0][0]] = {x[0][1]: sanitize(x[1])} except: print("Failed sanitizing the config") raise Exception @@ -121,6 +140,7 @@ try: ): # Imports this library in a slow way because it is a pain and likes to not work try: import database + break except: continue @@ -176,8 +196,7 @@ try: return time2 def buttonPress(status): # Will run this script everytime the button is pressed - minimum = database.search( - "internet", "id=(SELECT MIN(id) FROM internet)") + minimum = database.search("internet", "id=(SELECT MIN(id) FROM internet)") minimum = int(minimum[5]) - 1 if minimum == 0: minimum = -1 @@ -190,10 +209,10 @@ try: else: writeLog("Internet Schedule changed to on due to button", 5) database.appendValue( - "internet", ["2", "1", "2", "1", str( - time.time() + 3600), str(minimum)] + "internet", ["2", "1", "2", "1", str(time.time() + 3600), str(minimum)] ) - def backupDatabase(): # Used to backup the database + + def backupDatabase(): # Used to backup the database timeData = callTime() month = timeData[0] day = timeData[1] @@ -203,9 +222,12 @@ try: file = f"{int(time.time())}or{month}-{day}-{year}at{hour}:{minute}.sql" database.backUp(file) return file + def dailyMaintenance(): # Will run daily and on boot try: - if not os.path.isfile(location + "restore.json"): # Makes sure that it does not disrupt a restore + if not os.path.isfile( + location + "restore.json" + ): # Makes sure that it does not disrupt a restore file = backupDatabase() writeLog(f"Ran backup on server and saved it to {file}", 18) else: @@ -216,10 +238,13 @@ try: backupLocation = configuration["database"]["backupLocation"] files = glob.glob(f"{backupLocation}/*.sql") for x in range(len(files)): - files[x] = files[x][len(backupLocation)+1:] + files[x] = files[x][len(backupLocation) + 1 :] for x in files: try: - if int(x[:x.find("or")]) < time.time() - configuration["database"]["backupLength"]: + if ( + int(x[: x.find("or")]) + < time.time() - configuration["database"]["backupLength"] + ): os.remove(f"{backupLocation}/{x}") writeLog(f"Removed old backup due to age, named {x}", 20) except: @@ -227,7 +252,7 @@ try: # Gets a list of all backups to store in a file for easier access. files = glob.glob(f"{backupLocation}/*.sql") for x in range(len(files)): - files[x] = files[x][len(backupLocation)+1:] + files[x] = files[x][len(backupLocation) + 1 :] files.sort(reverse=True) writeFile(location + "/backups.json", files) # Will repair all databases and update them @@ -237,13 +262,23 @@ try: for x in repaired: writeLog(f"Database {x} was corrupted/missing and was restored", 9) # Will clean the golf games database - deleted = database.trueSearch(f"SELECT ID FROM golfGame WHERE turnStartTime<{time.time()-86400}") + deleted = database.trueSearch( + f"SELECT ID FROM golfGame WHERE turnStartTime<{time.time()-86400}" + ) for x in deleted: writeLog(f"Game #{x[0]} deleted because it is too old", 16) - database.command(f"DELETE FROM golfGame WHERE turnStartTime<{time.time()-86400}") # Removes games that have not been touched for more than 24 hours - database.command("DELETE FROM golfGamePlayers WHERE NOT EXISTS (SELECT * FROM golfGame WHERE golfGamePlayers.gameID = golfGame.ID)") # Removes players from games that do not exist - database.command("DELETE FROM golfGameCards WHERE NOT EXISTS (SELECT * FROM golfGame WHERE golfGameCards.gameID = golfGame.ID)") # Removes players from games that do not exist - database.command(f"DELETE FROM cookieClicker WHERE lastUpdate<{(time.time()-86400*30)*1000}") # Removes cookie clicker data that has not been touched for a month + database.command( + f"DELETE FROM golfGame WHERE turnStartTime<{time.time()-86400}" + ) # Removes games that have not been touched for more than 24 hours + database.command( + "DELETE FROM golfGamePlayers WHERE NOT EXISTS (SELECT * FROM golfGame WHERE golfGamePlayers.gameID = golfGame.ID)" + ) # Removes players from games that do not exist + database.command( + "DELETE FROM golfGameCards WHERE NOT EXISTS (SELECT * FROM golfGame WHERE golfGameCards.gameID = golfGame.ID)" + ) # Removes players from games that do not exist + database.command( + f"DELETE FROM cookieClicker WHERE lastUpdate<{(time.time()-86400*30)*1000}" + ) # Removes cookie clicker data that has not been touched for a month writeLog("Server maintenance ran succesfully.", 12) # Makes sure that the vendor folder is blocked try: @@ -251,22 +286,22 @@ try: except: 1 with open(location + "vendor/.htaccess", "w") as f: - f.write("""Order allow,deny -Deny from all""") + f.write( + """Order allow,deny +Deny from all""" + ) - while True: # will wait until connected to internet + # Waits until the database is ready + while True: try: - urllib.request.urlopen("https://google.com") + db, cursor = database.connect() + cursor.close() + db.close() break - except Exception: - try: - urllib.request.urlopen("https://bing.com") - break - except Exception: - # Skips the waiting if development machine (So you don't have to wait 2 minutes for the booting) - if (developmentMachine): - break - continue + except Exception as e: + print(f"Database connection failed: {e}") + time.sleep(1) + continue # Runs stuff that runs every boot dailyMaintenance() # Will turn on the internet to make sure that it is on @@ -312,8 +347,7 @@ Deny from all""") os.remove(location + "maintenance-mode") lastBackup = callTime()[1] try: - minimum = database.search( - "internet", "id=(SELECT MIN(id) FROM internet)") + minimum = database.search("internet", "id=(SELECT MIN(id) FROM internet)") if not minimum: database.appendValue("internet", internetOnDeafult) minimum = internetOnDeafult @@ -347,21 +381,27 @@ Deny from all""") # Will check every 2 seconds if the button is pressed and when it is show it on the led and then wait another second to verify that it is an actual press while True: time.sleep(2) - if os.path.isfile(location + "restart.json"): # Used to restart the server + if os.path.isfile(location + "restart.json"): # Used to restart the server writeLog("Server is being restarted", 12) os.remove(location + "restart.json") os.system(f"python3 {__file__} restart") exit() - if os.path.isfile(location + "update.json"): # Used to update the server + if os.path.isfile(location + "update.json"): # Used to update the server writeLog("Server is being updated.", 19) os.remove(location + "update.json") - os.system(f"git --work-tree={location[:-6]} --git-dir={location[:-5]}.git reset --hard") - os.system(f"git --work-tree={location[:-6]} --git-dir={location[:-5]}.git pull > {location}updateInfo.log") + os.system( + f"git --work-tree={location[:-6]} --git-dir={location[:-5]}.git reset --hard" + ) + os.system( + f"git --work-tree={location[:-6]} --git-dir={location[:-5]}.git pull > {location}updateInfo.log" + ) os.system(f"{location[:-5]}python/update.sh") os.system(f"composer --working-dir={location} update") os.system(f"chown www-data:www-data {location}updateInfo.log") writeLog("Server updated successfully.", 19) - if os.path.isfile(location + "restore.json"): # Used to restore a previous version of the database + if os.path.isfile( + location + "restore.json" + ): # Used to restore a previous version of the database try: file = readFile(location + "restore.json") f = open(location + "maintenance-mode", "w") @@ -371,7 +411,7 @@ Deny from all""") biggest = 0 for x in backups: try: - check = int(x[:x.find("or")]) + check = int(x[: x.find("or")]) if check > biggest: biggest = check file = x @@ -387,7 +427,7 @@ Deny from all""") writeLog(f"Backup {file} was succesfully restored", 18) except: writeLog(f"Restore for {file} failed", 9) - #Makes sure to clean up after it is done + # Makes sure to clean up after it is done try: os.remove(location + "restore.json") except: @@ -416,4 +456,4 @@ except Exception as e: except Exception: print("crash") while True: - time.sleep(1) \ No newline at end of file + time.sleep(1) diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..bc8f6bd --- /dev/null +++ b/start.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e + + +# Start Apache in the foreground +apache2ctl -D FOREGROUND & + +# Run restart.py in the foreground +python3 /var/www/python/restart.py \ No newline at end of file