blog-image

BorgWarehouse® with Kubernetes

  • dHENRY
  • 03/11/2023
  • (Reading time : 4 mn)

(**) Translated with www.DeepL.com/Translator

Benjamin (Raven) a member of the MytinyDC team behind the BorgWareHouse project, has upgraded his containerized application. Now it’s time to install it in the Kubernetes cluster.

How can Borgwarehouse be used with MytinyDC?

To replace BackupPC, which is responsible for backing up server configuration locally.
BackupPC is an excellent tool, which has done me proud, but has become too complex to install and configure.

With this new system, I have a container for storing data, and a script that performs daily backups of all servers.

Requirements

  • volumes to store configuration and backup data sent by Borg customers.
  • network access: ssh and https
  • WARNING**: For technical reasons linked to the use of the openssh-server service, the container cannot be run in READ-ONLY (Openshift).

Volumes

As indicated in its very detailed documentation (from the docker-compose file):

  • /home/borgwarehouse/app/config
  • /home/borgwarehouse/.ssh
  • /ssh_host:/etc/ssh
  • /repos:/home/borgwarehouse/repos

4 Persistent volumes are required, some of which will be used to store a single file in read-write mode (forget ConfigMap). The idea is to preserve all data from one instance to the next.

Network services

To be usable, this deployment must expose 2 ports:

  • ssh/tcp redirected to container port 22
  • http/tcp redirected to container port 3000

Use a reverse proxy to switch to “http S”. If you wish to use your own certificates within the container, adapt your “Services”/“Ingress” configuration.

graph TD U(user) A(admin) subgraph container HTTP(Http server) SSHS(Ssh server) end A-->|administration http|container U-->|borg backup process ssh|container

Les manifests

If there are any volunteers to provide Helm distribution, contact Raven.

YAML components

apiVersion: "v1"
kind: "Namespace"
metadata:
  name: "borgwarehouse"
  labels:
    name: "borgwarehouse"
---
# only if you need credential to pull image
apiVersion: 'v1'
kind: 'Secret'
metadata:
  name: 'dockerregistry'
  namespace: 'borgwarehouse'
type: 'kubernetes.io/dockerconfigjson'
data:
  .dockerconfigjson : your-secret-as-base64-encoded
---
apiVersion: v1
kind: "Secret"
metadata:
  name: "borgwarehouse-secret-envvars"
  namespace: "borgwarehouse"
type: "Opaque"
stringData:
  # Url to reach the IHM service
  NEXTAUTH_URL: "https://your.domain.com"
  NEXTAUTH_SECRET: "your-secret"
  CRONJOB_KEY: your-other-secret
  FQDN: "your.domain.com"
  # Port to reach ssh service
  SSH_SERVER_PORT: "your-exposed-ssh-port"
---
apiVersion: "v1"
kind: "PersistentVolumeClaim"
# in regards your cloud configuration

# 4 volumes - for config, /etc/ssh & ~/.ssh you could set to 1Mi
#             && repos set to (WyW)Gi
#  accessModes:
#    - "ReadWriteOnce"
#  resources:
#    requests:
#      storage: "1Mi"
---
# Adapt to your needs
apiVersion: "v1"
kind: "LimitRange"
metadata:
  name: "limitrange-borgwarehouse"
  namespace: "borgwarehouse"
spec:
  limits:
    - default:
        cpu: "1500m"
        memory: "800Mi"
      defaultRequest:
        cpu: "10m"
        memory: "50Mi"
      max:
        cpu: "1500m"
        memory: "800Mi"
      min:
        cpu: "10m"
        memory: "50Mi"
      type: Container
---
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
  name: "borgwarehouse"
  namespace: "borgwarehouse"
