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..2cdc286 --- /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 = 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/.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/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e531fe3 --- /dev/null +++ b/.github/workflows/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 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..1655ddb --- /dev/null +++ b/apache-module-custom/docker-compose.yml @@ -0,0 +1,20 @@ +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 + env_file: "../.env" + 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..0113e18 --- /dev/null +++ b/apache-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -0,0 +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/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..5bda15c --- /dev/null +++ b/apache-module/docker-compose.yml @@ -0,0 +1,20 @@ +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 + env_file: "../.env" + 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..0113e18 --- /dev/null +++ b/apache-module/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -0,0 +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/app/agent-as-reverse-proxy.png b/app/agent-as-reverse-proxy.png new file mode 100644 index 0000000..1c92fe7 Binary files /dev/null and b/app/agent-as-reverse-proxy.png differ diff --git a/app/apache-module.png b/app/apache-module.png new file mode 100644 index 0000000..575514d Binary files /dev/null and b/app/apache-module.png differ diff --git a/app/nginx-module.png b/app/nginx-module.png new file mode 100644 index 0000000..16536e6 Binary files /dev/null and b/app/nginx-module.png differ 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..fe78968 100644 --- a/docker-compose.yml +++ b/nginx-module-custom/docker-compose.yml @@ -6,17 +6,15 @@ 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 + env_file: "../.env" + 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..0113e18 --- /dev/null +++ b/nginx-module-custom/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -0,0 +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/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..84b2e66 --- /dev/null +++ b/nginx-module/docker-compose.yml @@ -0,0 +1,20 @@ +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 + env_file: "../.env" + 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..0113e18 --- /dev/null +++ b/nginx-module/services/redirectionio-agent/etc/redirectionio/agent.yml @@ -0,0 +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/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