Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/chart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ permissions:

env:
REGISTRY: oci://ghcr.io/ferrlabs/charts
CHART: ghcr.io/ferrlabs/charts/roxycloud
CHART: ghcr.io/ferrlabs/charts/stashden

jobs:
publish:
Expand Down Expand Up @@ -47,8 +47,8 @@ jobs:

helm registry login ghcr.io -u "$REGISTRY_USER" --password-stdin <<< "$GITHUB_TOKEN"
cosign login ghcr.io -u "$REGISTRY_USER" --password-stdin <<< "$GITHUB_TOKEN"
helm package deploy/helm/roxycloud --version "$VERSION" --app-version "$VERSION"
helm push "roxycloud-${VERSION}.tgz" "$REGISTRY" 2>&1 | tee push.log
helm package deploy/helm/stashden --version "$VERSION" --app-version "$VERSION"
helm push "stashden-${VERSION}.tgz" "$REGISTRY" 2>&1 | tee push.log

DIGEST=$(grep -oE 'sha256:[0-9a-f]{64}' push.log | head -1)
if [ -z "$DIGEST" ]; then
Expand All @@ -58,4 +58,4 @@ jobs:

cosign sign --yes "${CHART}@${DIGEST}"

echo "Pushed and signed \`${REGISTRY}/roxycloud:${VERSION}\` at \`${DIGEST}\`" >> "$GITHUB_STEP_SUMMARY"
echo "Pushed and signed \`${REGISTRY}/stashden:${VERSION}\` at \`${DIGEST}\`" >> "$GITHUB_STEP_SUMMARY"
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ jobs:
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5
- name: A chart that does not render is worse than no chart
run: |
helm lint deploy/helm/roxycloud --set database.url=x --set jwt.secret=y
helm lint deploy/helm/stashden --set database.url=x --set jwt.secret=y
curl -fsSL https://github.com/yannh/kubeconform/releases/download/v0.7.0/kubeconform-linux-amd64.tar.gz | tar -xz -C /usr/local/bin kubeconform
helm template roxycloud deploy/helm/roxycloud --set database.url=postgres://u:p@db/roxycloud --set jwt.secret=secret --set ingress.enabled=true --set ingress.host=roxycloud.example --set ingress.tls.enabled=true --set ingress.tls.secretName=roxycloud-tls | kubeconform -strict -summary
helm template roxycloud deploy/helm/roxycloud --set database.existingSecret=roxycloud-database --set jwt.existingSecret=roxycloud-jwt --set persistence.enabled=false --set config.blobSweepIntervalSeconds=0 | kubeconform -strict -summary
helm template roxycloud deploy/helm/roxycloud --set database.url=postgres://u:p@db/roxycloud --set jwt.secret=secret --set blobs.backend=s3 --set blobs.s3.bucket=roxycloud --set blobs.s3.existingSecret=roxycloud-s3 --set replicaCount=3 | kubeconform -strict -summary
helm template stashden deploy/helm/stashden --set database.url=postgres://u:p@db/roxycloud --set jwt.secret=secret --set ingress.enabled=true --set ingress.host=roxycloud.example --set ingress.tls.enabled=true --set ingress.tls.secretName=roxycloud-tls | kubeconform -strict -summary
helm template stashden deploy/helm/stashden --set database.existingSecret=roxycloud-database --set jwt.existingSecret=roxycloud-jwt --set persistence.enabled=false --set config.blobSweepIntervalSeconds=0 | kubeconform -strict -summary
helm template stashden deploy/helm/stashden --set database.url=postgres://u:p@db/roxycloud --set jwt.secret=secret --set blobs.backend=s3 --set blobs.s3.bucket=roxycloud --set blobs.s3.existingSecret=roxycloud-s3 --set replicaCount=3 | kubeconform -strict -summary

compose:
runs-on: ubuntu-latest
Expand Down
11 changes: 7 additions & 4 deletions .github/workflows/image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ on:
type: boolean

env:
IMAGE: ghcr.io/ferrlabs/roxycloud-api
IMAGE: ghcr.io/ferrlabs/stashden-api
LEGACY_IMAGE: ghcr.io/ferrlabs/roxycloud-api

jobs:
build:
Expand Down Expand Up @@ -67,8 +68,8 @@ jobs:
file: deploy/Dockerfile
platforms: ${{ matrix.platform }}
labels: |
org.opencontainers.image.title=roxycloud-api
org.opencontainers.image.description=The RoxyCloud API
org.opencontainers.image.title=stashden-api
org.opencontainers.image.description=The Stashden API
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.revision=${{ steps.source.outputs.sha }}
org.opencontainers.image.version=${{ inputs.version }}
Expand Down Expand Up @@ -118,7 +119,9 @@ jobs:
- id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6
with:
images: ${{ env.IMAGE }}
images: |
${{ env.IMAGE }}
${{ env.LEGACY_IMAGE }}
tags: |
type=semver,pattern={{version}},value=v${{ inputs.version }}
type=semver,pattern={{major}}.{{minor}},value=v${{ inputs.version }}
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,16 +183,17 @@ second deployment and no CORS to configure. Hosting the bundle elsewhere still w
`STASHDEN_API_URL` pointing at the API, serve it however you like, and name its origin in
`CORS_ALLOWED_ORIGINS`.

