🧯BuckUp

This section documents backup strategies for each middleware/app deployed in the 72602 cluster.

Backup Quick Reference

ServiceMethodDataFrequencyRestore
PostgreSQLpg_dumpAll databasesDaily cronspsql restore
RedisRDB/AOFCache dataOn-demandAuto on restart
Miniomc mirrorObject storagePeriodicmc mirror reverse
N8NWeb UI exportWorkflows + credentialsManualWeb UI import
Uptime KumaWeb UI BackupMonitors + settingsManualWeb UI upload
Open WebUISQLite copyChat history + configManualFile replace
HomepageGit-managedDashboard configOn commitkubectl apply
ElasticSearchSnapshot APIIndexesScheduledSnapshot restore
Git reposGitHub hostingSource codeAutomaticGit clone
Mar 7, 2024

Subsections of 🧯BuckUp

PostgreSQL

Prerequisites

alias pgk='kubectl -n database exec deployment/postgresql --'

全量备份所有数据库

pgk pg_dumpall -U postgres > postgresql-full-$(date +%Y%m%d).sql

备份单个数据库

pgk pg_dump -U postgres <dbname> > <dbname>-$(date +%Y%m%d).sql

备份到 PVC 内

pgk sh -c 'pg_dumpall -U postgres > /bitnami/postgresql/backup-$(date +%Y%m%d).sql'

从备份文件恢复

# 全量恢复
cat postgresql-full-20260512.sql | pgk psql -U postgres

# 单库恢复(先创建空库)
pgk psql -U postgres -c "CREATE DATABASE <dbname>;"
cat <dbname>-20260512.sql | pgk psql -U postgres -d <dbname>

定时备份(CronJob)

apiVersion: batch/v1
kind: CronJob
metadata:
  name: postgresql-backup
  namespace: database
spec:
  schedule: "0 3 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: m.daocloud.io/docker.io/bitnami/postgresql:latest
            command:
            - sh
            - -c
            - |
              pg_dumpall -U postgres -h postgresql \
                > /backup/postgresql-$(date +%Y%m%d%H%M).sql
              find /backup -name "*.sql" -mtime +7 -delete
            volumeMounts:
            - name: backup
              mountPath: /backup
          restartPolicy: Never
          volumes:
          - name: backup
            hostPath:
              path: /data/backups/postgresql
May 12, 2026

Redis

Manual RDB backup

# Trigger RDB save
kubectl -n storage exec redis-shared-master-0 -- redis-cli -a <password> SAVE

# Copy RDB file
kubectl -n storage cp redis-shared-master-0:/data/dump.rdb ./redis-backup-$(date +%Y%m%d).rdb

Manual AOF backup

# Trigger AOF rewrite
kubectl -n storage exec redis-shared-master-0 -- redis-cli -a <password> BGREWRITEAOF

# Copy AOF file
kubectl -n storage cp redis-shared-master-0:/data/appendonly.aof.1.base.rdb ./redis-aof-$(date +%Y%m%d).rdb

Restore

# Copy backup file to pod
kubectl -n storage cp ./redis-backup-20260512.rdb redis-shared-master-0:/data/dump.rdb

# Restart pod to reload RDB
kubectl -n storage delete pod redis-shared-master-0
# Redis will load dump.rdb on startup

⚠️ Redis data is ephemeral cache — for most apps, losing Redis is inconvenient but not catastrophic. Prioritize PostgreSQL backups.

May 12, 2026

Minio

Prerequisites

alias mc='kubectl -n storage exec deployment/minio -- mc'
mc config host add myminio http://minio.storage.svc:9000 <access-key> <secret-key>

Backup a bucket

mc mirror myminio/my-bucket ./backups/my-bucket/

Restore a bucket

mc mirror ./backups/my-bucket/ myminio/my-bucket

Backup all buckets (script)

for bucket in $(mc ls myminio | awk '{print $NF}'); do
  echo "Backing up $bucket ..."
  mc mirror myminio/$bucket ./backups/$bucket/
done

Scheduled backup (CronJob)

apiVersion: batch/v1
kind: CronJob
metadata:
  name: minio-backup
  namespace: storage
