diff --git a/autoconf/Dockerfile b/autoconf/Dockerfile index cbec6f9..8c4ac1e 100644 --- a/autoconf/Dockerfile +++ b/autoconf/Dockerfile @@ -1,9 +1,5 @@ -FROM nginx:1.20.1-alpine AS builder - FROM alpine -COPY --from=builder /etc/nginx/ /opt/confs/nginx - COPY autoconf/dependencies.sh /tmp RUN chmod +x /tmp/dependencies.sh && \ /tmp/dependencies.sh && \ diff --git a/autoconf/Dockerfile-amd64 b/autoconf/Dockerfile-amd64 index 7f6a385..8253bbb 100644 --- a/autoconf/Dockerfile-amd64 +++ b/autoconf/Dockerfile-amd64 @@ -1,9 +1,5 @@ -FROM nginx:1.20.1-alpine AS builder - FROM amd64/alpine -COPY --from=builder /etc/nginx/ /opt/confs/nginx - COPY autoconf/dependencies.sh /tmp RUN chmod +x /tmp/dependencies.sh && \ /tmp/dependencies.sh && \ diff --git a/autoconf/Dockerfile-arm32v7 b/autoconf/Dockerfile-arm32v7 index 7dfcd5b..e1dba48 100644 --- a/autoconf/Dockerfile-arm32v7 +++ b/autoconf/Dockerfile-arm32v7 @@ -3,12 +3,9 @@ FROM alpine AS builder ENV QEMU_URL https://github.com/balena-io/qemu/releases/download/v4.0.0%2Bbalena2/qemu-4.0.0.balena2-arm.tar.gz RUN apk add curl && curl -L ${QEMU_URL} | tar zxvf - -C . --strip-components 1 -FROM nginx:1.20.1-alpine AS builder2 - FROM arm32v7/alpine COPY --from=builder qemu-arm-static /usr/bin -COPY --from=builder2 /etc/nginx/ /opt/confs/nginx COPY autoconf/dependencies.sh /tmp RUN chmod +x /tmp/dependencies.sh && \ diff --git a/autoconf/Dockerfile-arm64v8 b/autoconf/Dockerfile-arm64v8 index cf19146..1d756b3 100644 --- a/autoconf/Dockerfile-arm64v8 +++ b/autoconf/Dockerfile-arm64v8 @@ -3,12 +3,9 @@ FROM alpine AS builder ENV QEMU_URL https://github.com/balena-io/qemu/releases/download/v4.0.0%2Bbalena2/qemu-4.0.0.balena2-aarch64.tar.gz RUN apk add curl && curl -L ${QEMU_URL} | tar zxvf - -C . --strip-components 1 -FROM nginx:1.20.1-alpine AS builder2 - FROM arm64v8/alpine COPY --from=builder qemu-aarch64-static /usr/bin -COPY --from=builder2 /etc/nginx/ /opt/confs/nginx COPY autoconf/dependencies.sh /tmp RUN chmod +x /tmp/dependencies.sh && \ diff --git a/autoconf/Dockerfile-i386 b/autoconf/Dockerfile-i386 index 0c7b578..9b788b0 100644 --- a/autoconf/Dockerfile-i386 +++ b/autoconf/Dockerfile-i386 @@ -1,9 +1,5 @@ -FROM nginx:1.20.1-alpine AS builder - FROM i386/alpine -COPY --from=builder /etc/nginx/ /opt/confs/nginx - COPY autoconf/dependencies.sh /tmp RUN chmod +x /tmp/dependencies.sh && \ /tmp/dependencies.sh && \ diff --git a/confs/global/mime.types b/confs/global/mime.types new file mode 100644 index 0000000..7c7cdef --- /dev/null +++ b/confs/global/mime.types @@ -0,0 +1,96 @@ +types { + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/javascript js; + application/atom+xml atom; + application/rss+xml rss; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + + font/woff woff; + font/woff2 woff2; + + application/java-archive jar war ear; + application/json json; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.ms-excel xls; + application/vnd.ms-fontobject eot; + application/vnd.ms-powerpoint ppt; + application/vnd.oasis.opendocument.graphics odg; + application/vnd.oasis.opendocument.presentation odp; + application/vnd.oasis.opendocument.spreadsheet ods; + application/vnd.oasis.opendocument.text odt; + application/vnd.openxmlformats-officedocument.presentationml.presentation + pptx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + xlsx; + application/vnd.openxmlformats-officedocument.wordprocessingml.document + docx; + application/vnd.wap.wmlc wmlc; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xspf+xml xspf; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mp2t ts; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; +} diff --git a/examples/web-ui/docker-compose.yml b/examples/web-ui/docker-compose.yml index 8eda5a7..40da258 100644 --- a/examples/web-ui/docker-compose.yml +++ b/examples/web-ui/docker-compose.yml @@ -29,6 +29,7 @@ services: - admin.website.com_USE_REVERSE_PROXY=yes - admin.website.com_REVERSE_PROXY_URL=/admin/ # change it to something hard to guess - admin.website.com_REVERSE_PROXY_HOST=http://myui:5000/ + - admin.website.com_USE_MODSECURITY=no labels: - "bunkerized-nginx.UI" diff --git a/gen/main.py b/gen/main.py index bf8701f..2780281 100755 --- a/gen/main.py +++ b/gen/main.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -import argparse, os, sys +import argparse, os, sys, shutil import utils from Configurator import Configurator @@ -51,6 +51,14 @@ if __name__ == "__main__" : config = configurator.get_config() print(config) + # Remove old config + for filename in os.listdir(args.output): + file_path = os.path.join(args.output, filename) + if os.path.isfile(file_path) or os.path.islink(file_path): + os.unlink(file_path) + elif os.path.isdir(file_path): + shutil.rmtree(file_path) + # Generate the files from templates and config templator = Templator(config, args.templates, args.output, args.target) templator.render_global() diff --git a/ui/Config.py b/ui/Config.py index 0172310..53ad683 100644 --- a/ui/Config.py +++ b/ui/Config.py @@ -1,4 +1,4 @@ -import json, uuid, glob, copy +import json, uuid, glob, copy, re, subprocess class Config : @@ -25,10 +25,16 @@ class Config : def __gen_conf(self, global_conf, services_conf) : conf = copy.deepcopy(global_conf) + servers = conf["SERVER_NAME"].split(" ") + if conf["SERVER_NAME"] == "" : + servers = [] for service in services_conf : first_server = service["SERVER_NAME"].split(" ")[0] + if not first_server in servers : + servers.append(first_server) for k, v in service.items() : conf[first_server + "_" + k] = v + conf["SERVER_NAME"] = " ".join(servers) env_file = "/tmp/" + str(uuid.uuid4()) + ".env" self.__dict_to_env(env_file, conf) proc = subprocess.run(["/bin/su", "-c", "/opt/gen/main.py --settings /opt/settings.json --templates /opt/confs --output /etc/nginx --variables " + env_file, "nginx"], capture_output=True) @@ -38,7 +44,7 @@ class Config : def get_settings(self) : return self.__settings - + def get_config(self) : return self.__env_to_dict("/etc/nginx/global.env") @@ -54,10 +60,10 @@ class Config : check = False for category in self.__settings : for param in self.__settings[category]["params"] : - if type != "multiple" : + if param["type"] != "multiple" : real_params = [param] else : - real_params = param + real_params = param["params"] for real_param in real_params : if k == real_param["env"] and real_param["context"] == "multisite" and re.search(real_param["regex"], v) : check = True @@ -72,10 +78,12 @@ class Config : raise Exception("Service " + service["SERVER_NAME"] + " already exists.") services.append(variables) self.__gen_conf(global_env, services) + return "Configuration for " + variables["SERVER_NAME"] + " has been generated." def edit_service(self, old_server_name, variables) : self.delete_service(old_server_name) self.new_service(variables) + return "Configuration for " + old_server_name + " has been edited." def delete_service(self, server_name) : @@ -90,5 +98,10 @@ class Config : new_services.append(service) if not found : raise Exception("Can't delete missing " + server_name + " configuration.") + new_servers = global_env["SERVER_NAME"].split(" ") + if server_name in new_servers : + new_servers.remove(server_name) + global_env["SERVER_NAME"] = " ".join(new_servers) self.__gen_conf(global_env, new_services) + return "Configuration for " + server_name + " has been deleted." diff --git a/ui/Dockerfile b/ui/Dockerfile index 9b8caf7..18329b4 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -1,9 +1,5 @@ -FROM nginx:1.20.1-alpine AS builder - FROM alpine -COPY --from=builder /etc/nginx/ /opt/confs/nginx - COPY ui/dependencies.sh /tmp RUN chmod +x /tmp/dependencies.sh && \ /tmp/dependencies.sh && \ @@ -11,6 +7,7 @@ RUN chmod +x /tmp/dependencies.sh && \ COPY gen/ /opt/gen COPY confs/site/ /opt/confs/site +COPY confs/global/ /opt/confs/global COPY ui/ /opt/entrypoint COPY settings.json /opt diff --git a/ui/Dockerfile-amd64 b/ui/Dockerfile-amd64 index d266435..6d6c663 100644 --- a/ui/Dockerfile-amd64 +++ b/ui/Dockerfile-amd64 @@ -1,9 +1,5 @@ -FROM nginx:1.20.1-alpine AS builder - FROM amd64/alpine -COPY --from=builder /etc/nginx/ /opt/confs/nginx - COPY ui/dependencies.sh /tmp RUN chmod +x /tmp/dependencies.sh && \ /tmp/dependencies.sh && \ @@ -11,6 +7,7 @@ RUN chmod +x /tmp/dependencies.sh && \ COPY gen/ /opt/gen COPY confs/site/ /opt/confs/site +COPY confs/global/ /opt/confs/global COPY ui/ /opt/entrypoint COPY settings.json /opt diff --git a/ui/Dockerfile-arm32v7 b/ui/Dockerfile-arm32v7 index c172e95..a069b38 100644 --- a/ui/Dockerfile-arm32v7 +++ b/ui/Dockerfile-arm32v7 @@ -1,14 +1,11 @@ -FROM alpine AS builder1 +FROM alpine AS builder ENV QEMU_URL https://github.com/balena-io/qemu/releases/download/v4.0.0%2Bbalena2/qemu-4.0.0.balena2-arm.tar.gz RUN apk add curl && curl -L ${QEMU_URL} | tar zxvf - -C . --strip-components 1 -FROM nginx:1.20.1-alpine AS builder2 - FROM arm32v7/alpine -COPY --from=builder1 qemu-arm-static /usr/bin -COPY --from=builder2 /etc/nginx/ /opt/confs/nginx +COPY --from=builder qemu-arm-static /usr/bin COPY ui/dependencies.sh /tmp RUN chmod +x /tmp/dependencies.sh && \ @@ -17,6 +14,7 @@ RUN chmod +x /tmp/dependencies.sh && \ COPY gen/ /opt/gen COPY confs/site/ /opt/confs/site +COPY confs/global/ /opt/confs/global COPY ui/ /opt/entrypoint COPY settings.json /opt diff --git a/ui/Dockerfile-arm64v8 b/ui/Dockerfile-arm64v8 index 755d965..b886aa2 100644 --- a/ui/Dockerfile-arm64v8 +++ b/ui/Dockerfile-arm64v8 @@ -1,14 +1,11 @@ -FROM alpine AS builder1 +FROM alpine AS builder ENV QEMU_URL https://github.com/balena-io/qemu/releases/download/v4.0.0%2Bbalena2/qemu-4.0.0.balena2-aarch64.tar.gz RUN apk add curl && curl -L ${QEMU_URL} | tar zxvf - -C . --strip-components 1 -FROM nginx:1.20.1-alpine AS builder2 - FROM arm64v8/alpine -COPY --from=builder1 qemu-aarch64-static /usr/bin -COPY --from=builder2 /etc/nginx/ /opt/confs/nginx +COPY --from=builder qemu-aarch64-static /usr/bin COPY ui/dependencies.sh /tmp RUN chmod +x /tmp/dependencies.sh && \ @@ -17,6 +14,7 @@ RUN chmod +x /tmp/dependencies.sh && \ COPY gen/ /opt/gen COPY confs/site/ /opt/confs/site +COPY confs/global/ /opt/confs/global COPY ui/ /opt/entrypoint COPY settings.json /opt diff --git a/ui/Dockerfile-i386 b/ui/Dockerfile-i386 index a61c1c2..e060bdf 100644 --- a/ui/Dockerfile-i386 +++ b/ui/Dockerfile-i386 @@ -1,9 +1,5 @@ -FROM nginx:1.20.1-alpine AS builder - FROM i386/alpine -COPY --from=builder /etc/nginx/ /opt/confs/nginx - COPY ui/dependencies.sh /tmp RUN chmod +x /tmp/dependencies.sh && \ /tmp/dependencies.sh && \ @@ -11,6 +7,7 @@ RUN chmod +x /tmp/dependencies.sh && \ COPY gen/ /opt/gen COPY confs/site/ /opt/confs/site +COPY confs/global/ /opt/confs/global COPY ui/ /opt/entrypoint COPY settings.json /opt diff --git a/ui/entrypoint.py b/ui/entrypoint.py index 7dc233e..1d746d8 100644 --- a/ui/entrypoint.py +++ b/ui/entrypoint.py @@ -5,7 +5,7 @@ from flask import Flask, render_template, current_app, request from Docker import Docker from Config import Config import utils -import os, json, re, traceback +import os, json, re, copy, traceback app = Flask(__name__, static_url_path="/", static_folder="static", template_folder="templates") ABSOLUTE_URI = "" @@ -76,7 +76,7 @@ def services(): raise Exception("Missing operation parameter on /services.") # Check variables - variables = copy.deepcopy(request.form) + variables = copy.deepcopy(request.form.to_dict()) if not "OLD_SERVER_NAME" in request.form and request.form["operation"] == "edit" : raise Exception("Missing OLD_SERVER_NAME parameter.") if request.form["operation"] in ["new", "edit"] : @@ -98,10 +98,14 @@ def services(): operation = app.config["CONFIG"].edit_service(request.form["OLD_SERVER_NAME"], variables) elif request.form["operation"] == "delete" : operation = app.config["CONFIG"].delete_service(request.form["SERVER_NAME"]) + + # Reload containers + for instance in app.config["DOCKER"].get_instances() : + app.config["DOCKER"].reload_instance(instance.id) # Display services services = app.config["CONFIG"].get_services() return render_template("services.html", title="Services", services=services, operation=operation) except Exception as e : - return render_template("error.html", title="Error", error=str(e) + traceback.format_exc()) \ No newline at end of file + return render_template("error.html", title="Error", error=str(e) + traceback.format_exc()) diff --git a/ui/templates/services-edit.html b/ui/templates/services-edit.html index 1c22dd8..f2352bf 100644 --- a/ui/templates/services-edit.html +++ b/ui/templates/services-edit.html @@ -24,9 +24,9 @@