From 50b33ba29422b1ca7c44f8d61740e7213b718121 Mon Sep 17 00:00:00 2001 From: Xavier Lacot Date: Wed, 22 May 2024 11:52:56 +0200 Subject: [PATCH 1/5] add several example docker layouts --- .env.dist | 1 + .gitignore | 1 + LICENSE.md | 2 +- README.md | 79 +++++------------- agent-as-reverse-proxy/README.md | 18 ++++ agent-as-reverse-proxy/docker-compose.yml | 22 +++++ .../services}/redirectionio-agent/Dockerfile | 2 +- .../etc/redirectionio/agent.yml | 7 ++ apache-module-custom/README.md | 33 ++++++++ apache-module-custom/docker-compose.yml | 19 +++++ .../services/apache/Dockerfile | 62 ++++++++++++++ .../apache2/conf/extra/httpd-vhosts.conf | 6 ++ .../services/redirectionio-agent/Dockerfile | 23 +++++ .../etc/redirectionio/agent.yml | 3 + apache-module/README.md | 27 ++++++ apache-module/docker-compose.yml | 19 +++++ apache-module/services/apache/Dockerfile | 32 +++++++ .../services/apache/apache2-foreground | 10 +++ .../apache2/sites-enabled/000-default.conf | 33 ++++++++ .../services/redirectionio-agent/Dockerfile | 23 +++++ .../etc/redirectionio/agent.yml | 3 + app/agent-as-reverse-proxy.png | Bin 0 -> 9730 bytes app/apache-module.png | Bin 0 -> 16309 bytes app/nginx-module.png | Bin 0 -> 15175 bytes nginx-module-custom/README.md | 38 +++++++++ .../docker-compose.yml | 11 +-- .../services/nginx}/Dockerfile | 34 ++++---- .../services/nginx}/etc/nginx/nginx.conf | 21 ++--- .../etc/nginx/templates/default.conf.template | 8 ++ .../services/redirectionio-agent/Dockerfile | 23 +++++ .../etc/redirectionio/agent.yml | 3 + nginx-module/README.md | 27 ++++++ nginx-module/docker-compose.yml | 19 +++++ .../services}/nginx/Dockerfile | 13 ++- .../services/nginx/default.template | 2 +- nginx-module/services/nginx/entrypoint.sh | 8 ++ .../services/redirectionio-agent/Dockerfile | 23 +++++ .../etc/redirectionio/agent.yml | 3 + .../etc/redirectionio/agent.yml | 3 - 39 files changed, 554 insertions(+), 107 deletions(-) create mode 100644 .env.dist create mode 100644 .gitignore create mode 100644 agent-as-reverse-proxy/README.md create mode 100644 agent-as-reverse-proxy/docker-compose.yml rename {services => agent-as-reverse-proxy/services}/redirectionio-agent/Dockerfile (96%) create mode 100644 agent-as-reverse-proxy/services/redirectionio-agent/etc/redirectionio/agent.yml create mode 100644 apache-module-custom/README.md create mode 100644 apache-module-custom/docker-compose.yml create mode 100644 apache-module-custom/services/apache/Dockerfile create mode 100644 apache-module-custom/services/apache/usr/local/apache2/conf/extra/httpd-vhosts.conf create mode 100644 apache-module-custom/services/redirectionio-agent/Dockerfile create mode 100644 apache-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml create mode 100644 apache-module/README.md create mode 100644 apache-module/docker-compose.yml create mode 100644 apache-module/services/apache/Dockerfile create mode 100755 apache-module/services/apache/apache2-foreground create mode 100644 apache-module/services/apache/etc/apache2/sites-enabled/000-default.conf create mode 100644 apache-module/services/redirectionio-agent/Dockerfile create mode 100644 apache-module/services/redirectionio-agent/etc/redirectionio/agent.yml create mode 100644 app/agent-as-reverse-proxy.png create mode 100644 app/apache-module.png create mode 100644 app/nginx-module.png create mode 100644 nginx-module-custom/README.md rename docker-compose.yml => nginx-module-custom/docker-compose.yml (64%) rename {services/nginx-compiled => nginx-module-custom/services/nginx}/Dockerfile (93%) rename {services/nginx-compiled => nginx-module-custom/services/nginx}/etc/nginx/nginx.conf (58%) create mode 100644 nginx-module-custom/services/nginx/etc/nginx/templates/default.conf.template create mode 100644 nginx-module-custom/services/redirectionio-agent/Dockerfile create mode 100644 nginx-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml create mode 100644 nginx-module/README.md create mode 100644 nginx-module/docker-compose.yml rename {services => nginx-module/services}/nginx/Dockerfile (51%) rename services/nginx/etc/nginx/sites-enabled/default => nginx-module/services/nginx/default.template (85%) create mode 100755 nginx-module/services/nginx/entrypoint.sh create mode 100644 nginx-module/services/redirectionio-agent/Dockerfile create mode 100644 nginx-module/services/redirectionio-agent/etc/redirectionio/agent.yml delete mode 100644 services/redirectionio-agent/etc/redirectionio/agent.yml diff --git a/.env.dist b/.env.dist new file mode 100644 index 0000000..d4a9bd7 --- /dev/null +++ b/.env.dist @@ -0,0 +1 @@ +REDIRECTIONIO_PROJECT_KEY=PASTE HERE YOUR REDIRECTION.IO PROJECT KEY diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/LICENSE.md b/LICENSE.md index 94bb3bd..2ab7436 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2021 redirection.io +Copyright (c) 2021-present redirection.io Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/README.md b/README.md index d6c48a5..fd1ad95 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# redirection.io nginx module Docker example +# redirection.io Docker examples It is quite common to use Docker in development or production environments. As -this has been requested by several of our users, we have set up a short example -of a Docker stack for the redirection.io agent and nginx module. +this has been requested by several of our users, we have set up different examples +to show how to integrate redirection.io in various Docker setups. ## Usage @@ -11,71 +11,32 @@ of a Docker stack for the redirection.io agent and nginx module. git clone https://github.com/redirectionio/docker-example.git cd docker-example ``` - * create an account and a project on [redirection.io](https://redirection.io), retrieve your `project key` in [redirection.io's manager](https://redirection.io/manager) and copy it in the nginx configuration file: - * [for the apt-installed nginx module version](./services/nginx/etc/nginx/sites-enabled/default#L9) - * [for the compiled nginx module version](./services/nginx-compiled/etc/nginx/nginx.conf#L35) - ```nginx - redirectionio_project_key PUT HERE YOUR PROJECT KEY; + * create an account and a project on [redirection.io](https://redirection.io), retrieve your `project key` in [redirection.io's manager](https://redirection.io/manager) and copy it + * copy the `.env.dist` file to `.env` and paste your `project key` in it: + ```sh + cp .env.dist .env + ``` + * choose one of the docker layouts (see below), and: + ```sh + cd ``` - The `project key` can be found on the "Instances" screen of your project: - simply click on "Setup on your infrastructure". * build the infrastructure: ```sh - docker-compose build + docker compose build ``` * run it: ```sh - docker-compose up -d + docker compose up -d ``` + * open your browser and go to [http://localhost:8080/](http://localhost:8080/) -Head to: - * [http://localhost:8080/](http://localhost:8080/) to use a nginx module installed from our packages repository. - * [http://localhost:8081/](http://localhost:8081/) to use a nginx module compiled during the install. - -## Explanations - -The `service` directory contains three services: - - * **redirectionio-agent**: a simple Dockerfile to get the agent running - * **nginx**: a nginx Dockerfile based on the Ubuntu 20.04 image, with nginx and - the redirection.io nginx module installed from our apt repository - * **nginx-compiled**: a nginx Dockerfile based on the official nginx image, - with all the directives to get the redirection.io nginx module built and - loaded - -Depending on your install requirements, the version of nginx that you are using -and other specific nginx modules that you want to use, you can either use the -`nginx` or the `nginx-compiled` services as examples. - -### redirectionio-agent - -The agent is installed using our [manual installation](https://redirection.io/documentation/developer-documentation/installation-of-the-agent#manual-installation) instructions. Note that we have enabled a `/var/lib/redirectionio` volume, used to store [redirection.io agent's cache data](https://redirection.io/documentation/developer-documentation/agent-configuration-reference#datadir). - -### nginx - -This is a standard Ubuntu 20.04 image, with the distribution-provided nginx package, and [libnginx-mod-redirectionio installed from our deb repository, as explained in our documentation](https://redirection.io/documentation/developer-documentation/nginx-module#debian-and-apt-based-distributions). - -It defines a single VirtualHost, [for which redirection is enabled](./services/nginx/etc/nginx/sites-enabled/default#L8-L9). - -### nginx-compiled - -Nginx dynamic modules require binary compatibility to be properly loaded, which -means that they have to be compiled with the exact same configuration directives -like your `nginx` binary. - -redirection.io offers APT and RPM repositories, with many versions of -`libnginx-mod-redirectionio` to match classical distribution nginx packages. -However, should your nginx install vary from these traditional layouts, you will -be forced to compile our nginx module yourself, to match your own nginx version. +## Available Docker layouts -This is what the [nginx Dockerfile](./services/nginx-compiled/Dockerfile) achieves. Basically: - * it downloads the nginx sources in the same version like the installed `nginx` binary - * it downloads and build the libredirectionio - * it downloads the redirection.io nginx module - * it builds this module with the same configure arguments the installed `nginx` binary was configured - * it moves the build module in the right folder - * it [loads the module](./services/nginx-compiled/etc/nginx/nginx.conf#L7) in the nginx configuration - * it [enables redirection.io for the server](./services/nginx-compiled/etc/nginx/nginx.conf#L34-L35) + * [**agent-as-reverse-proxy**](./agent-as-reverse-proxy/README.md): the redirection.io agent, installed from our repository, is used as a reverse proxy. This is the most simple and recommended setup. + * [**apache-module**](./apache-module/README.md): a simple Apache setup, with redirection.io module installed from our apt repository + * [**apache-module-custom**](./apache-module-custom/README.md): an Apache setup with the redirection.io module compiled from sources + * [**nginx-module**](./nginx-module/README.md): a simple nginx setup, with redirection.io module installed from our apt repository + * [**nginx-module-custom**](./nginx-module-custom/README.md): a nginx setup with the redirection.io module compiled from sources ## Help and troubleshooting diff --git a/agent-as-reverse-proxy/README.md b/agent-as-reverse-proxy/README.md new file mode 100644 index 0000000..be6bf67 --- /dev/null +++ b/agent-as-reverse-proxy/README.md @@ -0,0 +1,18 @@ +# Using the redirection.io agent as a reverse proxy in a Docker environment + +This example shows how to use the redirection.io agent as a reverse proxy in a Docker environment. It is the most simple and versatile way to install redirection.io in your Docker stack, as it can be used with any backend service. The redirection.io agent act as a very fast reverse proxy, intercepting requests and responses between the client and the backend service. + +> [!TIP] +> You can read more about [the redirection.io agent as a reverse proxy in our documentation](https://redirection.io/documentation/developer-documentation/the-agent-as-a-reverse-proxy). + +## Description + +The `service` directory contains the **redirectionio-agent** service: a simple Dockerfile to get the agent running. The [`/etc/redirectionio/agent.yml`](./services/redirectionio-agent/etc/redirectionio/agent.yml) file is used to configure the agent and proxify the traffic to a backend service. + +The `docker-compose.yml` file also mentions a `nginx` service, which is a simple Nginx server used as a backend service. You can replace it with your own backend service. + +![The redirection.io agent as a reverse proxy](../app/agent-as-reverse-proxy.png) + +### redirectionio-agent + +The agent is installed using our [manual installation](https://redirection.io/documentation/developer-documentation/installation-of-the-agent#manual-installation) instructions. Note that we have enabled a `/var/lib/redirectionio` volume, used to store [redirection.io agent's cache data](https://redirection.io/documentation/developer-documentation/agent-configuration-reference#datadir). diff --git a/agent-as-reverse-proxy/docker-compose.yml b/agent-as-reverse-proxy/docker-compose.yml new file mode 100644 index 0000000..8873b1b --- /dev/null +++ b/agent-as-reverse-proxy/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3' + +volumes: + redirectionio-agent-data: {} + +services: + redirectionio-agent: + build: services/redirectionio-agent + env_file: "../.env" + environment: + - INSTANCE_NAME=docker-reverse-proxy + ports: + - "8080:80" + volumes: + - redirectionio-agent-data:/var/lib/redirectionio + + # this is the application backend service + # it can be any other HTTP service + nginx: + image: nginx + volumes: + - ../app:/usr/share/nginx/html diff --git a/services/redirectionio-agent/Dockerfile b/agent-as-reverse-proxy/services/redirectionio-agent/Dockerfile similarity index 96% rename from services/redirectionio-agent/Dockerfile rename to agent-as-reverse-proxy/services/redirectionio-agent/Dockerfile index df5ce88..9a4e6de 100644 --- a/services/redirectionio-agent/Dockerfile +++ b/agent-as-reverse-proxy/services/redirectionio-agent/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.12 as alpine +FROM alpine:3.19 as alpine WORKDIR /tmp diff --git a/agent-as-reverse-proxy/services/redirectionio-agent/etc/redirectionio/agent.yml b/agent-as-reverse-proxy/services/redirectionio-agent/etc/redirectionio/agent.yml new file mode 100644 index 0000000..f2156d2 --- /dev/null +++ b/agent-as-reverse-proxy/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -0,0 +1,7 @@ +instance_name: "${INSTANCE_NAME}" + +proxies: + - + listen: 0.0.0.0:80 + forward: http://nginx:80 + project_key: "${REDIRECTIONIO_PROJECT_KEY}" diff --git a/apache-module-custom/README.md b/apache-module-custom/README.md new file mode 100644 index 0000000..268144f --- /dev/null +++ b/apache-module-custom/README.md @@ -0,0 +1,33 @@ +# Compiling the redirection.io Apache module in a Docker environment + +It may happen that your hosting provider or provisioning solution installs a custom version of Apache, in non-standard paths or with incompatible dependencies. In this case, you may need to compile the redirection.io Apache module [from the sources](https://github.com/redirectionio/libapache2-mod-redirectionio). + +This example shows how to compile the redirection.io Apache module and load it in the latest release of the Apache image. + +## Description + +The `service` directory contains two services: + + * **apache**: an Apache Dockerfile based on the [`httpd`](https://hub.docker.com/_/httpd/) image, with redirection.io Apache module compiled from the sources. + * **redirectionio-agent**: a simple Dockerfile to get the agent running + +![The redirection.io apache module](../app/apache-module.png) + +### apache + +redirection.io offers APT and RPM repositories, with many versions of +`libapache2-mod-redirectionio` to match classical distribution apache packages. +However, should your apache2 install vary from these traditional layouts, you will +be forced to compile our apache module yourself, to match your own apache version. + +This is what the [apache Dockerfile](./services/apache/Dockerfile) achieves. Basically: + * it downloads and builds the libredirectionio + * it downloads the redirection.io apache2 module + * it builds this module + * it moves the built module in the right folder + * it [loads the module](./services/apache/Dockerfile#L61) in the Apache configuration + * it [enables redirection.io for the server](./services/apache/usr/local/apache2/conf/extra/httpd-vhosts.conf#L4-L5) + +### redirectionio-agent + +The agent is installed using our [manual installation](https://redirection.io/documentation/developer-documentation/installation-of-the-agent#manual-installation) instructions. Note that we have enabled a `/var/lib/redirectionio` volume, used to store [redirection.io agent's cache data](https://redirection.io/documentation/developer-documentation/agent-configuration-reference#datadir). diff --git a/apache-module-custom/docker-compose.yml b/apache-module-custom/docker-compose.yml new file mode 100644 index 0000000..276faf5 --- /dev/null +++ b/apache-module-custom/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3' + +volumes: + redirectionio-agent-data: {} + +services: + apache: + build: services/apache + env_file: "../.env" + ports: + - "8080:80" + volumes: + - ../app:/usr/local/apache2/htdocs + redirectionio-agent: + build: services/redirectionio-agent + environment: + - INSTANCE_NAME=docker-apache-custom + volumes: + - redirectionio-agent-data:/var/lib/redirectionio diff --git a/apache-module-custom/services/apache/Dockerfile b/apache-module-custom/services/apache/Dockerfile new file mode 100644 index 0000000..a6e2416 --- /dev/null +++ b/apache-module-custom/services/apache/Dockerfile @@ -0,0 +1,62 @@ +FROM httpd:2.4 + +# install build tools +RUN apt update \ + && apt install -y \ + autoconf \ + build-essential \ + curl \ + gawk \ + libgd-dev \ + libgeoip-dev \ + libpcre3-dev \ + libperl-dev \ + libssl-dev \ + libxml2-dev \ + libxslt-dev \ + libzip-dev \ + apache2-dev \ + procps \ + unzip \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* + +# install Rust +ENV RUSTUP_HOME=/opt/rust +ENV CARGO_HOME=/opt/rust +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.76.0 -y --no-modify-path +ENV PATH=/opt/rust/bin:$PATH +RUN mkdir -p /opt/rust/registry + +# get libredirectionio sources +WORKDIR /tmp +RUN wget -O libredirectionio-master.zip https://github.com/redirectionio/libredirectionio/archive/master.zip \ + && unzip libredirectionio-master.zip + +# build libredirectionio +WORKDIR /tmp/libredirectionio-master +RUN autoreconf -i \ + && ./configure \ + && make clean \ + && make \ + && make install + +# get apache2 redirection.io module sources +WORKDIR /tmp +RUN wget -O libapache2-mod-redirectionio-master.zip https://github.com/redirectionio/libapache2-mod-redirectionio/archive/master.zip \ + && unzip libapache2-mod-redirectionio-master.zip + +# build the module +WORKDIR /tmp/libapache2-mod-redirectionio-master +RUN autoreconf -i \ + && ./configure \ + && make clean \ + && make \ + && make install + +# Configuration +COPY usr /usr + +RUN echo "LoadModule redirectionio_module /usr/lib/apache2/modules/mod_redirectionio.so" >> /usr/local/apache2/conf/httpd.conf +RUN echo "Include conf/extra/httpd-vhosts.conf" >> /usr/local/apache2/conf/httpd.conf diff --git a/apache-module-custom/services/apache/usr/local/apache2/conf/extra/httpd-vhosts.conf b/apache-module-custom/services/apache/usr/local/apache2/conf/extra/httpd-vhosts.conf new file mode 100644 index 0000000..f629b3e --- /dev/null +++ b/apache-module-custom/services/apache/usr/local/apache2/conf/extra/httpd-vhosts.conf @@ -0,0 +1,6 @@ + + DocumentRoot /usr/local/apache2/htdocs + + RedirectionioProjectKey "${REDIRECTIONIO_PROJECT_KEY}" + RedirectionioPass "tcp://redirectionio-agent:10301" + diff --git a/apache-module-custom/services/redirectionio-agent/Dockerfile b/apache-module-custom/services/redirectionio-agent/Dockerfile new file mode 100644 index 0000000..9a4e6de --- /dev/null +++ b/apache-module-custom/services/redirectionio-agent/Dockerfile @@ -0,0 +1,23 @@ +FROM alpine:3.19 as alpine + +WORKDIR /tmp + +RUN apk add --no-cache wget ca-certificates \ + && wget https://packages.redirection.io/dist/stable/2/any/redirectionio-agent-latest_any_amd64.tar.gz \ + && tar -xzvf redirectionio-agent-latest_any_amd64.tar.gz + +FROM scratch + +# Binary copied from tar +COPY --from=alpine /tmp/redirection-agent/redirectionio-agent /usr/local/bin/redirectionio-agent + +# Configuration, can be replaced by your own +COPY etc /etc + +# Root SSL Certificates, needed as we do HTTPS requests to our service +COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +# Cache storage for rules +VOLUME /var/lib/redirectionio + +CMD ["/usr/local/bin/redirectionio-agent"] diff --git a/apache-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml b/apache-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml new file mode 100644 index 0000000..ee5c670 --- /dev/null +++ b/apache-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -0,0 +1,3 @@ +instance_name: "${INSTANCE_NAME}" + +listen: 0.0.0.0:10301 diff --git a/apache-module/README.md b/apache-module/README.md new file mode 100644 index 0000000..f68733e --- /dev/null +++ b/apache-module/README.md @@ -0,0 +1,27 @@ +# Using the redirection.io Apache module in a Docker environment + +We distribute our Apache module as [Debian/Ubuntu](https://redirection.io/documentation/developer-documentation/apache-module#debian-and-apt-based-distributions) or [Red Hat](https://redirection.io/documentation/developer-documentation/apache-module#red-hat-and-rpm-based-distributions) packages, which are available in our repositories. + +This example shows how to use the pre-compiled redirection.io Apache module provided in our repositories in a Docker environment. + +> [!TIP] +> If your Apache setup is not compatible with our pre-compiled packages, you can [compile the module from sources](../apache-module-custom/README.md). + +## Description + +The `service` directory contains two services: + + * **apache**: an Apache Dockerfile based on the Ubuntu 24.04 image, with Apache and the redirection.io Apache module installed from our apt repository + * **redirectionio-agent**: a simple Dockerfile to get the agent running + +![The redirection.io apache module](../app/apache-module.png) + +### apache + +This is a standard Ubuntu 24.04 image, with the distribution-provided apache2 package, and [libapache2-mod-redirectionio installed from our deb repository, as explained in our documentation](https://redirection.io/documentation/developer-documentation/apache-module#debian-and-apt-based-distributions). + +It defines a single VirtualHost, [for which redirection is enabled](./services/apache/etc/apache2/sites-enabled/000-default.conf#L15-L16). + +### redirectionio-agent + +The agent is installed using our [manual installation](https://redirection.io/documentation/developer-documentation/installation-of-the-agent#manual-installation) instructions. Note that we have enabled a `/var/lib/redirectionio` volume, used to store [redirection.io agent's cache data](https://redirection.io/documentation/developer-documentation/agent-configuration-reference#datadir). diff --git a/apache-module/docker-compose.yml b/apache-module/docker-compose.yml new file mode 100644 index 0000000..4c0067f --- /dev/null +++ b/apache-module/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3' + +volumes: + redirectionio-agent-data: {} + +services: + apache: + build: services/apache + env_file: "../.env" + ports: + - "8080:80" + volumes: + - ../app:/var/www + redirectionio-agent: + build: services/redirectionio-agent + environment: + - INSTANCE_NAME=docker-apache + volumes: + - redirectionio-agent-data:/var/lib/redirectionio diff --git a/apache-module/services/apache/Dockerfile b/apache-module/services/apache/Dockerfile new file mode 100644 index 0000000..6d7ba56 --- /dev/null +++ b/apache-module/services/apache/Dockerfile @@ -0,0 +1,32 @@ +FROM ubuntu:22.04 + +RUN DEBIAN_FRONTEND=noninteractive apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y \ + apt-transport-https \ + gettext \ + gnupg2 \ + apache2 \ + tzdata \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* + +RUN mkdir -p /etc/apt/keyrings \ + && wget -qO- https://packages.redirection.io/gpg.key | tee /etc/apt/keyrings/redirectionio-archive-keyring.asc \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/redirectionio-archive-keyring.asc] https://packages.redirection.io/deb/stable/2 jammy main" | tee -a /etc/apt/sources.list.d/packages_redirection_io_deb.list \ + && apt-get update \ + && apt-get install -y \ + libapache2-mod-redirectionio \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* + +# https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop +STOPSIGNAL SIGWINCH + +# Configuration +COPY etc /etc + +COPY apache2-foreground /usr/bin/ + +CMD ["apache2-foreground"] diff --git a/apache-module/services/apache/apache2-foreground b/apache-module/services/apache/apache2-foreground new file mode 100755 index 0000000..dd758cc --- /dev/null +++ b/apache-module/services/apache/apache2-foreground @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +export APACHE_RUN_DIR=/var/run/apache2 +export APACHE_ARGUMENTS="-DFOREGROUND $@" + +# Apache gets grumpy about PID files pre-existing +rm -f ${APACHE_RUN_DIR}/apache2.pid + +exec /usr/sbin/apachectl start diff --git a/apache-module/services/apache/etc/apache2/sites-enabled/000-default.conf b/apache-module/services/apache/etc/apache2/sites-enabled/000-default.conf new file mode 100644 index 0000000..ca72a40 --- /dev/null +++ b/apache-module/services/apache/etc/apache2/sites-enabled/000-default.conf @@ -0,0 +1,33 @@ + + # The ServerName directive sets the request scheme, hostname and port that + # the server uses to identify itself. This is used when creating + # redirection URLs. In the context of virtual hosts, the ServerName + # specifies what hostname must appear in the request's Host: header to + # match this virtual host. For the default virtual host (this file) this + # value is not decisive as it is used as a last resort host regardless. + # However, you must set it for any further virtual host explicitly. + #ServerName www.example.com + + ServerAdmin webmaster@localhost + DocumentRoot /var/www + + + RedirectionioProjectKey "${REDIRECTIONIO_PROJECT_KEY}" + RedirectionioPass "tcp://redirectionio-agent:10301" + + # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, + # error, crit, alert, emerg. + # It is also possible to configure the loglevel for particular + # modules, e.g. + #LogLevel info ssl:warn + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + # For most configuration files from conf-available/, which are + # enabled or disabled at a global level, it is possible to + # include a line for only one particular virtual host. For example the + # following line enables the CGI configuration for this host only + # after it has been globally disabled with "a2disconf". + #Include conf-available/serve-cgi-bin.conf + diff --git a/apache-module/services/redirectionio-agent/Dockerfile b/apache-module/services/redirectionio-agent/Dockerfile new file mode 100644 index 0000000..9a4e6de --- /dev/null +++ b/apache-module/services/redirectionio-agent/Dockerfile @@ -0,0 +1,23 @@ +FROM alpine:3.19 as alpine + +WORKDIR /tmp + +RUN apk add --no-cache wget ca-certificates \ + && wget https://packages.redirection.io/dist/stable/2/any/redirectionio-agent-latest_any_amd64.tar.gz \ + && tar -xzvf redirectionio-agent-latest_any_amd64.tar.gz + +FROM scratch + +# Binary copied from tar +COPY --from=alpine /tmp/redirection-agent/redirectionio-agent /usr/local/bin/redirectionio-agent + +# Configuration, can be replaced by your own +COPY etc /etc + +# Root SSL Certificates, needed as we do HTTPS requests to our service +COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +# Cache storage for rules +VOLUME /var/lib/redirectionio + +CMD ["/usr/local/bin/redirectionio-agent"] diff --git a/apache-module/services/redirectionio-agent/etc/redirectionio/agent.yml b/apache-module/services/redirectionio-agent/etc/redirectionio/agent.yml new file mode 100644 index 0000000..ee5c670 --- /dev/null +++ b/apache-module/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -0,0 +1,3 @@ +instance_name: "${INSTANCE_NAME}" + +listen: 0.0.0.0:10301 diff --git a/app/agent-as-reverse-proxy.png b/app/agent-as-reverse-proxy.png new file mode 100644 index 0000000000000000000000000000000000000000..1c92fe79252ab99d7cf9635d51d5dd8e5e95cb0d GIT binary patch literal 9730 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 NO-buf(L?jM{{atT7eD|2 literal 0 HcmV?d00001 diff --git a/app/apache-module.png b/app/apache-module.png new file mode 100644 index 0000000000000000000000000000000000000000..575514d429b362aa502b1b3bc9737a931617f023 GIT binary patch literal 16309 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 literal 0 HcmV?d00001 diff --git a/app/nginx-module.png b/app/nginx-module.png new file mode 100644 index 0000000000000000000000000000000000000000..16536e686eb52624520fbe7fb7e28478a3cd24e9 GIT binary patch literal 15175 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 literal 0 HcmV?d00001 diff --git a/nginx-module-custom/README.md b/nginx-module-custom/README.md new file mode 100644 index 0000000..3f04685 --- /dev/null +++ b/nginx-module-custom/README.md @@ -0,0 +1,38 @@ +# Compiling the redirection.io nginx module in a Docker environment + +It may happen that your hosting provider or provisioning solution installs a custom version of nginx, in non-standard paths or with incompatible dependencies. In this case, you may need to compile the redirection.io nginx module [from the sources](https://github.com/redirectionio/libnginx-mod-redirectionio). + +This example shows how to compile the redirection.io nginx module and load it in the latest release of the nginx image. + +## Description + +The `service` directory contains two services: + + * **nginx**: an nginx Dockerfile based on the [`nginx`](https://hub.docker.com/_/nginx/) image, with redirection.io nginx module compiled from the sources. + * **redirectionio-agent**: a simple Dockerfile to get the agent running + +![The redirection.io nginx module](../app/nginx-module.png) + +### nginx + +Nginx dynamic modules require binary compatibility to be properly loaded, which +means that they have to be compiled with the exact same configuration directives +like your `nginx` binary. + +redirection.io offers APT and RPM repositories, with many versions of +`libnginx-mod-redirectionio` to match classical distribution nginx packages. +However, should your nginx install vary from these traditional layouts, you will +be forced to compile our nginx module yourself, to match your own nginx version. + +This is what the [nginx Dockerfile](./services/nginx/Dockerfile) achieves. Basically: + * it downloads and builds the libredirectionio + * it downloads the nginx sources in the same version like the installed `nginx` binary + * it downloads the redirection.io nginx module + * it builds this module with the same configure arguments the installed `nginx` binary was configured + * it moves the built module in the right folder + * it [loads the module](./services/nginx/etc/nginx/nginx.conf#L7) in the nginx configuration + * it [enables redirection.io for the server](./services/nginx/etc/nginx/templates/default.conf.template#L6-L7) + +### redirectionio-agent + +The agent is installed using our [manual installation](https://redirection.io/documentation/developer-documentation/installation-of-the-agent#manual-installation) instructions. Note that we have enabled a `/var/lib/redirectionio` volume, used to store [redirection.io agent's cache data](https://redirection.io/documentation/developer-documentation/agent-configuration-reference#datadir). diff --git a/docker-compose.yml b/nginx-module-custom/docker-compose.yml similarity index 64% rename from docker-compose.yml rename to nginx-module-custom/docker-compose.yml index bd33c7e..5f8f6b3 100644 --- a/docker-compose.yml +++ b/nginx-module-custom/docker-compose.yml @@ -6,17 +6,14 @@ volumes: services: nginx: build: services/nginx + env_file: "../.env" ports: - "8080:80" volumes: - - ./app:/var/www - nginx-compiled: - build: services/nginx-compiled - ports: - - "8081:80" - volumes: - - ./app:/var/www + - ../app:/var/www redirectionio-agent: build: services/redirectionio-agent + environment: + - INSTANCE_NAME=docker-nginx-custom volumes: - redirectionio-agent-data:/var/lib/redirectionio diff --git a/services/nginx-compiled/Dockerfile b/nginx-module-custom/services/nginx/Dockerfile similarity index 93% rename from services/nginx-compiled/Dockerfile rename to nginx-module-custom/services/nginx/Dockerfile index 58116d9..50246eb 100644 --- a/services/nginx-compiled/Dockerfile +++ b/nginx-module-custom/services/nginx/Dockerfile @@ -1,10 +1,11 @@ -FROM nginx:1.19 +FROM nginx:1.25 # install build tools RUN apt update \ && apt install -y \ autoconf \ build-essential \ + curl \ gawk \ libgd-dev \ libgeoip-dev \ @@ -18,28 +19,13 @@ RUN apt update \ procps \ unzip \ wget \ - gawk \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* -# get nginx redirection.io module sources -WORKDIR /tmp -RUN wget -O libnginx-mod-redirectionio-master.zip https://github.com/redirectionio/libnginx-mod-redirectionio/archive/master.zip \ - && unzip libnginx-mod-redirectionio-master.zip - -# get nginx sources -WORKDIR /root -RUN NGINX_VERSION=`nginx -v 2>&1 | gawk 'match($0,/nginx version: nginx\/([0-9\.]+?)/,a) {print a[1]}'` \ - && echo $NGINX_VERSION \ - && wget http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz \ - && tar -xzvf nginx-$NGINX_VERSION.tar.gz \ - && mv /root/nginx-$NGINX_VERSION /root/nginx \ - && rm nginx-$NGINX_VERSION.tar.gz - # install Rust ENV RUSTUP_HOME=/opt/rust ENV CARGO_HOME=/opt/rust -RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.67.1 -y --no-modify-path +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.76.0 -y --no-modify-path ENV PATH=/opt/rust/bin:$PATH RUN mkdir -p /opt/rust/registry @@ -56,6 +42,20 @@ RUN autoreconf -i \ && make \ && make install +# get nginx redirection.io module sources +WORKDIR /tmp +RUN wget -O libnginx-mod-redirectionio-master.zip https://github.com/redirectionio/libnginx-mod-redirectionio/archive/master.zip \ + && unzip libnginx-mod-redirectionio-master.zip + +# get nginx sources +WORKDIR /root +RUN NGINX_VERSION=`nginx -v 2>&1 | gawk 'match($0,/nginx version: nginx\/([0-9\.]+?)/,a) {print a[1]}'` \ + && echo $NGINX_VERSION \ + && wget http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz \ + && tar -xzvf nginx-$NGINX_VERSION.tar.gz \ + && mv /root/nginx-$NGINX_VERSION /root/nginx \ + && rm nginx-$NGINX_VERSION.tar.gz + # build the module WORKDIR /root/nginx diff --git a/services/nginx-compiled/etc/nginx/nginx.conf b/nginx-module-custom/services/nginx/etc/nginx/nginx.conf similarity index 58% rename from services/nginx-compiled/etc/nginx/nginx.conf rename to nginx-module-custom/services/nginx/etc/nginx/nginx.conf index dac065b..44f46dd 100644 --- a/services/nginx-compiled/etc/nginx/nginx.conf +++ b/nginx-module-custom/services/nginx/etc/nginx/nginx.conf @@ -1,15 +1,17 @@ user nginx; -worker_processes 1; +worker_processes auto; -error_log /proc/self/fd/2; -pid /var/run/nginx.pid; +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; load_module modules/ngx_http_redirectionio_module.so; + events { worker_connections 1024; } + http { include /etc/nginx/mime.types; default_type application/octet-stream; @@ -18,7 +20,7 @@ http { '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; - access_log /proc/self/fd/1; + access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; @@ -27,14 +29,5 @@ http { #gzip on; - server { - listen 0.0.0.0:80; - root /var/www; - - redirectionio_pass redirectionio-agent:10301; - redirectionio_project_key "PUT HERE YOUR PROJECT KEY"; - - error_log /proc/self/fd/2; - access_log /proc/self/fd/1; - } + include /etc/nginx/conf.d/*.conf; } diff --git a/nginx-module-custom/services/nginx/etc/nginx/templates/default.conf.template b/nginx-module-custom/services/nginx/etc/nginx/templates/default.conf.template new file mode 100644 index 0000000..28df697 --- /dev/null +++ b/nginx-module-custom/services/nginx/etc/nginx/templates/default.conf.template @@ -0,0 +1,8 @@ +server { + listen 80; + listen [::]:80; + root /var/www; + + redirectionio_pass redirectionio-agent:10301; + redirectionio_project_key "${REDIRECTIONIO_PROJECT_KEY}"; +} diff --git a/nginx-module-custom/services/redirectionio-agent/Dockerfile b/nginx-module-custom/services/redirectionio-agent/Dockerfile new file mode 100644 index 0000000..9a4e6de --- /dev/null +++ b/nginx-module-custom/services/redirectionio-agent/Dockerfile @@ -0,0 +1,23 @@ +FROM alpine:3.19 as alpine + +WORKDIR /tmp + +RUN apk add --no-cache wget ca-certificates \ + && wget https://packages.redirection.io/dist/stable/2/any/redirectionio-agent-latest_any_amd64.tar.gz \ + && tar -xzvf redirectionio-agent-latest_any_amd64.tar.gz + +FROM scratch + +# Binary copied from tar +COPY --from=alpine /tmp/redirection-agent/redirectionio-agent /usr/local/bin/redirectionio-agent + +# Configuration, can be replaced by your own +COPY etc /etc + +# Root SSL Certificates, needed as we do HTTPS requests to our service +COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +# Cache storage for rules +VOLUME /var/lib/redirectionio + +CMD ["/usr/local/bin/redirectionio-agent"] diff --git a/nginx-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml b/nginx-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml new file mode 100644 index 0000000..ee5c670 --- /dev/null +++ b/nginx-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -0,0 +1,3 @@ +instance_name: "${INSTANCE_NAME}" + +listen: 0.0.0.0:10301 diff --git a/nginx-module/README.md b/nginx-module/README.md new file mode 100644 index 0000000..847c594 --- /dev/null +++ b/nginx-module/README.md @@ -0,0 +1,27 @@ +# Using the redirection.io nginx module in a Docker environment + +We distribute our nginx module as [Debian/Ubuntu](https://redirection.io/documentation/developer-documentation/nginx-module#debian-and-apt-based-distributions) or [Red Hat](https://redirection.io/documentation/developer-documentation/nginx-module#red-hat-and-rpm-based-distributions) packages, which are available in our repositories. + +This example shows how to use the pre-compiled redirection.io nginx module provided in our repositories in a Docker environment. + +> [!TIP] +> If your nginx setup is not compatible with our pre-compiled packages, you can [compile the module from sources](../nginx-module-custom/README.md). + +## Description + +The `service` directory contains two services: + + * **nginx**: a nginx Dockerfile based on the Ubuntu 24.04 image, with nginx and the redirection.io nginx module installed from our apt repository + * **redirectionio-agent**: a simple Dockerfile to get the agent running + +![The redirection.io nginx module](../app/nginx-module.png) + +### nginx + +This is a standard Ubuntu 24.04 image, with the distribution-provided nginx package, and [libnginx-mod-redirectionio installed from our deb repository, as explained in our documentation](https://redirection.io/documentation/developer-documentation/nginx-module#debian-and-apt-based-distributions). + +It defines a single VirtualHost, [for which redirection is enabled](./services/nginx/default.template#L8-L9). + +### redirectionio-agent + +The agent is installed using our [manual installation](https://redirection.io/documentation/developer-documentation/installation-of-the-agent#manual-installation) instructions. Note that we have enabled a `/var/lib/redirectionio` volume, used to store [redirection.io agent's cache data](https://redirection.io/documentation/developer-documentation/agent-configuration-reference#datadir). diff --git a/nginx-module/docker-compose.yml b/nginx-module/docker-compose.yml new file mode 100644 index 0000000..a5998f6 --- /dev/null +++ b/nginx-module/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3' + +volumes: + redirectionio-agent-data: {} + +services: + nginx: + build: services/nginx + env_file: "../.env" + ports: + - "8080:80" + volumes: + - ../app:/var/www + redirectionio-agent: + build: services/redirectionio-agent + environment: + - INSTANCE_NAME=docker-nginx + volumes: + - redirectionio-agent-data:/var/lib/redirectionio diff --git a/services/nginx/Dockerfile b/nginx-module/services/nginx/Dockerfile similarity index 51% rename from services/nginx/Dockerfile rename to nginx-module/services/nginx/Dockerfile index d944787..84bee85 100644 --- a/services/nginx/Dockerfile +++ b/nginx-module/services/nginx/Dockerfile @@ -1,17 +1,19 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 RUN DEBIAN_FRONTEND=noninteractive apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y \ && DEBIAN_FRONTEND=noninteractive apt-get install -y \ apt-transport-https \ + gettext \ gnupg2 \ nginx \ wget \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* -RUN wget -q -O - https://packages.redirection.io/gpg.key | apt-key add - \ - && echo "deb https://packages.redirection.io/deb/stable/2 focal main" | tee -a /etc/apt/sources.list.d/packages_redirection_io_deb.list \ +RUN mkdir -p /etc/apt/keyrings \ + && wget -qO- https://packages.redirection.io/gpg.key | tee /etc/apt/keyrings/redirectionio-archive-keyring.asc \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/redirectionio-archive-keyring.asc] https://packages.redirection.io/deb/stable/2 jammy main" | tee -a /etc/apt/sources.list.d/packages_redirection_io_deb.list \ && apt-get update \ && apt-get install -y \ libnginx-mod-redirectionio \ @@ -19,6 +21,9 @@ RUN wget -q -O - https://packages.redirection.io/gpg.key | apt-key add - \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* # Configuration -COPY etc /etc +COPY default.template /tmp/default.template + +COPY entrypoint.sh /tmp/entrypoint.sh +ENTRYPOINT ["/tmp/entrypoint.sh"] CMD ["nginx", "-g", "daemon off;"] diff --git a/services/nginx/etc/nginx/sites-enabled/default b/nginx-module/services/nginx/default.template similarity index 85% rename from services/nginx/etc/nginx/sites-enabled/default rename to nginx-module/services/nginx/default.template index d17f0e9..eaa95e9 100644 --- a/services/nginx/etc/nginx/sites-enabled/default +++ b/nginx-module/services/nginx/default.template @@ -6,7 +6,7 @@ server { root /var/www; redirectionio_pass redirectionio-agent:10301; - redirectionio_project_key "PUT HERE YOUR PROJECT KEY"; + redirectionio_project_key "${REDIRECTIONIO_PROJECT_KEY}"; location / { # First attempt to serve request as file, then diff --git a/nginx-module/services/nginx/entrypoint.sh b/nginx-module/services/nginx/entrypoint.sh new file mode 100755 index 0000000..9488d51 --- /dev/null +++ b/nginx-module/services/nginx/entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e + +export REDIRECTIONIO_PROJECT_KEY +envsubst '${REDIRECTIONIO_PROJECT_KEY}' < /tmp/default.template > /etc/nginx/sites-enabled/default + +exec "$@" diff --git a/nginx-module/services/redirectionio-agent/Dockerfile b/nginx-module/services/redirectionio-agent/Dockerfile new file mode 100644 index 0000000..9a4e6de --- /dev/null +++ b/nginx-module/services/redirectionio-agent/Dockerfile @@ -0,0 +1,23 @@ +FROM alpine:3.19 as alpine + +WORKDIR /tmp + +RUN apk add --no-cache wget ca-certificates \ + && wget https://packages.redirection.io/dist/stable/2/any/redirectionio-agent-latest_any_amd64.tar.gz \ + && tar -xzvf redirectionio-agent-latest_any_amd64.tar.gz + +FROM scratch + +# Binary copied from tar +COPY --from=alpine /tmp/redirection-agent/redirectionio-agent /usr/local/bin/redirectionio-agent + +# Configuration, can be replaced by your own +COPY etc /etc + +# Root SSL Certificates, needed as we do HTTPS requests to our service +COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +# Cache storage for rules +VOLUME /var/lib/redirectionio + +CMD ["/usr/local/bin/redirectionio-agent"] diff --git a/nginx-module/services/redirectionio-agent/etc/redirectionio/agent.yml b/nginx-module/services/redirectionio-agent/etc/redirectionio/agent.yml new file mode 100644 index 0000000..ee5c670 --- /dev/null +++ b/nginx-module/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -0,0 +1,3 @@ +instance_name: "${INSTANCE_NAME}" + +listen: 0.0.0.0:10301 diff --git a/services/redirectionio-agent/etc/redirectionio/agent.yml b/services/redirectionio-agent/etc/redirectionio/agent.yml deleted file mode 100644 index b20503f..0000000 --- a/services/redirectionio-agent/etc/redirectionio/agent.yml +++ /dev/null @@ -1,3 +0,0 @@ -instance_name: "redirectionio-nginx-docker-demo" - -listen: 0.0.0.0:10301 From 11c550b158bc063cd27ff7613439f694b8a6d19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFck=20Piera?= Date: Wed, 22 May 2024 15:57:45 +0200 Subject: [PATCH 2/5] Preload rules in examples agents --- apache-module-custom/docker-compose.yml | 1 + .../services/redirectionio-agent/etc/redirectionio/agent.yml | 5 +++++ apache-module/docker-compose.yml | 1 + .../services/redirectionio-agent/etc/redirectionio/agent.yml | 5 +++++ nginx-module-custom/docker-compose.yml | 1 + .../services/redirectionio-agent/etc/redirectionio/agent.yml | 5 +++++ nginx-module/docker-compose.yml | 1 + .../services/redirectionio-agent/etc/redirectionio/agent.yml | 5 +++++ 8 files changed, 24 insertions(+) diff --git a/apache-module-custom/docker-compose.yml b/apache-module-custom/docker-compose.yml index 276faf5..1655ddb 100644 --- a/apache-module-custom/docker-compose.yml +++ b/apache-module-custom/docker-compose.yml @@ -13,6 +13,7 @@ services: - ../app:/usr/local/apache2/htdocs redirectionio-agent: build: services/redirectionio-agent + env_file: "../.env" environment: - INSTANCE_NAME=docker-apache-custom volumes: diff --git a/apache-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml b/apache-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml index ee5c670..0113e18 100644 --- a/apache-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml +++ b/apache-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -1,3 +1,8 @@ instance_name: "${INSTANCE_NAME}" listen: 0.0.0.0:10301 + +# Keys of projects to preload +# This allows to preload the agent with some projects rulesets at startup time +project_keys: + - "${REDIRECTIONIO_PROJECT_KEY}" diff --git a/apache-module/docker-compose.yml b/apache-module/docker-compose.yml index 4c0067f..5bda15c 100644 --- a/apache-module/docker-compose.yml +++ b/apache-module/docker-compose.yml @@ -13,6 +13,7 @@ services: - ../app:/var/www redirectionio-agent: build: services/redirectionio-agent + env_file: "../.env" environment: - INSTANCE_NAME=docker-apache volumes: diff --git a/apache-module/services/redirectionio-agent/etc/redirectionio/agent.yml b/apache-module/services/redirectionio-agent/etc/redirectionio/agent.yml index ee5c670..0113e18 100644 --- a/apache-module/services/redirectionio-agent/etc/redirectionio/agent.yml +++ b/apache-module/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -1,3 +1,8 @@ instance_name: "${INSTANCE_NAME}" listen: 0.0.0.0:10301 + +# Keys of projects to preload +# This allows to preload the agent with some projects rulesets at startup time +project_keys: + - "${REDIRECTIONIO_PROJECT_KEY}" diff --git a/nginx-module-custom/docker-compose.yml b/nginx-module-custom/docker-compose.yml index 5f8f6b3..fe78968 100644 --- a/nginx-module-custom/docker-compose.yml +++ b/nginx-module-custom/docker-compose.yml @@ -13,6 +13,7 @@ services: - ../app:/var/www redirectionio-agent: build: services/redirectionio-agent + env_file: "../.env" environment: - INSTANCE_NAME=docker-nginx-custom volumes: diff --git a/nginx-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml b/nginx-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml index ee5c670..0113e18 100644 --- a/nginx-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml +++ b/nginx-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -1,3 +1,8 @@ instance_name: "${INSTANCE_NAME}" listen: 0.0.0.0:10301 + +# Keys of projects to preload +# This allows to preload the agent with some projects rulesets at startup time +project_keys: + - "${REDIRECTIONIO_PROJECT_KEY}" diff --git a/nginx-module/docker-compose.yml b/nginx-module/docker-compose.yml index a5998f6..84b2e66 100644 --- a/nginx-module/docker-compose.yml +++ b/nginx-module/docker-compose.yml @@ -13,6 +13,7 @@ services: - ../app:/var/www redirectionio-agent: build: services/redirectionio-agent + env_file: "../.env" environment: - INSTANCE_NAME=docker-nginx volumes: diff --git a/nginx-module/services/redirectionio-agent/etc/redirectionio/agent.yml b/nginx-module/services/redirectionio-agent/etc/redirectionio/agent.yml index ee5c670..0113e18 100644 --- a/nginx-module/services/redirectionio-agent/etc/redirectionio/agent.yml +++ b/nginx-module/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -1,3 +1,8 @@ instance_name: "${INSTANCE_NAME}" listen: 0.0.0.0:10301 + +# Keys of projects to preload +# This allows to preload the agent with some projects rulesets at startup time +project_keys: + - "${REDIRECTIONIO_PROJECT_KEY}" From d9fbaf47540acdfe5dde512e8092ab619ef6664a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFck=20Piera?= Date: Wed, 22 May 2024 15:57:11 +0200 Subject: [PATCH 3/5] Add continuous integration on examples --- .castor/.gitignore | 2 + .castor/castor.php | 151 ++++++++++++++++++++++++++++++++++++++++ .github/worflows/ci.yml | 29 ++++++++ 3 files changed, 182 insertions(+) create mode 100644 .castor/.gitignore create mode 100644 .castor/castor.php create mode 100644 .github/worflows/ci.yml diff --git a/.castor/.gitignore b/.castor/.gitignore new file mode 100644 index 0000000..361c134 --- /dev/null +++ b/.castor/.gitignore @@ -0,0 +1,2 @@ +.castor.stub.php +.env diff --git a/.castor/castor.php b/.castor/castor.php new file mode 100644 index 0000000..17e5293 --- /dev/null +++ b/.castor/castor.php @@ -0,0 +1,151 @@ +exists('.env')) { + io()->error('No .env file found. Please create one by copying the .env.dist file and filling in the required values.'); + return; + } + + stop(); + + if ($example) { + io()->title("Building and running example: $example"); + + example($example); + + return; + } + + io()->title('Building and running all examples'); + + foreach (get_examples() as $example) { + example($example); + } +} + +#[AsTask(description: 'Build the given example')] +function build( + #[AsArgument(description: 'The name of the specific example to run', autocomplete: 'get_examples')] + ?string $example = null, +): void +{ + if (!$example) { + foreach (get_examples() as $example) { + build($example); + } + return; + } + + io()->title("Building example: $example"); + + run('docker compose build', workingDirectory: $example); +} + +#[AsTask(description: 'Start the given example')] +function start( + #[AsArgument(description: 'The name of the specific example to run', autocomplete: 'get_examples')] + string $example, +): void +{ + io()->title("Starting example: $example"); + + run('docker compose up -d', workingDirectory: $example); + + sleep(2); +} + +#[AsTask(description: 'Test the given example')] +function test( + #[AsArgument(description: 'The name of the specific example to run', autocomplete: 'get_examples')] + string $example, +): void +{ + io()->title("Testing example: $example"); + + $fails = 0; + !assertResponse('/', 200) && $fails++; + !assertResponse('/example/301-rio.html', 301) && $fails++; + !assertResponse('/example/302-rio.html', 302) && $fails++; + !assertResponse('/example/404-nginx.html', 404) && $fails++; + !assertResponse('/example/404-rio.html', 404) && $fails++; + !assertResponse('/example/410-rio.html', 410) && $fails++; + + if ($fails > 0) { + throw new \RuntimeException("Some tests were not successful for example \"$example\""); + } + + io()->writeln(''); +} + +#[AsTask(description: 'Stop the given example')] +function stop( + #[AsArgument(description: 'The name of the specific example to run', autocomplete: 'get_examples')] + ?string $example = null, +): void +{ + if (!$example) { + foreach (get_examples() as $example) { + stop($example); + } + return; + } + + io()->title("Stopping example: $example"); + + run('docker compose stop', workingDirectory: $example, allowFailure: true); +} + +function get_examples(): iterable +{ + /** @var Symfony\Component\Finder\Finder $examples */ + $examples = finder() + ->in(context()->workingDirectory) + ->notName('app') + ->directories() + ->depth(0) + ->sortByName() + ; + + foreach ($examples as $example) { + yield $example->getBasename(); + } +} + +function example(string $example): void +{ + if (!fs()->exists("$example/docker-compose.yml")) { + throw new \RuntimeException("The example directory \"$example\" does not exist or does not contain a docker-compose.yml file"); + } + + build($example); + start($example); + test($example); + stop($example); +} + +function assertResponse(string $url, int $expectedStatusCode): bool +{ + $response = http_request('GET', 'http://127.0.0.1:8080' . $url, [ + 'max_redirects' => 0, + ]); + + $result = $response->getStatusCode() === $expectedStatusCode ? '✔️' : '❌'; + + io()->text("Asserting response for $url is status $expectedStatusCode: $result"); + + return $response->getStatusCode() === $expectedStatusCode; +} diff --git a/.github/worflows/ci.yml b/.github/worflows/ci.yml new file mode 100644 index 0000000..e531fe3 --- /dev/null +++ b/.github/worflows/ci.yml @@ -0,0 +1,29 @@ +name: Continuous Integration + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: "0 0 * * MON" + +jobs: + run-examples: + name: Run all examples + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + tools: castor + + - name: Setup .env + run: "echo 'REDIRECTIONIO_PROJECT_KEY=${{ secrets.REDIRECTIONIO_PROJECT_KEY }}' > $GITHUB_WORKSPACE/.env" + + - name: Build and run all examples + run: castor run From 5949fc2256b0c5db444546877390d81b20efa7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFck=20Piera?= Date: Wed, 22 May 2024 16:53:14 +0200 Subject: [PATCH 4/5] Fix typo --- .github/{worflows => workflows}/ci.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{worflows => workflows}/ci.yml (100%) diff --git a/.github/worflows/ci.yml b/.github/workflows/ci.yml similarity index 100% rename from .github/worflows/ci.yml rename to .github/workflows/ci.yml From d42ed1f4f77dc009f103243cc310d787db844672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFck=20Piera?= Date: Wed, 22 May 2024 17:05:07 +0200 Subject: [PATCH 5/5] Do not use unreleased function from Castor --- .castor/castor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.castor/castor.php b/.castor/castor.php index 17e5293..2cdc286 100644 --- a/.castor/castor.php +++ b/.castor/castor.php @@ -5,7 +5,7 @@ use function Castor\context; use function Castor\finder; use function Castor\fs; -use function Castor\http_request; +use function Castor\request; use function Castor\io; use function Castor\run; @@ -139,7 +139,7 @@ function example(string $example): void function assertResponse(string $url, int $expectedStatusCode): bool { - $response = http_request('GET', 'http://127.0.0.1:8080' . $url, [ + $response = request('GET', 'http://127.0.0.1:8080' . $url, [ 'max_redirects' => 0, ]);