spec:
  schedule: "0 4 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: m.daocloud.io/docker.io/minio/mc:latest
            command:
            - sh
            - -c
            - |
              mc alias set myminio http://minio.storage.svc:9000 $ACCESS_KEY $SECRET_KEY
              mc mirror myminio/ ./backup/$(date +%Y%m%d)/
            env:
            - name: ACCESS_KEY
              valueFrom:
                secretKeyRef:
                  name: minio
                  key: root-user
            - name: SECRET_KEY
              valueFrom:
                secretKeyRef:
                  name: minio
                  key: root-password
            volumeMounts:
            - name: backup
              mountPath: /backup
          restartPolicy: Never
          volumes:
          - name: backup
            hostPath:
              path: /data/backups/minio
May 12, 2026

N8N

N8N 内置了工作流导入导出功能:

  1. 登录 https://n8n.72602.online
  2. 进入 Workflows 列表页面
  3. 勾选需要备份的工作流
  4. 点击 Download → 导出为 JSON 文件
  5. 如需恢复,点击 Import from File

Method 2: API Export

# 获取所有工作流
curl -s -u <email>:<password> https://n8n.72602.online/rest/workflows \
  | jq . > n8n-workflows-$(date +%Y%m%d).json

Method 3: PostgreSQL Database Backup

N8N 的工作流定义存储在 PostgreSQL 中。备份 PG 即可包含 N8N 数据:

pg_dump -U postgres -h postgresql.database n8n > n8n-db-$(date +%Y%m%d).sql

N8N 的凭证(Credentials)包含 API key 等敏感信息,建议在 Export 时选择 Include Credentials 并妥善保管导出的文件。

May 12, 2026

Open WebUI

Backup Chat History (SQLite)

Open WebUI 的数据默认存储在 SQLite 数据库中:

# 备份数据库文件
kubectl -n ai exec open-webui-0 -- cat /app/backend/data/webui.db > open-webui-$(date +%Y%m%d).db

Restore

# 复制备份文件到 pod
kubectl -n ai cp open-webui-20260512.db open-webui-0:/app/backend/data/webui.db

# 重启 pod 以重新加载数据库
kubectl -n ai delete pod open-webui-0

注意事项

  • 备份文件包含:聊天记录、用户设置、外部连接配置
  • 不包含:对话中的文件附件(存储在 static/uploads/ 目录)
  • 如需完整恢复,还需备份上传文件:
    kubectl -n ai exec open-webui-0 -- tar czf - /app/backend/data/uploads > open-webui-uploads-$(date +%Y%m%d).tar.gz
May 12, 2026

Uptime Kuma

Backup via Web UI

Uptime Kuma 内置了备份功能:

  1. 登录 https://uptime.72602.online
  2. 进入 SettingsBackup
  3. 点击 Export → 下载 JSON 文件
  4. 备份文件包含:所有监控项、状态页配置、通知设置

Restore

  1. 登录 Uptime Kuma
  2. 进入 SettingsBackup
  3. 点击 Import → 选择之前下载的 JSON 文件
  4. 确认后自动恢复所有配置