On Kubernetes, `deploy/helm/roxycloud` deploys the API against a database you already run, with a
On Kubernetes, `deploy/helm/stashden` deploys the API against a database you already run, with a
volume for the blobs and an optional ingress. It does not bundle Postgres. It serves the web app,
since the image carries it. `deploy/helm/roxycloud/README.md` has the values and the reasoning.
since the image carries it. `deploy/helm/stashden/README.md` has the values and the reasoning, and
what a release installed from the former `roxycloud` chart needs to upgrade.

```bash
helm install roxycloud oci://ghcr.io/ferrlabs/charts/roxycloud --set database.url='postgres://roxycloud:password@postgres/roxycloud' --set jwt.secret="$(openssl rand -hex 32)"
helm install stashden oci://ghcr.io/ferrlabs/charts/stashden --set database.url='postgres://stashden:password@postgres/stashden' --set jwt.secret="$(openssl rand -hex 32)"
```

The release workflow publishes the chart to `oci://ghcr.io/ferrlabs/charts/roxycloud` and the image
to `ghcr.io/ferrlabs/roxycloud-api`, for amd64 and arm64, both under the release version, so the
The release workflow publishes the chart to `oci://ghcr.io/ferrlabs/charts/stashden` and the image
to `ghcr.io/ferrlabs/stashden-api`, for amd64 and arm64, both under the release version, so the
chart's default image needs no override.

## Endpoints
Expand Down
41 changes: 0 additions & 41 deletions deploy/helm/roxycloud/templates/_helpers.tpl

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
apiVersion: v2
name: roxycloud
description: RoxyCloud API, the server behind the web app, the desktop shell and folder sync
name: stashden
description: Stashden API, the server behind the web app, the desktop shell and folder sync
type: application
version: 0.32.0
appVersion: "0.32.0"
Expand Down
55 changes: 37 additions & 18 deletions deploy/helm/roxycloud/README.md → deploy/helm/stashden/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RoxyCloud chart
# Stashden chart

Deploys the RoxyCloud API: one replica, one volume for the blobs, and a Secret for the two values
Deploys the Stashden API: one replica, one volume for the blobs, and a Secret for the two values
it will not start without.

## What it does not do
Expand All @@ -16,35 +16,37 @@ by default. Point `ingress.host` at it and the app and the API are both there.

## The image

`ghcr.io/ferrlabs/roxycloud-api` is published by the release workflow, for `linux/amd64` and
`linux/arm64`, tagged with the exact version, the minor line and `latest`. The chart pins the exact
`ghcr.io/ferrlabs/stashden-api` is published by the release workflow, for `linux/amd64` and
`linux/arm64`, tagged with the exact version, the minor line and `latest`. The same image is still
pushed to `ghcr.io/ferrlabs/roxycloud-api`, the name it had before the project became Stashden, for
anyone who has not switched yet. The chart pins the exact
version through `appVersion`, so an upgrade moves the image and the chart together.

Building your own is still one command, which is what you want for a fork or an unreleased commit:

```bash
docker build -f deploy/Dockerfile -t your.registry/roxycloud-api:0.13.0 .
docker push your.registry/roxycloud-api:0.13.0
docker build -f deploy/Dockerfile -t your.registry/stashden-api:0.13.0 .
docker push your.registry/stashden-api:0.13.0
```

## Installing

Each release publishes this chart to `oci://ghcr.io/ferrlabs/charts/roxycloud` under the release
Each release publishes this chart to `oci://ghcr.io/ferrlabs/charts/stashden` under the release
version, signed with cosign by the release workflow. Add `--version` to pin one instead of taking the
latest:

```bash
helm install roxycloud oci://ghcr.io/ferrlabs/charts/roxycloud \
--set database.url='postgres://roxycloud:password@postgres/roxycloud' \
helm install stashden oci://ghcr.io/ferrlabs/charts/stashden \
--set database.url='postgres://stashden:password@postgres/stashden' \
--set jwt.secret="$(openssl rand -hex 32)"
```

From a checkout, with an image you built yourself:

