Setting Up Seafile on Kubernetes on Rocky Linux
Setting Up Seafile on Kubernetes on Rocky Linux
Seafile 13 Steps
- Label the
green-hillsnode and say that it has local storage available:
kubectl label nodes green-hills local-storage-available=true
- Create the
namespace:
kubectl create ns seafile
- Install EPEL:
dnf install -y epel-release
- Install
pwgen:
dnf install -y pwgen
- To make the
jwt private key, run:
pwgen -s 40 1
- Create the
secretMap:
kubectl create secret generic seafile-secret --namespace seafile \
--from-literal=JWT_PRIVATE_KEY='<your-jwt-private-key>' \
--from-literal=SEAFILE_MYSQL_DB_PASSWORD='<your-secure-password>' \
--from-literal=INIT_SEAFILE_ADMIN_PASSWORD='<your-secure-password>' \
--from-literal=INIT_SEAFILE_MYSQL_ROOT_PASSWORD='<your-secure-password>' \
--from-literal=REDIS_PASSWORD='<your-secure-password>' \
--from-literal=S3_SECRET_KEY='' \
--from-literal=S3_SSE_C_KEY=''
- Create the
seafile-k8s-yamldirectory:
mkdir -p /opt/seafile-k8s-yaml
- Create the
mysqldirectory
mkdir -p /opt/mysql-k8s-yaml
- Create the
mysql-datadirectory to store all of the database data in/root:
mkdir -p /root/mysql-data
mkdir -p /root/redis-data
mkdir -p /root/elasticsearch-data
- Pull down all of the required
yamlfiles forseafile:
wget -P /opt/seafile-k8s-yaml https://manual.seafile.com/13.0/repo/k8s/cluster/seafile-backend-deployment.yaml
wget -P /opt/seafile-k8s-yaml https://manual.seafile.com/13.0/repo/k8s/cluster/seafile-persistentvolume.yaml
wget -P /opt/seafile-k8s-yaml https://manual.seafile.com/13.0/repo/k8s/cluster/seafile-persistentvolumeclaim.yaml
wget -P /opt/seafile-k8s-yaml https://manual.seafile.com/13.0/repo/k8s/cluster/seafile-service.yaml
wget -P /opt/seafile-k8s-yaml https://manual.seafile.com/13.0/repo/k8s/cluster/seafile-env.yaml
- Set
seafile-persistentvolume.yamlto the following:
cat << "EOF" | tee /opt/seafile-k8s-yaml/seafile-persistentvolume.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: seafile-data
spec:
capacity:
storage: 10.9Ti
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
hostPath:
path: /mnt/sonic
EOF
- Set the
seafile-persistentvolumeclaim.yamlas the following:
cat << "EOF" | tee /opt/seafile-k8s-yaml/seafile-persistentvolumeclaim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: seafile-data
namespace: seafile
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10.9Ti
storageClassName: local-storage
EOF
- Set
seafile-backend-deployment.yamlas the following:
cat << "EOF" | tee /opt/seafile-k8s-yaml/seafile-backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: seafile-backend
namespace: seafile
spec:
replicas: 1
selector:
matchLabels:
app: seafile-backend
template:
metadata:
labels:
app: seafile-backend
spec:
enableServiceLinks: false
initContainers:
- name: set-ownership
image: busybox
command: ['sh', '-c', 'chown -R root:root /shared']
volumeMounts:
- name: seafile-data
mountPath: /shared
containers:
- name: seafile-backend
image: seafileltd/seafile-pro-mc:13.0-latest
env:
- name: CLUSTER_SERVER
value: "true"
- name: CLUSTER_MODE
value: "backend"
envFrom:
- configMapRef:
name: seafile-env
- secretRef:
name: seafile-secret
volumeMounts:
- name: seafile-data
mountPath: /shared
volumes:
- name: seafile-data
persistentVolumeClaim:
claimName: seafile-data
restartPolicy: Always
imagePullSecrets:
- name: regcred
EOF
- The setup for
seafile-env.yaml:
cat << "EOF" | tee /opt/seafile-k8s-yaml/seafile-env.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: seafile-env
namespace: seafile
data:
# for Seafile server
TIME_ZONE: "Asia/Tokyo"
SEAFILE_LOG_TO_STDOUT: "true"
SITE_ROOT: "/"
SEAFILE_SERVER_HOSTNAME: "192.168.1.100"
SEAFILE_SERVER_PROTOCOL: "http"
# for database
SEAFILE_MYSQL_DB_HOST: "mysql"
SEAFILE_MYSQL_DB_PORT: "3306"
SEAFILE_MYSQL_DB_USER: "seafile"
SEAFILE_MYSQL_DB_CCNET_DB_NAME: "ccnet_db"
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME: "seafile_db"
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME: "seahub_db"
# for cached
CACHE_PROVIDER: "redis" # or "memcached"
## for redis
REDIS_HOST: "redis-leader"
REDIS_PASSWORD: "<your-secure-password>"
REDIS_PORT: "6379"
## for memcached
MEMCACHED_HOST: "192.168.1.100"
MEMCACHED_PORT: "11211"
# for s3
SEAF_SERVER_STORAGE_TYPE: "disk"
S3_COMMIT_BUCKET: ""
S3_FS_BUCKET: ""
S3_BLOCK_BUCKET: ""
S3_KEY_ID: ""
S3_USE_V4_SIGNATURE: "true"
S3_AWS_REGION: "us-east-1"
S3_HOST: ""
S3_USE_HTTPS: "true"
S3_PATH_STYLE_REQUEST: "false"
# for notification
ENABLE_NOTIFICATION_SERVER: "false"
NOTIFICATION_SERVER_URL: ""
# for seadoc
ENABLE_SEADOC: "true"
SEADOC_SERVER_URL: "192.168.1.100" # only valid in ENABLE_SEADOC = true
# initialization (only valid in first-time deployment and CLUSTER_INIT_MODE = true)
CLUSTER_INIT_MODE: "true"
## for Seafile admin
INIT_SEAFILE_ADMIN_EMAIL: "howard.a.vanderwal@protonmail.com"
## for cluster basic service
CLUSTER_INIT_ES_HOST: "elasticsearch"
CLUSTER_INIT_ES_PORT: "9200"
# Seafile AI
ENABLE_SEAFILE_AI: "yes"
SEAFILE_AI_SERVER_URL: "192.168.1.100"
# Matedata server
MD_FILE_COUNT_LIMIT: "100000"
EOF
chown -R 1000:1000 /root/elasticsearch-data
restorecon -R -v /root/elasticsearch-data
seafile-service.yamlconfiguration:
cat << "EOF" | tee /opt/seafile-k8s-yaml/seafile-service.yaml
apiVersion: v1
kind: Service
metadata:
name: seafile
namespace: seafile
spec:
selector:
app: seafile-frontend
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30007
EOF
- Create the following
mysqlyamlfiles:
cat << "EOF" | tee /opt/mysql-k8s-yaml/mysql-service.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: seafile
spec:
ports:
- port: 3306
protocol: TCP
targetPort: 3306
selector:
app: mysql
EOF
cat << "EOF" | tee /opt/mysql-k8s-yaml/mysql-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: seafile
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:9
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
EOF
cat << "EOF" | tee /opt/mysql-k8s-yaml/mysql-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv-volume
namespace: seafile
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/root/mysql-data"
EOF
cat << "EOF" | tee /opt/mysql-k8s-yaml/mysql-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
namespace: seafile
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
EOF
- Set up Elasticsearch
# 1️⃣ Host directory for persistence
sudo mkdir -p /root/elasticsearch-data
# 2️⃣ Apply PV & PVC
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: PersistentVolume
metadata:
name: es-pv-volume
namespace: seafile
spec:
storageClassName: manual
capacity:
storage: 30Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/root/elasticsearch-data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: es-pv-claim
namespace: seafile
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 30Gi
EOF
# 3️⃣ Deploy ES
kubectl apply -f - <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: elasticsearch
namespace: seafile
spec:
replicas: 1
selector:
matchLabels:
app: elasticsearch
template:
metadata:
labels:
app: elasticsearch
spec:
containers:
- name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.10
env:
- name: discovery.type
value: "single-node"
- name: ES_JAVA_OPTS
value: "-Xms512m -Xmx512m"
ports:
- containerPort: 9200
volumeMounts:
- name: es-data
mountPath: /usr/share/elasticsearch/data
volumes:
- name: es-data
persistentVolumeClaim:
claimName: es-pv-claim
---
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
namespace: seafile
spec:
selector:
app: elasticsearch
ports:
- protocol: TCP
port: 9200
targetPort: 9200
type: ClusterIP
EOF
# 4️⃣ Update Seafile ConfigMap (replace host)
sed -i 's/CLUSTER_INIT_ES_HOST:.*/CLUSTER_INIT_ES_HOST: "elasticsearch"/' /opt/seafile-k8s-yaml/seafile-env.yaml
sed -i 's/CLUSTER_INIT_ES_PORT:.*/CLUSTER_INIT_ES_PORT: "9200"/' /opt/seafile-k8s-yaml/seafile-env.yaml
kubectl apply -f /opt/seafile-k8s-yaml/seafile-env.yaml
- Deploy the
mysqldeployment:
kubectl apply -f /opt/mysql-k8s-yaml
- Deploy the
seafiledeployment:
kubectl apply -f /opt/seafile-k8s-yaml/
- Create the Redis directory:
mkdir -p /opt/redis-k8s-yaml
- Deploy the Redis instance:
cat << "EOF" | tee /opt/redis-k8s-yaml/redis-leader-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-leader
namespace: seafile
labels:
app: redis
role: leader
tier: backend
spec:
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
role: leader
tier: backend
spec:
containers:
- name: leader
image: "registry.k8s.io/redis@sha256:cb111d1bd870a6a471385a4a69ad17469d326e9dd91e0e455350cacf36e1b3ee"
args: ["redis-server", "--requirepass", "password"]
ports:
- containerPort: 6379
EOF
- Create the Redis Leader Service:
cat << "EOF" | tee /opt/redis-k8s-yaml/redis-leader-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-leader
namespace: seafile
labels:
app: redis
role: leader
tier: backend
spec:
type: ClusterIP
ports:
- protocol: TCP
port: 6379
selector:
app: redis
role: leader
tier: backend
EOF
- Apply the Redis yaml files:
kubectl apply -f /opt/redis-k8s-yaml/
- Download the
frontendseafiledeployment yaml:
wget -P /opt/seafile-k8s-yaml https://manual.seafile.com/13.0/repo/k8s/cluster/seafile-frontend-deployment.yaml
- Set the
seafile-frontend-deployment.yamlto the following:
cat << "EOF" | tee /opt/seafile-k8s-yaml/seafile-frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: seafile-frontend
namespace: seafile
spec:
selector:
matchLabels:
app: seafile-frontend
template:
metadata:
labels:
app: seafile-frontend
spec:
enableServiceLinks: false
initContainers:
- name: set-ownership
image: busybox
command: ['sh', '-c', 'chown -R root:root /shared']
volumeMounts:
- name: seafile-data
mountPath: /shared
containers:
- name: seafile-frontend
image: seafileltd/seafile-pro-mc:13.0-latest
env:
- name: CLUSTER_SERVER
value: "true"
- name: CLUSTER_MODE
value: "frontend"
envFrom:
- configMapRef:
name: seafile-env
- secretRef:
name: seafile-secret
ports:
- containerPort: 80
volumeMounts:
- name: seafile-data
mountPath: /shared
volumes:
- name: seafile-data
persistentVolumeClaim:
claimName: seafile-data
restartPolicy: Always
imagePullSecrets:
- name: regcred
EOF
- Set
seafile-envto the following:
cat << "EOF" | tee /opt/seafile-k8s-yaml/seafile-env.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: seafile-env
namespace: seafile
data:
# for Seafile server
TIME_ZONE: "Asia/Tokyo"
SEAFILE_LOG_TO_STDOUT: "true"
SITE_ROOT: "/"
SEAFILE_SERVER_HOSTNAME: "192.168.1.100"
SEAFILE_SERVER_PROTOCOL: "http"
# for database
SEAFILE_MYSQL_DB_HOST: "mysql"
SEAFILE_MYSQL_DB_PORT: "3306"
SEAFILE_MYSQL_DB_USER: "seafile"
SEAFILE_MYSQL_DB_CCNET_DB_NAME: "ccnet_db"
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME: "seafile_db"
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME: "seahub_db"
# for cached
CACHE_PROVIDER: "redis" # or "memcached"
## for redis
REDIS_HOST: "redis-leader"
REDIS_PASSWORD: "<your-secure-password>"
REDIS_PORT: "6379"
## for memcached
MEMCACHED_HOST: "192.168.1.100"
MEMCACHED_PORT: "11211"
# for s3
SEAF_SERVER_STORAGE_TYPE: "disk"
S3_COMMIT_BUCKET: ""
S3_FS_BUCKET: ""
S3_BLOCK_BUCKET: ""
S3_KEY_ID: ""
S3_USE_V4_SIGNATURE: "true"
S3_AWS_REGION: "us-east-1"
S3_HOST: ""
S3_USE_HTTPS: "true"
S3_PATH_STYLE_REQUEST: "false"
# for notification
ENABLE_NOTIFICATION_SERVER: "false"
NOTIFICATION_SERVER_URL: ""
# for seadoc
ENABLE_SEADOC: "true"
SEADOC_SERVER_URL: "192.168.1.100" # only valid in ENABLE_SEADOC = true
# initialization (only valid in first-time deployment and CLUSTER_INIT_MODE = true)
CLUSTER_INIT_MODE: "false"
## for Seafile admin
INIT_SEAFILE_ADMIN_EMAIL: "howard.a.vanderwal@protonmail.com"
## for cluster basic service
CLUSTER_INIT_ES_HOST: "elasticsearch"
CLUSTER_INIT_ES_PORT: "9200"
# Seafile AI
ENABLE_SEAFILE_AI: "yes"
SEAFILE_AI_SERVER_URL: "192.168.1.100"
# Matedata server
MD_FILE_COUNT_LIMIT: "100000"
EOF
- Apply all of the yaml files again:
kubectl apply -f /opt/seafile-k8s-yaml/
- To transfer data, install
nfs-utilson both the Worker Node and the Client:
sudo dnf install -y nfs-utils
- If on ZFS and using datasets, do the following instead:
sudo zfs set sharenfs='rw=@192.168.1.102,no_root_squash' tails
- Check to make sure NFS on ZFS was shared properly:
sudo zfs get sharenfs tails
- ExportFS:
sudo exportfs -ra
- Restart the service:
sudo systemctl restart nfs-server rpcbind
-
If on another filesystem or NOT using datasets with ZFS, use this method:
-
Add the following into
/etc/exportsfor the Worker Node:
cat << "EOF" | tee /etc/exports
/mnt/tails 192.168.1.102(rw,sync,no_subtree_check,no_root_squash)
EOF
- Enable the NFS server on the Worker Node:
sudo systemctl enable --now nfs-server
- Ensure these services are allowed through the Worker Node’s firewall:
sudo firewall-cmd --zone=public --permanent --add-service=mountd
sudo firewall-cmd --zone=public --permanent --add-service=nfs
sudo firewall-cmd --zone=public --permanent --add-service=rpc-bind
sudo firewall-cmd --reload
- On the Client machine, create the following directory:
sudo mkdir -p /nfs/green_hills-tails
- Mount the NFS share on the Client:
sudo mount 192.168.1.100:/mnt/tails /nfs/green_hills-tails
- Add the following into
/etc/fstabon the Client:
cat << "EOF" | sudo tee -a /etc/fstab
192.168.1.100:/mnt/tails /nfs/green_hills-tails nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0
EOF