注意事项

  • 备份文件不包含监控历史数据,只包含配置
  • 历史数据存储在 SQLite 数据库中(/app/data/kuma.db
  • 如需保留历史,可以备份 SQLite 文件:
    kubectl -n monitor exec deploy/uptime-kuma -- cat /app/data/kuma.db > kuma-backup-$(date +%Y%m%d).db
May 12, 2026

Subsections of ElasticSearch

ES [Local Disk]

Preliminary

  • ElasticSearch has installed, if not check link

  • The elasticsearch.yml has configed path.repo, which should be set the same value of settings.location (this will be handled by helm chart, don’t worry)

    ES argocd-app yaml
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: elastic-search
    spec:
      syncPolicy:
        syncOptions:
        - CreateNamespace=true
      project: default
      source:
        repoURL: https://charts.bitnami.com/bitnami
        chart: elasticsearch
        targetRevision: 19.11.3
        helm:
          releaseName: elastic-search
          values: |
            global:
              kibanaEnabled: true
            clusterName: elastic
            image:
              registry: m.zjvis.net/docker.io
              pullPolicy: IfNotPresent
            security:
              enabled: false
            service:
              type: ClusterIP
            extraConfig:
              path:
                repo: /tmp
            ingress:
              enabled: true
              annotations:
                cert-manager.io/cluster-issuer: self-signed-ca-issuer
                nginx.ingress.kubernetes.io/rewrite-target: /$1
              hostname: elastic-search.dev.72602.online
              ingressClassName: nginx
              path: /?(.*)
              tls: true
            master:
              masterOnly: false
              replicaCount: 1
              persistence:
                enabled: false
              resources:
                requests:
                  cpu: 2
                  memory: 1024Mi
                limits:
                  cpu: 4
                  memory: 4096Mi
              heapSize: 2g
            data:
              replicaCount: 0
              persistence:
                enabled: false
            coordinating:
              replicaCount: 0
            ingest:
              enabled: true
              replicaCount: 0
              service:
                enabled: false
                type: ClusterIP
              ingress:
                enabled: false
            metrics:
              enabled: false
              image:
                registry: m.zjvis.net/docker.io
                pullPolicy: IfNotPresent
            volumePermissions:
              enabled: false
              image:
                registry: m.zjvis.net/docker.io
                pullPolicy: IfNotPresent
            sysctlImage:
              enabled: true
              registry: m.zjvis.net/docker.io
              pullPolicy: IfNotPresent
            kibana:
              elasticsearch:
                hosts:
                  - '{{ include "elasticsearch.service.name" . }}'
                port: '{{ include "elasticsearch.service.ports.restAPI" . }}'
            esJavaOpts: "-Xmx2g -Xms2g"        
      destination:
        server: https://kubernetes.default.svc
        namespace: application

    diff from oirginal file :

    extraConfig:
        path:
          repo: /tmp

Methods

Elasticsearch 做备份有两种方式,

  1. 是将数据导出成文本文件,比如通过elasticdump、esm等工具将存储在 Elasticsearch 中的数据导出到文件中。
  2. 是使用snapshot接口实现快照功能,增量备份文件

第一种方式相对简单,在数据量小的时候比较实用,但当应对大数据量场景时,更推荐使用snapshot api 的方式。

Steps

buckup

asdadas

  1. 创建快照仓库repo -> my_fs_repository
curl -k -X PUT "https://elastic-search.dev.72602.online:32443/_snapshot/my_fs_repository?pretty" -H 'Content-Type: application/json' -d'
{
  "type": "fs",
  "settings": {
    "location": "/tmp"
  }
}
'

你也能使用storage-class 挂载一个路径在pod中,将snapshot文件存放在外挂路径上

  1. 验证集群各个节点是否可以使用这个快照仓库repo
curl -k -X POST "https://elastic-search.dev.72602.online:32443/_snapshot/my_fs_repository/_verify?pretty"
  1. 查看快照仓库repo
curl -k -X GET "https://elastic-search.dev.72602.online:32443/_snapshot/_all?pretty"
  1. 查看某一个快照仓库repo的具体setting
curl -k -X GET "https://elastic-search.dev.72602.online:32443/_snapshot/my_fs_repository?pretty"
  1. 分析一个快照仓库repo
curl -k -X POST "https://elastic-search.dev.72602.online:32443/_snapshot/my_fs_repository/_analyze?blob_count=10&max_blob_size=1mb&timeout=120s&pretty"
  1. 手动打快照
curl -k -X PUT "https://elastic-search.dev.72602.online:32443/_snapshot/my_fs_repository/ay_snap_02?pretty"
使用SLM自动打快照(没生效)

Thank you!

  1. 查看指定快照仓库repo 可用的快照
curl -k -X GET "https://elastic-search.dev.72602.online:32443/_snapshot/my_fs_repository/*?verbose=false&pretty"
  1. 测试恢复
# Delete an index
curl -k -X DELETE "https://elastic-search.dev.72602.online:32443/books?pretty"

# restore that index
curl -k -X POST "https://elastic-search.dev.72602.online:32443/_snapshot/my_fs_repository/ay_snap_02/_restore?pretty" -H 'Content-Type: application/json' -d'
{
  "indices": "books"
}
'

# query
curl -k -X GET "https://elastic-search.dev.72602.online:32443/books/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_all": {}
  }
}
'
Oct 7, 2024

ES [S3 Compatible]

