# README
gproxy is a reverse proxy service AND library for creating flexible, expression-based, lets-encrypt/acme secured gRPC/http reverse proxies
GProxy as a Library
go get -u github.com/graphikDB/gproxy
- Automatic LetsEncrypt/Acme Based SSL Encryption
- Transparent gRPC Proxy(including streaming)
- Transparent http Proxy(including websockets)
- Expression-Based Routing
- Expression-Based Acme Host Policies
- Functional Arguments for extensive configuration of http(s) & grpc servers
- Graceful Shutdown
proxy, err := gproxy.New(ctx,
// serve unencrypted http/gRPC traffic on port 8080
gproxy.WithInsecurePort(8080),
// serve encrypted http/gRPC traffic on port 443
gproxy.WithSecurePort(443),
// if the request is http & the request host contains localhost, proxy to the target http server
// expression attributes: (this.http<bool>, this.grpc<bool>, this.host<string>, this.headers<map>, this.path<string>)
gproxy.WithRoute(fmt.Sprintf(`this.http && this.host.endsWith('graphikdb.io') => "%s"`, httpServer.URL)),
// if the request is gRPC & the request host contains localhost, proxy to the target gRPC server
gproxy.WithRoute(fmt.Sprintf(`this.grpc && this.host.endsWith('graphikdb.io') => "%s"`, grpcServer.URL)),
// when deploying, set the letsencrypt list of allowed domains
// expression attributes: (this.host<string>)
gproxy.WithAcmePolicy("this.host.contains('graphikdb.io')"))
if err != nil {
fmt.Println(err.Error())
return
}
// start blocking server
if err := proxy.Serve(ctx); err != nil {
fmt.Println(err.Error())
return
}
GProxy as a Service
docker:
docker pull graphikDB:gproxy:v1.0.2
homebrew(Mac):
brew tap graphik/tools [email protected]:graphikDB/graphik-homebrew.git
brew install gproxy
- Automatic LetsEncrypt/Acme Based SSL Encryption
- Transparent gRPC Proxy(including streaming)
- Transparent http Proxy(including websockets)
- Graceful Shutdown
- CORS
- Expression-Based Acme Host Policies
- Expression-Based Routing
- 12-Factor Config
- Hot Reload Config
- Dockerized(graphikDB:gproxy:v1.0.2)
- K8s Deployment Manifest
default config path: ./gproxy.yaml which may be changed with the --config flag or the GRAPHIK_CONFIG environmental variable
Example Config:
debug: true
autocert:
## expression attributes: (this.host<string>)
policy: "this.host.contains('graphikdb.io')"
routing:
## expression attributes: (this.http<bool>, this.grpc<bool>, this.host<string>, this.headers<map>, this.path<string>)
- "this.http && this.host.endsWith('graphikdb.io') => 'http://localhost:7821'"
- "this.grpc && this.host.endsWith('graphikdb.io') => 'localhost:7820'"
server:
insecure_port: 8080
secure_port: 443
cors:
origins: "*"
methods: "*"
headers:
- "GET"
- "POST"
- "PUT"
- "DELETE"
- "PATCH"
watch: true # hot reload config changes
Deployment
Kubernetes
example manifest:
apiVersion: v1
kind: Namespace
metadata:
name: gproxy
---
kind: ConfigMap
apiVersion: v1
metadata:
name: gproxy-config
namespace: gproxy
data:
gproxy.yaml: |-
debug: true
autocert:
## expression attributes: (this.host<string>)
policy: "this.host.contains('graphikdb.io')"
routing:
## expression attributes: (this.http<bool>, this.grpc<bool>, this.host<string>, this.headers<map>, this.path<string>)
- "this.http && this.host.endsWith('graphikdb.io') => { 'target': 'http://localhost:7821' }"
- "this.grpc && this.host.endsWith('graphikdb.io') => { 'target': 'localhost:7820' }"
server:
insecure_port: 80
secure_port: 443
cors:
origins: "*"
methods: "*"
headers:
- "GET"
- "POST"
- "PUT"
- "DELETE"
- "PATCH"
watch: true # hot reload config changes
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: gproxy
namespace: gproxy
labels:
app: gproxy
spec:
replicas: 1
selector:
matchLabels:
app: gproxy
serviceName: "gproxy"
template:
metadata:
labels:
app: gproxy
spec:
containers:
- name: gproxy
image: graphikdb/gproxy:v1.0.2
imagePullPolicy: Always
ports:
- containerPort: 80
- containerPort: 443
env:
- name: GPROXY_CONFIG
value: /tmp/gproxy/gproxy.yaml
volumeMounts:
- mountPath: /tmp/certs
name: certs-volume
- mountPath: /tmp/gproxy/gproxy.yaml
name: config-volume
subPath: gproxy.yaml
volumes:
- name: config-volume
configMap:
name: gproxy-config
volumeClaimTemplates:
- metadata:
name: certs-volume
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Mi
---
apiVersion: v1
kind: Service
metadata:
name: gproxy
namespace: gproxy
spec:
selector:
app: gproxy
ports:
- protocol: TCP
port: 80
name: insecure
- protocol: TCP
port: 443
name: secure
type: LoadBalancer
---
save to k8s.yaml & apply with
kubectl apply -f k8s.yaml
watch as pods come up:
kubectl get pods -n gproxy -w
check LoadBalancer ip:
kubectl get svc -n gproxy
# Functions
New creates a new proxy instance.
WithAcmePolicy sets an decision expression that specifies which host names the Acme client may respond to expression ref: github.com/graphikdb/trigger ex this.host.contains('graphikdb.io') expression attributes: (this.host<string>).
WithAutoRedirectHttps makes the proxy redirect http requests to https(443).
WithCertCacheDir sets the directory in which certificates will be cached (default: /tmp/certs).
WithGrpcInit executes the functions against the insecure grpc server before it starts.
WithGrpcsInit executes the functions against the grpc secure server before it starts.
WithHttpInit executes the functions against the http server before it starts.
WithHttpsInit executes the functions against the https server before it starts.
WithInsecurePort sets the port that non-encrypted traffic will be served on(default: 80).
WithLogger sets the proxies logger instance(optional).
WithMiddlewares may be used as an HttpInit option to add http middlewares to a server.
WithRoute adds a trigger/expression based route to the reverse proxy expression attributes: (this.http<bool>, this.grpc<bool>, this.host<string>, this.headers<map>, this.path<string>).
WithSecurePort sets the port that encrypted traffic will be served on(default: 443).
# Type aliases
Opt is a function that configures a Proxy instance.