spec:
  # Adapt to your needs
  revisionHistoryLimit: 1
  strategy:
    type: "Recreate" # | rollingUpdate
  selector:
    matchLabels:
      app: "borgwarehouse"
  replicas: 1
  template:
    metadata:
      labels:
        app: "borgwarehouse"
    spec:
      imagePullSecrets:
        - name: "dockerregistry" # If you need secret to pull image
      securityContext:
        runAsUser: 1001
        runAsGroup: 1001
        fsGroup: 1001
        runAsNonRoot: true
      containers:
        - name: "borgwarehouse"
      containers:
      - name: 'borgwarehouse'
        env:
          - name: 'NEXTAUTH_URL'
            valueFrom :
              secretKeyRef:
                name: 'borgwarehouse-secret-envvars'
                key: 'NEXTAUTH_URL'
                optional: false
          - name: 'NEXTAUTH_SECRET'
            valueFrom :
              secretKeyRef:
                name: 'borgwarehouse-secret-envvars'
                key: 'NEXTAUTH_SECRET'
                optional: false
          - name: 'CRONJOB_KEY'
            valueFrom :
              secretKeyRef:
                name: 'borgwarehouse-secret-envvars'
                key: 'CRONJOB_KEY'
                optional: false
          - name: 'FQDN'
            valueFrom :
              secretKeyRef:
                name: 'borgwarehouse-secret-envvars'
                key: 'FQDN'
                optional: false
          - name: 'SSH_SERVER_PORT'
            valueFrom :
              secretKeyRef:
                name: 'borgwarehouse-secret-envvars'
                key: 'SSH_SERVER_PORT'
          image: "borgwarehouse/borgwarehouse:latest" # lastest is a bad practise...
          # Adapt to your needs
          imagePullPolicy: "Always"
          readinessProbe:
            httpGet:
              path: "/"
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 30
            timeoutSeconds: 3
          startupProbe:
            httpGet:
              path: "/"
              port: 3000
            periodSeconds: 10
            failureThreshold: 30
          livenessProbe:
            httpGet:
              path: "/"
              port: 3000
            periodSeconds: 120
            timeoutSeconds: 3
          securityContext:
          ports:
            - containerPort: 22
              protocol: "TCP"
              name: "port-22"
            - containerPort: 3000
              protocol: "TCP"
              name: "port-3000"
          volumeMounts:
            - mountPath: "/home/borgwarehouse/app/config"
              name: "xxxxx-borgwarehouse-config"
            - mountPath: "/home/borgwarehouse/repos"
              name: "xxxxx-borgwarehouse-repos"
            - mountPath: "/home/borgwarehouse/.ssh"
              name: "xxxxx-borgwarehouse-homedirssh"
            - mountPath: "/etc/ssh"
              name: "xxxxx-borgwarehouse-etcssh"
      volumes:
        - name: "xxxxx-borgwarehouse-config"
          persistentVolumeClaim:
            # because only this claimref is able to use final volumes
            claimName: "claimref-xxxxx-borgwarehouse-config"
        - name: "xxxxx-borgwarehouse-repos"
          persistentVolumeClaim:
            claimName: "claimref-xxxxx-borgwarehouse-repos"
        - name: "xxxxx-borgwarehouse-homedirssh"
          persistentVolumeClaim:
            claimName: "claimref-xxxxx-borgwarehouse-homedirssh"
        - name: "xxxxx-borgwarehouse-etcssh"
          persistentVolumeClaim:
            claimName: "claimref-xxxxx-borgwarehouse-etcssh"
---
apiVersion: "v1"
kind: "Service"
metadata:
  name: "borgwarehouse-app-port-22"
  namespace: "borgwarehouse"
spec:
  # Adapt to your cluster configuration
  type: "NodePort"
  ports:
    - port: 22
      protocol: "TCP"
      targetPort: 22
      name: "port-borgwarehouse-22"
  selector:
    app: "borgwarehouse"
---
apiVersion: "v1"
kind: "Service"
metadata:
  name: "borgwarehouse-app-port-3000"
  namespace: "borgwarehouse"
spec:
  # Adapt to your cluster configuration
  type: "NodePort"
  ports:
    - port: 3000
      protocol: "TCP"
      targetPort: 3000
      name: "port-borgwarehouse-3000"
  selector:
    app: "borgwarehouse"
---
## Your ingress definitions...
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: "borgwarehouse-app-port-3000"
  namespace: "borgwarehouse"
[...]
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: "borgwarehouse-app-port-22"
  namespace: "borgwarehouse"

After integration and application startup, check network access. To connect, please refer to the original documentation

+++

(**) Translated with www.DeepL.com/Translator

(*) Image Rendering Powered by