Preliminary

  • ElasticSearch has installed, if not check link

    ES argocd-app yaml
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: elastic-search
    spec:
      syncPolicy:
        syncOptions:
        - CreateNamespace=true
      project: default
      source:
        repoURL: https://charts.bitnami.com/bitnami
        chart: elasticsearch
        targetRevision: 19.11.3
        helm:
          releaseName: elastic-search
          values: |
            global:
              kibanaEnabled: true
            clusterName: elastic
            image:
              registry: m.zjvis.net/docker.io
              pullPolicy: IfNotPresent
            security:
              enabled: true
            service:
              type: ClusterIP
            extraEnvVars:
            - name: S3_ACCESSKEY
              value: admin
            - name: S3_SECRETKEY
              value: ZrwpsezF1Lt85dxl
            extraConfig:
              s3:
                client:
                  default:
                    protocol: http
                    endpoint: "http://<PRIVATE_STORAGE_HOST>:9090"
                    path_style_access: true
            initScripts:
              configure-s3-client.sh: |
                elasticsearch_set_key_value "s3.client.default.access_key" "${S3_ACCESSKEY}"
                elasticsearch_set_key_value "s3.client.default.secret_key" "${S3_SECRETKEY}"
            hostAliases:
            - ip: <PRIVATE_STORAGE_HOST>
              hostnames:
              - minio-api.dev.72602.online
            ingress:
              enabled: true
              annotations:
                cert-manager.io/cluster-issuer: self-signed-ca-issuer
                nginx.ingress.kubernetes.io/rewrite-target: /$1
              hostname: elastic-search.dev.72602.online
              ingressClassName: nginx
              path: /?(.*)
              tls: true
            master:
              masterOnly: false
              replicaCount: 1
              persistence:
                enabled: false
              resources:
                requests:
                  cpu: 2
                  memory: 1024Mi
                limits:
                  cpu: 4
                  memory: 4096Mi
              heapSize: 2g
            data:
              replicaCount: 0
              persistence:
                enabled: false
            coordinating:
              replicaCount: 0
            ingest:
              enabled: true
              replicaCount: 0
              service:
                enabled: false
                type: ClusterIP
              ingress:
                enabled: false
            metrics:
              enabled: false
              image:
                registry: m.zjvis.net/docker.io
                pullPolicy: IfNotPresent
            volumePermissions:
              enabled: false
              image:
                registry: m.zjvis.net/docker.io
                pullPolicy: IfNotPresent
            sysctlImage:
              enabled: true
              registry: m.zjvis.net/docker.io
              pullPolicy: IfNotPresent
            kibana:
              elasticsearch:
                hosts:
                  - '{{ include "elasticsearch.service.name" . }}'
                port: '{{ include "elasticsearch.service.ports.restAPI" . }}'
            esJavaOpts: "-Xmx2g -Xms2g"        
      destination:
        server: https://kubernetes.default.svc
        namespace: application

    diff from oirginal file :

    extraEnvVars:
    - name: S3_ACCESSKEY
      value: admin
    - name: S3_SECRETKEY
      value: ZrwpsezF1Lt85dxl
    extraConfig:
      s3:
        client:
          default:
            protocol: http
            endpoint: "http://<PRIVATE_STORAGE_HOST>:9090"
            path_style_access: true
    initScripts:
      configure-s3-client.sh: |
        elasticsearch_set_key_value "s3.client.default.access_key" "${S3_ACCESSKEY}"
        elasticsearch_set_key_value "s3.client.default.secret_key" "${S3_SECRETKEY}"
    hostAliases:
    - ip: <PRIVATE_STORAGE_HOST>
      hostnames:
      - minio-api.dev.72602.online

Methods

Elasticsearch 做备份有两种方式,

  1. 是将数据导出成文本文件,比如通过elasticdump、esm等工具将存储在 Elasticsearch 中的数据导出到文件中。
  2. 是使用snapshot接口实现快照功能,增量备份文件

第一种方式相对简单,在数据量小的时候比较实用,但当应对大数据量场景时,更推荐使用snapshot api 的方式。

Steps

buckup

asdadas

  1. 创建快照仓库repo -> my_s3_repository
