Compare commits
18 Commits
Defgard
...
e488c1eac1
| Author | SHA1 | Date | |
|---|---|---|---|
| e488c1eac1 | |||
| 2502ae556d | |||
| 328b8e40b7 | |||
| 53f68f6cd3 | |||
| c53a41433d | |||
| 8a0dc3d35b | |||
| 0bcf91830c | |||
| e1284dfcf9 | |||
| 74727d5092 | |||
| b504737ccd | |||
| 44e1fca7c4 | |||
| 99730bcd0f | |||
| 300dbe9857 | |||
| 8252e8664d | |||
| 9379a33afb | |||
| 92dd36c4f7 | |||
| 79c7ceeec1 | |||
| e1dfdf156d |
@@ -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
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
docker-compose/.env
|
||||||
|
docker-compose/.volumes
|
||||||
|
.idea
|
||||||
@@ -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.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="docs/header.png" alt="defguard">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# 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.
|
||||||
@@ -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/
|
||||||
@@ -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
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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: []
|
||||||
@@ -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/
|
||||||
@@ -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"
|
||||||
@@ -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
|
||||||
Binary file not shown.
Binary file not shown.
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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 }}
|
||||||
@@ -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
|
||||||
@@ -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=<YOUR_AUTH_SECRET>
|
||||||
|
# Secret used for JWT cryptography in YubiBridge GRPC communication
|
||||||
|
DEFGUARD_YUBIBRIDGE_SECRET=<DEFGUARD_YUBIBRIDGE_SECRET>
|
||||||
|
# Secret used for JWT cryptography in gateway GRPC communication
|
||||||
|
DEFGUARD_GATEWAY_SECRET=<DEFGUARD_GATEWAY_SECRET>
|
||||||
|
# Secret used for private cookies cryptography; must be at least 64 characters long
|
||||||
|
DEFGUARD_SECRET_KEY=<DEFGUARD_SECRET_KEY>
|
||||||
|
# Database password
|
||||||
|
DEFGUARD_DB_PASSWORD=<YOUR_DB_PASSWORD>
|
||||||
|
# Public URL of your Defguard instance
|
||||||
|
# E.g.: https://defguard.mycompany.com
|
||||||
|
DEFGUARD_URL=<YOUR_DEFGUARD_URL>
|
||||||
|
# Webauthn RP ID (https://w3c.github.io/webauthn/#rp-id)
|
||||||
|
# E.g.: defguard.mycompany.com (without http/https)
|
||||||
|
DEFGUARD_WEBAUTHN_RP_ID=<YOUR_DEFGUARD_WEBAUTHN_RP_ID>
|
||||||
|
# Public URL of your defguard proxy gRPC server
|
||||||
|
# DEFGUARD_PROXY_URL=<YOUR_PROXY_GRPC_URL>
|
||||||
|
# Public URL of your enrollment service
|
||||||
|
# E.g.: https://enrollment.mycompany.com
|
||||||
|
# DEFGUARD_ENROLLMENT_URL=<YOUR_PROXY_URL> # [ENROLLMENT]
|
||||||
|
# Token used for VPN gateway authorization
|
||||||
|
# DEFGUARD_TOKEN=<GATEWAY_TOKEN> # [VPN]
|
||||||
|
# Enable insecure cookies when not using HTTPS
|
||||||
|
# DEFGUARD_COOKIE_INSECURE=true # [HTTP]
|
||||||
@@ -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]
|
||||||
+890
@@ -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> domain where defguard web UI will be available"
|
||||||
|
echo -e "\t--enrollment-domain <domain> domain where enrollment service will be available"
|
||||||
|
echo -e "\t--use-https configure reverse proxy to use HTTPS"
|
||||||
|
echo -e "\t--volume <directory> Docker volumes directory - default: ${VOLUME_DIR}"
|
||||||
|
echo -e "\t--vpn-name <name> VPN location name"
|
||||||
|
echo -e "\t--vpn-ip <address> VPN server address & netmask (e.g. 10.0.50.1/24)"
|
||||||
|
echo -e "\t--vpn-gateway-ip <ip> VPN gateway external IP (! NOT DOMAIN - IP)"
|
||||||
|
echo -e "\t--vpn-gateway-port <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 <<EOF
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
[alt_names]
|
||||||
|
DNS.1 = ${CFG_DOMAIN}
|
||||||
|
DNS.2 = core
|
||||||
|
DNS.3 = localhost
|
||||||
|
EOF
|
||||||
|
openssl x509 -req -in ${SSL_DIR}/defguard-grpc.csr -CA ${SSL_DIR}/defguard-ca.pem -CAkey ${SSL_DIR}/defguard-ca.key -passin pass:"${PASSPHRASE}" -CAcreateserial \
|
||||||
|
-out ${SSL_DIR}/defguard-grpc.crt -days 1000 -sha256 -extfile ${SSL_DIR}/defguard-grpc.ext 2>&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 <<EOF
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
[alt_names]
|
||||||
|
DNS.1 = proxy
|
||||||
|
DNS.2 = localhost
|
||||||
|
EOF
|
||||||
|
openssl x509 -req -in ${SSL_DIR}/defguard-proxy-grpc.csr -CA ${SSL_DIR}/defguard-ca.pem -CAkey ${SSL_DIR}/defguard-ca.key -passin pass:"${PASSPHRASE}" -CAcreateserial \
|
||||||
|
-out ${SSL_DIR}/defguard-proxy-grpc.crt -days 1000 -sha256 -extfile ${SSL_DIR}/defguard-proxy-grpc.ext 2>&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} <<EOF
|
||||||
|
${CFG_DEFGUARD_URL} {
|
||||||
|
reverse_proxy core:8000
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if [ "$CFG_ENABLE_ENROLLMENT" ]; then
|
||||||
|
cat >>${caddyfile_path} <<EOF
|
||||||
|
${CFG_ENROLLMENT_URL} {
|
||||||
|
reverse_proxy proxy:8080
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >>${caddyfile_path} <<EOF
|
||||||
|
:80 {
|
||||||
|
respond 404
|
||||||
|
}
|
||||||
|
:443 {
|
||||||
|
respond 404
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch_base_compose_file() {
|
||||||
|
echo -n " ${TXT_BEGIN} Fetching base compose file to ${PROD_COMPOSE_FILE}... "
|
||||||
|
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf "${BASE_COMPOSE_FILE_URL}" -o "${PROD_COMPOSE_FILE}" 2>&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
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
@@ -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=<DEFGUARD_GRPC_URL>
|
||||||
|
# Token from Defguard app to secure gRPC connection, available on network page.
|
||||||
|
DEFGUARD_TOKEN=<DEFGUARD_TOKEN>
|
||||||
|
# Defines how often (in seconds) should interface statistics be sent to Defguard server
|
||||||
|
DEFGUARD_STATS_PERIOD=30
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck (tteckster)
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
____ __
|
||||||
|
/ __ \____ _____ ___ _____/ /__ __________ ____ ____ __ __
|
||||||
|
/ /_/ / __ `/ __ \/ _ \/ ___/ / _ \/ ___/ ___/___/ __ \/ __ `/ |/_/
|
||||||
|
/ ____/ /_/ / /_/ / __/ / / / __(__ |__ )___/ / / / /_/ /> <
|
||||||
|
/_/ \__,_/ .___/\___/_/ /_/\___/____/____/ /_/ /_/\__, /_/|_|
|
||||||
|
/_/ /____/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="Paperless-ngx"
|
||||||
|
var_disk="10"
|
||||||
|
var_cpu="2"
|
||||||
|
var_ram="2048"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
if [[ ! -d /opt/paperless ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
RELEASE=$(curl -s https://api.github.com/repos/paperless-ngx/paperless-ngx/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
||||||
|
|
||||||
|
UPD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUPPORT" --radiolist --cancel-button Exit-Script "Spacebar = Select" 11 58 2 \
|
||||||
|
"1" "Update Paperless-ngx to $RELEASE" ON \
|
||||||
|
"2" "Paperless-ngx Credentials" OFF \
|
||||||
|
3>&1 1>&2 2>&3)
|
||||||
|
header_info
|
||||||
|
if [ "$UPD" == "1" ]; then
|
||||||
|
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
|
||||||
|
msg_info "Stopping all Paperless-ngx Services"
|
||||||
|
systemctl stop paperless-consumer paperless-webserver paperless-scheduler paperless-task-queue.service
|
||||||
|
msg_ok "Stopped all Paperless-ngx Services"
|
||||||
|
|
||||||
|
msg_info "Updating to ${RELEASE}"
|
||||||
|
cd ~
|
||||||
|
wget -q https://github.com/paperless-ngx/paperless-ngx/releases/download/$RELEASE/paperless-ngx-$RELEASE.tar.xz
|
||||||
|
tar -xf paperless-ngx-$RELEASE.tar.xz
|
||||||
|
cp -r /opt/paperless/paperless.conf paperless-ngx/
|
||||||
|
cp -r paperless-ngx/* /opt/paperless/
|
||||||
|
cd /opt/paperless
|
||||||
|
pip install -r requirements.txt &>/dev/null
|
||||||
|
cd /opt/paperless/src
|
||||||
|
/usr/bin/python3 manage.py migrate &>/dev/null
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated to ${RELEASE}"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
cd ~
|
||||||
|
rm paperless-ngx-$RELEASE.tar.xz
|
||||||
|
rm -rf paperless-ngx
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
|
||||||
|
msg_info "Starting all Paperless-ngx Services"
|
||||||
|
systemctl start paperless-consumer paperless-webserver paperless-scheduler paperless-task-queue.service
|
||||||
|
sleep 1
|
||||||
|
msg_ok "Started all Paperless-ngx Services"
|
||||||
|
msg_ok "Updated Successfully!\n"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if [ "$UPD" == "2" ]; then
|
||||||
|
cat paperless.creds
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:8008${CL} \n"
|
||||||
Reference in New Issue
Block a user