Project Overview
What You Will Learn
- Who the Radical Faeries are and what they need from Junovy
- What you will build: two live apps with databases, secrets, and TLS
- How this project differs from Chapter 9 (more apps, more moving parts)
- The four phases of client onboarding
The Mission
You are going to onboard a real client: the Radical Faeries. They are a queer spiritual and social community that organises gatherings, rituals, and shared projects. They need two tools hosted on the Junovy platform:
- BookStack -- an internal wiki for sharing knowledge, meeting notes, and community documentation
- Rallly -- a meeting scheduler for coordinating gatherings and events
When this project is complete, both apps will be live:
https://bookstack.radical-faeries.junovy.com
https://rallly.radical-faeries.junovy.com
Both will be served over HTTPS with automatic TLS certificates, running in containers managed by Kubernetes, deployed through GitOps.
Training Note: In the real Junovy platform, BookStack and Rallly run as shared services (support.junovy.com and gather.junovy.com), not as per-tenant deployments. This project deliberately deploys them inside a tenant namespace as a learning exercise -- it teaches the HelmRelease, ExternalSecret, and Ingress patterns you will use for any app. In production, you would follow this same pattern but with different applications.
How This Differs from Chapter 9
In Chapter 9, you deployed a single static web app. This project is closer to what real client onboarding looks like. Here is the comparison:
| Aspect | Chapter 9 (Godot Game) | Chapter 10 (Radical Faeries) |
|---|---|---|
| Number of apps | 1 | 2 (BookStack + Rallly) |
| Databases | None | MySQL (BookStack) + PostgreSQL (Rallly) |
| Secrets in Vault | None | Database credentials, app keys, mail config |
| ExternalSecrets | None | 2 ExternalSecret resources |
| HelmReleases | None (raw Deployment) | 2 HelmRelease resources |
| Ingress resources | 1 | 2 (one per app) |
| Complexity | Starter | Realistic production workload |
Think of Chapter 9 as a tutorial level. This chapter is the first real mission.
The Four Phases
Here is what you will do, broken into one page per phase:
| Phase | Page | What Happens |
|---|---|---|
| 1 | Plan the Tenant | Decide namespace name, list required apps, databases, secrets, and domains |
| 2 | Create the Tenant from Scratch | Build the directory, namespace, Vault secrets, and ExternalSecrets |
| 3 | Deploy Apps for the Faeries | Write HelmRelease manifests for BookStack and Rallly, plus Ingress resources |
| 4 | Verify and Handoff | Push to Git, reconcile with Flux, verify everything works, hand off to the client |
Each phase builds on the previous one. By the end, you will have onboarded a multi-app client from scratch.
Prerequisites
Before you start, make sure you have the following ready:
| Prerequisite | How to Check |
|---|---|
| Completed Chapter 9 | You have a working tenant deployment under your belt |
| Understand secrets (Chapter 7) | You know what Vault and ExternalSecrets do |
| VPN access (WireGuard) | ping robin.spynl.net responds |
| Vault access | vault status shows "Initialized: true, Sealed: false" |
dds-k8s-cluster repo cloned |
ls ~/workspace/junovy/dds-k8s-cluster/clients/ shows existing tenants |
kubectl configured for the cluster |
kubectl cluster-info --context admin@dds-prod-de-fsn1 shows the API server |
flux CLI installed |
flux version shows output |
| Helm CLI installed | helm version shows output |
If any of these are not set up yet, refer back to Chapter 6 (Your Toolbox) and Chapter 7 (Secrets and Security).
What You Are Building
Here is a quick sketch of the final architecture inside the hst-radical-faeries namespace:
hst-radical-faeries namespace
├── BookStack (PHP app)
│ ├── HelmRelease → runs BookStack container + MySQL sidecar
│ ├── ExternalSecret → pulls DB creds + app key from Vault
│ ├── Ingress → bookstack.radical-faeries.junovy.com (TLS)
│ └── PersistentVolume → stores uploads and attachments
│
└── Rallly (Node.js app)
├── HelmRelease → runs Rallly container
├── ExternalSecret → pulls DB URL + secret key from Vault
└── Ingress → rallly.radical-faeries.junovy.com (TLS)
Everything is defined in YAML, committed to Git, and deployed automatically by Flux.
Key Takeaways
- The Radical Faeries need BookStack (wiki) and Rallly (scheduler) hosted on Junovy
- This project involves two apps, two databases, secrets in Vault, and two Ingress resources
- There are four phases: Plan, Create Tenant, Deploy Apps, Verify and Handoff
- The final URLs are
bookstack.radical-faeries.junovy.comandrallly.radical-faeries.junovy.com
What Is Next
Next up: Plan the Tenant where you will map out every resource, secret, and file before writing a single line of YAML.