curl -k -X PUT "https://elastic-search.dev.72602.online:32443/_snapshot/my_s3_repository?pretty" -H 'Content-Type: application/json' -d'
{
  "type": "s3",
  "settings": {
    "bucket": "local-test",
    "client": "default",
    "endpoint": "http://<PRIVATE_STORAGE_HOST>:9000"
  }
}
'

你也能使用storage-class 挂载一个路径在pod中,将snapshot文件存放在外挂路径上

  1. 验证集群各个节点是否可以使用这个快照仓库repo
curl -k -X POST "https://elastic-search.dev.72602.online:32443/_snapshot/my_s3_repository/_verify?pretty"
  1. 查看快照仓库repo
curl -k -X GET "https://elastic-search.dev.72602.online:32443/_snapshot/_all?pretty"
  1. 查看某一个快照仓库repo的具体setting
curl -k -X GET "https://elastic-search.dev.72602.online:32443/_snapshot/my_s3_repository?pretty"
  1. 分析一个快照仓库repo
curl -k -X POST "https://elastic-search.dev.72602.online:32443/_snapshot/my_s3_repository/_analyze?blob_count=10&max_blob_size=1mb&timeout=120s&pretty"
  1. 手动打快照
curl -k -X PUT "https://elastic-search.dev.72602.online:32443/_snapshot/my_s3_repository/ay_s3_snap_02?pretty"
使用SLM自动打快照(没生效)

Thank you!

  1. 查看指定快照仓库repo 可用的快照
curl -k -X GET "https://elastic-search.dev.72602.online:32443/_snapshot/my_s3_repository/*?verbose=false&pretty"
  1. 测试恢复
# Delete an index
curl -k -X DELETE "https://elastic-search.dev.72602.online:32443/books?pretty"

# restore that index
curl -k -X POST "https://elastic-search.dev.72602.online:32443/_snapshot/my_s3_repository/ay_s3_snap_02/_restore?pretty" -H 'Content-Type: application/json' -d'
{
  "indices": "books"
}
'

# query
curl -k -X GET "https://elastic-search.dev.72602.online:32443/books/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_all": {}
  }
}
'
Oct 7, 2024

ES Auto BackUp

Preliminary

  • ElasticSearch has installed, if not check link

  • We use local disk to save the snapshots, more deatils check link

  • And the security is enabled.

    ES argocd-app yaml
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: elastic-search
    spec:
      syncPolicy:
        syncOptions:
        - CreateNamespace=true
      project: default
      source:
        repoURL: https://charts.bitnami.com/bitnami
        chart: elasticsearch
        targetRevision: 19.11.3
        helm:
          releaseName: elastic-search
          values: |
            global:
              kibanaEnabled: true
            clusterName: elastic
            image:
              registry: m.zjvis.net/docker.io
              pullPolicy: IfNotPresent
            security:
              enabled: true
              tls:
                autoGenerated: true
            service:
              type: ClusterIP
            extraConfig:
              path:
                repo: /tmp
            ingress:
              enabled: true
              annotations:
                cert-manager.io/cluster-issuer: self-signed-ca-issuer
                nginx.ingress.kubernetes.io/rewrite-target: /$1
              hostname: elastic-search.dev.72602.online
              ingressClassName: nginx
              path: /?(.*)
              tls: true
            master:
              masterOnly: false
              replicaCount: 1
              persistence:
                enabled: false
              resources:
                requests:
                  cpu: 2
                  memory: 1024Mi
                limits:
                  cpu: 4
                  memory: 4096Mi
              heapSize: 2g
            data:
              replicaCount: 0
              persistence:
                enabled: false
            coordinating:
              replicaCount: 0
            ingest:
              enabled: true
              replicaCount: 0
              service:
                enabled: false
                type: ClusterIP
              ingress:
                enabled: false
            metrics:
              enabled: false
              image:
                registry: m.zjvis.net/docker.io
                pullPolicy: IfNotPresent
            volumePermissions:
              enabled: false
              image:
                registry: m.zjvis.net/docker.io
                pullPolicy: IfNotPresent
            sysctlImage:
              enabled: true
              registry: m.zjvis.net/docker.io
              pullPolicy: IfNotPresent
            kibana:
              elasticsearch:
                hosts:
                  - '{{ include "elasticsearch.service.name" . }}'
                port: '{{ include "elasticsearch.service.ports.restAPI" . }}'
            esJavaOpts: "-Xmx2g -Xms2g"        
      destination:
        server: https://kubernetes.default.svc
        namespace: application

    diff from oirginal file :

    security:
      enabled: true
    extraConfig:
        path:
          repo: /tmp