```bash
helm install roxycloud deploy/helm/roxycloud \
--set image.repository=your.registry/roxycloud-api \
--set database.url='postgres://roxycloud:password@postgres/roxycloud' \
helm install stashden deploy/helm/stashden \
--set image.repository=your.registry/stashden-api \
--set database.url='postgres://stashden:password@postgres/stashden' \
--set jwt.secret="$(openssl rand -hex 32)" \
--set bootstrapAdmin.email=you@example.com \
--set bootstrapAdmin.password='at least twelve characters'
Expand All @@ -55,16 +57,31 @@ in External Secrets or a sealed secret:

```yaml
database:
existingSecret: roxycloud-database
existingSecret: stashden-database
existingSecretKey: url
jwt:
existingSecret: roxycloud-jwt
existingSecret: stashden-jwt
existingSecretKey: secret
```

The bootstrap administrator is created once, on a database with no accounts, and ignored after that.
Rotating `jwt.secret` invalidates every session token in circulation.

## Upgrading from the roxycloud chart

The chart was called `roxycloud` before the project became Stashden, and the chart name is part of
every resource name and of the Deployment's selector, which Kubernetes does not let an upgrade
change. A release installed from the old chart keeps its names by setting `nameOverride`:

```bash
helm upgrade roxycloud oci://ghcr.io/ferrlabs/charts/stashden \
--reuse-values --set nameOverride=roxycloud
```

Without it, the upgrade fails on the selector, and a fresh install beside it would create an empty
claim instead of using the one that holds the blobs. The image moves to `stashden-api` on its own,
since the chart's default now points there and it is the same image.

## One replica

`replicas` is not a value. The blob store is a directory, the claim is `ReadWriteOnce`, and two pods
Expand All @@ -79,7 +96,7 @@ over a kept claim means telling the chart to adopt it rather than create a secon

```yaml
persistence:
existingClaim: roxycloud
existingClaim: stashden
```

Turn `persistence.retain` off if you would rather uninstall took the data with it. Nothing else in
Expand All @@ -89,7 +106,7 @@ this chart is capable of deleting the blob store.

| Value | Default | Purpose |
|---|---|---|
| `image.repository` | `ghcr.io/ferrlabs/roxycloud-api` | Image to run |
| `image.repository` | `ghcr.io/ferrlabs/stashden-api` | Image to run |
| `image.tag` | chart `appVersion` | Tag to run |
| `database.url` | none | Postgres connection string, required unless `database.existingSecret` is set |
| `database.existingSecret` | none | Secret already holding the connection string |
Expand Down Expand Up @@ -118,10 +135,12 @@ this chart is capable of deleting the blob store.
| `ingress.tls.enabled` | `false` | Serve the host over TLS |
| `ingress.tls.secretName` | none | Required when TLS is on |
| `resources` | none | Container requests and limits |
| `nameOverride` | chart name | Name used for the resources and the `app.kubernetes.io/name` label |
| `fullnameOverride` | none | Full resource name, overriding the release and chart names |

## Checking a change to the chart

```bash
helm lint deploy/helm/roxycloud --set database.url=x --set jwt.secret=y
helm template roxycloud deploy/helm/roxycloud --set database.url=x --set jwt.secret=y | kubeconform -strict -summary
helm lint deploy/helm/stashden --set database.url=x --set jwt.secret=y
helm template stashden deploy/helm/stashden --set database.url=x --set jwt.secret=y | kubeconform -strict -summary
```
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{ .Chart.Name }} {{ .Chart.AppVersion }} is installed as {{ include "roxycloud.fullname" . }}.
{{ .Chart.Name }} {{ .Chart.AppVersion }} is installed as {{ include "stashden.fullname" . }}.

The API answers on port {{ .Values.service.port }}.
{{- if .Values.ingress.enabled }}
Expand All @@ -7,7 +7,7 @@ It is reachable at http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Valu

Nothing exposes it yet. To look at it from your machine:

kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "roxycloud.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }}
kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "stashden.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }}
curl http://localhost:{{ .Values.service.port }}/health
{{- end }}
{{- if not .Values.bootstrapAdmin.email }}
Expand Down
41 changes: 41 additions & 0 deletions deploy/helm/stashden/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{{- define "stashden.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{- define "stashden.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else if contains (include "stashden.name" .) .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name (include "stashden.name" .) | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}

{{- define "stashden.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{ include "stashden.selectorLabels" . }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{- define "stashden.selectorLabels" -}}
app.kubernetes.io/name: {{ include "stashden.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{- define "stashden.databaseSecret" -}}
{{- default (include "stashden.fullname" .) .Values.database.existingSecret }}
{{- end }}

{{- define "stashden.jwtSecret" -}}
{{- default (include "stashden.fullname" .) .Values.jwt.existingSecret }}
{{- end }}

{{- define "stashden.claimName" -}}
{{- default (include "stashden.fullname" .) .Values.persistence.existingClaim }}
{{- end }}

{{- define "stashden.s3Secret" -}}
{{- .Values.blobs.s3.existingSecret | default (include "stashden.fullname" .) -}}
{{- end -}}
Loading
Loading