This is the Experimental version (Latest). It is under active development and may change. For the most reliable documentation, use the version selector in the top-right to switch to Stable, or click here to go to the Stable version's homepage.
SeaweedFS (Bootstrap) Installation
Last updated:
SeaweedFS (Bootstrap) is the minimal instance required to break the circular dependency between storage and the database. It provides the initial S3 endpoint for CloudnativePG.
Installation
Section titled “Installation”-
Connect to
🟢 ManagementKubernetes Cluster ; _i.e w/ Kubeconfig File.Set Kubeconfig File
Ensure you have defined and loaded your Global Shell Variables as described in Shell Variables.
Terminal window source $BASE_WORKING_DIR/shell-values/kubernetes/management_cluster.vars.sh -
Prepare Required Shell Variables
Ensure
K8S_INGRESS_TLS_CERTIFICATE_SECRET_NAMEandK8S_STORAGE_CLASS_NAMEare defined as per the Shell Variables guide. Other credentials and domain names are loaded from yourtools/*.vars.shfiles. -
Create Namespace for SeaweedFS Bootstrap
Terminal window kubectl create namespace seaweedfs-bootstrap -
Create SeaweedFS S3 Configuration
Terminal window cat <<EOF > $BASE_WORKING_DIR/kubernetes-manifests/seaweedfs-bootstrap-s3.yaml---# S3 Credentials for SeaweedFS (Minimal/Bootstrap)apiVersion: v1kind: Secrettype: Opaquemetadata:name: seaweedfs-s3-secretnamespace: seaweedfs-bootstrapstringData:# ----------------------------------------------------------------------------# INPUT CONFIGURATION (YAML)# Run 'scripts/seaweedfs-utils.sh update <this_file>' to generate the JSON below.# ----------------------------------------------------------------------------s3_config_input: |users:- name: adminpassword: "${SEAWEEDFS_BOOTSTRAP_S3_ADMIN_PASSWORD}"actions:- Admin- Read- Write- List- Tagging- name: postgres-backuppassword: "${SEAWEEDFS_BOOTSTRAP_S3_POSTGRES_BACKUP_PASSWORD}"actions:- "Read:postgres-backups"- "Write:postgres-backups"- "List:postgres-backups"- "Tagging:postgres-backups"# ----------------------------------------------------------------------------# GENERATED CONFIGURATION (JSON) - DO NOT EDIT MANUALLY# ----------------------------------------------------------------------------seaweedfs_s3_config: ""EOFTerminal window # Generate proper JSON formatted config into the configuration file$BASE_WORKING_DIR/assets/scripts/seaweedfs-utils.sh update $BASE_WORKING_DIR/kubernetes-manifests/seaweedfs-bootstrap-s3.yamlApply the configuration:
Terminal window kubectl apply -f $BASE_WORKING_DIR/kubernetes-manifests/seaweedfs-bootstrap-s3.yaml -
Add SeaweedFS Helm Repository
Terminal window helm repo add seaweedfs https://seaweedfs.github.io/seaweedfs/helmhelm repo update -
Create SeaweedFS Bootstrap Helm Values
Terminal window cat <<EOF > $BASE_WORKING_DIR/helm-values/seaweedfs-bootstrap-values.yamlglobal:imageName: chrislusf/seaweedfsloggingLevel: 1enableSecurity: false# Disable global replication (Relies on Longhorn)enableReplication: false# "000" = No replication at SeaweedFS levelreplicationPlacement: "000"master:enabled: truereplicas: 1# Default volume size is 1GB (1000MB) in this chart, fitting ~10 volumes in 10GivolumeSizeLimitMB: 1000# Security ContextpodSecurityContext:enabled: truefsGroup: 1000fsGroupChangePolicy: "OnRootMismatch"containerSecurityContext:enabled: truerunAsUser: 1000runAsGroup: 1000runAsNonRoot: trueprivileged: falseallowPrivilegeEscalation: falseseccompProfile:type: RuntimeDefaultcapabilities:drop: ["ALL"]# Persistence for Master (Metadata/Sequence)data:type: "persistentVolumeClaim"size: "1Gi"storageClass: "${K8S_STORAGECLASS_NAME}"logs:type: "stdout/stderr"volume:enabled: truereplicas: 1ipBind: "0.0.0.0"minFreeSpacePercent: 5# Security ContextpodSecurityContext:enabled: truefsGroup: 1000fsGroupChangePolicy: "OnRootMismatch"containerSecurityContext:enabled: truerunAsUser: 1000runAsGroup: 1000runAsNonRoot: trueprivileged: falseallowPrivilegeEscalation: falseseccompProfile:type: RuntimeDefaultcapabilities:drop: ["ALL"]# Persistence for Volume (Data)dataDirs:- name: datatype: "persistentVolumeClaim"size: "10Gi"storageClass: "${K8S_STORAGECLASS_NAME}"maxVolumes: 10extraArgs: []filer:enabled: truereplicas: 1port: 9001 # MinIO Console compatibility# Security ContextpodSecurityContext:enabled: truefsGroup: 1000fsGroupChangePolicy: "OnRootMismatch"containerSecurityContext:enabled: truerunAsUser: 1000runAsGroup: 1000runAsNonRoot: trueprivileged: falseallowPrivilegeEscalation: falseseccompProfile:type: RuntimeDefaultcapabilities:drop: ["ALL"]# Persistence for Filer (Metadata)data:type: "persistentVolumeClaim"size: "1Gi"storageClass: "${K8S_STORAGECLASS_NAME}"logs:type: "stdout/stderr"# Ingress for Filer (SeaweedFS WebUI)ingress:enabled: falseclassName: nginxhost: "${SEAWEEDFS_BOOTSTRAP_FILER_DOMAIN}"path: "/"pathType: Prefixannotations:nginx.ingress.kubernetes.io/proxy-body-size: "0"ingress.kubernetes.io/proxy-body-size: "0"# Basic Auth Configuration# nginx.ingress.kubernetes.io/auth-type: basic# nginx.ingress.kubernetes.io/auth-secret: seaweedfs-filer-basic-auth# nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"tls:- secretName: "${K8S_INGRESS_TLS_CERTIFICATE_SECRET_NAME}"hosts:- "${SEAWEEDFS_BOOTSTRAP_FILER_DOMAIN}"s3:enabled: truereplicas: 1port: 9000 # MinIO API compatibilityenableAuth: trueexistingConfigSecret: seaweedfs-s3-secret# Security ContextpodSecurityContext:enabled: truefsGroup: 1000fsGroupChangePolicy: "OnRootMismatch"containerSecurityContext:enabled: truerunAsUser: 1000runAsGroup: 1000runAsNonRoot: trueprivileged: falseallowPrivilegeEscalation: falseseccompProfile:type: RuntimeDefaultcapabilities:drop: ["ALL"]logs:type: "stdout/stderr"# Ingress for S3 APIingress:enabled: trueclassName: nginxhost: "${SEAWEEDFS_BOOTSTRAP_API_DOMAIN}"path: "/"pathType: Prefixannotations:nginx.ingress.kubernetes.io/proxy-body-size: "0"ingress.kubernetes.io/proxy-body-size: "0"tls:- secretName: "${K8S_INGRESS_TLS_CERTIFICATE_SECRET_NAME}"hosts:- "${SEAWEEDFS_BOOTSTRAP_API_DOMAIN}"admin:enabled: truesecret:adminUser: "admin"adminPassword: "${SEAWEEDFS_BOOTSTRAP_ADMIN_PASSWORD}"ingress:enabled: trueclassName: nginxhost: "${SEAWEEDFS_BOOTSTRAP_ADMIN_DOMAIN}"path: "/"pathType: Prefixtls:- secretName: "${K8S_INGRESS_TLS_CERTIFICATE_SECRET_NAME}"hosts:- "${SEAWEEDFS_BOOTSTRAP_ADMIN_DOMAIN}"# Security ContextpodSecurityContext:enabled: truefsGroup: 1000fsGroupChangePolicy: "OnRootMismatch"containerSecurityContext:enabled: truerunAsUser: 1000runAsGroup: 1000runAsNonRoot: trueprivileged: falseallowPrivilegeEscalation: falseseccompProfile:type: RuntimeDefaultcapabilities:drop: ["ALL"]EOF -
Install SeaweedFS Bootstrap Helm Release
Terminal window helm upgrade --install seaweedfs-bootstrap seaweedfs/seaweedfs \--version 4.0.407 \--namespace seaweedfs-bootstrap \-f $BASE_WORKING_DIR/helm-values/seaweedfs-bootstrap-values.yaml -
Provision SeaweedFS Buckets
Terminal window cat <<EOF > $BASE_WORKING_DIR/kubernetes-manifests/seaweedfs-bootstrap-job-provisioning.yamlapiVersion: batch/v1kind: Jobmetadata:name: seaweedfs-bootstrap-provisioningnamespace: seaweedfs-bootstraplabels:app.kubernetes.io/name: seaweedfs-bootstrapapp.kubernetes.io/component: provisioningspec:ttlSecondsAfterFinished: 300template:metadata:labels:app.kubernetes.io/name: seaweedfs-bootstrapapp.kubernetes.io/component: provisioningspec:restartPolicy: OnFailure# Security ContextsecurityContext:runAsNonRoot: truerunAsUser: 10000fsGroup: 10000seccompProfile:type: RuntimeDefaultcontainers:- name: provisionerimage: chrislusf/seaweedfs:4.07# Security ContextsecurityContext:allowPrivilegeEscalation: falsereadOnlyRootFilesystem: falserunAsNonRoot: truerunAsUser: 10000capabilities:drop: ["ALL"]# Resource Limitsresources:requests:memory: "64Mi"cpu: "100m"limits:memory: "128Mi"cpu: "200m"env:# Target SeaweedFS Master (Minimal/Bootstrap instance)- name: WEED_MASTERvalue: "seaweedfs-master:9333"# Target SeaweedFS Filer (Minimal/Bootstrap instance)- name: WEED_FILERvalue: "seaweedfs-filer:9001"# Comma-separated list of buckets to create- name: SEAWEEDFS_BUCKETSvalue: "postgres-backups"command:- "/bin/sh"- "-c"- |set -eecho "[INFO] Starting SeaweedFS Bootstrap Provisioning..."echo "[INFO] Target Master: \$WEED_MASTER"echo "[INFO] Target Filer: \$WEED_FILER"echo "[INFO] Buckets: \$SEAWEEDFS_BUCKETS"# 1. Wait for Master Leaderecho "[INFO] Waiting for SeaweedFS Master Leader..."START_TIME=\$(date +%s)TIMEOUT=300until echo cluster.ps | weed shell -master=\$WEED_MASTER > /dev/null 2>&1; doCURRENT_TIME=\$(date +%s)ELAPSED_TIME=\$((\$CURRENT_TIME - \$START_TIME))if [ \$ELAPSED_TIME -gt \$TIMEOUT ]; thenecho "[ERROR] Timeout waiting for SeaweedFS Master at \$WEED_MASTER"exit 1fiecho "[WAIT] Connecting to master... (\${ELAPSED_TIME}s)"sleep 5doneecho "[INFO] Connected to Master."# 2. Wait for Filer (required for bucket creation)echo "[INFO] Waiting for SeaweedFS Filer..."until echo fs.ls / | weed shell -master=\$WEED_MASTER -filer=\$WEED_FILER > /dev/null 2>&1; doCURRENT_TIME=\$(date +%s)ELAPSED_TIME=\$((\$CURRENT_TIME - \$START_TIME))if [ \$ELAPSED_TIME -gt \$TIMEOUT ]; thenecho "[ERROR] Timeout waiting for SeaweedFS Filer at \$WEED_FILER"exit 1fiecho "[WAIT] Connecting to filer... (\${ELAPSED_TIME}s)"sleep 5doneecho "[INFO] Connected to Filer."# 3. Create Buckets# Generate weed shell scriptSCRIPT_FILE="/tmp/provision.weed"echo "# Auto-generated provisioning script" > \$SCRIPT_FILE# POSIX compliant way to split comma-separated stringecho "\$SEAWEEDFS_BUCKETS" | tr ',' '\n' | while read -r bucket; do# Trim whitespacebucket=\$(echo "\$bucket" | sed 's/^[[:space:]]*//;s/[[:space:]]*\$//')if [ -n "\$bucket" ]; thenecho "s3.bucket.create -name \$bucket" >> \$SCRIPT_FILEecho "[INFO] Added bucket creation command for: \$bucket"fidoneecho "s3.bucket.list" >> \$SCRIPT_FILE# Executeecho "[INFO] Executing provisioning commands:"cat \$SCRIPT_FILEecho "----------------------------------------"# Run weed shell with better error handlingOUTPUT_FILE="/tmp/output.log"if ! cat \$SCRIPT_FILE | weed shell -master=\$WEED_MASTER -filer=\$WEED_FILER 2>&1 | tee \$OUTPUT_FILE; then# Check if error is just "bucket already exists"if grep -qi "already exist\|AlreadyExists" \$OUTPUT_FILE; thenecho "[WARN] Some buckets already exist (expected, continuing...)"elseecho "[ERROR] Bucket creation failed with unexpected error:"cat \$OUTPUT_FILEexit 1fifiecho "[INFO] Bucket creation completed."# 4. Verify bucket creationecho "[INFO] Verifying bucket creation..."BUCKET_LIST=\$(echo s3.bucket.list | weed shell -master=\$WEED_MASTER -filer=\$WEED_FILER 2>&1)echo "\$SEAWEEDFS_BUCKETS" | tr ',' '\n' | while read -r bucket; dobucket=\$(echo "\$bucket" | sed 's/^[[:space:]]*//;s/[[:space:]]*\$//')if [ -n "\$bucket" ]; thenif echo "\$BUCKET_LIST" | grep -q "\$bucket"; thenecho "[SUCCESS] Bucket '\$bucket' exists"elseecho "[ERROR] Bucket '\$bucket' NOT found!"echo "[DEBUG] Available buckets:"echo "\$BUCKET_LIST"exit 1fifidoneecho "[SUCCESS] All buckets verified successfully!"EOFApply the provisioning job:
Terminal window kubectl apply -f $BASE_WORKING_DIR/kubernetes-manifests/seaweedfs-bootstrap-job-provisioning.yaml
Post-Installation
Section titled “Post-Installation”-
Verify Pod Status
Terminal window kubectl get pods -n seaweedfs-bootstrap💡 All components should be
Running:NAME READY STATUS RESTARTS AGEseaweedfs-admin-0 1/1 Running 0 ...seaweedfs-filer-0 1/1 Running 0 ...seaweedfs-master-0 1/1 Running 0 ...seaweedfs-s3-XXXXXXXXXX-YYYYY 1/1 Running 0 ...seaweedfs-volume-0 1/1 Running 0 ...seaweedfs-bootstrap-provisioning 0/1 Completed 0 ... -
Verify Admin UI and Buckets
- Access the SeaweedFS Bootstrap Admin UI at
https://${SEAWEEDFS_BOOTSTRAP_ADMIN_DOMAIN}. - Login with the admin credentials defined in
${SEAWEEDFS_BOOTSTRAP_ADMIN_PASSWORD}. - Navigate to the Buckets tab and confirm that the
postgres-backupsbucket has been successfully created.
- Access the SeaweedFS Bootstrap Admin UI at
Finished?
Use the below navigation to proceed