Methods

Steps

auto buckup
  1. 创建快照仓库repo -> slm_fs_repository
curl --user elastic:L9shjg6csBmPZgCZ -k -X PUT "https://10.88.0.143:30294/_snapshot/slm_fs_repository?pretty" -H 'Content-Type: application/json' -d'
{
  "type": "fs",
  "settings": {
    "location": "/tmp"
  }
}
'

你也能使用storage-class 挂载一个路径在pod中,将snapshot文件存放在外挂路径上

  1. 验证集群各个节点是否可以使用这个快照仓库repo
curl --user elastic:L9shjg6csBmPZgCZ  -k -X POST "https://10.88.0.143:30294/_snapshot/slm_fs_repository/_verify?pretty"
  1. 查看快照仓库repo
curl --user elastic:L9shjg6csBmPZgCZ  -k -X GET "https://10.88.0.143:30294/_snapshot/_all?pretty"
  1. 查看某一个快照仓库repo的具体setting
curl --user elastic:L9shjg6csBmPZgCZ  -k -X GET "https://10.88.0.143:30294/_snapshot/slm_fs_repository?pretty"
  1. 分析一个快照仓库repo
curl --user elastic:L9shjg6csBmPZgCZ  -k -X POST "https://10.88.0.143:30294/_snapshot/slm_fs_repository/_analyze?blob_count=10&max_blob_size=1mb&timeout=120s&pretty"
  1. 查看指定快照仓库repo 可用的快照
curl --user elastic:L9shjg6csBmPZgCZ  -k -X GET "https://10.88.0.143:30294/_snapshot/slm_fs_repository/*?verbose=false&pretty"
  1. 创建SLM admin 角色
curl --user elastic:L9shjg6csBmPZgCZ -k -X POST "https://10.88.0.143:30294/_security/role/slm-admin?pretty" -H 'Content-Type: application/json' -d'
{
  "cluster": [ "manage_slm", "cluster:admin/snapshot/*" ],
  "indices": [
    {
      "names": [ ".slm-history-*" ],
      "privileges": [ "all" ]
    }
  ]
}
'
  1. 创建自动备份cornjob
curl --user elastic:L9shjg6csBmPZgCZ -k -X PUT "https://10.88.0.143:30294/_slm/policy/nightly-snapshots?pretty" -H 'Content-Type: application/json' -d'
{
  "schedule": "0 30 1 * * ?",       
  "name": "<nightly-snap-{now/d}>", 
  "repository": "slm_fs_repository",    
  "config": {
    "indices": "*",                 
    "include_global_state": true    
  },
  "retention": {                    
    "expire_after": "30d",
    "min_count": 5,
    "max_count": 50
  }
}
'
  1. 启动自动备份
curl --user elastic:L9shjg6csBmPZgCZ -k -X POST "https://10.88.0.143:30294/_slm/policy/nightly-snapshots/_execute?pretty"
  1. 查看SLM备份历史
curl --user elastic:L9shjg6csBmPZgCZ -k -X GET "https://10.88.0.143:30294/_slm/stats?pretty"
  1. 测试恢复
# Delete an index
curl --user elastic:L9shjg6csBmPZgCZ  -k -X DELETE "https://10.88.0.143:30294/books?pretty"

# restore that index
curl --user elastic:L9shjg6csBmPZgCZ  -k -X POST "https://10.88.0.143:30294/_snapshot/slm_fs_repository/my_snapshot_2099.05.06/_restore?pretty" -H 'Content-Type: application/json' -d'
{
  "indices": "books"
}
'

# query
curl --user elastic:L9shjg6csBmPZgCZ  -k -X GET "https://10.88.0.143:30294/books/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_all": {}
  }
}
'
Oct 7, 2024

Example Shell Script

Init ES Backup Setting

create an ES backup setting in s3, and make an snapshot after creation

#!/bin/bash
ES_HOST="http://192.168.58.2:30910"
ES_BACKUP_REPO_NAME="s3_fs_repository"
S3_CLIENT="default"
ES_BACKUP_BUCKET_IN_S3="es-snapshot"
ES_SNAPSHOT_TAG="auto"

