In search of the next Nextcloud Operator ➡️⛅
Developing a Nextcloud Operator: Part1 : only to find a AGPL 3.0 dilemma, an empty repository and hacking together a new operator.
TLDR; I started hacking on a Nextcloud Operator.
14th October 2024 (daytime)
So, I started hacking with the GlassKube Operator as I wanted an easy way to create and manage Nextcloud instances on Kubernetes and while searching for this an operator I found GlassKube. There isn’t a lot of documentation on how to run it with Mac. It’s either that or I didn’t search hard enough. Anyways, here’s how you can get start developing with it.
Prerequisites for GlassKube Operator
brew install openjdk gradleAfter installing the developer dependencies and making sure you have things like kubectl etc. installed, which you will usually require to work with Kubernetes based tools, let’s go ahead and run the operator in development mode.
This operator is written in Java/Kotlin which gives me the heebie jeebies from back in the Jenkins days when I worked on the openshift-sync-plugin and the openshift-client-plugin for Jenkins, because this operator uses the fabric8io kubernetes client. It was fun working with it then but now it’s nice to see it again, being used in this format.
The preferred distro for development with glasskube is minikube so let’s start the minikube cluster
minikube startLet’s clone the repo and understand how the build for GlassKube works and how we can get started working on this operator ASAP.
git clone https://github.com/glasskube/operator
cd operator
# Build
gradle
gradle check
gradle operator:installCrdAfter this you can start the operator directly with the following command…
gradle operator:bootRunbut you will get cascading failures related the operator’s dependencies.
Let’s take a hacky approach and install the operator helm chart, scale the deployment of the operator to 0 and then run the above command again so that we can ensure the availability of runtime dependencies without having to iterating through these dependencies and installing all of them one by one which would take much more time.
# install via helm
helm repo add glasskube https://charts.glasskube.eu/
helm repo update
kubectl delete crds --all # run this because we installed all the crds in the last command and helm won't work if it cannot install the crds again
# install glasskube operator
helm install go glasskube/glasskube-operatorThis above installs the glasskube-operator successfully. Let’s build an image and then push it to minikube using the following command.
gradle operator:loadImageThe above command will ensure that minikube has access to a newly built image from the source code. After running this command, I get the “docker.io/glasskube/operator:0.13.14-SNAPSHOT” image in the list of images accessible to my minikube.
minikube image lsWith the above command you can list these images for yourself.
Deploying Nextcloud using the Glasskube Operator
Let’s use the YAML below to create a Nextcloud instance.
apiVersion: glasskube.eu/v1alpha1
kind: Nextcloud
metadata:
name: nextcloud
spec:
host: nextcloud.mycompany.eu
defaultPhoneRegion: DE
apps:
office:
host: office.nextcloud.mycompany.euCreate a yaml file with the above contents and call it nextcloud.yaml.
kubectl create -f nextcloud.yamlI ran this and Nextcloud didn’t work as expected. Had a lot of errors in the operator logs. Gonna get onto debugging this tomorrow now.
15th October 2024 (extremely early morning, carry over from the last day)
The maintainer and author let me know that this operator is in maintenance mode as you can see below.
The AGPL 3.0 Dilemma
I decided to install GlassKube and see if there is a package which they provide in the current version of the package manager, but seems like they don’t support Nextcloud yet. It might be because of Nextcloud’s AGPL 3.0 license which doesn’t allow people to use Nextcloud as part of a service offering over the network. The newer Glasskube repo on the other hand has moved to Apache 2.0 license and don’t think they would want to support Nextcloud because of that. The Glasskube operator on the other hand is LGPL 3.0 License. AGPL has a stronger copyleft so the LGPL operator will be subject to it probably.
Stronger copyleft refers to a type of licensing that imposes strict requirements on derivative works based on the original licensed software.
Here, the strict requirements are given by AGPL.
I will do more justice to GlassKube in a future post, for now, I need a Nextcloud Operator.
nextcloud/operator
All of us have this one project idea (in my case, many) where you create a placeholder repository on Github to ensure that one day you might just finish that project you always wanted to start. This repository seems like a project like that, created 4 years, ago and waiting to get started.
nextcloud/helm
The Nextcloud Helm Chart seems to be in active maintenance.
A new Nextcloud Operator
If something already has a Helm chart which works extremely well, I would rather create an operator that wraps around that Helm chart and then at that point the Helm chart can be managed by the FluxCD Helm Controller. I have used this method before to create an operator where the target application that needed to be managed had a very comprehensive helm chart and it made sense to write an operator to manage the creation of these Helm charts. The operator here will be an abstraction layer over the creation and management of these charts. Any of the dependencies regarding storage, networking, CI/CD, backups etc. which nextcloud might have, will be managed by the operator itself.
Hacking together an operator
15th October 2024 (daytime)
Let’s start hacking on this. Committing everything to the repository below.
https://github.com/waveywaves/nextcloud-operator.gitInitialize the operator with Operator SDK after installation.
brew install operator-sdkoperator-sdk init --domain waveywaves.com --repo github.com/waveywaves/nextcloud-operator .This will populate the project with the operator-sdk boilerplate.
Now, let’s add a NextCloud CustomResourceDefinition.
operator-sdk create api --group nc --version v1beta1 --kind NextcloudAfter running the above you should have a scaffold operator and a basic CRD created. Say yes to all options when
make install && make runThe above will run the operator and start listening for resources of kind Nextcloud.
kubectl create -f config/samples/nc_v1beta1_nextcloud.yaml
kubectl get nextcloud
NAME AGE
nextcloud-sample 7sCreating a Nextcloud instance through the FluxCD Helm Controller
We need the FluxCD source and helm controllers so that we can have it manage the Helm chart for us. We can later on figure out a way to make sure these are installed along side the operator in a helm chart.
flux install --namespace=flux-system --components="source-controller,helm-controller"The above will install the necessary CRDs and controllers to which our NextCloud operator will delegate to. To be able to manage these CRDs through our operator let’s add these schemes to to the operator schemes. First add the dependencies below in the cmd/main.go.
fluxhelmv2beta1 "github.com/fluxcd/helm-controller/api/v2beta1"
fluxsourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2"And add the code below in the init() function.
utilruntime.Must(fluxhelmv2beta1.AddToScheme(scheme))
utilruntime.Must(fluxsourcev1beta2.AddToScheme(scheme))Once the above code is added, we can be sure of this operator being able to work well with FluxCD Custom Resource which we need. I am taking a break here as moving forward, we only have a basic integration job to ensure that the Helm Chart for Nextcloud is deployed for the operator once the user creates an instance of the Nextcloud Custom Resouce.
Nextcloud CRD → Nextcloud Helm chart creation
16th October 2024 (daytime)
It has been a nice morning and I need to prep for an interview so we are gonna try and get through this as quickly as possible.
Let’s listen to some Cory Wong while we get through this.
Whenever a Nextcloud Custom Resource is created we would like to create an adjacent HelmRelease which would create a (surprise surprise) a Helm release for Nextcloud. I have gone through a lot of programming blogs in the heyday of blogging so I know for a fact how hard it can be to read through some of these, so I am going to put the whole code below and in the comments you can read what I have done, and why I have done what I have had to do.
Let’s install a helm chart for Nextcloud locally just to be sure.
helm repo add nextcloud https://nextcloud.github.io/helm/
helm install nc nextcloud/nextcloudI get an output from the above command and reduce it to the commands below to make this testing easier.
export APP_HOST=127.0.0.1
export APP_PASSWORD=$(kubectl get secret --namespace default nc-nextcloud -o jsonpath="{.data.nextcloud-password}" | base64 --decode)
helm upgrade nc nextcloud/nextcloud --set nextcloud.password=$APP_PASSWORD,nextcloud.host=$APP_HOST,service.type=ClusterIP,mariadb.enabled=falseRun the command below and go to https://127.0.0.1:8080 to login into your Nextcloud instance.
kubectl port-forward service/nc-nextcloud 8080:8080username: admin
password: changemeUse the username and password above to login.
We get the above page after logging in, this is where we are going to stop. We are going to use the same helm values we used in the last step to intialize Nextcloud.
helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
nc default 2 2024-10-16 12:41:42.116235 +0530 IST deployed nextcloud-6.1.0 30.0.0 We need to deploy the v6.1.0 chart through the operator.
Now, let’s make the following changes to the code. First, add a Status field. This will be in a nextcloud_types.go
// NextcloudStatus defines the observed state of Nextcloud
type NextcloudStatus struct {
HelmReleaseName string `json:"helmReleaseName"`
}Next, update the controller reconcile loop as I have done in this commit. I will be refactoring everything in a commit later. Not a big fan of editing while writing.
In one terminal instance run …
make runIn another one run …
kubectl create -f config/samples/nc_v1beta1_nextcloud.yamlFind the Nextcloud Operator code here.
We are also going to set the LICENSE to AGPL 3.0 because Nextcloud is AGPL 3.0 and that extends to us as well.
Next Steps
Lifecycle
We need to make sure that the correct Conditions are set on creation of the Nextcloud instance.
Networking
I need to first make sure that the Nextcloud instance is easily accessible over a Network. Right now we are using ClusterIP, but ideally we should be able to assign a host to the Nextcloud instance and access it like a normal human being instead of port forwarding it.
There is a lot more we can do, but for next time we will focus only on the above two steps. Let me know in the comments if there are some specific next steps you would like to see.





