From 9a8f33f0b4cd10c1ab1585b8b097a776b06ced7e Mon Sep 17 00:00:00 2001 From: Adam JOLY Date: Fri, 17 Jan 2025 16:49:53 +0100 Subject: [PATCH] =?UTF-8?q?=E3=80=8C=E2=9C=A8=E3=80=8D=20feat:=20Should=20?= =?UTF-8?q?be=20working?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 14 ++ srcs/cmd/nginx/entrypoint/entrypoint.go | 175 ++++++++++++++++++ srcs/configs/nginx/entry/cert-gen.sh | 9 + srcs/configs/nginx/ff.conf | 19 -- .../configs/nginx/templates/www.conf.template | 26 +++ srcs/docker-compose.yml | 19 +- srcs/docker/mariadb/Dockerfile | 2 +- srcs/docker/nginx/Dockerfile | 31 +++- srcs/docker/nginx/docker-healthcheck.sh | 3 - .../wp.conf => docker/nginx/health.conf} | 7 +- srcs/docker/nginx/nginx-health.conf | 33 ---- srcs/docker/wordpress/Dockerfile | 2 +- srcs/go.mod | 3 +- srcs/go.sum | 2 + srcs/internal/env/env_util.go | 6 +- 15 files changed, 272 insertions(+), 79 deletions(-) create mode 100644 srcs/cmd/nginx/entrypoint/entrypoint.go create mode 100755 srcs/configs/nginx/entry/cert-gen.sh delete mode 100644 srcs/configs/nginx/ff.conf create mode 100644 srcs/configs/nginx/templates/www.conf.template delete mode 100644 srcs/docker/nginx/docker-healthcheck.sh rename srcs/{configs/nginx/wp.conf => docker/nginx/health.conf} (54%) delete mode 100644 srcs/docker/nginx/nginx-health.conf create mode 100644 srcs/go.sum diff --git a/Makefile b/Makefile index 8774b98..30c4585 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,9 @@ DOCKERFILE_DB := $(DOCKER_CONTEXT)$(DOCKER_FOLDER)/$(DB_SERVER_NAME)/Dockerfile DOCKERFILE_WEVSRV := $(DOCKER_CONTEXT)$(DOCKER_FOLDER)/$(WEB_SERVER_NAME)/Dockerfile DOCKERFILE_CMS := $(DOCKER_CONTEXT)$(DOCKER_FOLDER)/$(CMS_NAME)/Dockerfile +all: + docker compose -f $(DOCKER_CONTEXT)docker-compose.yml up -d --build + build-db: docker build -f $(DOCKERFILE_DB) -t $(DB_SERVER_NAME) $(DOCKER_CONTEXT) @@ -26,6 +29,15 @@ start-nginx: start-wordp: docker compose -f $(DOCKER_CONTEXT)docker-compose.yml up wordpress-php --build +stop: + docker compose -f $(DOCKER_CONTEXT)docker-compose.yml stop + +clean: stop + docker system prune + +fclean: clean + docker system prune -a + clean-db: docker stop inception-db docker container rm inception-db @@ -43,4 +55,6 @@ clean-nginx: docker container rm inception-nginx docker image rm inception-nginx +re: clean all + .PHONY: cms-build db-build websrv-build clean-db clean-nginx diff --git a/srcs/cmd/nginx/entrypoint/entrypoint.go b/srcs/cmd/nginx/entrypoint/entrypoint.go new file mode 100644 index 0000000..16ea957 --- /dev/null +++ b/srcs/cmd/nginx/entrypoint/entrypoint.go @@ -0,0 +1,175 @@ +package main + +import ( + "bytes" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "strings" + + "git.keyzox.me/42_adjoly/inception/internal/env" + "git.keyzox.me/42_adjoly/inception/internal/log" + "golang.org/x/sys/unix" +) + +func addStreamConf(confFile, stream_output_dir string) { + confBlock := "stream {\n include +" + stream_output_dir + "/*.conf;\n}" + + reg, err := regexp.Compile("\\s*stream\\s*\\{") + if err != nil { + log.Fatal(err) + } + content, err := os.ReadFile(confFile) + if err != nil { + log.Fatal(err) + } + if reg.MatchString(string(content)) == true { + _log.Log("note", "Stream block already present in "+confFile) + return + } + file, err := os.OpenFile(confFile, os.O_APPEND|os.O_WRONLY, 0) + if err != nil { + log.Fatal(err) + } + defer file.Close() + file.WriteString(confBlock) + _log.Log("note", "Added stream block in config") +} + +func streamTemplate(template_dir, stream_suffix string) { + stream_output_dir := env.EnvCheck("NGINX_ENVSUBST_STREAM_OUTPUT_DIR", "/etc/nginx/stream-conf.d") + + os.Mkdir(stream_output_dir, 0755) + if unix.Access(stream_output_dir, unix.W_OK) != nil { + _log.Log("error", "Stream template output directory not writable "+stream_output_dir) + } + + dir, err := os.ReadDir(template_dir) + + if err != nil { + _log.Log("error", "Error reading "+template_dir+" folder") + } + addStreamConf("/etc/nginx/nginx.conf", stream_output_dir) + _log.Log("note", "Loading stream templates...") + for _, v := range dir { + reg, err := regexp.Compile(stream_suffix + "$") + if err != nil { + log.Fatal(err) + } + if reg.MatchString(v.Name()) == true { + if v.IsDir() == false { + path := filepath.Join(template_dir, v.Name()) + content, err := os.ReadFile(path) + if err != nil { + _log.Log("warn", "Can't read file : "+v.Name()) + continue + } + cmd := exec.Command("envsubst") + cmd.Stdin = bytes.NewReader(content) + finalFile, err := os.Create(strings.TrimSuffix(stream_output_dir+"/"+v.Name(), stream_suffix)) + if err != nil { + log.Fatal(err) + } + cmd.Stdout = finalFile + } + } + } + _log.Log("note", "Stream template loaded !") +} + +func subStTemplate() { + template_dir := env.EnvCheck("NGINX_ENVSUBST_TEMPLATE_DIR", "/etc/nginx/templates") + template_suffix := env.EnvCheck("NGINX_ENVSUBST_TEMPLATE_SUFFIX", ".template") + stream_suffix := env.EnvCheck("NGINX_ENVSUBST_STREAM_TEMPLATE_SUFFIX", ".stream-template") + output_dir := env.EnvCheck("NGINX_ENVSUBST_OUTPUT_DIR", "/etc/nginx/http.d") + + unix.Access(template_dir, unix.W_OK) + unix.Access(output_dir, unix.W_OK) + + dir, err := os.ReadDir(template_dir) + + if err != nil { + _log.Log("error", "Error reading "+template_dir+" folder") + } + _log.Log("note", "Loading templates...") + for _, v := range dir { + reg, err := regexp.Compile(template_suffix + "$") + if err != nil { + log.Fatal(err) + } + if reg.MatchString(v.Name()) == true { + if v.IsDir() == false { + path := filepath.Join(template_dir, v.Name()) + content, err := os.ReadFile(path) + if err != nil { + _log.Log("warn", "Can't read file : "+v.Name()) + continue + } + cmd := exec.Command("envsubst") + cmd.Stdin = bytes.NewReader(content) + finalFile, err := os.Create(strings.TrimSuffix(output_dir+"/"+v.Name(), template_suffix)) + if err != nil { + log.Fatal(err) + } + cmd.Stdout = finalFile + if err := cmd.Run(); err != nil { + log.Fatal(err) + } + } + } + } + _log.Log("note", "Template loaded !") + i := 0 + + reg, err := regexp.Compile(stream_suffix + "$") + for _, v := range dir { + if reg.MatchString(v.Name()) { + i++; + } + } + if i == 0 { + _log.Log("note", "No stream template found, skipping...") + return + } + streamTemplate(template_dir, stream_suffix) +} + +func main() { + args := os.Args + + if args[1] == "nginx" || args[1] == "nginx-debug" { + _log.Log("note", "Entrypoint script for NGINX Server started") + + subStTemplate() + + dir, err := os.ReadDir("/docker-entrypoint.d") + if err != nil { + log.Fatal(err) + } + _log.Log("note", "Running entrypoint scripts") + for _, v := range dir { + os.Chmod("/docker-entrypoint.d/" + v.Name(), 0755) + cmd := exec.Command("/docker-entrypoint.d/" + v.Name()) + cmd.Env = os.Environ() + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin + if err := cmd.Run(); err != nil { + fmt.Printf("Error running script(%s): %v\n", v.Name(), err) + os.Exit(1) + } + } + _log.Log("note", "Starting NGINX") + } + cmd := exec.Command(args[1], args[2:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin + if err := cmd.Run(); err != nil { + fmt.Printf("Error running NGINX: %v\n", err) + os.Exit(1) + } +} diff --git a/srcs/configs/nginx/entry/cert-gen.sh b/srcs/configs/nginx/entry/cert-gen.sh new file mode 100755 index 0000000..bee7c43 --- /dev/null +++ b/srcs/configs/nginx/entry/cert-gen.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +if [ ! -f ${NGINX_SSL_KEY_FILE} ]; then + echo "Generating certs" + mkdir -p /etc/nginx/ssl + openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${NGINX_SSL_KEY_FILE} -out ${NGINX_SSL_CERT_FILE} -subj "/C=FR/ST=IDF/L=Angouleme/O=42/OU=42/CN=adjoly.42.fr/UID=adjoly" +else + printf "Key already exist not recreating\n" +fi diff --git a/srcs/configs/nginx/ff.conf b/srcs/configs/nginx/ff.conf deleted file mode 100644 index 481aa8a..0000000 --- a/srcs/configs/nginx/ff.conf +++ /dev/null @@ -1,19 +0,0 @@ -server { - listen 80; - - server_name adjoly.42.fr; - root /var/www/html; - - index index.php index.html index.htm; - - location / { - try_files $uri $uri/ /index.php?$args; - } - - location ~ \.php$ { - include fastcgi_params; - fastcgi_pass php-fpm:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - } -} diff --git a/srcs/configs/nginx/templates/www.conf.template b/srcs/configs/nginx/templates/www.conf.template new file mode 100644 index 0000000..34b45a3 --- /dev/null +++ b/srcs/configs/nginx/templates/www.conf.template @@ -0,0 +1,26 @@ +server { + listen 443 ssl; + + server_name adjoly.42.fr www.adjoly.42.fr; + + root /var/www/html/; + index index.php; + + ssl_certificate $NGINX_SSL_CERT_FILE; + ssl_certificate_key $NGINX_SSL_KEY_FILE; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_session_timeout 10m; + + keepalive_timeout 60; + + location / { + try_files $uri $uri/ =404; + } + + location ~ \.php$ { + include fastcgi.conf; + fastcgi_pass $NGINX_PHP_HOST:9000; + fastcgi_index index.php; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + } +} diff --git a/srcs/docker-compose.yml b/srcs/docker-compose.yml index 297399f..82a1436 100644 --- a/srcs/docker-compose.yml +++ b/srcs/docker-compose.yml @@ -13,18 +13,26 @@ services: container_name: inception-nginx build: context: . - dockerfile: docker/nginx/dockerfile + dockerfile: docker/nginx/Dockerfile networks: - inception environment: - TZ=Europe/Paris + - NGINX_PHP_HOST=inception-wordp-php + - NGINX_SSL_KEY_FILE=/etc/nginx/ssl/adjoly-wp.key + - NGINX_SSL_CERT_FILE=/etc/nginx/ssl/adjoly-wp.crt depends_on: - - wordpress-php - - db + wordpress-php: + condition: service_started + db: + condition: service_started volumes: - wp-site:/var/www/html + - ./configs/nginx/templates:/etc/nginx/templates + - ./configs/nginx/entry:/docker-entrypoint.d ports: - - "443:443" + - "8443:443" + - "8080:80" restart: unless-stopped wordpress-php: @@ -34,6 +42,9 @@ services: dockerfile: docker/wordpress/Dockerfile networks: - inception + depends_on: + db: + condition: service_started environment: - PHP_MEMORY_LIMIT="512M" - PHP_MAX_UPLOAD="50M" diff --git a/srcs/docker/mariadb/Dockerfile b/srcs/docker/mariadb/Dockerfile index b2e5ce4..2e093c6 100644 --- a/srcs/docker/mariadb/Dockerfile +++ b/srcs/docker/mariadb/Dockerfile @@ -39,4 +39,4 @@ WORKDIR /var/lib/mysql EXPOSE 3306 CMD [ "mariadbd", "--user=mysql" ] -HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD /docker-healthcheck +HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=1s --start-interval=2s CMD /docker-healthcheck diff --git a/srcs/docker/nginx/Dockerfile b/srcs/docker/nginx/Dockerfile index 505467d..7562023 100644 --- a/srcs/docker/nginx/Dockerfile +++ b/srcs/docker/nginx/Dockerfile @@ -4,22 +4,37 @@ ADD docker/alpine/alpine-minirootfs-3.21.2-x86_64.tar.gz / LABEL version="0.1" LABEL maintainer="KeyZox" +COPY go.mod /build/go.mod +COPY cmd /build/cmd +COPY internal /build/internal + RUN set -x \ && addgroup -g 101 -S nginx\ && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \ - && apk add --no-cache nginx tzdata \ + && apk add --no-cache go nginx openssl tzdata envsubst curl \ + && cd /build \ + && go get git.keyzox.me/42_adjoly/inception/cmd/nginx/entrypoint \ + && go build git.keyzox.me/42_adjoly/inception/cmd/nginx/entrypoint \ + && cp /build/entrypoint /docker-entrypoint \ + && chmod +x /docker-entrypoint \ + && apk del go \ && ln -sf /dev/stdout /var/log/nginx/access.log \ - && ln -sf /dev/stderr /var/log/nginx/error.log + && ln -sf /dev/stderr /var/log/nginx/error.log \ + && rm -Rf /build \ + && rm -rf /var/cache/apk/* \ + && mkdir -p /var/www/html \ + && mkdir -p /etc/nginx/conf.d \ + && mkdir /docker-entrypoint.d -VOLUME /etc/nginx -RUN mkdir -p /etc/nginx/sites-available - -COPY docker-healthcheck.sh /docker-healthcheck.sh -RUN chmod +x /docker-healthcheck.sh +VOLUME /etc/nginx/templates +VOLUME /docker-entrypoint.d +COPY docker/nginx/health.conf /etc/nginx/http.d/health.conf +ENTRYPOINT [ "/docker-entrypoint" ] WORKDIR /etc/nginx + STOPSIGNAL SIGQUIT EXPOSE 80 CMD [ "nginx", "-g", "daemon off;" ] -HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD /docker-healthcheck.sh +HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=1s --start-interval=2s CMD curl http://127.0.0.1:80/health || exit 1 diff --git a/srcs/docker/nginx/docker-healthcheck.sh b/srcs/docker/nginx/docker-healthcheck.sh deleted file mode 100644 index 9709d3a..0000000 --- a/srcs/docker/nginx/docker-healthcheck.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -curl -f http://localhost/health || exit 1 diff --git a/srcs/configs/nginx/wp.conf b/srcs/docker/nginx/health.conf similarity index 54% rename from srcs/configs/nginx/wp.conf rename to srcs/docker/nginx/health.conf index bfa756a..c8da809 100644 --- a/srcs/configs/nginx/wp.conf +++ b/srcs/docker/nginx/health.conf @@ -1,10 +1,5 @@ server { - listen 80; - - location / { - root /usr/share/nginx/html; - index index.html index.htm; - } + listen 127.0.0.1:80; location /health { access_log off; diff --git a/srcs/docker/nginx/nginx-health.conf b/srcs/docker/nginx/nginx-health.conf deleted file mode 100644 index 3137041..0000000 --- a/srcs/docker/nginx/nginx-health.conf +++ /dev/null @@ -1,33 +0,0 @@ -user nginx; -worker_processes 1; - -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx/nginx.pid; - -events { - worker_connections 1024; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - sendfile on; - access_log /var/log/nginx/access.log; - keepalive_timeout 3000; - server { - listen 80; - root /www; - index index.php index.html index.htm; - server_name localhost; - client_max_body_size 32m; - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /var/lib/nginx/html; - } - location ~ \.php$ { - fastcgi_pass 127.0.0.1:9000; - fastcgi_index index.php; - include fastcgi.conf; - } - } -} diff --git a/srcs/docker/wordpress/Dockerfile b/srcs/docker/wordpress/Dockerfile index 3a64785..e1096f3 100644 --- a/srcs/docker/wordpress/Dockerfile +++ b/srcs/docker/wordpress/Dockerfile @@ -46,4 +46,4 @@ STOPSIGNAL SIGQUIT EXPOSE 9000 CMD [ "php-fpm84", "-F" ] -HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1 +HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=1s --start-interval=2s CMD cgi-fcgi -bind -connect 127.0.0.1:${PHP_PORT:-9000} || exit 1 diff --git a/srcs/go.mod b/srcs/go.mod index ca06097..37e1a23 100644 --- a/srcs/go.mod +++ b/srcs/go.mod @@ -2,5 +2,4 @@ module git.keyzox.me/42_adjoly/inception go 1.23.4 -require ( -) +require golang.org/x/sys v0.29.0 // indirect diff --git a/srcs/go.sum b/srcs/go.sum new file mode 100644 index 0000000..0664caa --- /dev/null +++ b/srcs/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/srcs/internal/env/env_util.go b/srcs/internal/env/env_util.go index 56e5d49..350a648 100644 --- a/srcs/internal/env/env_util.go +++ b/srcs/internal/env/env_util.go @@ -7,7 +7,8 @@ import ( "git.keyzox.me/42_adjoly/inception/internal/log" ) -func FileEnv(Value string, Default string) string { +// Check if the "Value" exist in the env if not check if a "Value_FILE" exist and if still not just return default value +func FileEnv(Value, Default string) string { val, is := os.LookupEnv(Value) if is { @@ -25,6 +26,7 @@ func FileEnv(Value string, Default string) string { return Default } +// Check if the "Value" exist in the env check if not just return default value func EnvCheck(Value, Default string) string { val, is := os.LookupEnv(Value) @@ -37,7 +39,7 @@ func EnvCheck(Value, Default string) string { func EscapeEnv(str string) string { if str[0] == '"' && str[len(str) - 1] == '"' { return strings.TrimPrefix(strings.TrimSuffix(str, "\""), "\"") - } else if str[0] == '"' && str[len(str) - 1] == '"' { + } else if str[0] == '\'' && str[len(str) - 1] == '\'' { return strings.TrimPrefix(strings.TrimSuffix(str, "'"), "'") } else { return str