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.
]]>