The post NGINX Feature Flag Reverse Proxy appeared first on Justin Silver.
]]>Use NGINX as a reverse proxy to different back-end servers based on feature-flags set in the ngx_http_auth_request_module
add-on. In my implementation for Secret Party the subdomain is used to determine which event/party a Note that this is a template file and some variables are set from the environment – $DOMAIN
, $PROXY_*_HOST
, $PROXY_*_PORT
, etc.
First create the upstream servers that we can proxy the request to. Here we will use “green”, “blue”, and “red”.
# this is the server that handles the "auth" request upstream upstream_auth { server $PROXY_AUTH_HOST:$PROXY_AUTH_PORT; } # backend app server "green" upstream upstream_green { server $PROXY_GREEN_HOST:$PROXY_GREEN_PORT; } # backend app server "blue" upstream upstream_blue { server $PROXY_BLUE_HOST:$PROXY_BLUE_PORT; } # backend app server "red" upstream upstream_red { server $PROXY_RED_HOST:$PROXY_RED_PORT; }
Next we create a mapping of route name to upstream server. This will let us choose the backend/upstream server without an evil if
.
# map service names from auth header to upstream service map $wildcard_feature_route $wildcard_service_route { default upstream_green; 'green' upstream_green; 'blue' upstream_blue; 'red' upstream_red; }
Optionally we can also support arbitrary response codes in this mapping – note that they will be strings not numbers. This uses the auth response code to choose the route that is used for the proxy from the mapping above – so the HTTP Status Code to string to Upstream Server.
# map http codes from auth response (as string!) to upstream service map $wildcard_backend_status $wildcard_mapped_route { default 'green'; '480' 'green'; '481' 'blue'; '482' 'red'; }
The Auth Handler is where NGINX sends the auth request so we assume we are handling something like http://upstream_auth/feature-flags/$host
. This endpoint chooses the route that we use either by setting a header called X-Feature-Route
with a string name that matches the mapping above, or can respond with a 4xx error code to also specify a route from the other mapping above. You get the gist.
function handleFeatureFlag(req, res) { // use the param/header data to choose the backend route // const hostname = req.params.hostname; const route = someFlag? 'green' : 'blue'; // this header is used to figure out a proxy route res.header('X-Feature-Route', route); return res.status(200).send(); }
function handleFeatureFlag(req, res) { // this http response code can be used to figure out a proxy route too! const status = someFlag ? 481 : 482; // blue, red return res.status(status).send(); }
To tie it together create a server that uses an auth request to http://upstream_auth/feature-flags/$host
. This API endpoint uses the hostname to choose the upstream service to use to fulfill the request, either by setting a header of X-Feature-Route
or returning an error code other than 200 or 401 – anything else will be returned as a 500 to NGINX which can then use the string value of this code as a route hint.
server { listen 80; # listen on wildcard subdomains server_name *.$DOMAIN; # internal feature flags route to upstream_auth location = /feature-flags { internal; # make an api request for the feature flags, pass the hostname rewrite .* /feature-flags/$host? break; proxy_pass http://upstream_auth; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Original-Remote-Addr $remote_addr; proxy_set_header X-Original-Host $host; } # handle all requests for the wildcard location / { # get routing from feature flags auth_request /feature-flags; # set Status Code response to variable auth_request_set $wildcard_backend_status $upstream_status; # set X-Feature-Route header to variable auth_request_set $wildcard_feature_route $upstream_http_x_feature_route; # this is a 401 response error_page 401 = @process_backend; # anything not a 200 or 401 returns a 500 error error_page 500 = @process_backend; # this is a 200 response try_files @ @process_request; } # handle 500 errors to get the underlying code location @process_backend { # set the status code as a string mapped to a service name set $wildcard_feature_route $wildcard_mapped_route; # now process the request as normal try_files @ @process_request; } # send the request to the correct backend server location @process_request { proxy_read_timeout 10s; proxy_cache off; proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # use the mapping to determine which service to route the request to proxy_pass http://$wildcard_service_route; } }
The post NGINX Feature Flag Reverse Proxy appeared first on Justin Silver.
]]>The post Fantom Lachesis Full Node RPC appeared first on Justin Silver.
]]>Create an Alpine Linux image to run the lachesis
node for the Fantom cryptocurrency.
FROM alpine:latest as build-stage ARG LACHESIS_VERSION=release/1.0.0-rc.0 ENV GOROOT=/usr/lib/go ENV GOPATH=/go ENV PATH=$GOROOT/bin:$GOPATH/bin:/build:$PATH RUN set -xe; \ apk add --no-cache --virtual .build-deps \ # get the build dependencies for go git make musl-dev go linux-headers; \ # install fantom lachesis from github mkdir -p ${GOPATH}; cd ${GOPATH}; \ git clone --single-branch --branch ${LACHESIS_VERSION} https://github.com/Fantom-foundation/go-lachesis.git; \ cd go-lachesis; \ make build -j$(nproc); \ mv build/lachesis /usr/local/bin; \ rm -rf /go; \ # remove our build dependencies apk del .build-deps; FROM alpine:latest as lachesis # copy the binary COPY --from=build-stage /usr/local/bin/lachesis /usr/local/bin/lachesis COPY run.sh /usr/local/bin WORKDIR /root ENV LACHESIS_PORT=5050 ENV LACHESIS_HTTP=18545 ENV LACHESIS_API=eth,ftm,debug,admin,web3,personal,net,txpool ENV LACHESIS_VERBOSITY=2 EXPOSE ${LACHESIS_PORT} EXPOSE ${LACHESIS_HTTP} VOLUME [ "/root/.lachesis" ] CMD ["run.sh"]
The run.sh
just starts the nodes with the ports you set in the environment.
#!/usr/bin/env sh set -xe lachesis \ --port ${LACHESIS_PORT} \ --http \ --http.addr "0.0.0.0" \ --http.port ${LACHESIS_HTTP} \ --http.api "${LACHESIS_API}" \ --nousb \ --verbosity ${LACHESIS_VERBOSITY}
Use docker-compose to define the TCP/UDP ports to expose as well as a data volume to persist the blockchain data.
version: '3.4' services: lachesis: image: doublesharp/fantom-lachesis:latest restart: always ports: - '5050:5050' - '5050:5050/udp' - '18545:18545' volumes: - lachesis:/root/.lachesis environment: LACHESIS_VERBOSITY: 2 volumes: lachesis: {}
The post Fantom Lachesis Full Node RPC appeared first on Justin Silver.
]]>The post Using APK for Alpine Linux with Docker appeared first on Justin Silver.
]]>Some quick tips on how to use apk
for Alpine Linux in a Docker environment. Some common use cases might be to install command line tools you will use in scripts, or to compile a PHP extension. In the former you will often be able to access a binary, and not need to worry about polluting much of your Docker layer with extra files. When you need to compile something however – like a PHP extension – you may need several build tools as well as libraries that you don’t need to keep around after you compile the module.
This first example is common for installing command line tools:
RUN apk add --no-cache --update \ bash curl findutils sed sudo
The next example shows how to compile PHP modules and remove their dependencies after compilation.
RUN set -xe; \ apk add --no-cache --virtual .build-deps $PHPIZE_DEPS \ # build tools autoconf g++ gcc make \ # lib tools bzip2-dev freetype-dev gettext-dev icu-dev imagemagick-dev libintl libjpeg-turbo-dev \ # libmcrypt-dev libpng-dev libxslt-dev libzip-dev \ ; \ docker-php-ext-configure \ gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ \ ; \ docker-php-ext-install -j$(nproc) \ bcmath bz2 calendar exif gettext gd intl mysqli opcache pcntl pdo_mysql soap xsl zip \ ; \ pecl channel-update pecl.php.net && \ pecl install -o -f \ redis \ ; \ docker-php-ext-enable \ redis \ ; \ runDeps="$( \ scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \ | tr ',' '\n' \ | sort -u \ | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ )"; \ apk add --virtual .phpexts-rundeps $runDeps; \ apk del .build-deps
The post Using APK for Alpine Linux with Docker appeared first on Justin Silver.
]]>The post Docker-CE on CentOS 7 appeared first on Justin Silver.
]]>Install Docker-CE (not just “docker) to get the latest version on CentOS.
yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum makecache fast yum install -y docker-ce chkconfig docker on service docker start
Update firewalld to allow host/container traffic.
Restart firewalld to pick up the changes.
# trust the docker interface firewall-cmd --permanent --zone=trusted --change-interface=docker0 # accept IPv4 traffic firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 4 -i docker0 -j ACCEPT # any ports on the host you want to access from the containers (strapi port 1337 here) firewall-cmd --permanent --zone=trusted --add-port=1337/tcp firewall-cmd --reload service docker restart
Create a group named “docker” and add any users that are allowed to create containers.
groupadd docker # allow users to access docker by adding them to the docker group # usermod -aG docker $USER
Use an entrypoint file to create an entry in /etc/hosts to point to the host. Requires ping
and ip
on the machine, on Debian these are found in the apt packages inetutils-ping
and iproute
.
#!/bin/bash # fix for linux hosts HOST_DOMAIN="host.docker.internal" ping -q -c1 $HOST_DOMAIN > /dev/null 2>&1 if [ $? -ne 0 ]; then HOST_IP=$(ip route | awk 'NR==1 {print $3}') echo -e "$HOST_IP\t$HOST_DOMAIN" >> /etc/hosts fi exec "$@"
The post Docker-CE on CentOS 7 appeared first on Justin Silver.
]]>