gproxy is a reverse proxy service AND library for creating flexible, expression-based, lets-encrypt/acme secured gRPC/http reverse proxies
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
}
docker:
docker pull graphikDB:gproxy:v1.0.2
homebrew(Mac):
brew tap graphik/tools git@github.com: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
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