Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
f94133b505 | |||
60c869a141 | |||
347dff8ea8 | |||
82dacc05d9 | |||
f67be8dbb8 | |||
c4bd44f3f4 | |||
9d83a6768d | |||
45dbb893d1 | |||
eaa86fd867 | |||
37d6785ee2 | |||
27a80c7b25 | |||
1eb8c99d2c | |||
5c326ed1ae | |||
fb2aa0f67c | |||
fb81d51e29 |
35
Dockerfile
35
Dockerfile
@ -1,20 +1,19 @@
|
||||
FROM node:10-alpine
|
||||
FROM node:lts-alpine
|
||||
|
||||
RUN adduser -D -h /home/app app \
|
||||
&& apk add --update --no-cache \
|
||||
bash \
|
||||
jq \
|
||||
git
|
||||
WORKDIR /home/app
|
||||
ARG WIKI_PACKAGE=wiki@0.19.0
|
||||
RUN su app -c "npm install -g --prefix . $WIKI_PACKAGE"
|
||||
RUN su app -c "mkdir .wiki"
|
||||
COPY configure-wiki set-owner-name ./
|
||||
RUN chown app configure-wiki set-owner-name
|
||||
VOLUME "/home/app/.wiki"
|
||||
ENV DOMAIN=localhost
|
||||
ENV OWNER_NAME="The Owner"
|
||||
ENV COOKIE=insecure
|
||||
RUN apk add --update --no-cache \
|
||||
dumb-init \
|
||||
git \
|
||||
jq
|
||||
WORKDIR "/home/node"
|
||||
ARG WIKI_PACKAGE=wiki@0.21.0
|
||||
ARG WIKI_CLIENT=wiki-client@0.20.1
|
||||
ARG WIKI_SERVER=wiki-server@0.17.5
|
||||
RUN su node -c "npm install -g --prefix . $WIKI_PACKAGE" \
|
||||
&& su node -c "cd /home/node/lib/node_modules/wiki && npm install --save $WIKI_CLIENT $WIKI_SERVER"
|
||||
RUN su node -c "mkdir -p .wiki"
|
||||
VOLUME "/home/node/.wiki"
|
||||
EXPOSE 3000
|
||||
USER app
|
||||
CMD ["/home/app/bin/wiki"]
|
||||
USER node
|
||||
ENV PATH="${PATH}:/home/node/bin"
|
||||
ENTRYPOINT ["dumb-init"]
|
||||
CMD ["wiki", "--farm", "--security_type=friends"]
|
||||
|
65
README.md
65
README.md
@ -1,59 +1,60 @@
|
||||
# Federated Wiki Farm
|
||||
|
||||
http://fed.wiki.org
|
||||
Start Playing Federated Wiki: http://start.fed.wiki
|
||||
|
||||
Although this container can run alone, I use and develop it with
|
||||
a reverse proxy. See: https://github.com/dobbs/wiki-tls
|
||||
### Run a local wiki farm
|
||||
|
||||
See also http://local-farm.wiki.dbbs.co for many more details.
|
||||
docker run -p 3000:3000 -it --rm \
|
||||
dobbs/farm
|
||||
|
||||
### Get acquainted with wiki.
|
||||
Visit http://localhost:3000 and http://anything.localtest.me:3000
|
||||
|
||||
Launch the container:
|
||||
``` bash
|
||||
docker run -p 3000:3000 -it --rm \
|
||||
dobbs/farm
|
||||
```
|
||||
### Run a local wiki that will survive a reboot
|
||||
|
||||
Visit http://localhost:3000
|
||||
docker run -p 3000:3000 -it --rm \
|
||||
-v ~/.wiki:/home/node/.wiki \
|
||||
dobbs/farm
|
||||
|
||||
### Make your wiki survive a reboot
|
||||
Your wiki pages and configuration will be saved in the ~/.wiki folder.
|
||||
|
||||
Create a volume:
|
||||
# Release Notes for 1.0.0
|
||||
|
||||
``` bash
|
||||
docker volume create dot-wiki
|
||||
```
|
||||
This is a significant **breaking** change from pre-1.0 releases. Especially:
|
||||
|
||||
Launch the container:
|
||||
``` bash
|
||||
docker run -p 3000:3000 -it --rm \
|
||||
-v dot-wiki:/home/app/.wiki \
|
||||
dobbs/farm
|
||||
```
|
||||
* changed the user from `app` (`uid=1001(app) gid=1001(app) groups=1001(app)`)
|
||||
to `node` (`uid=1000(node) gid=1000(node) groups=1000(node),1000(node)`)
|
||||
|
||||
Visit http://localhost:3000
|
||||
* no longer installing `bash`, `configure-wiki`, nor `set-owner-name`
|
||||
|
||||
* no longer creating `/home/app/.wiki/wiki.json`
|
||||
|
||||
Those changes in particular will impose some work on authors upgrading
|
||||
from previous versions.
|
||||
|
||||
The last non-breaking revision is 0.52.0 https://github.com/dobbs/farm/tree/0.52.0#readme
|
||||
|
||||
# Development
|
||||
|
||||
This image's tag does not match the version of the included wiki software.
|
||||
This image's tag does not match the version of the included wiki
|
||||
software. Our version indicates the scale of changes in this tiny
|
||||
devops pipeline. For example, when we changed the `USER` directive and
|
||||
removed the wiki config generation scripts, we bumped the major
|
||||
version from 0.50.x to 1.0.x.
|
||||
|
||||
Notes to self:
|
||||
|
||||
``` bash
|
||||
docker build --tag dobbs/farm:0.51.0 .
|
||||
git tag -am "" '0.51.0'
|
||||
git push --tags
|
||||
docker build --tag dobbs/farm:1.0.2 .
|
||||
git tag -am "" '1.0.2'
|
||||
git push origin '1.0.2'
|
||||
```
|
||||
|
||||
The repos in Dockerhub and GitHub are configured to automatically build new tags.
|
||||
|
||||
# Publish experimental plugins
|
||||
|
||||
Invoke Dockerhub and GitHub integration.
|
||||
``` bash
|
||||
docker build \
|
||||
--tag dobbs/farm:0.14.0-frame \
|
||||
--build-arg WIKI_PACKAGE='dobbs/wiki#frame' \
|
||||
.
|
||||
docker push dobbs/farm:0.14.0-frame
|
||||
git tag -am "" '1.0.2-pre-0217'
|
||||
git push --atomic origin master '1.0.2-pre-0217'
|
||||
```
|
||||
|
@ -1,72 +0,0 @@
|
||||
#!/bin/bash -eu
|
||||
set -o pipefail
|
||||
|
||||
main() {
|
||||
initialize-environment-vars
|
||||
assert-file-privileges || report-errors-and-exit
|
||||
ensure-owner-file
|
||||
ensure-config-file
|
||||
show-configs
|
||||
}
|
||||
|
||||
initialize-environment-vars() {
|
||||
ERRORS=''
|
||||
readonly OWNER_FILE=/home/app/.wiki/$DOMAIN.owner.json
|
||||
readonly CONFIG_FILE=/home/app/.wiki/config.json
|
||||
}
|
||||
|
||||
assert-file-privileges() {
|
||||
[ -w /home/app/.wiki ] \
|
||||
|| ERRORS="app cannot write to /home/app/.wiki\n${ERRORS}"
|
||||
|
||||
[ ${#ERRORS} == 0 ]
|
||||
}
|
||||
|
||||
report-errors-and-exit() {
|
||||
echo -e $ERRORS
|
||||
echo "exiting."
|
||||
exit 1
|
||||
}
|
||||
|
||||
ensure-owner-file() {
|
||||
if [ ! -r "$OWNER_FILE" ]; then
|
||||
jq -n --arg name "$OWNER_NAME" --arg secret $(random-string) \
|
||||
'.name = $name | .friend.secret = $secret' > $OWNER_FILE
|
||||
fi
|
||||
}
|
||||
|
||||
ensure-config-file() {
|
||||
if [ ! -r "$CONFIG_FILE" ]; then
|
||||
> $CONFIG_FILE \
|
||||
jq -n -M \
|
||||
--arg admin $(jq -r .friend.secret $OWNER_FILE) \
|
||||
--arg random $(random-string) \
|
||||
--arg cookie $COOKIE \
|
||||
--arg domain $DOMAIN \
|
||||
--arg owner $OWNER_FILE \
|
||||
'
|
||||
.admin = $admin
|
||||
| .autoseed = true
|
||||
| .farm = true
|
||||
| .cookieSecret = $random
|
||||
| .secure_cookie = ("secure" == $cookie)
|
||||
| .security_type = "friends"
|
||||
| .wikiDomains[$domain].id = "/home/app/.wiki/\($domain).owner.json"
|
||||
'
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
random-string() {
|
||||
node -e 'console.log(require("crypto").randomBytes(64).toString("hex"))'
|
||||
}
|
||||
|
||||
show-configs() {
|
||||
set -x
|
||||
ls -l $OWNER_FILE $CONFIG_FILE
|
||||
cat $OWNER_FILE
|
||||
cat $CONFIG_FILE
|
||||
set +x
|
||||
}
|
||||
|
||||
main
|
53
examples/k8s/README.md
Normal file
53
examples/k8s/README.md
Normal file
@ -0,0 +1,53 @@
|
||||
# Wiki Farm in Kubernetes
|
||||
|
||||
There are easier ways to get started with federated wiki. Here we are
|
||||
using wiki to drive some learning about kubernetes.
|
||||
|
||||
# We're using MacOS, Docker Desktop, and k3d
|
||||
|
||||
brew cask install docker
|
||||
brew install k3d
|
||||
|
||||
mkdir -p ~/.wiki-k8s ~/workspace/fedwiki
|
||||
k3d create \
|
||||
--server-arg --tls-san="127.0.0.1" \
|
||||
--publish 80:80 \
|
||||
-v "$HOME/.wiki-k8s:/macos/.wiki-k8s" \
|
||||
-v "$HOME/workspace/fedwiki:/macos/fedwiki" \
|
||||
--name wiki
|
||||
|
||||
# example ~/.wiki-k8s/config.json
|
||||
|
||||
{
|
||||
"admin": "any memorable password",
|
||||
"autoseed": true,
|
||||
"farm": true,
|
||||
"cookieSecret": "any random string",
|
||||
"secure_cookie": false,
|
||||
"security_type": "friends",
|
||||
"wikiDomains": {
|
||||
"simple.localtest.me": {
|
||||
"id": "/home/node/.wiki/config.owner.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# example ~/.wiki-k8s/config.owner.json
|
||||
|
||||
`.friend.secret` must match the `.admin` field from `config.json`
|
||||
|
||||
{
|
||||
"name": "The Owner",
|
||||
"friend": {
|
||||
"secret": "any memorable password"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Deploy Wiki
|
||||
|
||||
kubectl apply -f wiki.yaml
|
||||
|
||||
# Play with the wiki
|
||||
|
||||
open http://simple.localtest.me
|
29
examples/k8s/vault/README.md
Normal file
29
examples/k8s/vault/README.md
Normal file
@ -0,0 +1,29 @@
|
||||
# HashiCorp Vault in kubernetes
|
||||
|
||||
HashiCorp recomend installing vault via helm. Your author prefers
|
||||
plain old kubernetes configs.
|
||||
|
||||
So we generated the yaml via helm's template command.
|
||||
|
||||
helm template incubator/vault \
|
||||
--name-template=vault \
|
||||
--replicaCount=1 \
|
||||
--set vault.dev=false \
|
||||
--set vault.config.storage.file.path=/macos/.wiki-k8s/vault \
|
||||
| egrep -v 'heritage: "?Helm"?' \
|
||||
> vault.html
|
||||
|
||||
kubectl apply -k .
|
||||
kubectl port-forward svc/vault 8200:8200 &> /dev/null &
|
||||
|
||||
export VAULT_ADDR=http://127.0.0.1:8200
|
||||
vault status
|
||||
vault operator init
|
||||
vault operator unseal
|
||||
# paste key-fragment 1
|
||||
vault operator unseal
|
||||
# paste key-fragment 2
|
||||
vault operator unseal
|
||||
# paste key-fragment 3
|
||||
vault login
|
||||
# paste root token
|
16
examples/k8s/vault/deployment-volumes.yaml
Normal file
16
examples/k8s/vault/deployment-volumes.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: vault
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: vault
|
||||
volumeMounts:
|
||||
- name: vault-data
|
||||
mountPath: /macos/.wiki-k8s/vault
|
||||
volumes:
|
||||
- name: vault-data
|
||||
hostPath:
|
||||
path: /macos/.wiki-k8s/vault
|
10
examples/k8s/vault/kustomization.yaml
Normal file
10
examples/k8s/vault/kustomization.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
images:
|
||||
- name: vault
|
||||
newName: vault
|
||||
newTag: 1.3.1
|
||||
resources:
|
||||
- vault.yaml
|
||||
patchesStrategicMerge:
|
||||
- deployment-volumes.yaml
|
181
examples/k8s/vault/vault.yaml
Normal file
181
examples/k8s/vault/vault.yaml
Normal file
@ -0,0 +1,181 @@
|
||||
---
|
||||
# Source: vault/templates/clusterrolebinding.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: vault
|
||||
labels:
|
||||
app: vault
|
||||
release: "vault"
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:auth-delegator
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: vault
|
||||
namespace: default
|
||||
---
|
||||
# Source: vault/templates/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: "vault-config"
|
||||
labels:
|
||||
app: "vault"
|
||||
release: "vault"
|
||||
data:
|
||||
config.json: |
|
||||
{"listener":{"tcp":{"address":"[::]:8200","cluster_address":"[::]:8201","tls_disable":true}},"storage":{"file":{"path":"/macos/.wiki-k8s/vault"}}}
|
||||
---
|
||||
# Source: vault/templates/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: vault
|
||||
labels:
|
||||
app: vault
|
||||
release: vault
|
||||
annotations:
|
||||
{}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: vault
|
||||
release: vault
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: vault
|
||||
release: vault
|
||||
annotations:
|
||||
checksum/config: 6868eb00aa48ca9485c365c3523ae431e7031233a1c046817a32c61e24ea817d
|
||||
spec:
|
||||
containers:
|
||||
- name: vault
|
||||
image: "vault:1.2.3"
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["vault", "server", "-config", "/vault/config/config.json"]
|
||||
ports:
|
||||
- containerPort: 8200
|
||||
name: api
|
||||
- containerPort: 8201
|
||||
name: cluster-address
|
||||
livenessProbe:
|
||||
# Alive if Vault is successfully responding to requests
|
||||
httpGet:
|
||||
path: /v1/sys/health?standbyok=true&uninitcode=204&sealedcode=204&
|
||||
port: 8200
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
# Ready depends on preference
|
||||
httpGet:
|
||||
path: /v1/sys/health?standbycode=204&uninitcode=204&
|
||||
port: 8200
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
add:
|
||||
- IPC_LOCK
|
||||
env:
|
||||
- name: POD_IP
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.podIP
|
||||
- name: VAULT_API_ADDR
|
||||
value: "http://$(POD_IP):8200"
|
||||
- name: VAULT_CLUSTER_ADDR
|
||||
value: "https://$(POD_IP):8201"
|
||||
- name: VAULT_LOG_LEVEL
|
||||
value: "info"
|
||||
resources:
|
||||
{}
|
||||
volumeMounts:
|
||||
- name: vault-config
|
||||
mountPath: /vault/config/
|
||||
- name: vault-root
|
||||
mountPath: /root/
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: 'vault'
|
||||
release: 'vault'
|
||||
topologyKey: kubernetes.io/hostname
|
||||
weight: 100
|
||||
serviceAccountName: vault
|
||||
volumes:
|
||||
- name: vault-config
|
||||
configMap:
|
||||
name: "vault-config"
|
||||
- name: vault-root
|
||||
emptyDir: {}
|
||||
---
|
||||
# Source: vault/templates/pdb.yaml
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: vault
|
||||
spec:
|
||||
maxUnavailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: vault
|
||||
release: vault
|
||||
---
|
||||
# Source: vault/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: vault
|
||||
labels:
|
||||
app: vault
|
||||
release: vault
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 8200
|
||||
protocol: TCP
|
||||
targetPort: 8200
|
||||
name: api
|
||||
selector:
|
||||
app: vault
|
||||
release: vault
|
||||
---
|
||||
# Source: vault/templates/serviceaccount.yaml
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: vault
|
||||
labels:
|
||||
app: vault
|
||||
release: "vault"
|
||||
---
|
||||
# Source: vault/templates/tests/test-vault-status.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "vault-vault-status-test"
|
||||
annotations:
|
||||
"helm.sh/hook": test-success
|
||||
spec:
|
||||
containers:
|
||||
- name: vault-vault-status-test
|
||||
image: "vault:1.2.3"
|
||||
env:
|
||||
- name: VAULT_ADDR
|
||||
value: http://vault.default:8200
|
||||
command: ["sh", "-c", "vault status"]
|
||||
restartPolicy: Never
|
71
examples/k8s/wiki.yaml
Normal file
71
examples/k8s/wiki.yaml
Normal file
@ -0,0 +1,71 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: wiki-deployment
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: wiki
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: wiki
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: farm
|
||||
image: dobbs/farm:1.0.1
|
||||
command: ["wiki"]
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
volumeMounts:
|
||||
- name: dot-wiki
|
||||
mountPath: /home/node/.wiki
|
||||
- name: fedwiki
|
||||
mountPath: /home/node/fedwiki
|
||||
volumes:
|
||||
- name: dot-wiki
|
||||
hostPath:
|
||||
path: /macos/.wiki-k8s
|
||||
- name: fedwiki
|
||||
hostPath:
|
||||
path: /macos/fedwiki
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: wiki-service
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
targetPort: 3000
|
||||
port: 80
|
||||
selector:
|
||||
app: wiki
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: simple-wiki
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: traefik
|
||||
spec:
|
||||
rules:
|
||||
- host: simple.localtest.me
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: wiki-service
|
||||
servicePort: http
|
||||
- host: "*.simple.localtest.me"
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: wiki-service
|
||||
servicePort: http
|
@ -1,39 +0,0 @@
|
||||
#!/bin/bash -eu
|
||||
set -o pipefail
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename $0) NAME
|
||||
|
||||
replaces the owner's name in $OWNER_FILE
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
initialize-environment-vars $@ || { usage; exit 1; }
|
||||
backup-and-save-name
|
||||
report-success
|
||||
}
|
||||
|
||||
initialize-environment-vars() {
|
||||
readonly OWNER_FILE=/home/app/.wiki/$DOMAIN.owner.json
|
||||
readonly OWNER_BACKUP_FILE=$OWNER_FILE-saved-$(date --iso-8601=minutes)
|
||||
readonly NAME=${@:-missing}
|
||||
[ ! "$NAME" == "missing" ]
|
||||
}
|
||||
|
||||
backup-and-save-name() {
|
||||
mv $OWNER_FILE $OWNER_BACKUP_FILE
|
||||
jq ".name = \"$NAME\"" $OWNER_BACKUP_FILE > $OWNER_FILE
|
||||
}
|
||||
|
||||
report-success() {
|
||||
cat <<EOF
|
||||
Owner's name changed to "$NAME"
|
||||
Previous config is saved in ${OWNER_BACKUP_FILE##$PWD/}
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
main "$@"
|
Reference in New Issue
Block a user