CHECK_RESPONSE=$(curl -s -k -X POST "$ES_HOST/_snapshot/$ES_BACKUP_REPO_NAME/_verify?pretty" )
CHECKED_NODES=$(echo "$CHECK_RESPONSE" | jq -r '.nodes')


if [ "$CHECKED_NODES" == null ]; then
  echo "Doesn't exist an ES backup setting..."
  echo "A default backup setting will be generated. (using '$S3_CLIENT' s3 client and all backup files will be saved in a bucket : '$ES_BACKUP_BUCKET_IN_S3'"

  CREATE_RESPONSE=$(curl -s -k -X PUT "$ES_HOST/_snapshot/$ES_BACKUP_REPO_NAME?pretty" -H 'Content-Type: application/json' -d "{\"type\":\"s3\",\"settings\":{\"bucket\":\"$ES_BACKUP_BUCKET_IN_S3\",\"client\":\"$S3_CLIENT\"}}")
  CREATE_ACKNOWLEDGED_FLAG=$(echo "$CREATE_RESPONSE" | jq -r '.acknowledged')

  if [ "$CREATE_ACKNOWLEDGED_FLAG" == true ]; then
    echo "Buckup setting '$ES_BACKUP_REPO_NAME' has been created successfully!"
  else
    echo "Failed to create backup setting '$ES_BACKUP_REPO_NAME', since $$CREATE_RESPONSE"
  fi
else
  echo "Already exist an ES backup setting '$ES_BACKUP_REPO_NAME'"
fi

CHECK_RESPONSE=$(curl -s -k -X POST "$ES_HOST/_snapshot/$ES_BACKUP_REPO_NAME/_verify?pretty" )
CHECKED_NODES=$(echo "$CHECK_RESPONSE" | jq -r '.nodes')

if [ "$CHECKED_NODES" != null ]; then
  SNAPSHOT_NAME="meta-data-$ES_SNAPSHOT_TAG-snapshot-$(date +%s)"
  SNAPSHOT_CREATION=$(curl -s -k -X PUT "$ES_HOST/_snapshot/$ES_BACKUP_REPO_NAME/$SNAPSHOT_NAME")
  echo "Snapshot $SNAPSHOT_NAME has been created."
else
  echo "Failed to create snapshot $SNAPSHOT_NAME ."
fi
Mar 14, 2024

Homepage

Backup

Homepage 的配置全部存储在 Git 仓库中:

路径内容
manifests/homepage/config/bookmarks.yaml书签
manifests/homepage/config/services.yaml服务 widgets
manifests/homepage/config/settings.yaml布局设置
manifests/homepage/config/widgets.yaml仪表盘小部件
manifests/homepage/config/docker.yamlDocker 集成
manifests/homepage/config/kubernetes.yamlK8s 集成
manifests/homepage/configmap.yaml生成的 ConfigMap

恢复步骤

# 1. 确认配置文件正确
bash scripts/gen-homepage-configmap.sh

# 2. 更新 ConfigMap
kubectl -n monitor apply -f manifests/homepage/configmap.yaml

# 3. 触发重载
kubectl -n monitor rollout restart deploy/homepage
May 12, 2026

Git / GitLab

GitLab

Backup GitLab via Omnibus

# 创建备份(Omnibus 安装)
sudo gitlab-rake gitlab:backup:create

# 备份文件位置
ls -la /var/opt/gitlab/backups/

# 恢复
sudo gitlab-rake gitlab:backup:restore BACKUP=<timestamp>

Backup GitLab on Kubernetes

# 备份数据库
kubectl -n gitlab exec deploy/gitlab -- gitlab-backup create

# 复制备份到本地
kubectl -n gitlab cp gitlab-pod:/var/opt/gitlab/backups/<backup-file> ./

GitHub (General)

当前项目托管在 GitHub 上,数据安全由 GitHub 保障。

如需额外备份:

# 备份所有仓库
gh repo list --limit 100 --json nameWithOwner -q '.[].nameWithOwner' | \
  while read repo; do
    git clone --mirror "https://github.com/$repo" "backups/$repo.git"
  done
May 12, 2026

Subsections of Git / GitLab

K8s