Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • stackspin/stackspin-flux-example
  • xeruf/stackspout
2 results
Show changes
Commits on Source (201)
Showing
with 561 additions and 76 deletions
# Example repository for customizing a Stackspin cluster
Example boilerplate for a custom [flux](https://fluxcd.io/) repository
which can be added to a [Stackspin](https://stackspin.net) cluster.
The main use-case is to add additional applications
which are not integrated into Stackspin (yet).
For a more advanced example
see the [flux2-kustomize-helm-example](https://github.com/fluxcd/flux2-kustomize-helm-example)
repository.
This repo's directory structure is similar to the `flux2-kustomize-helm-example`
one.
## Basic configuration
We'll start with a very basic configuration:
* It uses a public git repo
* No secrets are included
* No forking/modifications needed, install as it is
# Stackspin Outwards - Stackspout
This repository extends [Stackspin](https://open.greenhost.net/stackspin/stackspin)
with extra applications and overrides
to make it more commercially/professionally interesting.
Once stabilized, the aim is to contribute as much upstream as possible.
Stackspout is used in day-to-day business
with a double-digit user number,
so all experiments happen carefully.
## Tools
Useful tools for administration:
- my `stack` CLI helper, currently part of my dotfiles:
https://git.jfischer.org/xeruf/dotfiles/src/branch/main/.config/shell/server#L11
- stackspin docs:
https://docs.stackspin.net/en/v2/system_administration/customizing.html
### Guide: Create OAuth Credentials for an external service
- add a line in `basic/install.sh` and run it to generate the secret
- append another OAuth2Client definition to `basic/overrides/oauth-clients.yaml`,
adjusting `metadata.name` and `spec.secretName` as well as `spec.redirectUris`
- apply changes to the cluster
- obtain the generated `client_secret` for your application from kubernetes:
kubectl get secret -n flux-system stackspin-APP-oauth-variables --template '{{.data.client_secret}}' | base64 -d
with client_id:
kubectl get secret -n flux-system stackspin-APP-oauth-variables --template '{{.data.client_id}}{{"\n"}}{{.data.client_secret}}{{"\n"}}' | while read in; do echo $in | base64 -d; echo; done
## Customizations
### Overrides
- Adds many Nextcloud extensions and some configuration
- Add Email Auth back to Zulip
### New Applications
below list is formatted as:
> subdomain: Service (helmrepo, if not provided by the service authors)
#### Stable including Single-Sign-On
- dev: Gitea
- do: Vikunja (k8s-at-home - migrating to truecharts)
- ninja: InvoiceNinja
#### In Development
- people: SuiteCRM (bitnami repo)
- time: Kimai (robjuz repo)
#### Planned
- meet: Jitsi Meet
- wiki: Wiki (maybe wikijs, but I'd like something that integrated with Nextcloud and Markdown/Orgdown)
#### Ideas
- link: URL Shortener
- Bonfire
### Issues to tackle
#### Structurally
- generate_secrets.py was copied from Stackpin
#### Functionally
- Nextcloud too slow - add Redis
- Preconfigure user settings in Nextcloud, Vikunja and more
## Installation
> Warning: Lots of experiments happening here!
Apply it to your cluster:
......@@ -25,41 +70,13 @@ Apply it to your cluster:
basic/install.sh
```
List the resource created by this flux repo:
List the resource related to this repo:
```sh
kubectl -n example-basic get gitrepositories
kubectl -n example-basic get kustomizations
kubectl -n example-basic get helmreleases
kubectl -n example-basic get pods
kubectl get gitrepositories -A
kubectl get kustomization -A -o=jsonpath='{.items[?(@.spec.sourceRef.name=="stackspout")].metadata.name}'
kubectl -n stackspout get helmreleases
kubectl -n stackspout get pods
```
Show output of the single app applied, [podinfo](https://github.com/stefanprodan/podinfo)
```sh
curl --resolve podinfo.local:80:CLUSTER_IPV4_ADDRESS http://podinfo.local
```
## What's next ?
There are two ways of using a custom flux repo to host your custom config/apps
on a Stackspin cluster.
### A) Manage secrets manually
This approach is easier to start with,
because you don't need to configure your cluster to handle encrypted secrets
and access to a private git repository.
* Fork this repository into a public git repo, cloneable via `https://`
### Everything in version control, including secrets
* Fork this repository into a private git repo, cloneable via `ssh://`
* [Configure flux to use ssh instead of https for cloning](https://fluxcd.io/docs/components/source/gitrepositories/#ssh-authentication)
* You shouln't rely solely on transport encryption for your git repository
but rather end-to-end encrypt your secrets.
Different methods are available for flux:
* [Sops](https://fluxcd.io/docs/guides/mozilla-sops/)
[Sops section in flux2-kustomize-helm-example](https://github.com/fluxcd/flux2-kustomize-helm-example#encrypt-kubernetes-secrets)
* [Sealed Secrets](https://fluxcd.io/docs/guides/sealed-secrets/)
But there are also ConfigMaps, Secrets, StatefulSets, PVCs, Helmrepos and all that stuff...
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gitea-data
namespace: stackspout
labels:
stackspin.net/backupSet: "gitea"
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 2Gi
storageClassName: local-path
apiVersion: hydra.ory.sh/v1alpha1
kind: OAuth2Client
metadata:
name: gitea-oauth-client
# Has to live in the same namespace as the stackspin-wordpress-oauth-variables secret
namespace: flux-system
spec:
# TODO copied from wekan: https://github.com/wekan/wekan/wiki/Keycloak
grantTypes:
- authorization_code
- refresh_token
- client_credentials
- implicit
responseTypes:
- id_token
- code
scope: "openid profile email stackspin_roles"
secretName: stackspin-gitea-oauth-variables
redirectUris:
- https://code.${domain}/user/oauth2/Stackspin/callback
tokenEndpointAuthMethod: client_secret_post
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gitea-postgres
namespace: stackspout
labels:
stackspin.net/backupSet: "gitea"
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 2Gi
storageClassName: local-path
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: gitea
namespace: stackspout
spec:
releaseName: gitea
chart:
spec:
# https://gitea.com/gitea/helm-chart/tags
chart: gitea
version: 6.0.5
sourceRef:
kind: HelmRepository
name: gitea
namespace: flux-system
interval: 5m
valuesFrom:
- kind: ConfigMap
name: stackspin-gitea-values
optional: false
# Allow overriding values by ConfigMap or Secret
- kind: ConfigMap
name: stackspin-gitea-override
optional: true
- kind: Secret
name: stackspin-gitea-override
optional: true
apiVersion: v1
kind: ConfigMap
metadata:
name: stackspin-gitea-values
namespace: stackspout
data:
values.yaml: |
ingress:
enabled: true
annotations:
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
hosts:
- host: "code.${domain}"
paths:
- path: /
pathType: Prefix
tls:
- secretName: gitea-tls
hosts:
- "code.${domain}"
gitea:
# https://gitea.com/gitea/helm-chart/src/branch/main#oauth2-settings
oauth:
- name: Stackspin
provider: "openidConnect"
key: "${client_id}"
secret: "${client_secret}"
autoDiscoverUrl: "https://sso.${domain}/.well-known/openid-configuration"
iconUrl: "https://dashboard.${domain}/favicon-32x32.png"
# https://docs.gitea.io/en-us/config-cheat-sheet
config:
repository:
DEFAULT_PUSH_CREATE_PRIVATE: false
ENABLE_PUSH_CREATE_USER: true
ENABLE_PUSH_CREATE_ORG: true
server:
ROOT_URL: "https://code.${domain}"
LANDING_PAGE: login
openid:
ENABLE_OPENID_SIGNUP: true
service:
DISABLE_REGISTRATION: false
ALLOW_ONLY_EXTERNAL_REGISTRATION: true
log:
LEVEL: "Trace"
persistence:
enabled: true
existingClaim: gitea-data
postgresql:
persistence:
enabled: true
existingClaim: gitea-postgres
service:
ssh:
hostPort: 22
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- vikunja-oauth-client.yaml
- vikunja-release.yaml
- vikunja-values-configmap.yaml
- vikunja-postgres-pvc.yaml
apiVersion: hydra.ory.sh/v1alpha1
kind: OAuth2Client
metadata:
name: vikunja-test-oauth-client
# Has to live in the same namespace as the stackspin-wordpress-oauth-variables secret
namespace: flux-system
spec:
# TODO copied from wekan: https://github.com/wekan/wekan/wiki/Keycloak
grantTypes:
- authorization_code
- refresh_token
- client_credentials
- implicit
responseTypes:
- id_token
- code
scope: "openid profile email stackspin_roles"
secretName: stackspin-vikunja-test-oauth-variables
redirectUris:
- https://do-test.${domain}/auth/openid/stackspin
tokenEndpointAuthMethod: client_secret_post
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: vikunja-test-postgres
namespace: stackspout
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 2Gi
storageClassName: local-path
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: vikunja-test
namespace: stackspout
spec:
releaseName: vikunja-test
chart:
spec:
# https://github.com/truecharts/charts/blob/master/charts/stable/vikunja/Chart.yaml
chart: vikunja
version: 6.0.22
sourceRef:
kind: HelmRepository
name: truecharts
namespace: flux-system
interval: 5m
valuesFrom:
- kind: ConfigMap
name: stackspin-vikunja-values
optional: false
- kind: ConfigMap
name: stackspin-vikunja-test-values
optional: false
# Allow overriding values by ConfigMap or Secret
- kind: ConfigMap
name: stackspin-vikunja-override
optional: true
- kind: Secret
name: stackspin-vikunja-override
optional: true
apiVersion: v1
kind: ConfigMap
metadata:
name: stackspin-vikunja-test-values
namespace: stackspout
data:
# https://github.com/truecharts/charts/blob/master/charts/stable/vikunja/values.yaml
values.yaml: |
image:
tag: unstable
imagePullPolicy: Always
frontendImage:
tag: unstable
imagePullPolicy: Always
configmap:
config:
data:
vikunja.yaml: |-
auth:
openid:
# https://vikunja.io/docs/config-options/#openid
# Example: https://github.com/go-vikunja/api/blob/main/config.yml.sample#L289-L312
enabled: true
redirecturl: "https://do-test.${domain}/auth/openid/"
providers:
- name: Stackspin
authurl: "https://sso.${domain}/"
clientid: "${client_id}"
clientsecret: "${client_secret}"
service:
frontendurl: "https://do-test.${domain}"
motd: "This is a test instance, do not use for production data as it can vanish without notice! Use Stackspin login, as usual."
timezone: "CET"
JWTSecret: "${jwt}"
database:
type: postgres
host: vikunja-test-postgresql
password: "${postgresql_password}"
log:
path: "/app/vikunja"
http: stdout
database: stderr
databaselevel: debug
ingress:
main:
enabled: true
primary: false
annotations:
kubernetes.io/tls-acme: "true"
hosts:
- host: "do-test.${domain}"
paths:
- path: /
pathType: Prefix
tls:
- secretName: vikunja-test-tls
hosts:
- "do-test.${domain}"
#persistence:
# files:
# labels:
# stackspin.net/backupSet: "vikunja"
postgresql:
# https://github.com/truecharts/charts/blob/master/charts/dependency/postgresql/values.yaml
#enabled: true
postgresqlDatabase: vikunja
postgresqlUsername: vikunja
postgresqlPassword: "${postgresql_password}"
#persistence:
# db:
# enabled: true
# # -- Sets the persistence type
# # Valid options are: simplePVC, simpleHP, pvc, emptyDir, secret, configMap, hostPath or custom
# type: pvc
# mountPath: "/bitnami/postgresql"
# # -- If you want to reuse an existing claim, the name of the existing PVC can be passed here.
# existingClaim: vikunja-test-postgres
#volumeClaimTemplates:
# db:
# enabled: false
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: vikunja-files
namespace: stackspout
labels:
stackspin.net/backupSet: "vikunja"
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 2Gi
storageClassName: local-path
apiVersion: hydra.ory.sh/v1alpha1
kind: OAuth2Client
metadata:
name: vikunja-oauth-client
# Has to live in the same namespace as the stackspin-wordpress-oauth-variables secret
namespace: flux-system
spec:
# TODO copied from wekan: https://github.com/wekan/wekan/wiki/Keycloak
grantTypes:
- authorization_code
- refresh_token
- client_credentials
- implicit
responseTypes:
- id_token
- code
scope: "openid profile email stackspin_roles"
secretName: stackspin-vikunja-oauth-variables
redirectUris:
- https://do.${domain}/auth/openid/stackspin
tokenEndpointAuthMethod: client_secret_post
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: vikunja-postgres
namespace: stackspout
labels:
stackspin.net/backupSet: "vikunja"
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 2Gi
storageClassName: local-path
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: vikunja
namespace: stackspout
spec:
releaseName: vikunja
chart:
spec:
chart: vikunja
version: 5.5.3
sourceRef:
kind: HelmRepository
name: k8s-at-home
namespace: flux-system
interval: 5m
valuesFrom:
- kind: ConfigMap
name: stackspin-vikunja-values
optional: false
# Allow overriding values by ConfigMap or Secret
- kind: ConfigMap
name: stackspin-vikunja-override
optional: true
- kind: Secret
name: stackspin-vikunja-override
optional: true
apiVersion: v1
kind: ConfigMap
metadata:
name: stackspin-vikunja-values
namespace: stackspout
data:
# Defaults: https://github.com/k8s-at-home/charts/blob/master/charts/stable/vikunja/values.yaml
# Inherits: https://github.com/k8s-at-home/library-charts/blob/main/charts/stable/common/values.yaml
values.yaml: |
additionalContainers:
api:
image: vikunja/api:latest
imagePullPolicy: Always
volumeMounts: [{"mountPath":"/etc/vikunja/config.yml","name":"vikunja-config","subPath":"Vikunja.yaml"}, {"mountPath":"/etc/vikunja/files","name":"files"}]
frontend:
image: vikunja/frontend:latest
imagePullPolicy: Always
vikunja:
config: |-
auth:
openid:
# https://vikunja.io/docs/config-options/#openid
# Example: https://github.com/go-vikunja/api/blob/main/config.yml.sample#L289-L312
enabled: true
redirecturl: "https://do.${domain}/auth/openid/"
providers:
- name: Stackspin
authurl: "https://sso.${domain}/"
clientid: "${client_id}"
clientsecret: "${client_secret}"
local:
enabled: false
mailer:
enabled: "${outgoing_mail_enabled}"
host: "${outgoing_mail_smtp_host}"
port: "${outgoing_mail_smtp_port}"
username: "${outgoing_mail_smtp_user}"
password: "${outgoing_mail_smtp_password}"
fromemail: "${outgoing_mail_from_address}"
forcessl: true
# TODO Configure PVC for file uploads
service:
frontendurl: "https://do.${domain}"
motd: "Please allow public profile discovery in settings!"
timezone: "CET"
JWTSecret: "${jwt}"
database:
type: postgres
host: vikunja-postgresql
password: "${postgresql_password}"
log:
path: "/app/vikunja"
http: file
database: stderr
databaselevel: debug
persistence:
files:
enabled: true
existingClaim: vikunja-files
ingress:
main:
enabled: true
primary: false
annotations:
kubernetes.io/tls-acme: "true"
hosts:
- host: "do.${domain}"
# TODO Helm template rather than repetition in every file? See https://github.com/k8s-at-home/library-charts/blob/4d09a8ddbdf11c278101b74b36720b5f7c17cd71/charts/stable/common/values.yaml#L342
paths:
- path: /
pathType: Prefix
tls:
- secretName: vikunja-tls
hosts:
- "do.${domain}"
caddy:
# TODO is caddy needed at all?
noTls: true
postgresql:
enabled: true
postgresqlDatabase: vikunja
postgresqlUsername: vikunja
postgresqlPassword: "${postgresql_password}"
persistence:
enabled: true
existingClaim: vikunja-postgres
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: podinfo
namespace: example-basic
spec:
releaseName: podinfo
chart:
spec:
# https://artifacthub.io/packages/helm/podinfo/podinfo
chart: podinfo
version: 6.1.1
sourceRef:
kind: HelmRepository
name: podinfo
namespace: example-basic
interval: 60m
# Default values
# https://github.com/stefanprodan/podinfo/blob/master/charts/podinfo/values.yaml
values:
ingress:
enabled: true
#!/bin/sh -e
# Generates kubernetes kustomizations
find -mindepth 1 -maxdepth 1 -type d | while read dir;
do echo "$dir"
{ echo 'apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:'
find $dir -type f -not -name "*.bak" -not -name "kustomization.yaml" -printf " - %f\n"; } | tee $dir/kustomization.yaml
done
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: invoiceninja-mariadb
namespace: stackspout
labels:
stackspin.net/backupSet: "invoiceninja"
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
storageClassName: local-path
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: invoiceninja-data
namespace: stackspout
labels:
stackspin.net/backupSet: "invoiceninja"
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 2Gi
storageClassName: local-path