diff --git a/defguardDocker/deployment/.github/workflows/release.yml b/defguardDocker/deployment/.github/workflows/release.yml
new file mode 100644
index 0000000..5da777d
--- /dev/null
+++ b/defguardDocker/deployment/.github/workflows/release.yml
@@ -0,0 +1,41 @@
+name: Release Charts
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ release:
+ runs-on: [self-hosted, Linux, X64]
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Configure Git
+ run: |
+ git config user.name "$GITHUB_ACTOR"
+ git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
+
+ - name: Install Helm
+ uses: azure/setup-helm@v3
+ with:
+ version: v3.14.0
+
+ # https://github.com/helm/chart-releaser-action/issues/74
+ - name: Add repositories
+ run: |
+ for dir in $(ls -d charts/*/); do
+ helm dependency list $dir 2> /dev/null | tail +2 | head -n -1 | awk '{ print "helm repo add " $1 " " $3 }' | while read cmd; do $cmd; done
+ done
+
+ - name: Run chart-releaser
+ uses: helm/chart-releaser-action@v1.6.0
+ env:
+ CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ with:
+ charts_dir: charts
+ skip_existing: true
diff --git a/defguardDocker/deployment/.github/workflows/test.yml b/defguardDocker/deployment/.github/workflows/test.yml
new file mode 100644
index 0000000..65a0a9a
--- /dev/null
+++ b/defguardDocker/deployment/.github/workflows/test.yml
@@ -0,0 +1,46 @@
+name: Test setup script
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'docker-compose/**'
+ - '.github/workflows/test.yml'
+
+jobs:
+ test:
+ name: Test setup script
+ runs-on: [self-hosted, Linux]
+ steps:
+ - name: Login to GitHub container registry
+ uses: docker/login-action@v2
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Create working directory
+ run: mkdir temp
+ - name: Run setup script
+ env:
+ DEFGUARD_DOMAIN: "id.localhost"
+ DEFGUARD_ENROLLMENT_DOMAIN: "enrollment.localhost"
+ DEFGUARD_VPN_NAME: "test_location"
+ DEFGUARD_VPN_IP: "10.0.60.1/24"
+ DEFGUARD_VPN_GATEWAY_IP: "10.20.20.40"
+ DEFGUARD_VPN_GATEWAY_PORT: "50050"
+ CORE_IMAGE_TAG: latest
+ PROXY_IMAGE_TAG: latest
+ GATEWAY_IMAGE_TAG: latest
+ working-directory: temp
+ run: curl --proto '=https' --tlsv1.2 -sSf -L https://raw.githubusercontent.com/DefGuard/deployment/main/docker-compose/setup.sh | bash -s - --non-interactive
+ - name: Sleep for 10 seconds
+ working-directory: temp
+ run: sleep 10s
+ - name: Test defguard is available
+ working-directory: temp
+ run: curl -f http://id.localhost/api/v1/health
+ - name: Stop compose stack
+ if: always()
+ working-directory: temp
+ run: docker-compose down
diff --git a/defguardDocker/deployment/.gitignore b/defguardDocker/deployment/.gitignore
new file mode 100644
index 0000000..e5c0d50
--- /dev/null
+++ b/defguardDocker/deployment/.gitignore
@@ -0,0 +1,3 @@
+docker-compose/.env
+docker-compose/.volumes
+.idea
diff --git a/defguardDocker/deployment/LICENSE b/defguardDocker/deployment/LICENSE
new file mode 100644
index 0000000..8ddd140
--- /dev/null
+++ b/defguardDocker/deployment/LICENSE
@@ -0,0 +1,13 @@
+Copyright 2023 teonite ventures sp. z o.o. (teonite)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/defguardDocker/deployment/README.md b/defguardDocker/deployment/README.md
new file mode 100644
index 0000000..8e6b830
--- /dev/null
+++ b/defguardDocker/deployment/README.md
@@ -0,0 +1,16 @@
+
+
+
+
+# Defguard deployment
+
+Check our [documentation](https://defguard.gitbook.io/defguard/features/setting-up-your-instance) for deployment
+instructions.
+
+## Community and Support
+
+Find us on Matrix: [#defguard:teonite.com](https://matrix.to/#/#defguard:teonite.com)
+
+## Contribution
+
+Please review the [Contributing guide](https://defguard.gitbook.io/defguard/for-developers/contributing) for information on how to get started contributing to the project. You might also find our [environment setup guide](https://defguard.gitbook.io/defguard/for-developers/dev-env-setup) handy.
diff --git a/defguardDocker/deployment/charts/defguard-proxy/.helmignore b/defguardDocker/deployment/charts/defguard-proxy/.helmignore
new file mode 100644
index 0000000..0e8a0eb
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/defguardDocker/deployment/charts/defguard-proxy/Chart.yaml b/defguardDocker/deployment/charts/defguard-proxy/Chart.yaml
new file mode 100644
index 0000000..61a06d9
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+name: defguard-proxy
+description: Defguard proxy is a public-facing proxy for core defguard service
+
+type: application
+version: 0.3.5
+appVersion: 0.5.0
diff --git a/defguardDocker/deployment/charts/defguard-proxy/templates/NOTES.txt b/defguardDocker/deployment/charts/defguard-proxy/templates/NOTES.txt
new file mode 100644
index 0000000..d8d21a5
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/templates/NOTES.txt
@@ -0,0 +1,20 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host }}/
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "defguard-proxy.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "defguard-proxy.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "defguard-proxy.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "defguard-proxy.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard-proxy/templates/_helpers.tpl b/defguardDocker/deployment/charts/defguard-proxy/templates/_helpers.tpl
new file mode 100644
index 0000000..b6b625e
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/templates/_helpers.tpl
@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "defguard-proxy.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "defguard-proxy.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "defguard-proxy.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "defguard-proxy.labels" -}}
+helm.sh/chart: {{ include "defguard-proxy.chart" . }}
+{{ include "defguard-proxy.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "defguard-proxy.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "defguard-proxy.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "defguard-proxy.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "defguard-proxy.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard-proxy/templates/config.yaml b/defguardDocker/deployment/charts/defguard-proxy/templates/config.yaml
new file mode 100644
index 0000000..5efcad2
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/templates/config.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ include "defguard-proxy.fullname" . }}-config
+ labels:
+ {{- include "defguard-proxy.labels" . | nindent 4 }}
+data:
+ DEFGUARD_PROXY_HTTP_PORT: {{ .Values.service.ports.http | quote }}
+ DEFGUARD_PROXY_GRPC_PORT: {{ .Values.service.ports.grpc | quote }}
diff --git a/defguardDocker/deployment/charts/defguard-proxy/templates/deployment.yaml b/defguardDocker/deployment/charts/defguard-proxy/templates/deployment.yaml
new file mode 100644
index 0000000..4e6da60
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/templates/deployment.yaml
@@ -0,0 +1,67 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "defguard-proxy.fullname" . }}
+ labels:
+ {{- include "defguard-proxy.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "defguard-proxy.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "defguard-proxy.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "defguard-proxy.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ envFrom:
+ - configMapRef:
+ name: {{ include "defguard-proxy.fullname" . }}-config
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: http
+ containerPort: {{ .Values.service.ports.http }}
+ protocol: TCP
+ - name: grpc
+ containerPort: {{ .Values.service.ports.grpc }}
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /api/v1/health
+ port: http
+ readinessProbe:
+ httpGet:
+ path: /api/v1/health
+ port: http
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/defguardDocker/deployment/charts/defguard-proxy/templates/grpc-service.yaml b/defguardDocker/deployment/charts/defguard-proxy/templates/grpc-service.yaml
new file mode 100644
index 0000000..b698b07
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/templates/grpc-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ traefik.ingress.kubernetes.io/service.serversscheme: h2c
+ name: {{ include "defguard-proxy.fullname" . }}-grpc
+ labels:
+ {{- include "defguard-proxy.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.ports.grpc }}
+ targetPort: grpc
+ protocol: TCP
+ name: grpc
+ selector:
+ {{- include "defguard-proxy.selectorLabels" . | nindent 4 }}
diff --git a/defguardDocker/deployment/charts/defguard-proxy/templates/ingress-grpc.yaml b/defguardDocker/deployment/charts/defguard-proxy/templates/ingress-grpc.yaml
new file mode 100644
index 0000000..30fdc66
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/templates/ingress-grpc.yaml
@@ -0,0 +1,52 @@
+{{- if .Values.ingress.grpc.enabled -}}
+{{- $fullName := include "defguard-proxy.fullname" . -}}
+{{- if and .Values.ingress.grpc.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
+ {{- if not (hasKey .Values.ingress.grpc.annotations "kubernetes.io/ingress.class") }}
+ {{- $_ := set .Values.ingress.grpc.annotations "kubernetes.io/ingress.class" .Values.ingress.grpc.className}}
+ {{- end }}
+{{- end }}
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}-grpc
+ labels:
+ {{- include "defguard-proxy.labels" . | nindent 4 }}
+ {{- with .Values.ingress.grpc.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if and .Values.ingress.grpc.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
+ ingressClassName: {{ .Values.ingress.grpc.className }}
+ {{- end }}
+ {{- if .Values.ingress.grpc.tls }}
+ tls:
+ - hosts:
+ - {{ .Values.ingress.grpc.host | quote }}
+ secretName: {{ printf "%s-grpc-tls" .Values.ingress.grpc.host }}
+ {{- end }}
+ rules:
+ - host: {{ .Values.ingress.grpc.host | quote }}
+ http:
+ paths:
+ - path: /
+ {{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
+ pathType: ImplementationSpecific
+ {{- end }}
+ backend:
+ {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
+ service:
+ name: {{ $fullName }}-grpc
+ port:
+ number: {{ .Values.service.ports.grpc }}
+ {{- else }}
+ serviceName: {{ $fullName }}-grpc
+ servicePort: {{ .Values.service.ports.grpc }}
+ {{- end }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard-proxy/templates/ingress-web.yaml b/defguardDocker/deployment/charts/defguard-proxy/templates/ingress-web.yaml
new file mode 100644
index 0000000..e13c124
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/templates/ingress-web.yaml
@@ -0,0 +1,52 @@
+{{- if .Values.ingress.web.enabled -}}
+{{- $fullName := include "defguard-proxy.fullname" . -}}
+{{- if and .Values.ingress.web.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
+ {{- if not (hasKey .Values.ingress.web.annotations "kubernetes.io/ingress.class") }}
+ {{- $_ := set .Values.ingress.web.annotations "kubernetes.io/ingress.class" .Values.ingress.web.className}}
+ {{- end }}
+{{- end }}
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}-web
+ labels:
+ {{- include "defguard-proxy.labels" . | nindent 4 }}
+ {{- with .Values.ingress.web.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if and .Values.ingress.web.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
+ ingressClassName: {{ .Values.ingress.web.className }}
+ {{- end }}
+ {{- if .Values.ingress.web.tls }}
+ tls:
+ - hosts:
+ - {{ .Values.ingress.web.host | quote }}
+ secretName: {{ printf "%s-web-tls" .Values.ingress.web.host }}
+ {{- end }}
+ rules:
+ - host: {{ .Values.ingress.web.host | quote }}
+ http:
+ paths:
+ - path: /
+ {{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
+ pathType: ImplementationSpecific
+ {{- end }}
+ backend:
+ {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
+ service:
+ name: {{ $fullName }}-web
+ port:
+ number: {{ .Values.service.ports.http }}
+ {{- else }}
+ serviceName: {{ $fullName }}-web
+ servicePort: {{ .Values.service.ports.http }}
+ {{- end }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard-proxy/templates/service.yaml b/defguardDocker/deployment/charts/defguard-proxy/templates/service.yaml
new file mode 100644
index 0000000..151f128
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/templates/service.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "defguard-proxy.fullname" . }}-web
+ labels:
+ {{- include "defguard-proxy.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.ports.http }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ selector:
+ {{- include "defguard-proxy.selectorLabels" . | nindent 4 }}
diff --git a/defguardDocker/deployment/charts/defguard-proxy/templates/serviceaccount.yaml b/defguardDocker/deployment/charts/defguard-proxy/templates/serviceaccount.yaml
new file mode 100644
index 0000000..a77a067
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "defguard-proxy.serviceAccountName" . }}
+ labels:
+ {{- include "defguard-proxy.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard-proxy/values.yaml b/defguardDocker/deployment/charts/defguard-proxy/values.yaml
new file mode 100644
index 0000000..02d3491
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard-proxy/values.yaml
@@ -0,0 +1,42 @@
+affinity: {}
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 10
+fullnameOverride: ""
+image:
+ pullPolicy: IfNotPresent
+ repository: ghcr.io/defguard/defguard-proxy
+ tag: ""
+imagePullSecrets: []
+ingress:
+ grpc:
+ annotations: {}
+ className: ""
+ enabled: true
+ host: enrollment-grpc.local
+ tls: false
+ web:
+ annotations: {}
+ className: ""
+ enabled: true
+ host: enrollment.local
+ tls: false
+nameOverride: ""
+nodeSelector: {}
+podAnnotations: {}
+podLabels: {}
+podSecurityContext: {}
+publicUrl: "http://enrollment.local"
+replicaCount: 1
+resources: {}
+securityContext: {}
+service:
+ ports:
+ http: 8080
+ grpc: 50051
+ type: ClusterIP
+serviceAccount:
+ annotations: {}
+ create: true
+tolerations: []
diff --git a/defguardDocker/deployment/charts/defguard/.helmignore b/defguardDocker/deployment/charts/defguard/.helmignore
new file mode 100644
index 0000000..0e8a0eb
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/defguardDocker/deployment/charts/defguard/Chart.lock b/defguardDocker/deployment/charts/defguard/Chart.lock
new file mode 100644
index 0000000..6a57515
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/Chart.lock
@@ -0,0 +1,9 @@
+dependencies:
+- name: postgresql
+ repository: https://charts.bitnami.com/bitnami
+ version: 12.12.10
+- name: defguard-proxy
+ repository: https://defguard.github.io/deployment
+ version: 0.3.5
+digest: sha256:de930b480616cfa369caf7b1447c5b3e729fce3e17994717ab0f64aa02c027e7
+generated: "2024-07-26T09:00:54.309522115+02:00"
diff --git a/defguardDocker/deployment/charts/defguard/Chart.yaml b/defguardDocker/deployment/charts/defguard/Chart.yaml
new file mode 100644
index 0000000..9444933
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/Chart.yaml
@@ -0,0 +1,17 @@
+apiVersion: v2
+name: defguard
+description: Defguard is an open-source enterprise wireGuard VPN with MFA and SSO
+
+type: application
+version: 0.7.6
+appVersion: 0.11.0
+
+dependencies:
+ - name: postgresql
+ condition: postgresql.enabled
+ version: 12.12.10
+ repository: https://charts.bitnami.com/bitnami
+ - name: defguard-proxy
+ condition: defguard-proxy.enabled
+ version: 0.3.5
+ repository: https://defguard.github.io/deployment
diff --git a/defguardDocker/deployment/charts/defguard/charts/defguard-proxy-0.3.5.tgz b/defguardDocker/deployment/charts/defguard/charts/defguard-proxy-0.3.5.tgz
new file mode 100644
index 0000000..830a28c
Binary files /dev/null and b/defguardDocker/deployment/charts/defguard/charts/defguard-proxy-0.3.5.tgz differ
diff --git a/defguardDocker/deployment/charts/defguard/charts/postgresql-12.12.10.tgz b/defguardDocker/deployment/charts/defguard/charts/postgresql-12.12.10.tgz
new file mode 100644
index 0000000..89bcc97
Binary files /dev/null and b/defguardDocker/deployment/charts/defguard/charts/postgresql-12.12.10.tgz differ
diff --git a/defguardDocker/deployment/charts/defguard/templates/NOTES.txt b/defguardDocker/deployment/charts/defguard/templates/NOTES.txt
new file mode 100644
index 0000000..4550aad
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/NOTES.txt
@@ -0,0 +1,20 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host }}/
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "defguard.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "defguard.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "defguard.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "defguard.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard/templates/_helpers.tpl b/defguardDocker/deployment/charts/defguard/templates/_helpers.tpl
new file mode 100644
index 0000000..b373720
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/_helpers.tpl
@@ -0,0 +1,78 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "defguard.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "defguard.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "defguard.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "defguard.labels" -}}
+helm.sh/chart: {{ include "defguard.chart" . }}
+{{ include "defguard.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "defguard.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "defguard.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "defguard.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "defguard.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
+{{/*
+Define OpenID secret name
+*/}}
+{{- define "defguard.openidSecretName" -}}
+{{- $name := "openid-key" }}
+{{- $name }}
+{{- end }}
+
+{{/*
+Define JWT secret name
+*/}}
+{{- define "defguard.jwtSecretName" -}}
+{{- $name := "jwt-secrets" }}
+{{- $name }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard/templates/defguard-config.yaml b/defguardDocker/deployment/charts/defguard/templates/defguard-config.yaml
new file mode 100644
index 0000000..b645b48
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/defguard-config.yaml
@@ -0,0 +1,30 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ include "defguard.fullname" . }}-config
+ labels:
+ {{- include "defguard.labels" . | nindent 4 }}
+data:
+ {{- if .Values.cookie.domain }}
+ DEFGUARD_COOKIE_DOMAIN: {{ .Values.cookie.domain }}
+ {{- end }}
+ DEFGUARD_COOKIE_INSECURE: {{ .Values.cookie.insecure | quote }}
+ DEFGUARD_DB_HOST: {{ .Values.postgresql.host | default (printf "%s-postgresql" (include "defguard.fullname" .)) }}
+ DEFGUARD_DB_PORT: {{ .Values.postgresql.port | quote}}
+ DEFGUARD_DB_NAME: {{ .Values.postgresql.auth.database }}
+ DEFGUARD_DB_USER: {{ .Values.postgresql.auth.username }}
+ DEFGUARD_GRPC_PORT: {{ .Values.service.ports.grpc | quote }}
+ DEFGUARD_ENROLLMENT_URL: {{ index .Values "defguard-proxy" "publicUrl" }}
+ {{- if .Values.proxyUrl }}
+ DEFGUARD_PROXY_URL: {{ .Values.proxyUrl }}
+ {{- end }}
+ DEFGUARD_URL: {{ .Values.publicUrl }}
+ DEFGUARD_WEBAUTHN_RP_ID: {{ .Values.ingress.web.host }}
+ {{- if .Values.ldap.enabled }}
+ DEFGUARD_LDAP_ADMIN_GROUP: {{ .Values.ldap.admin_group | quote }}
+ DEFGUARD_LDAP_BIND_PASSWORD: {{ .Values.ldap.bind_password | quote }}
+ DEFGUARD_LDAP_BIND_USERNAME: {{ .Values.ldap.bind_username | quote }}
+ DEFGUARD_LDAP_GROUP_SEARCH_BASE: {{ .Values.ldap.group_search_base | quote }}
+ DEFGUARD_LDAP_USER_SEARCH_BASE: {{ .Values.ldap.user_search_base | quote }}
+ DEFGUARD_LDAP_URL: {{ .Values.ldap.url | quote }}
+ {{- end }}
diff --git a/defguardDocker/deployment/charts/defguard/templates/defguard-deployment.yaml b/defguardDocker/deployment/charts/defguard/templates/defguard-deployment.yaml
new file mode 100644
index 0000000..f1713a0
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/defguard-deployment.yaml
@@ -0,0 +1,105 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "defguard.fullname" . }}
+ labels:
+ {{- include "defguard.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "defguard.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "defguard.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "defguard.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ env:
+ - name: DEFGUARD_DB_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: {{ .Values.postgresql.auth.existingSecret }}
+ key: {{ .Values.postgresql.auth.existingSecretPasswordKey | default "password" }}
+ - name: DEFGUARD_AUTH_SECRET
+ valueFrom:
+ secretKeyRef:
+ name: {{ .Values.existingJwtSecret | default (include "defguard.jwtSecretName" .) }}
+ key: auth
+ - name: DEFGUARD_GATEWAY_SECRET
+ valueFrom:
+ secretKeyRef:
+ name: {{ .Values.existingJwtSecret | default (include "defguard.jwtSecretName" .) }}
+ key: gateway
+ - name: DEFGUARD_YUBIBRIDGE_SECRET
+ valueFrom:
+ secretKeyRef:
+ name: {{ .Values.existingJwtSecret | default (include "defguard.jwtSecretName" .) }}
+ key: yubi-bridge
+ - name: DEFGUARD_SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: {{ .Values.existingJwtSecret | default (include "defguard.jwtSecretName" .) }}
+ key: secret-key
+ - name: DEFGUARD_OPENID_KEY
+ value: "/etc/defguard-openid-key.pem"
+ envFrom:
+ - configMapRef:
+ name: {{ include "defguard.fullname" . }}-config
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: http
+ containerPort: 8000
+ protocol: TCP
+ - name: grpc
+ containerPort: 50055
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /api/v1/health
+ port: http
+ readinessProbe:
+ httpGet:
+ path: /api/v1/health
+ port: http
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ volumeMounts:
+ - name: openid-key
+ mountPath: "/etc/defguard-openid-key.pem"
+ readOnly: true
+ subPath: openid-key
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ volumes:
+ - name: openid-key
+ secret:
+ secretName: {{ .Values.existingOpenIdSecret | default (include "defguard.openidSecretName" .) }}
+ optional: false
diff --git a/defguardDocker/deployment/charts/defguard/templates/defguard-secret.yaml b/defguardDocker/deployment/charts/defguard/templates/defguard-secret.yaml
new file mode 100644
index 0000000..b5758e1
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/defguard-secret.yaml
@@ -0,0 +1,25 @@
+{{ if not .Values.existingJwtSecret }}
+{{- $auth := (randAlpha 16) | b64enc | quote }}
+{{- $gateway := (randAlpha 16) | b64enc | quote }}
+{{- $yubiBridge := (randAlpha 16) | b64enc | quote }}
+{{- $secretKey := (randAlpha 64) | b64enc | quote }}
+{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "defguard.jwtSecretName" .)) }}
+{{- if $secret }}
+{{- $auth = index $secret.data "auth" }}
+{{- $gateway = index $secret.data "gateway" }}
+{{- $yubiBridge = index $secret.data "yubi-bridge" }}
+{{- $secretKey = index $secret.data "secret-key" }}
+{{- end }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ include "defguard.jwtSecretName" . }}
+ labels:
+ {{- include "defguard.labels" . | nindent 4 }}
+type: Opaque
+data:
+ auth: {{ $auth }}
+ gateway: {{ $gateway }}
+ yubi-bridge: {{ $yubiBridge }}
+ secret-key: {{ $secretKey }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard/templates/defguard-service.yaml b/defguardDocker/deployment/charts/defguard/templates/defguard-service.yaml
new file mode 100644
index 0000000..fa6f8cf
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/defguard-service.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "defguard.fullname" . }}-web
+ labels:
+ {{- include "defguard.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.ports.http }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ selector:
+ {{- include "defguard.selectorLabels" . | nindent 4 }}
diff --git a/defguardDocker/deployment/charts/defguard/templates/grpc-service.yaml b/defguardDocker/deployment/charts/defguard/templates/grpc-service.yaml
new file mode 100644
index 0000000..edfef6c
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/grpc-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ traefik.ingress.kubernetes.io/service.serversscheme: h2c
+ name: {{ include "defguard.fullname" . }}-grpc
+ labels:
+ {{- include "defguard.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.ports.grpc }}
+ targetPort: grpc
+ protocol: TCP
+ name: grpc
+ selector:
+ {{- include "defguard.selectorLabels" . | nindent 4 }}
diff --git a/defguardDocker/deployment/charts/defguard/templates/ingress-grpc.yaml b/defguardDocker/deployment/charts/defguard/templates/ingress-grpc.yaml
new file mode 100644
index 0000000..189ce8e
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/ingress-grpc.yaml
@@ -0,0 +1,52 @@
+{{- if .Values.ingress.grpc.enabled -}}
+{{- $fullName := include "defguard.fullname" . -}}
+{{- if and .Values.ingress.grpc.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
+ {{- if not (hasKey .Values.ingress.grpc.annotations "kubernetes.io/ingress.class") }}
+ {{- $_ := set .Values.ingress.grpc.annotations "kubernetes.io/ingress.class" .Values.ingress.grpc.className}}
+ {{- end }}
+{{- end }}
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}-grpc
+ labels:
+ {{- include "defguard.labels" . | nindent 4 }}
+ {{- with .Values.ingress.grpc.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if and .Values.ingress.grpc.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
+ ingressClassName: {{ .Values.ingress.grpc.className }}
+ {{- end }}
+ {{- if .Values.ingress.grpc.tls }}
+ tls:
+ - hosts:
+ - {{ .Values.ingress.grpc.host | quote }}
+ secretName: {{ printf "%s-grpc-tls" .Values.ingress.grpc.host }}
+ {{- end }}
+ rules:
+ - host: {{ .Values.ingress.grpc.host | quote }}
+ http:
+ paths:
+ - path: /
+ {{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
+ pathType: ImplementationSpecific
+ {{- end }}
+ backend:
+ {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
+ service:
+ name: {{ $fullName }}-grpc
+ port:
+ number: {{ .Values.service.ports.grpc }}
+ {{- else }}
+ serviceName: {{ $fullName }}-grpc
+ servicePort: {{ .Values.service.ports.grpc }}
+ {{- end }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard/templates/ingress-web.yaml b/defguardDocker/deployment/charts/defguard/templates/ingress-web.yaml
new file mode 100644
index 0000000..c53c7c6
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/ingress-web.yaml
@@ -0,0 +1,52 @@
+{{- if .Values.ingress.web.enabled -}}
+{{- $fullName := include "defguard.fullname" . -}}
+{{- if and .Values.ingress.web.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
+ {{- if not (hasKey .Values.ingress.web.annotations "kubernetes.io/ingress.class") }}
+ {{- $_ := set .Values.ingress.web.annotations "kubernetes.io/ingress.class" .Values.ingress.web.className}}
+ {{- end }}
+{{- end }}
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}-web
+ labels:
+ {{- include "defguard.labels" . | nindent 4 }}
+ {{- with .Values.ingress.web.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if and .Values.ingress.web.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
+ ingressClassName: {{ .Values.ingress.web.className }}
+ {{- end }}
+ {{- if .Values.ingress.web.tls }}
+ tls:
+ - hosts:
+ - {{ .Values.ingress.web.host | quote }}
+ secretName: {{ printf "%s-web-tls" .Values.ingress.web.host }}
+ {{- end }}
+ rules:
+ - host: {{ .Values.ingress.web.host | quote }}
+ http:
+ paths:
+ - path: /
+ {{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
+ pathType: ImplementationSpecific
+ {{- end }}
+ backend:
+ {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
+ service:
+ name: {{ $fullName }}-web
+ port:
+ number: {{ .Values.service.ports.http }}
+ {{- else }}
+ serviceName: {{ $fullName }}-web
+ servicePort: {{ .Values.service.ports.http }}
+ {{- end }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard/templates/openid-secret.yaml b/defguardDocker/deployment/charts/defguard/templates/openid-secret.yaml
new file mode 100644
index 0000000..ba67053
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/openid-secret.yaml
@@ -0,0 +1,16 @@
+{{ if not .Values.existingOpenIdSecret }}
+{{- $openIdKey := (genPrivateKey "rsa") | b64enc | quote }}
+{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "defguard.openidSecretName" .)) }}
+{{- if $secret }}
+{{- $openIdKey = index $secret.data "openid-key" }}
+{{- end }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ include "defguard.openidSecretName" . }}
+ labels:
+ {{- include "defguard.labels" . | nindent 4 }}
+type: Opaque
+data:
+ openid-key: {{ $openIdKey }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard/templates/postgresql-secret.yaml b/defguardDocker/deployment/charts/defguard/templates/postgresql-secret.yaml
new file mode 100644
index 0000000..efdc2c4
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/postgresql-secret.yaml
@@ -0,0 +1,19 @@
+{{ if .Values.postgresql.enabled }}
+{{- $password := (randAlpha 16) | b64enc | quote }}
+{{- $postgresPassword := (randAlpha 16) | b64enc | quote }}
+{{- $secret := (lookup "v1" "Secret" .Release.Namespace .Values.postgresql.auth.existingSecret) }}
+{{- if $secret }}
+{{- $password = index $secret.data "password" }}
+{{- $postgresPassword = index $secret.data "postgres-password" }}
+{{- end }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Values.postgresql.auth.existingSecret }}
+ labels:
+ {{- include "defguard.labels" . | nindent 4 }}
+type: Opaque
+data:
+ password: {{ $password }}
+ postgres-password: {{ $postgresPassword }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard/templates/serviceaccount.yaml b/defguardDocker/deployment/charts/defguard/templates/serviceaccount.yaml
new file mode 100644
index 0000000..1efc1cc
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "defguard.serviceAccountName" . }}
+ labels:
+ {{- include "defguard.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/defguardDocker/deployment/charts/defguard/values.yaml b/defguardDocker/deployment/charts/defguard/values.yaml
new file mode 100644
index 0000000..408019d
--- /dev/null
+++ b/defguardDocker/deployment/charts/defguard/values.yaml
@@ -0,0 +1,75 @@
+affinity: {}
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 10
+cookie:
+ domain: ""
+ insecure: false
+fullnameOverride: ""
+image:
+ pullPolicy: IfNotPresent
+ repository: ghcr.io/defguard/defguard
+ tag: ""
+imagePullSecrets: []
+ingress:
+ grpc:
+ annotations: {}
+ className: ""
+ enabled: true
+ host: defguard-grpc.local
+ tls: false
+ web:
+ annotations: {}
+ className: ""
+ enabled: true
+ host: defguard.local
+ tls: false
+existingJwtSecret: ""
+ldap:
+ admin_group: ""
+ bind_password: ""
+ bind_username: ""
+ enabled: false
+ group_search_base: ""
+ url: ""
+ user_search_base: ""
+nameOverride: ""
+nodeSelector: {}
+existingOpenIdSecret: ""
+podAnnotations: {}
+podLabels: {}
+podSecurityContext: {}
+# sub-chart bitnami/postgresql
+postgresql:
+ enabled: true
+ host: "" # set if using external postgresql ~ enabled: false
+ port: 5432
+ auth:
+ database: defguard
+ existingSecret: postgres-password
+ existingSecretPasswordKey: "" # set if using external postgresql ~ enabled: false
+ username: defguard
+proxyUrl: ""
+publicUrl: "http://defguard.local"
+replicaCount: 1
+resources: {}
+securityContext: {}
+service:
+ ports:
+ grpc: 50055
+ http: 80
+ type: ClusterIP
+serviceAccount:
+ annotations: {}
+ create: true
+tolerations: []
+# sub-chart defguard-proxy
+defguard-proxy:
+ enabled: false
+ publicUrl: "http://enrollment.local"
+ ingress:
+ grpc:
+ host: defguard-proxy-grpc.local
+ web:
+ host: enrollment.local
diff --git a/defguardDocker/deployment/docker-compose/.env.template b/defguardDocker/deployment/docker-compose/.env.template
new file mode 100644
index 0000000..61c2e22
--- /dev/null
+++ b/defguardDocker/deployment/docker-compose/.env.template
@@ -0,0 +1,31 @@
+# The best way to define each secret is to generate random strings with e.g.:
+#
+# openssl rand -base64 48 #this will generate a 48chars random string
+#
+# Please provide secret strings (do not share them) for:
+#
+# Secret used for JWT cryptography
+DEFGUARD_AUTH_SECRET=
+# Secret used for JWT cryptography in YubiBridge GRPC communication
+DEFGUARD_YUBIBRIDGE_SECRET=
+# Secret used for JWT cryptography in gateway GRPC communication
+DEFGUARD_GATEWAY_SECRET=
+# Secret used for private cookies cryptography; must be at least 64 characters long
+DEFGUARD_SECRET_KEY=
+# Database password
+DEFGUARD_DB_PASSWORD=
+# Public URL of your Defguard instance
+# E.g.: https://defguard.mycompany.com
+DEFGUARD_URL=
+# Webauthn RP ID (https://w3c.github.io/webauthn/#rp-id)
+# E.g.: defguard.mycompany.com (without http/https)
+DEFGUARD_WEBAUTHN_RP_ID=
+# Public URL of your defguard proxy gRPC server
+# DEFGUARD_PROXY_URL=
+# Public URL of your enrollment service
+# E.g.: https://enrollment.mycompany.com
+# DEFGUARD_ENROLLMENT_URL= # [ENROLLMENT]
+# Token used for VPN gateway authorization
+# DEFGUARD_TOKEN= # [VPN]
+# Enable insecure cookies when not using HTTPS
+# DEFGUARD_COOKIE_INSECURE=true # [HTTP]
diff --git a/defguardDocker/deployment/docker-compose/docker-compose.yaml b/defguardDocker/deployment/docker-compose/docker-compose.yaml
new file mode 100644
index 0000000..6c8ee79
--- /dev/null
+++ b/defguardDocker/deployment/docker-compose/docker-compose.yaml
@@ -0,0 +1,110 @@
+services:
+ db:
+ image: postgres:15-alpine
+ restart: unless-stopped
+ environment:
+ POSTGRES_DB: defguard
+ POSTGRES_USER: defguard
+ POSTGRES_PASSWORD: ${DEFGUARD_DB_PASSWORD}
+ volumes:
+ - ${VOLUME_DIR:-./.volumes}/db:/var/lib/postgresql/data
+ # ports:
+ # - "5432:5432"
+
+ caddy: # [PROXY]
+ image: caddy:2.7-alpine # [PROXY]
+ restart: unless-stopped # [PROXY]
+ volumes: # [PROXY]
+ - ${VOLUME_DIR:-./.volumes}/caddy/data:/data # [PROXY]
+ - ${VOLUME_DIR:-./.volumes}/caddy/config:/config # [PROXY]
+ - ${VOLUME_DIR:-./.volumes}/caddy/Caddyfile:/etc/caddy/Caddyfile # [PROXY]
+ ports: # [PROXY]
+ #http
+ - "8002:80" # [PROXY]
+ #https
+ - "6443:443" # [PROXY]
+
+ core:
+ image: ghcr.io/defguard/defguard:${CORE_IMAGE_TAG:-latest}
+ restart: unless-stopped
+ environment:
+ DEFGUARD_AUTH_SECRET: ${DEFGUARD_AUTH_SECRET}
+ DEFGUARD_GATEWAY_SECRET: ${DEFGUARD_GATEWAY_SECRET}
+ DEFGUARD_YUBIBRIDGE_SECRET: ${DEFGUARD_YUBIBRIDGE_SECRET}
+ DEFGUARD_SECRET_KEY: ${DEFGUARD_SECRET_KEY}
+ DEFGUARD_DEFAULT_ADMIN_PASSWORD: ${DEFGUARD_DEFAULT_ADMIN_PASSWORD}
+ DEFGUARD_DB_HOST: db
+ DEFGUARD_DB_PORT: 5432
+ DEFGUARD_DB_USER: defguard
+ DEFGUARD_DB_PASSWORD: ${DEFGUARD_DB_PASSWORD}
+ DEFGUARD_DB_NAME: defguard
+ DEFGUARD_URL: ${DEFGUARD_URL}
+ DEFGUARD_LOG_LEVEL: info
+ DEFGUARD_WEBAUTHN_RP_ID: ${DEFGUARD_WEBAUTHN_RP_ID}
+ DEFGUARD_COOKIE_INSECURE: ${DEFGUARD_COOKIE_INSECURE:-false}
+ DEFGUARD_ENROLLMENT_URL: ${DEFGUARD_ENROLLMENT_URL} # [ENROLLMENT]
+ DEFGUARD_PROXY_URL: https://proxy:50052 # [ENROLLMENT]
+ DEFGUARD_PROXY_GRPC_CA: /ssl/defguard-ca.pem # [ENROLLMENT]
+ DEFGUARD_GRPC_CERT: /ssl/defguard-grpc.crt
+ DEFGUARD_GRPC_KEY: /ssl/defguard-grpc.key
+ ## RSA setup guide: https://defguard.gitbook.io/defguard/community-features/setting-up-your-instance/docker-compose#openid-rsa-setup
+ DEFGUARD_OPENID_KEY: /keys/rsakey.pem
+ ## LDAP setup guide: https://defguard.gitbook.io/defguard/features/ldap-synchronization-setup
+ # DEFGUARD_LDAP_URL: ldap://localhost:389 # [LDAP]
+ # DEFGUARD_LDAP_BIND_USERNAME: cn=admin,dc=example,dc=org # [LDAP]
+ # DEFGUARD_LDAP_BIND_PASSWORD: password # [LDAP]
+ ports:
+ # web
+ - "9876:8000"
+ # grpc
+ - "50055:50055"
+ depends_on:
+ - db
+ volumes:
+ # SSL setup guide: https://defguard.gitbook.io/defguard/features/setting-up-your-instance/docker-compose#ssl-setup
+ - ${VOLUME_DIR:-./.volumes}/ssl:/ssl
+ ## RSA setup guide: https://defguard.gitbook.io/defguard/community-features/setting-up-your-instance/docker-compose#openid-rsa-setup
+ - ${VOLUME_DIR:-./.volumes}/core/rsakey.pem:/keys/rsakey.pem
+ proxy: # [ENROLLMENT]
+ image: ghcr.io/defguard/defguard-proxy:${PROXY_IMAGE_TAG:-latest} # [ENROLLMENT]
+ restart: unless-stopped # [ENROLLMENT]
+ environment: # [ENROLLMENT]
+ DEFGUARD_PROXY_GRPC_PORT: 50052 # [ENROLLMENT]
+ DEFGUARD_PROXY_GRPC_CERT: /ssl/defguard-proxy-grpc.crt # [ENROLLMENT]
+ DEFGUARD_PROXY_GRPC_KEY: /ssl/defguard-proxy-grpc.key # [ENROLLMENT]
+ volumes: # [ENROLLMENT]
+ #SSL setup guide: https://defguard.gitbook.io/defguard/features/setting-up-your-instance/docker-compose#ssl-setup
+ - ${VOLUME_DIR:-./.volumes}/ssl:/ssl # [ENROLLMENT]
+ ports:
+ # web
+ - "8588:8080"
+ depends_on: # [ENROLLMENT]
+ - core # [ENROLLMENT]
+
+ gateway: # [VPN]
+ image: ghcr.io/defguard/gateway:${GATEWAY_IMAGE_TAG:-latest} # [VPN]
+ restart: unless-stopped # [VPN]
+ network_mode: "host" # [VPN]
+ environment: # [VPN]
+ DEFGUARD_GRPC_URL: https://localhost:50055 # [VPN]
+ DEFGUARD_GRPC_CA: /ssl/defguard-ca.pem # [VPN]
+ DEFGUARD_STATS_PERIOD: 30 # [VPN]
+ DEFGUARD_TOKEN: ${DEFGUARD_TOKEN} # [VPN]
+ volumes: # [VPN]
+ - ${VOLUME_DIR:-./.volumes}/ssl:/ssl # [VPN]
+ cap_add: # [VPN]
+ - NET_ADMIN # [VPN]
+
+ gateway-OpenVPN: # [VPN]
+ image: ghcr.io/defguard/gateway:${GATEWAY_IMAGE_TAG:-latest} # [VPN]
+ restart: unless-stopped # [VPN]
+ network_mode: "host" # [VPN]
+ environment: # [VPN]
+ DEFGUARD_GRPC_URL: https://localhost:50055 # [VPN]
+ DEFGUARD_GRPC_CA: /ssl/defguard-ca.pem # [VPN]
+ DEFGUARD_STATS_PERIOD: 30 # [VPN]
+ DEFGUARD_TOKEN: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJEZWZHdWFyZCIsInN1YiI6IkRFRkdVQVJELU5FVFdPUkstNSIsImNsaWVudF9pZCI6IjUiLCJleHAiOjYwMTkyNjE4NDMsIm5iZiI6MTcyNDI5NDU0OH0.cV9dgj0B7hjT7LaLqbZ0sp8u-Fl71X13mnDppFXaD4E
+ volumes: # [VPN]
+ - ${VOLUME_DIR:-./.volumes}/ssl:/ssl # [VPN]
+ cap_add: # [VPN]
+ - NET_ADMIN # [VPN]
diff --git a/defguardDocker/deployment/docker-compose/setup.log.rGByG7 b/defguardDocker/deployment/docker-compose/setup.log.rGByG7
new file mode 100644
index 0000000..e69de29
diff --git a/defguardDocker/deployment/docker-compose/setup.sh b/defguardDocker/deployment/docker-compose/setup.sh
new file mode 100755
index 0000000..e99814b
--- /dev/null
+++ b/defguardDocker/deployment/docker-compose/setup.sh
@@ -0,0 +1,890 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+
+# This is a script that sets up an entire defguard instance (including core,
+# gateway, enrollment proxy and reverse proxy). It's goal is to prepare
+# a working instance by running a single command.
+
+set -o errexit # abort on nonzero exitstatus
+set -o pipefail # don't hide errors within pipes
+
+# Global variables
+VERSION="1.0.2"
+SECRET_LENGTH=64
+PASSWORD_LENGTH=16
+
+VOLUME_DIR=".volumes"
+SSL_DIR="${VOLUME_DIR}/ssl"
+RSA_DIR="${VOLUME_DIR}/core"
+
+COMPOSE_FILE="docker-compose.yaml"
+ENV_FILE=".env"
+LOG_FILE=$(mktemp setup.log.XXXXXX)
+
+BASE_COMPOSE_FILE_URL="https://raw.githubusercontent.com/DefGuard/deployment/main/docker-compose/docker-compose.yaml"
+BASE_ENV_FILE_URL="https://raw.githubusercontent.com/DefGuard/deployment/main/docker-compose/.env.template"
+
+CORE_IMAGE_TAG="${CORE_IMAGE_TAG:-latest}"
+GATEWAY_IMAGE_TAG="${GATEWAY_IMAGE_TAG:-latest}"
+PROXY_IMAGE_TAG="${PROXY_IMAGE_TAG:-latest}"
+
+
+#####################
+### MAIN FUNCTION ###
+#####################
+
+main() {
+ is_utf_term
+ is_term_color
+ tput reset
+ print_header
+
+ # display help `--help` argument is found
+ for i in $*; do
+ test "$i" == "--help" && print_usage && exit 0
+
+ # run non interactive
+ if [[ "$i" == "--non-interactive" ]]; then
+ CFG_NON_INTERACTIVE=1
+ # we need to remove this element from $* or getopt will return an error
+ set -- $(remove_element "$i" $*)
+ fi
+
+ # configure https
+ if [[ "$i" == "--use-https" ]]; then
+ CFG_USE_HTTPS=1
+ # we need to remove this element from $* or getopt will return an error
+ set -- $(remove_element "$i" $*)
+ fi
+ done
+
+ #
+ # First let's gather the ENV/command line variables
+ #
+
+ # load configuration from env variables
+ load_configuration_from_env
+
+ # load configuration from CLI options
+ load_configuration_from_cli "$@"
+
+ # load configuration from user inputs
+ if [ X$CFG_VOLUME_DIR != X ]; then
+ VOLUME_DIR=${CFG_VOLUME_DIR}
+ SSL_DIR="${VOLUME_DIR}/ssl"
+ RSA_DIR="${VOLUME_DIR}/core"
+ fi
+
+ export VOLUME_DIR
+
+ # We have enough to check the enviromnent
+ # so check if necessary tools are available
+ check_environment
+
+ # load configuration from user inputs
+ if ! [ $CFG_NON_INTERACTIVE ]; then
+ load_configuration_from_input
+ fi
+
+ # check that all required configuration options are set
+ validate_required_variables
+
+ # generate external service URLs based on config
+ generate_external_urls
+
+ # print out config
+ print_config
+
+ # set current working directory
+ WORK_DIR_PATH=$(pwd)
+
+ # setup RSA & SSL keys
+ setup_keys
+
+ # generate caddyfile
+ create_caddyfile
+
+ # generate `.env` file
+ generate_env_file
+
+ # enable insecure cookies if not using HTTPS
+ if ! [ "$CFG_USE_HTTPS" ]; then
+ uncomment_feature "HTTP" "${PROD_ENV_FILE}"
+ fi
+
+ # generate base docker-compose file
+ PROD_COMPOSE_FILE="${WORK_DIR_PATH}/${COMPOSE_FILE}"
+ if [ -f "$PROD_COMPOSE_FILE" ]; then
+ echo -n " ${TXT_BEGIN} Using existing docker-compose file at ${PROD_COMPOSE_FILE}... "
+ print_confirmation
+ else
+ fetch_base_compose_file
+ fi
+
+ # enable reverse proxy in compose file
+ uncomment_feature "PROXY" "${PROD_COMPOSE_FILE}"
+
+ # enable enrollment service in compose file
+ if [ "$CFG_ENABLE_ENROLLMENT" ]; then
+ enable_enrollment
+ fi
+
+ # fetch latest images
+ echo " ${TXT_BEGIN} Fetching latest Docker images: "
+ $COMPOSE_CMD -f "${PROD_COMPOSE_FILE}" --env-file "${PROD_ENV_FILE}" pull
+
+ # enable and setup VPN gateway
+ if [ "$CFG_ENABLE_VPN" ]; then
+ enable_vpn_gateway
+ fi
+
+ # start docker-compose stack
+ echo " ${TXT_BEGIN} Starting docker-compose stack"
+ $COMPOSE_CMD -f "${PROD_COMPOSE_FILE}" --env-file "${PROD_ENV_FILE}" up -d
+ if [ $? -ne 0 ]; then
+ echo >&2 "ERROR: failed to start docker-compose stack"
+ exit 1
+ fi
+
+ print_instance_summary
+}
+
+########################
+### HELPER FUNCTIONS ###
+########################
+
+check_character_support() {
+ local char="$1"
+ echo -e "$char" | grep -q "$char"
+}
+
+is_utf_term() {
+ if check_character_support "√"; then
+ TXT_CHECK="✓"
+ TXT_BEGIN="▶"
+ TXT_SUB="▷"
+ TXT_STAR="★"
+ TXT_X="✗"
+ TXT_INPUT="✍"
+ else
+ TXT_CHECK="+"
+ TXT_BEGIN=">>"
+ TXT_SUB=">"
+ TXT_STAR="*"
+ TXT_X="x"
+ TXT_INPUT=" ::"
+ fi
+}
+
+is_term_color() {
+
+ if [[ $TERM == *"256"* ]]; then
+ C_RED="\033[31m"
+ C_GREEN="\033[32m"
+ C_YELLOW="\033[33m"
+ C_BLUE="\033[34m"
+ C_WHITE="\033[37m"
+ C_GREY="\033[90m"
+
+ C_LRED="\033[91m"
+ C_LGREEN="\033[92m"
+ C_LYELLOW="\033[93m"
+ C_LBLUE="\033[94m"
+
+ C_BOLD="\033[1m"
+ C_ITALICS="\033[3m"
+ C_BG_GREY="\033[100m"
+ C_END="\033[0m"
+ else
+ C_RED=""
+ C_GREEN=""
+ C_YELLOW=""
+ C_BLUE=""
+ C_WHITE=""
+ C_GREY=""
+
+ C_LRED=""
+ C_LGREEN=""
+ C_LYELLOW=""
+ C_LBLUE=""
+
+ C_BOLD=""
+ C_ITALICS=""
+ C_BG_GREY=""
+ C_END=""
+ fi
+}
+
+# remove array element
+remove_element() {
+ local remove=$1
+ local result=()
+ for element in "$@"; do
+ if [[ "$element" != "$remove" ]]; then
+ result+=("$element")
+ fi
+ done
+ echo "${result[@]}"
+}
+
+# Function to convert relative path to absolute path
+to_absolute_path() {
+ local path="$1"
+ if [[ "${path:0:1}" != "/" ]]; then
+ path="$(cd "$(dirname "$path")" && pwd)/$(basename "$path")"
+ fi
+ echo ${path}
+}
+
+print_header() {
+ echo -e "${C_LBLUE}"
+ cat << _EOF_
+ #
+ ## #
+ ## ## # # ## #
+ ## ## # # # #
+ # ## # #### # #### ##### #### # # #### ### #### #
+ # ## ## # ## # ## # # # # # # # # # ##
+ ## ## # # ######## # # # # # # # # #
+ # ## ## # # # ## # ##### # # ###### # # #
+ # ## # # ## # # # # # # # # # # ##
+ ## ## #### # ##### # ####### #### # #### # # #### #
+ ## ## # # #
+ ## # #######
+ #
+_EOF_
+ echo -e "${C_END}"
+ echo
+ echo "defguard docker-compose deployment setup script v${VERSION}"
+ echo -e "Copyright (C) 2023-2024 ${C_BOLD}teonite${C_END} <${C_BG_GREY}${C_YELLOW}https://teonite.com${C_END}>"
+ echo
+}
+
+print_confirmation() {
+ echo -e " ${C_LGREEN}${TXT_CHECK}${C_END} "
+}
+
+print_usage() {
+
+ echo "Usage: ${BASENAME} [options]"
+ echo
+ echo 'Available options:'
+ echo
+ echo -e "\t--help this help message"
+ echo -e "\t--non-interactive run in non-interactive mode - !REQUIRES SETTING all options/env vars"
+ echo -e "\t--domain domain where defguard web UI will be available"
+ echo -e "\t--enrollment-domain domain where enrollment service will be available"
+ echo -e "\t--use-https configure reverse proxy to use HTTPS"
+ echo -e "\t--volume Docker volumes directory - default: ${VOLUME_DIR}"
+ echo -e "\t--vpn-name VPN location name"
+ echo -e "\t--vpn-ip VPN server address & netmask (e.g. 10.0.50.1/24)"
+ echo -e "\t--vpn-gateway-ip VPN gateway external IP (! NOT DOMAIN - IP)"
+ echo -e "\t--vpn-gateway-port VPN gateway external port (your clients connect here)"
+ echo
+}
+
+command_exists() {
+ local command="$1"
+ command -v "$command" >/dev/null 2>&1
+}
+
+command_exists_check() {
+ local command="$1"
+ if ! command_exists "$command"; then
+ echo >&2 "ERROR: $command command not found"
+ echo >&2 "ERROR: dependency failed, exiting..."
+ exit 2
+ fi
+}
+
+check_environment() {
+ echo -n " ${TXT_BEGIN} Checking if all required tools are available..."
+ # compose can be provided by newer docker versions or a separate docker-compose
+ docker compose version >/dev/null 2>&1
+ if [ $? = 0 ]; then
+ COMPOSE_CMD="docker compose"
+ else
+ if command_exists docker-compose; then
+ COMPOSE_CMD="docker-compose"
+ else
+ echo
+ echo >&2 "ERROR: docker-compose or docker compose command not found"
+ echo >&2 "ERROR: dependency failed, exiting..."
+ exit 3
+ fi
+ fi
+
+ command_exists_check openssl
+ command_exists_check curl
+ command_exists_check grep
+
+ # Check if the volume dir is an absolute path since docker requires it
+ VOLUME_DIR=$(to_absolute_path "${VOLUME_DIR}")
+
+ if [ -d ${VOLUME_DIR} ]; then
+ echo
+ echo >&2 "ERROR: volume directory: ${VOLUME_DIR} exists."
+ echo >&2 "ERROR: this means, I would overwrite the configuration, database and certificates."
+ echo >&2 "ERROR: please backup or remove the volume directory."
+ exit 3
+ fi
+
+ # create all necessary directories
+ for dir in ${VOLUME_DIR} ${SSL_DIR} ${RSA_DIR}; do
+ mkdir ${dir}
+ if [ $? -ne 0 ]; then
+ echo >&2 "ERROR: cloud not create volume directory: ${dir}"
+ exit 3
+ fi
+ done
+
+ print_confirmation
+}
+
+load_configuration_from_env() {
+ echo -n " ${TXT_BEGIN} Loading configuration from environment variables... "
+ # required variables
+ CFG_DOMAIN="$DEFGUARD_DOMAIN"
+
+ # optional variables
+ CFG_VOLUME_DIR="$DEFGUARD_VOLUME_DIR"
+ CFG_VPN_NAME="$DEFGUARD_VPN_NAME"
+ CFG_VPN_IP="$DEFGUARD_VPN_IP"
+ CFG_VPN_GATEWAY_IP="$DEFGUARD_VPN_GATEWAY_IP"
+ CFG_VPN_GATEWAY_PORT="$DEFGUARD_VPN_GATEWAY_PORT"
+ CFG_ENROLLMENT_DOMAIN="$DEFGUARD_ENROLLMENT_DOMAIN"
+ if ! [ $CFG_USE_HTTPS ]; then
+ CFG_USE_HTTPS="$DEFGUARD_USE_HTTPS"
+ fi
+
+ print_confirmation
+}
+
+load_configuration_from_cli() {
+ echo -n " ${TXT_BEGIN} Loading configuration from CLI arguments... "
+
+ ARGUMENT_LIST=(
+ "domain"
+ "enrollment-domain"
+ "volume"
+ "vpn-name"
+ "vpn-ip"
+ "vpn-gateway-ip"
+ "vpn-gateway-port"
+ )
+
+ # read arguments
+ opts=$(
+ getopt \
+ --longoptions "$(printf "%s:," "${ARGUMENT_LIST[@]}")" \
+ --name "$(basename "$0")" \
+ --options "" \
+ -- "$@"
+ )
+
+ eval set --$opts
+
+ while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --domain)
+ CFG_DOMAIN=$2
+ shift 2
+ ;;
+
+ --enrollment-domain)
+ CFG_ENROLLMENT_DOMAIN=$2
+ shift 2
+ ;;
+
+ --volume)
+ CFG_VOLUME_DIR=$2
+ shift 2
+ ;;
+
+ --vpn-name)
+ CFG_VPN_NAME=$2
+ shift 2
+ ;;
+
+ --vpn-ip)
+ CFG_VPN_IP=$2
+ shift 2
+ ;;
+
+ --vpn-gateway-ip)
+ CFG_VPN_GATEWAY_IP=$2
+ shift 2
+ ;;
+
+ --vpn-gateway-port)
+ CFG_VPN_GATEWAY_PORT=$2
+ shift 2
+ ;;
+
+ *)
+ break
+ ;;
+ esac
+ done
+
+ print_confirmation
+}
+
+load_configuration_from_input() {
+ echo -ne "${C_ITALICS}${C_LBLUE}"
+ cat << _EOF_
+
+Please provide the values to configure your defguard instance. If you've
+already configured some options by setting environment variables or through
+CLI options, those will be used as defaults.
+
+If you prefer to disable this user input section, please restart the script
+with --non-interactive CLI flag.
+
+_EOF_
+
+echo -ne "${C_GREY}"
+cat << _EOF_
+
+Choose domains that will be used to expose your instance through Caddy
+reverse proxy. defguard uses a separate domain for the Web UI, and for
+the optional enrollment/desktop client configuration/password reset
+service.
+
+If you don't provide any domain for the enrollment service, the service
+itself will not be deployed.
+
+You can also enable HTTPS here (highly recommended), which will configure
+Caddy to automatically provision SSL certificates.
+_EOF_
+
+echo -ne "${C_BOLD}"
+cat << _EOF_
+
+Please note that this requires your server to have a public IP address
+and public DNS records for your chosen domains to be configured
+correctly (pointing to your server's IP address).
+
+_EOF_
+
+ echo -ne "${C_END}"
+
+ echo -e " ${C_BOLD}${C_GREEN}${TXT_STAR} General config ${TXT_STAR}${C_END}\n"
+
+ while [ X${domain} = "X" ]; do
+ echo -ne "${C_YELLOW}${TXT_INPUT}${C_END} "
+ read -p "Enter defguard domain [default: ${CFG_DOMAIN}]: " domain
+ if [ "$domain" ]; then
+ CFG_DOMAIN="$domain"
+ fi
+ done
+
+ echo -ne "${C_YELLOW}${TXT_INPUT}${C_END} "
+ read -p "Enter enrollment domain [default: ${CFG_ENROLLMENT_DOMAIN}]: " enroll
+ if [ "$enroll" ]; then
+ CFG_ENROLLMENT_DOMAIN="$enroll"
+ fi
+
+ use_https_bool_value="false"
+ if [ $CFG_USE_HTTPS ]; then use_https_bool_value="true"; fi
+ echo -ne "${C_YELLOW}${TXT_INPUT}${C_END} "
+ read -p "Use HTTPS [default: ${use_https_bool_value}]: " https
+ if [ "$https" ]; then
+ CFG_USE_HTTPS=1
+ fi
+
+ echo
+ echo -e " ${C_BOLD}${C_GREEN}${TXT_STAR} WireGuard VPN${TXT_STAR}${C_END}\n"
+
+ echo -ne "${C_ITALICS}${C_GREY}"
+ cat << _EOF_
+
+If you wish to configure and deploy WireGuard VPN gateway, please
+provide your VPN location name. To skip, just press enter and VPN will
+not be configured.
+_EOF_
+
+ echo -ne "${C_END}\n"
+
+ echo -ne "${C_YELLOW}${TXT_INPUT}${C_END} "
+ read -p "Enter VPN location name [default: ${CFG_VPN_NAME}]: " vpn_name
+ if [ "$vpn_name" ]; then
+ CFG_VPN_NAME="$vpn_name"
+ fi
+
+ if [ "$CFG_VPN_NAME" ]; then
+ while [ X${vpn_ip} = "X" ]; do
+ echo -ne "${C_YELLOW}${TXT_INPUT}${C_END} "
+ read -p "Enter VPN server address and subnet (e.g. 10.0.60.1/24) [default: ${CFG_VPN_IP}]: " vpn_ip
+ if [ "$vpn_ip" ]; then
+ CFG_VPN_IP="$vpn_ip"
+ fi
+ done
+
+ echo -ne "${C_ITALICS}${C_GREY}"
+ cat << _EOF_
+
+Now we'll configure a public endpoint (IP + port) that your WireGuard
+client devices will use to safely connect to your gateway from the
+public internet.
+
+Since we'll be starting the gateway on this server the IP address should
+be the same as your server's public IP address.
+_EOF_
+ echo -ne "${C_BOLD}"
+ cat << _EOF_
+Please also remember that your firewall should be configured
+to allow incoming UDP traffic on the chosen WireGuard port.
+_EOF_
+
+ echo -ne "${C_END}"
+
+ while [ X${public_ip} = "X" ]; do
+ echo -ne "${C_YELLOW}${TXT_INPUT}${C_END} "
+ read -p "Enter VPN gateway public IP (no domains!) [default: ${CFG_VPN_GATEWAY_IP}]: " public_ip
+ if [ "$public_ip" ]; then
+ CFG_VPN_GATEWAY_IP="$public_ip"
+ fi
+ done
+
+ while [ X${public_port} = "X" ]; do
+ echo -ne "${C_YELLOW}${TXT_INPUT}${C_END} "
+ read -p "Enter VPN gateway public port [default: ${CFG_VPN_GATEWAY_PORT}]: " public_port
+ if [ "$public_port" ]; then
+ CFG_VPN_GATEWAY_PORT="$public_port"
+ fi
+ done
+
+ else
+ echo -e " ${C_BOLD}${C_RED}${TXT_X} ${C_GREY} WireGuard VPN skipped${C_END}\n"
+ fi
+
+ echo
+ echo -e "${C_BOLD}${C_GREEN}Thank you. We'll now proceed with the deployment using provided values.${C_END}"
+}
+
+check_required_variable() {
+ local var_name="$1"
+ if [ -z "${!var_name}" ]; then
+ echo >&2 "ERROR: ${var_name} configuration option not set"
+ exit 4
+ fi
+}
+
+validate_required_variables() {
+ echo -n " ${TXT_BEGIN} Validating configuration options..."
+ check_required_variable "CFG_DOMAIN"
+
+ # if VPN name is given validate other VPN configurations are present
+ if [ "$CFG_VPN_NAME" ]; then
+ CFG_ENABLE_VPN=1
+ check_required_variable "CFG_VPN_IP"
+ check_required_variable "CFG_VPN_GATEWAY_IP"
+ check_required_variable "CFG_VPN_GATEWAY_PORT"
+ fi
+
+ print_confirmation
+}
+
+generate_external_urls() {
+ # prepare full defguard URL
+ if [ $CFG_USE_HTTPS ]; then
+ CFG_DEFGUARD_URL="https://${CFG_DOMAIN}"
+ else
+ CFG_DEFGUARD_URL="http://${CFG_DOMAIN}"
+ fi
+
+ # prepare full enrollment URL
+ if [ "$CFG_ENROLLMENT_DOMAIN" ]; then
+ CFG_ENABLE_ENROLLMENT=1
+ if [ "$CFG_USE_HTTPS" ]; then
+ CFG_ENROLLMENT_URL="https://${CFG_ENROLLMENT_DOMAIN}"
+ else
+ CFG_ENROLLMENT_URL="http://${CFG_ENROLLMENT_DOMAIN}"
+ fi
+ fi
+}
+
+print_config() {
+ echo
+ echo " ${TXT_BEGIN} Setting up your defguard instance with following config:"
+ echo
+ echo -e " ${TXT_SUB} data volume: ${C_BOLD}${VOLUME_DIR}${C_END}"
+ echo
+ echo -e " ${TXT_SUB} domain: ${C_BOLD}${CFG_DOMAIN}${C_END}"
+ echo -e " ${TXT_SUB} web UI URL: ${C_BOLD}${CFG_DEFGUARD_URL}${C_END}"
+
+ if [ "$CFG_VPN_NAME" ]; then
+ echo -e " ${TXT_SUB} VPN location name: ${C_BOLD}${CFG_VPN_NAME}${C_END}"
+ echo -e " ${TXT_SUB} VPN address: ${C_BOLD}${CFG_VPN_IP}${C_END}"
+ echo -e " ${TXT_SUB} VPN gateway IP: ${C_BOLD}${CFG_VPN_GATEWAY_IP}${C_END}"
+ echo -e " ${TXT_SUB} VPN gateway port: ${C_BOLD}${CFG_VPN_GATEWAY_PORT}${C_END}"
+ fi
+
+ if [ "$CFG_ENROLLMENT_DOMAIN" ]; then
+ echo -e " ${TXT_SUB} Enrollment service domain: ${C_BOLD}${CFG_ENROLLMENT_DOMAIN}${C_END}"
+ echo -e " ${TXT_SUB} Enrollment service URL: ${C_BOLD}${CFG_ENROLLMENT_URL}${C_END}"
+ fi
+ echo
+ echo -e " ${TXT_BEGIN} All executed command's results are in log file: ${C_BOLD}${LOG_FILE}${C_END}"
+ echo
+}
+
+setup_keys() {
+ echo " ${TXT_BEGIN} Setting up SSL certificates and RSA keys..."
+ if [ -d ${SSL_DIR} -a "$(ls -A ${SSL_DIR})" ]; then
+ echo " ${TXT_SUB} Using existing SSL certificates from ${SSL_DIR}"
+ else
+ generate_certs
+ fi
+
+ if [ -d ${RSA_DIR} -a "$(ls -A ${RSA_DIR})" ]; then
+ echo " ${TXT_SUB} Using existing RSA keys from ${RSA_DIR}."
+ else
+ generate_rsa
+ fi
+}
+
+generate_certs() {
+ echo " ${TXT_BEGIN} Creating new SSL certificates in ${SSL_DIR}..."
+ mkdir -p ${SSL_DIR}
+
+ PASSPHRASE=$(generate_secret)
+
+ echo "PEM passphrase for SSL certificates set to '${PASSPHRASE}'."
+
+ # generate private key for CA
+ openssl genrsa -des3 -out ${SSL_DIR}/defguard-ca.key -passout pass:"${PASSPHRASE}" 2048 2>&1 >> ${LOG_FILE}
+ # generate Root Certificate
+ # TODO: allow configuring CA parameters
+ openssl req -x509 -new -nodes -key ${SSL_DIR}/defguard-ca.key -sha256 -days 1825 -out ${SSL_DIR}/defguard-ca.pem -passin pass:"${PASSPHRASE}" -subj "/C=PL/ST=Zachodniopomorskie/L=Szczecin/O=Example/OU=IT Department/CN=${CFG_DOMAIN}" 2>&1 >> ${LOG_FILE}
+
+ # generate CA-signed certificate for defguard gRPC
+ openssl genrsa -out ${SSL_DIR}/defguard-grpc.key 2048 2>&1 >> ${LOG_FILE}
+
+ openssl req -new -key ${SSL_DIR}/defguard-grpc.key -out ${SSL_DIR}/defguard-grpc.csr -subj "/C=PL/ST=Zachodniopomorskie/L=Szczecin/O=Example/OU=IT Department/CN=${CFG_DOMAIN}" 2>&1 >> ${LOG_FILE}
+ cat >${SSL_DIR}/defguard-grpc.ext <&1 >> ${LOG_FILE}
+
+ # generate CA-signed certificate for defguard proxy gRPC
+ openssl genrsa -out ${SSL_DIR}/defguard-proxy-grpc.key 2048 2>&1 >> ${LOG_FILE}
+
+ openssl req -new -key ${SSL_DIR}/defguard-proxy-grpc.key -out ${SSL_DIR}/defguard-proxy-grpc.csr -subj "/C=PL/ST=Zachodniopomorskie/L=Szczecin/O=Example/OU=IT Department/CN=${CFG_DOMAIN}" 2>&1 >> ${LOG_FILE}
+ cat >${SSL_DIR}/defguard-proxy-grpc.ext <&1 >> ${LOG_FILE}
+}
+
+generate_rsa() {
+ echo "Generating RSA keys in ${RSA_DIR}..."
+ mkdir -p ${RSA_DIR}
+ openssl genpkey -out ${RSA_DIR}/rsakey.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048 2>&1 >> ${LOG_FILE}
+
+}
+
+generate_secret() {
+ generate_secret_inner "${SECRET_LENGTH}"
+}
+
+generate_password() {
+ generate_secret_inner "${PASSWORD_LENGTH}"
+}
+
+generate_secret_inner() {
+ local length="$1"
+ openssl rand -base64 ${length} | tr -d "=+/" | tr -d '\n' | cut -c1-${length-1}
+}
+
+create_caddyfile() {
+ caddy_volume_path="${VOLUME_DIR}/caddy"
+ caddyfile_path="${caddy_volume_path}/Caddyfile"
+ mkdir -p ${caddy_volume_path}
+
+ cat >${caddyfile_path} <>${caddyfile_path} <>${caddyfile_path} <&1 >> ${LOG_FILE}
+
+ print_confirmation
+}
+
+generate_env_file() {
+ PROD_ENV_FILE="${WORK_DIR_PATH}/${ENV_FILE}"
+ fetch_base_env_file
+ update_env_file
+
+ print_confirmation
+}
+
+fetch_base_env_file() {
+ echo -e " ${TXT_BEGIN} Fetching base ${ENV_FILE} file for compose stack..."
+
+ curl --proto '=https' --tlsv1.2 -sSf "${BASE_ENV_FILE_URL}" -o "${PROD_ENV_FILE}" 2>&1 >> ${LOG_FILE}
+ print_confirmation
+}
+
+update_env_file() {
+ echo -n " ${TXT_BEGIN} Setting environment variables in ${ENV_FILE} file for compose stack..."
+
+ # set image versions
+ set_env_file_value "CORE_IMAGE_TAG" "${CORE_IMAGE_TAG}"
+ set_env_file_value "PROXY_IMAGE_TAG" "${PROXY_IMAGE_TAG}"
+ set_env_file_value "GATEWAY_IMAGE_TAG" "${GATEWAY_IMAGE_TAG}"
+
+ # fill in values
+ set_env_file_secret "DEFGUARD_AUTH_SECRET"
+ set_env_file_secret "DEFGUARD_YUBIBRIDGE_SECRET"
+ set_env_file_secret "DEFGUARD_GATEWAY_SECRET"
+ set_env_file_secret "DEFGUARD_SECRET_KEY"
+
+ # use existing password if set in env variable
+ if [ "$DEFGUARD_DB_PASSWORD" ]; then
+ set_env_file_value "DEFGUARD_DB_PASSWORD" "${DEFGUARD_DB_PASSWORD}"
+ else
+ set_env_file_password "DEFGUARD_DB_PASSWORD"
+ fi
+
+ DEFGUARD_DEFAULT_ADMIN_PASSWORD="$(generate_password)"
+ set_env_file_value "DEFGUARD_DEFAULT_ADMIN_PASSWORD" "${DEFGUARD_DEFAULT_ADMIN_PASSWORD}"
+
+ set_env_file_value "DEFGUARD_URL" "${CFG_DEFGUARD_URL}"
+ set_env_file_value "DEFGUARD_WEBAUTHN_RP_ID" "${CFG_DOMAIN}"
+ print_confirmation
+}
+
+set_env_file_value() {
+ # make sure variable exists in file
+ grep -qF "${1}=" "${PROD_ENV_FILE}" || echo "${1}=" >>"${PROD_ENV_FILE}"
+ sed -i "s@\(${1}\)=.*@\1=${2}@" "${PROD_ENV_FILE}"
+}
+
+set_env_file_secret() {
+ set_env_file_value "${1}" "$(generate_secret)" "${PROD_ENV_FILE}"
+}
+
+set_env_file_password() {
+ set_env_file_value "${1}" "$(generate_password)" "${PROD_ENV_FILE}"
+}
+
+uncomment_feature() {
+ sed -i "s@# \(.*\) # \[${1}\]@\1@" "${2}"
+}
+
+enable_enrollment() {
+ echo -n " ${TXT_BEGIN} Enabling enrollment proxy service in compose file..."
+
+ # update .env file
+ uncomment_feature "ENROLLMENT" "${PROD_ENV_FILE}"
+ set_env_file_value "DEFGUARD_ENROLLMENT_URL" "${CFG_ENROLLMENT_URL}"
+
+ # update compose file
+ uncomment_feature "ENROLLMENT" "${PROD_COMPOSE_FILE}"
+
+ print_confirmation
+}
+
+enable_vpn_gateway() {
+ echo " ${TXT_BEGIN} Enabling VPN gateway service..."
+
+ uncomment_feature "VPN" "${PROD_COMPOSE_FILE}"
+ uncomment_feature "VPN" "${PROD_ENV_FILE}"
+
+ # fetch latest image
+ echo " ${TXT_SUB} Fetching latest gateway image..."
+ $COMPOSE_CMD -f "${PROD_COMPOSE_FILE}" --env-file "${PROD_ENV_FILE}" pull gateway
+
+ # create VPN location
+ echo " ${TXT_BEGIN} Adding VPN to core & generating gateway token..."
+ VPN_NETWORK=`echo ${CFG_VPN_IP} | awk -F'[./]' '{print $1"."$2"."$3".0/"$5}'`
+ token=$($COMPOSE_CMD -f "${PROD_COMPOSE_FILE}" --env-file "${PROD_ENV_FILE}" run core init-vpn-location --name "${CFG_VPN_NAME}" --address "${CFG_VPN_IP}" --endpoint "${CFG_VPN_GATEWAY_IP}" --port "${CFG_VPN_GATEWAY_PORT}" --allowed-ips "${VPN_NETWORK}" | tail -n 1)
+ if [ $? -ne 0 ]; then
+ echo >&2 "ERROR: failed to create VPN network"
+ exit 1
+ fi
+
+ # add gateway token to .env file
+ set_env_file_value "DEFGUARD_TOKEN" "${token}"
+}
+
+print_instance_summary() {
+ echo
+ echo -e "${C_LGREEN} ${TXT_CHECK} defguard setup finished successfully${C_END}"
+ echo
+ echo "If your DNS configuration is correct your defguard instance should be available at:"
+ echo
+ echo -e "\t${TXT_SUB} Web UI: ${C_BOLD}${CFG_DEFGUARD_URL}${C_END}"
+ if [ "$CFG_ENABLE_ENROLLMENT" ]; then
+ echo -e "\t${TXT_SUB} Enrollment service: ${C_BOLD}${CFG_ENROLLMENT_URL}${C_END}"
+ fi
+ echo
+ echo -e " ${TXT_BEGIN} You can log into the UI using the default admin user:"
+ echo
+ echo -e "\t${TXT_SUB} username: ${C_BOLD}admin${C_END}"
+ echo -e "\t${TXT_SUB} password: ${C_BOLD}${DEFGUARD_DEFAULT_ADMIN_PASSWORD}${C_END}"
+ echo
+ if [ "$CFG_ENABLE_VPN" ]; then
+ echo -e "\t\tVPN server public endpoint is ${C_BOLD}${CFG_VPN_GATEWAY_IP}:${CFG_VPN_GATEWAY_PORT}${C_END}"
+ echo -e "\t\tVPN network is ${C_BOLD}${VPN_NETWORK}${C_END}"
+ echo -e "\t\t! Make sure your firewall allows external UDP traffic to port ${C_BOLD}${CFG_VPN_GATEWAY_PORT}${C_END} !"
+ echo
+ echo -e "\t\tTo test if the VPN is working: ping ${CFG_VPN_IP} (after connecting to VPN)"
+ fi
+ echo
+ echo -e "Files used to deploy your instance are stored in:"
+ echo -e "\t docker compose file: ${C_BOLD}${PROD_COMPOSE_FILE}${C_END}"
+ echo -e "\t docker compose environment: ${C_BOLD}${PROD_ENV_FILE}${C_END}"
+ echo
+ echo -e "Persistent data (docker volumes) is stored in ${C_BOLD}${VOLUME_DIR}${C_END}"
+ echo
+ echo -e " ${C_YELLOW}${TXT_STAR} To support our work, please star us on GitHub! ${TXT_STAR}${C_END}"
+ echo -e " ${C_YELLOW}${TXT_STAR} https://github.com/defguard/defguard ${TXT_STAR}${C_END}"
+ echo
+}
+
+# run main function
+main "$@" || exit 1
diff --git a/defguardDocker/deployment/docs/header.png b/defguardDocker/deployment/docs/header.png
new file mode 100644
index 0000000..3a02a4d
Binary files /dev/null and b/defguardDocker/deployment/docs/header.png differ
diff --git a/defguardDocker/deployment/gateway/.env.template b/defguardDocker/deployment/gateway/.env.template
new file mode 100644
index 0000000..69a402e
--- /dev/null
+++ b/defguardDocker/deployment/gateway/.env.template
@@ -0,0 +1,9 @@
+# Use userspace wireguard implementation, useful on systems without native wireguard support
+# Set to 0/1
+DEFGUARD_USERSPACE=0
+# Defguard GRPC URL, e.g.: defguard-grpc.mycompany.com
+DEFGUARD_GRPC_URL=
+# Token from Defguard app to secure gRPC connection, available on network page.
+DEFGUARD_TOKEN=
+# Defines how often (in seconds) should interface statistics be sent to Defguard server
+DEFGUARD_STATS_PERIOD=30
diff --git a/defguardDocker/deployment/gateway/docker-compose.yaml b/defguardDocker/deployment/gateway/docker-compose.yaml
new file mode 100644
index 0000000..807add2
--- /dev/null
+++ b/defguardDocker/deployment/gateway/docker-compose.yaml
@@ -0,0 +1,22 @@
+version: "3"
+services:
+ gateway:
+ image: ghcr.io/defguard/gateway:latest
+ restart: unless-stopped
+ network_mode: "host"
+ environment:
+ # load variables from .env file
+ - DEFGUARD_GRPC_URL
+ - DEFGUARD_TOKEN
+ - DEFGUARD_STATS_PERIOD
+ - RUST_LOG=debug
+ # SSL setup guide: https://defguard.gitbook.io/defguard/features/setting-up-your-instance/docker-compose#ssl-setup
+ # - DEFGUARD_GRPC_CA: /ssl/defguard-ca.pem
+ ports:
+ # wireguard endpoint
+ - "50051:50051/udp"
+ #volumes:
+ # SSL setup guide: https://defguard.gitbook.io/defguard/features/setting-up-your-instance/docker-compose#ssl-setup
+ #- ./.volumes/ssl:/ssl
+ cap_add:
+ - NET_ADMIN