---
# System prepended metadata

title: Adding NFS to your Harvester cluster

---

:::info
:bulb:This is an example of adding NFS to your Harvester cluster as a storage class.
:::

## :question:Purpose
:::success
Add a new storage class to your harvester cluster as an additional storage option to the built in longhorn storage.
:::

## :feet:Pre-Req steps
:::success
Pre-reqs make sure you have the tools and configurations to successfully complete all the main steps.
:::
1. Install Hauler (https://github.com/hauler-dev/hauler)

Linux/Darwin 
```
# installs latest release
curl -sfL https://get.hauler.dev | bash
```
Homebrew
```
# installs latest release
brew tap hauler-dev/homebrew-tap
brew install hauler
```
2. Hauler login
```
hauler login -u <redacted> -p <redacted> rgcrprod.azurecr.us
```
3. Carbide Public Key
```
curl -sfOL https://raw.githubusercontent.com/rancherfederal/carbide-releases/main/carbide-key.pub
```
4. Install kubectl
```
# Download the latest stable release for your architecture (e.g., AMD64)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

# Make the binary executable
chmod +x ./kubectl

# Move the executable to a directory in your PATH (e.g., /usr/local/bin)
sudo mv ./kubectl /usr/local/bin/kubectl

# Verify the installation
kubectl version --client
```
5. Install helm
```
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4
chmod 700 get_helm.sh
./get_helm.sh
#verify 
helm version
```
6. Turn on developer extensions
Go to preferences in the upper right then check the box for "Enable Extension developer features"
![screenshot.60](https://hackmd.io/_uploads/rkYt_bagWe.jpg)

7. Access embedded rancher
Go to support
Access Embedded Rancher UI
![screenshot.61](https://hackmd.io/_uploads/r146dWagWl.jpg)

8. Some sort of OCI Container Registry or plan to use Hauler as your temporary registry.
my setup has a Harbor Registry installed at registry.millennium.rebel.systems.


## :feet:Main Steps
:::success
Start
:::

1. Carbide License from RGS
i.e. eyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==
2. NFS CSI Image https://portal.ranchercarbide.dev/apps/kubernetes-csi-driver-nfs
3. Grab the hauler command and run on the system with hauler installed
```
hauler store sync --products apps-kubernetes-csi-driver-nfs=4.12.1 --platform linux/amd64 --key carbide-key.pub
```
4. Inspect the store and optionally share if you do not have a registry already
```
hauler store list
#optional if you don't have an existing registry
hauler store serve registry
```
5. Login to your registry for example
:::info 
Update for your environment registry.millennium.rebel.systems is mine
:::
```
hauler login registry.millennium.rebel.systems --username admin --password Harbor12345
```
6. Copy to your registry
```
hauler store copy registry://registry.millennium.rebel.systems --insecure
```
7. Get kubeconfig
Go to Support bottom left corner of the embeded rancher screen
Download KubeConfig
![screenshot.61](https://hackmd.io/_uploads/r146dWagWl.jpg)
Copy to server with kubectl
8. Set kubeconfig environment variable (alias if, for example, you are using a self signed cert)

```
#example location
export KUBECONFIG="~/myHarvester.yaml"
#only needed for untrusted ssl certs
alias kubectl='kubectl --insecure-skip-tls-verify'
```
9. Validate you can access the right server
```
kubectl get namespaces
```
example output
```
NAME                                     STATUS   AGE
carbide-stigatron-system                 Active   115m
cattle-dashboards                        Active   50d
cattle-fleet-clusters-system             Active   50d
cattle-fleet-local-system                Active   50d
cattle-fleet-system                      Active   50d
cattle-impersonation-system              Active   50d
cattle-logging-system                    Active   50d
cattle-monitoring-system                 Active   50d
cattle-provisioning-capi-system          Active   50d
cattle-system                            Active   50d
cattle-ui-plugin-system                  Active   50d
cert-manager                             Active   50d
cluster-fleet-local-local-1a3d67d0a899   Active   50d
default                                  Active   50d
fleet-default                            Active   50d
fleet-local                              Active   50d
git                                      Active   50d
harbor                                   Active   50d
harvester-public                         Active   50d
harvester-system                         Active   50d
kasm                                     Active   50d
kube-node-lease                          Active   50d
kube-public                              Active   50d
kube-system                              Active   50d
local                                    Active   50d
longhorn-system                          Active   50d
user-s7vr4                               Active   50d
```
10. Create helmchart for nfs 
:::info 
Update for your environment 
Chart/imageregistry registry.millennium.rebel.systems is mine.
Set the values for your nfs server "server" "share" etc
:::
vim mychart.yaml

Option 1 dedicated registry
```
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: nfs-csi-driver
  namespace: kube-system
spec:
  imagePullSecrets:
    - name: my-image-pull-secret
  chart: oci://<server hauler is on>:5000/hauler/kubernetes-csi-driver-nfs
  version: 4.12.1
  createNamespace: true
  insecureSkipTLSVerify: true
  targetNamespace: kube-system
  valuesContent: |-
    global:
      imageRegistry: "registry.millennium.rebel.systems"
    storageClass:
      create: true
      name: nfs-csi
      annotations:
        storageclass.kubernetes.io/is-default-class: "false"
      parameters:
        server: 10.0.1.100
        share: /volume1/harvester
    #     subDir:
    #     mountPermissions: "0"
    #     csi.storage.k8s.io/provisioner-secret is only needed for providing mountOptions in DeleteVolume
    #     csi.storage.k8s.io/provisioner-secret-name: "mount-options"
    #     csi.storage.k8s.io/provisioner-secret-namespace: "default"
    #   reclaimPolicy: Delete
    #   volumeBindingMode: Immediate
    #   mountOptions:
    #     - nfsvers=4.1
```

Option 2 using hauler registry
```
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: nfs-csi-driver
  namespace: kube-system
spec:
  imagePullSecrets:
    - name: my-image-pull-secret
  chart: oci://<server hauler is on>:5000/hauler/kubernetes-csi-driver-nfs
  version: 4.12.1
  createNamespace: true
  insecureSkipTLSVerify: true
  targetNamespace: kube-system
  valuesContent: |-
    global:
      imageRegistry: "<server hauler is on>:5000"
    storageClass:
      create: true
      name: nfs-csi
      annotations:
        storageclass.kubernetes.io/is-default-class: "false"
      parameters:
        server: 10.0.1.100
        share: /volume1/harvester
            #     subDir:
    #     mountPermissions: "0"
    #     csi.storage.k8s.io/provisioner-secret is only needed for providing mountOptions in DeleteVolume
    #     csi.storage.k8s.io/provisioner-secret-name: "mount-options"
    #     csi.storage.k8s.io/provisioner-secret-namespace: "default"
    #   reclaimPolicy: Delete
    #   volumeBindingMode: Immediate
    #   mountOptions:
    #     - nfsvers=4.1
```
11. Install nfs helmchart
```
kubectl apply -f mychart.yaml
```
12. Validate NFS storage class exists
Go to Harvester
Left menu Advanced
Storage Classes
"nfs-csi" should exist and be active![screenshot.59](https://hackmd.io/_uploads/SywuwbpeWl.jpg)

13. Test using the storage class
Go to volumes -> Create
Pick a namespace
Name the volume
Ensure the storage class is nfs-csi
Set a size 
Click create on the bottom
![screenshot.62](https://hackmd.io/_uploads/SycYKbpeWl.jpg)
If it ends up bound, that means your storage class (CSI) is working

14. Test an image download
Go to images -> Create
Pick a namespace
Name the image
URL: http://cloud-images.ubuntu.com/releases/jammy/release/ubuntu-22.04-server-cloudimg-amd64.img
Go to storage
Ensure the storage class is "nfs-csi"
Click create on the bottom
![screenshot.63](https://hackmd.io/_uploads/H1Zs9WalWe.jpg)
If both the volume create and the image create work (that means both the CSI, and the CDI CRD/storageprofile are working)

15. Create a VM with the new storage class and image
Go to Virtual Machines -> Create
Pick a namespace
Name the Vritual Machine
Basics pick cpu/ram and set ssh key if you so choose
![screenshot.64](https://hackmd.io/_uploads/rJkCs-agZx.jpg)
Set the volume 
Optional add an additonal drive
![screenshot.65](https://hackmd.io/_uploads/HJo_2-Txbg.jpg)
Set the Network(s)
![screenshot.66](https://hackmd.io/_uploads/H1Gsn-pe-l.jpg)
Click Create
:::warning
The VM status may initially be unschedulable as everything gets created but then should resolve to running in short order
:::
## Completion
:::success
Congratulations you have successfully added a new nfs storage class and validated it!!
:::
If everything was setup correctly you should have a new running vm
![screenshot.67](https://hackmd.io/_uploads/H1CBaZTl-x.jpg)

