diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..cbd769b --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,39 @@ +# woodpecker.yml +labels: + hostname: "macmini7" +clone: + git: + image: woodpeckerci/plugin-git + settings: + partial: false + depth: 1 +steps: + build-push: + name: build-push + when: + - path: + include: [ 'stack.yml','.woodpecker.yml', 'Dockerfile', 'docker-entrypoint.sh', 'nginx.conf.template', 'README.md' ] + image: woodpeckerci/plugin-docker-buildx + secrets: [REGISTRY_USER, REGISTRY_PASSWORD] + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + - echo compose up build + - docker compose build + - echo compose push + - docker compose push + - echo docker compose rm -f + - docker compose rm -f + deploy-config: + name: deploy-config + when: + - path: + include: [ 'stack.yml','.woodpecker.yml', 'Dockerfile', 'docker-entrypoint.sh', 'nginx.conf.template', 'README.md' ] + image: woodpeckerci/plugin-docker-buildx + secrets: [REGISTRY_USER, REGISTRY_PASSWORD] + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + - docker stack deploy --with-registry-auth -c ./stack.yml lan-to-nginx \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 7c8976c..7c6265b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,26 @@ -# Start from the official Nginx image +# Use the official NGINX image as a parent image FROM nginx:alpine -# Copy our custom Nginx configuration -COPY nginx.conf /etc/nginx/nginx.conf +# Set environment variables with default values +ENV BACKEND_HOST=git_git +ENV BACKEND_TCP_PORT=22 +ENV BACKEND_UDP_PORT=22 +# Set the default value of ALLOWED_IPS to cover typical Docker network ranges +# set this value to 0.0.0.0 in the Stack definition for allow all. +ENV ALLOWED_IPS="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16" +# Copy the script and configuration template into the container +COPY docker-entrypoint.sh /docker-entrypoint.sh +COPY nginx.conf.template /etc/nginx/nginx.conf.template +# Make the script executable +RUN chmod +x /docker-entrypoint.sh + +# HEALTHCHECK instruction using curl to check the health of the NGINX server +# Install curl, then set up the health check +RUN apk add --no-cache curl +HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ + CMD curl -f http://localhost:8080/healthz || exit 1 + +# Use the script as the entrypoint +ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..94efb93 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +### host-port-ingress-proxy + +1. **Docker Container Setup**: + - The Docker container is based on the official NGINX Alpine image. + - Several environment variables are defined in the Dockerfile to configure the NGINX reverse proxy. These include `BACKEND_HOST`, `BACKEND_TCP_PORT`, `BACKEND_UDP_PORT`, and `ALLOWED_IPS`. + - The Dockerfile also installs `curl` for health checking purposes and includes a custom entrypoint script. + +2. **NGINX Configuration**: + - A template for the NGINX configuration (`nginx.conf.template`) is used. This template is processed by the entrypoint script (`entrypoint.sh`) to replace placeholders with the actual environment variable values. + - The NGINX configuration sets up NGINX as a reverse proxy to forward TCP and UDP traffic to the configured backend host and ports. It also includes IP-based access control. + - Additionally, NGINX listens on a separate HTTP port (8080) with a specific location (`/healthz`) that always returns a `200 OK` response. This endpoint is used for health checks. + +3. **Health Checking**: + - The Dockerfile defines a `HEALTHCHECK` instruction that uses `curl` to periodically check the health of the NGINX server by accessing the `/healthz` endpoint. + - If the health check fails (does not return `200 OK`), Docker marks the container as unhealthy. + +4. **Running the Container**: + - When the container is run, the environment variables can be set to define the backend host, ports, and allowed IPs. + - Docker's health check mechanism monitors the container's health status by checking the `/healthz` endpoint. + +### Mermaid Diagram + +Here's a Mermaid diagram that visualizes the flow: + +```mermaid +graph LR + subgraph Docker Container + NGINX[NGINX Reverse Proxy] + ENTRYPOINT[Entrypoint Script] + CONFIG[nginx.conf.template] + HEALTHCHECK[Health Check] + + ENTRYPOINT -->|Processes| CONFIG + CONFIG -->|Configures| NGINX + NGINX -->|TCP/UDP Proxy| BACKEND[Backend Service] + NGINX -->|HTTP Health Check| HEALTHCHECK + HEALTHCHECK -->|curl /healthz| NGINX + end + + USER[User] -->|TCP/UDP Request| NGINX + NGINX -->|Responds| USER + DOCKER[Docker Daemon] -->|Periodic Check| HEALTHCHECK + + style NGINX fill:#f96,stroke:#333,stroke-width:2px + style BACKEND fill:#ff9,stroke:#333,stroke-width:2px + style USER fill:#9f6,stroke:#333,stroke-width:2px + style HEALTHCHECK fill:#6f9,stroke:#333,stroke-width:2px + style DOCKER fill:#f69,stroke:#333,stroke-width:2px +``` + +This diagram represents the flow of requests through the NGINX reverse proxy and how the health check mechanism works within the Docker container. The `NGINX Reverse Proxy` handles both TCP/UDP requests and health check requests, forwarding the former to the `Backend Service` and responding directly to the latter. The `Docker Daemon` periodically triggers the health check to ensure the NGINX server is functioning correctly. \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index d078b92..d166a6c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,14 +1,8 @@ version: '3.9' services: - nginx-proxy: + host-port-ingress-proxy: build: context: . dockerfile: Dockerfile - image: codeberg.org/Iridium-net/lan-to-nginx:latest - environment: - - BACKEND_ADDRESS=192.168.8.1 # Replace with your backend address - - BACKEND_PORT=80 # Replace with your backend port - ports: - - "80:80" # Map port 80 from the host to port 80 in the container - + image: git.nixc.us/colin/host-port-ingress-proxy:latest \ No newline at end of file diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..e1dc518 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# Substitute environment variables in the NGINX config template +envsubst < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf + +# Start NGINX +exec nginx -g 'daemon off;' diff --git a/nginx.conf b/nginx.conf deleted file mode 100644 index 2e7df9d..0000000 --- a/nginx.conf +++ /dev/null @@ -1,28 +0,0 @@ -user nginx; -worker_processes 1; - -events { - worker_connections 1024; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - # Load environment variables - env BACKEND_ADDRESS; - env BACKEND_PORT; - - server { - listen 80; - - location / { - # Use the environment variables for the proxy pass - proxy_pass http://$BACKEND_ADDRESS:$BACKEND_PORT; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } - } -} - diff --git a/nginx.conf.template b/nginx.conf.template new file mode 100644 index 0000000..4611d45 --- /dev/null +++ b/nginx.conf.template @@ -0,0 +1,31 @@ +events {} + +http { + server { + listen 8080; # Listen on a separate port for health checks + + location /healthz { + # Just return a 200 OK for any request to /healthz + return 200 'healthy\n'; + add_header Content-Type text/plain; + } + } +} + +stream { + # TCP proxy configuration + server { + listen ${BACKEND_TCP_PORT}; + allow ${ALLOWED_IPS}; # Apply IP restrictions based on the ALLOWED_IPS variable + deny all; + proxy_pass ${BACKEND_HOST}:${BACKEND_TCP_PORT}; + } + + # UDP proxy configuration + server { + listen ${BACKEND_UDP_PORT} udp; + allow ${ALLOWED_IPS}; # Apply IP restrictions + deny all; + proxy_pass ${BACKEND_HOST}:${BACKEND_UDP_PORT}; + } +} diff --git a/stack.yml b/stack.yml new file mode 100644 index 0000000..38672ee --- /dev/null +++ b/stack.yml @@ -0,0 +1,23 @@ +version: "3.9" + +networks: + traefik: + external: true + +services: + nginx: + image: git.nixc.us/colin/host-port-ingress-proxy:latest + ports: + - target: 22 + published: 2221 + protocol: udp + mode: host + environment: + - BACKEND_HOST=git_git + - BACKEND_UDP_PORT=22 + - BACKEND_TCP_PORT=22 + - ALLOWED_IPS=0.0.0.0 + networks: + - traefik + deploy: + replicas: 1 \ No newline at end of file