Skip to content

Commit 65462cb

Browse files
committed
feature: add plugin install system
1 parent d1326f8 commit 65462cb

13 files changed

Lines changed: 242 additions & 2 deletions

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
node_modules
22
dist
3+
4+
# The installer copies *.env.example -> *.env and fills in your site values.
5+
*.env
6+
!*.env.example

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,26 @@ npm run preview # serve dist/ at :4173 with CORS, for testing in a real panel
1818
| --- | --- |
1919
| `src/App.vue` | Your UI. Receives the logged-in `user` and the host `query` as props. |
2020
| `vite.config.ts` | Exposes `./App` as a Federation remote; declares shared singletons. |
21-
| `public/5stack-plugin.json` | The manifest the panel auto-detects. |
21+
| `public/5stack-plugin.json` | The manifest the panel auto-detects, including the `install` block. |
22+
| `k8s/` | kustomize package — `base/`, plus an `http` and an `https` overlay. |
2223
| `tailwind.config.js` | Pulls in the `@5stack/ui` preset so you inherit 5stack theming. |
2324
| `src/main.ts` | Standalone dev entry — **not** used when embedded in the panel. |
2425

26+
## Install it onto a 5stack cluster
27+
28+
From an operator's `5stack-panel` checkout:
29+
30+
```sh
31+
./plugin.sh 5stackgg/5stack-example-plugin
32+
```
33+
34+
That's the whole install: it reads the site's own config for the cluster,
35+
domain, and whether TLS terminates at the cluster, then applies `k8s/`. This
36+
repo is the minimal working example of the format — frontend only, so its
37+
manifest declares no database and no node pinning and the installer skips both
38+
questions. Copy `k8s/` and the `install` block as your starting point, and see
39+
[docs.5stack.gg/plugins/installing](https://docs.5stack.gg/plugins/installing).
40+
2541
## Try it against a running panel
2642

2743
```sh

k8s/base/deployment.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Frontend only — this plugin has no backend. The container is nginx serving the
2+
# built Module Federation remote; the panel fetches remoteEntry.js from it.
3+
apiVersion: apps/v1
4+
kind: Deployment
5+
metadata:
6+
name: example-plugin
7+
spec:
8+
selector:
9+
matchLabels:
10+
app: example-plugin
11+
strategy:
12+
type: Recreate
13+
template:
14+
metadata:
15+
labels:
16+
app: example-plugin
17+
spec:
18+
containers:
19+
- name: example-plugin
20+
image: ghcr.io/5stackgg/5stack-example-plugin:latest
21+
# :latest is republished on every push to main, so the tag alone
22+
# doesn't change — always re-pull it on restart.
23+
imagePullPolicy: Always
24+
ports:
25+
- containerPort: 80
26+
name: http
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# The host this plugin is served from. It must be a subdomain of the panel if
2+
# you ever add a backend — the 5stack session cookie is SameSite=Lax and never
3+
# reaches an unrelated domain.
4+
#
5+
# The panel's ./plugin.sh copies this file to example-plugin.env and fills the
6+
# value in from your site's WEB_DOMAIN; you only need to touch it if you're
7+
# applying the package by hand.
8+
EXAMPLE_PLUGIN_DOMAIN=hello.example.com

k8s/base/ingress.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# One ingress, no auth annotations: everything this plugin serves is public
2+
# static JS. There is no API to gate — the panel supplies the logged-in user to
3+
# the remote as a prop. A plugin with a backend needs more than this; see the
4+
# inventory plugin's ingresses, which split /api off to a backend Service.
5+
#
6+
# CORS and the no-store header on remoteEntry.js are set by the container's
7+
# nginx.conf, not here.
8+
#
9+
# No `tls:` on purpose — the base IS the plain-HTTP install, for sites whose
10+
# certificate is terminated in front of the cluster. ../overlays/https adds the
11+
# tls blocks by patch.
12+
apiVersion: networking.k8s.io/v1
13+
kind: Ingress
14+
metadata:
15+
name: example-plugin
16+
namespace: 5stack
17+
spec:
18+
ingressClassName: nginx
19+
rules:
20+
- host: ${EXAMPLE_PLUGIN_DOMAIN}
21+
http:
22+
paths:
23+
- backend:
24+
service:
25+
name: example-plugin
26+
port:
27+
number: 80
28+
path: /
29+
pathType: Prefix

k8s/base/kustomization.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# The whole plugin, HTTP-only. Both overlays build from this.
2+
#
3+
# The host is written once, into example-plugin.env, and the replacement below
4+
# pushes it wherever it's needed — here just the ingress rule; the https overlay
5+
# adds the tls host and the certificate's SAN from the same value. The panel's
6+
# ./plugin.sh fills that file in for you from your site's WEB_DOMAIN.
7+
apiVersion: kustomize.config.k8s.io/v1beta1
8+
kind: Kustomization
9+
10+
namespace: 5stack
11+
12+
resources:
13+
- deployment.yaml
14+
- service.yaml
15+
- ingress.yaml
16+
17+
configMapGenerator:
18+
- name: example-plugin-config
19+
envs:
20+
- example-plugin.env
21+
22+
replacements:
23+
- source:
24+
kind: ConfigMap
25+
name: example-plugin-config
26+
fieldPath: data.EXAMPLE_PLUGIN_DOMAIN
27+
targets:
28+
- select:
29+
kind: Ingress
30+
name: example-plugin
31+
fieldPaths:
32+
- spec.rules.0.host

k8s/base/service.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: example-plugin
5+
spec:
6+
ports:
7+
- port: 80
8+
targetPort: 80
9+
selector:
10+
app: example-plugin

k8s/kustomization.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Compatibility shim for the panel's ./custom.sh, which builds a directory root
2+
# and so needs a kustomization here. `./plugin.sh <repo>` doesn't use this file
3+
# — it builds the overlay it picked for your site directly.
4+
#
5+
# Defaults to the plain-HTTP install; point it at overlays/https if your panel
6+
# terminates TLS at the cluster.
7+
apiVersion: kustomize.config.k8s.io/v1beta1
8+
kind: Kustomization
9+
10+
resources:
11+
- overlays/http
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Plain-HTTP install — no certificate.
2+
#
3+
# For sites where TLS is already terminated in front of the cluster: a
4+
# Cloudflare proxy or tunnel, or any other reverse proxy. That is the panel's
5+
# REVERSE_PROXY=true, and ./plugin.sh picks this overlay when it reads that out
6+
# of your .5stack-env.config.
7+
#
8+
# Nothing to add — the base is already HTTP-only. It exists so the two installs
9+
# are symmetric: one directory each, and the installer just points kustomize at
10+
# whichever one your site needs.
11+
apiVersion: kustomize.config.k8s.io/v1beta1
12+
kind: Kustomization
13+
14+
resources:
15+
- ../../base
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# The plugin's own certificate.
2+
#
3+
# Not an entry added to the panel's shared 5stack-ssl cert: the panel rebuilds
4+
# that one from its own overlay on every ./update.sh, so anything a plugin added
5+
# there would be silently dropped on the next panel update.
6+
#
7+
# The Issuer is the namespaced Issuer the panel install creates when the site
8+
# terminates TLS itself. If yours is named something else, change issuerRef —
9+
# nothing else in this overlay depends on the name.
10+
#
11+
# ${EXAMPLE_PLUGIN_DOMAIN} is substituted by the replacement in
12+
# kustomization.yaml, from the same file the ingress host comes from.
13+
apiVersion: cert-manager.io/v1
14+
kind: Certificate
15+
metadata:
16+
name: example-plugin-ssl
17+
namespace: 5stack
18+
spec:
19+
secretName: example-plugin-ssl
20+
# Matches the panel's cert cadence: 90d lifetime, renewed with 10d to spare.
21+
duration: 2160h
22+
renewBefore: 240h
23+
dnsNames:
24+
- ${EXAMPLE_PLUGIN_DOMAIN}
25+
issuerRef:
26+
name: 5stack-issuer
27+
kind: Issuer

0 commit comments

Comments
 (0)