Compare commits

...

8 Commits

8 changed files with 514 additions and 2 deletions

View File

@@ -41,7 +41,7 @@ $(databases): .dbs/%.rec: %/ | .dbs/
# This two-variable read can only happen because of the quotes in the titles.
db.rec: $(databases)
$(warning rebuilding from $? )
$(info rebuilding from $? )
printf '%s\n' '%rec: guide' > $@
printf '%s\n' '%key: title' >> $@
printf '%s\n' '%type: requires rec guide' >> $@

View File

@@ -100,7 +100,13 @@ Try:
- `<Esc>kcw`
- ls -a<Esc>xxxx
Works with `python` too:
Readline can work with python one you set `PYTHON_BASIC_REPL` to `true`.
```sh
echo 'export PYTHON_BASIC_REPL=true' >> ~/.bashrc
exec bash
```
```python
im<C-n>os<Return>

54
data/newsraft.md Normal file
View File

@@ -0,0 +1,54 @@
---
title: "Newsraft"
tags: [ "data", "RSS" ]
requires: [ "Shell Scripts" ]
---
# Setup
Install newsraft, then:
```sh
mkdir ~/.config/newsraft
echo 'https://codeberg.org/newsraft/newsraft.atom "Newsraft git"' >> ~/.config/newsraft/feeds
newsraft
```
# Commands
Copy the default config file:
```
cp /usr/share/doc/newsraft/example/config ~/.config/newsraft/config
```
Add a line to check the man page while inside the program:
```
bind M exec man newsraft
```
This will fail, because the letter 'M' is taken by `mpv`.
Add this line to take the default link, and place it in a list of videos.
```
bind V mark-read; exec echo "%l" >> ~/.cache/vidlist.txt
```
# Videos
You can get an RSS feed from any YouTube video with this script:
```
#!/bin/sh
CHANNEL_ID="$(curl -s "$1" | tr ',' '\n' | grep -Po 'channelId":"\K[\w+-]+' | tail -1)"
FEED_URL="https://www.youtube.com/feeds/videos.xml?channel_id=$CHANNEL_ID"
CHANNEL_NAME="$(curl -s "$FEED_URL" | grep -m 1 -Po 'title\>\K[\w\s]+')"
printf '%s "%s"\n' "$FEED_URL" "$CHANNEL_NAME"
```

View File

@@ -0,0 +1,75 @@
---
title: "Store Host Password"
tags: [ "system", "ansible" ]
---
Make a hosts file with one host (your computer) and one variable, just to test:
```sh
hosts_file=hosts
fort="$(fortune -s | head -1)"
cowvar=cowsays
echo "[cows]
$HOSTNAME $cowvar='${fort}'" > "${hosts_file}"
```
Now ansible should be able to show that '${cowvar}' in a debug message:
```sh
ansible -i "$hosts_file" -m debug -a "msg='{{ ${cowvar} }}'" $HOSTNAME
```
Now to convert the hosts file to yaml, because it's very fashionable:
```sh
yaml_hosts=hosts.yaml
ansible-inventory -i ${hosts_file} --list -y | tee "${yaml_hosts}"
```
Now you should see where the `cowsays` variable goes.
You can safely place your `sudo` password next to that variable goes with `ansible-vault`, which will encrypt just that string.
```sh
pass="your password"
ansible-vault encrypt_string --name='ansible_sudo_pass' "${pass}"
```
If that works, you can add the password, but in `yaml` format.
You can do this manually, or use `gawk` to add ten spaces in front of the lines:
```sh
pass="your password"
ansible-vault encrypt_string --name='ansible_sudo_pass' "${pass}" | awk '{print " " $0}' >> "${yaml_hosts}"
```
Now to check that the inventory file works okay:
```sh
ansible-inventory -i ${yaml_hosts} --list -y
ansible -i "$hosts_file" -m debug -a "msg='{{ ${cowvar} }}'" $HOSTNAME
```
If that works, you can echo the debug message while becoming root.
Just add the `-J` flag so it will ask for the password:
```sh
ansible -i "${yaml_hosts}" -m debug -a "msg='{{ ${cowvar} }}'" $HOSTNAME --become -J
ansible -i "${yaml_hosts}" -m debug -a "msg={{ ansible_sudo_pass }}" $HOSTNAME --become -J
```
Now you can update using Ansible.
For Arch Linux:
```sh
ansible -i "${yaml_hosts}" -m community.general.pacman -a 'upgrade=true update_cache=true' $HOSTNAME --become -J
```
For Debian:
```sh
ansible -i "${yaml_hosts}" -m ansible.builtin.apt -a 'upgrade=full' $HOSTNAME --become -J
```

View File

@@ -0,0 +1,206 @@
---
title: "Kubernetes Basics"
tags: [ "virtualization", "kubernetes" ]
requires: [ "Kubernetes Setup" ]
---
Install `kubectl`.
> **NB:** Debian requires manual installation.[^kubedeb]
[^kubedeb]: https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/
# Read
1. Check the namespace: `kubectl get namespaces`
1. Check the `${kube-system}` namespace: `kubectl get deployments.apps --namespace kube-system'
1. Check host computers: `kubectl get nodes`
1. Check pods: `kubectl get pods`
```tree
Namespaces
├── Node_1: minikube
│ ├── deployment_1: nginx
│ │   ├── pod_1
│ │   └── pod_2
│ ├── deployment_2: database
│ │   ├── pod_1
│ │   ├── pod_2
│ │   ├── pod_3
│ │   └── pod_4
│   ├── deployment_3: prometheus
│   └── deployment_4: idk probably yaml
└── Node_1: physical server
├── deployment_1: nginx
│   ├── pod_1
│   └── pod_2
├── deployment_2: database
│   ├── pod_1
│   ├── pod_2
│   ├── pod_3
│   └── pod_4
├── deployment_3: prometheus
└── deployment_4: Abandoned wiki
```
## More Information
```bash
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-depl-68c944fcbc-2xbvq 1/1 Running 0 20m
$ kubectl describe pod nginx-depl-68c944fcbc-2xbvq
Name: nginx-depl-68c944fcbc-2xbvq
Namespace: default
Priority: 0
Service Account: default
Node: minikube/192.168.59.107
Start Time: Fri, 29 Aug 2025 19:26:29 +0200
Labels: app=nginx-depl
pod-template-hash=68c944fcbc
Annotations: <none>
Status: Running
IP: 10.244.0.3
IPs:
IP: 10.244.0.3
Controlled By: ReplicaSet/nginx-depl-68c944fcbc
Containers:
nginx:
Container ID: docker://aaa68e90ed9237dc0f98f9a21b0d7ddf3113188c62e72242d30cab4a43cbff98
Image: nginx
Image ID: docker-pullable://nginx@sha256:33e0bbc7ca9ecf108140af6288c7c9d1ecc77548cbfd3952fd8466a75edefe57
Port: <none>
Host Port: <none>
State: Running
Started: Fri, 29 Aug 2025 19:26:41 +0200
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9bgxx (ro)
Conditions:
Type Status
PodReadyToStartContainers True
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-9bgxx:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
Optional: false
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 24m default-scheduler Successfully assigned default/nginx-depl-68c944fcbc-2xbvq to minikube
Normal Pulling 24m kubelet Pulling image "nginx"
Normal Pulled 24m kubelet Successfully pulled image "nginx" in 11.204s (11.204s including waiting). Image size: 192385800 bytes.
Normal Created 24m kubelet Created container: nginx
Normal Started 24m kubelet Started container nginx
```
Pod copies are called a 'replicaset'.
# Create
Create a 'deployment' of `nginx`.
```sh
name="nginx-depl"
kubectl create deployment ${name} --image=nginx
kubectl get deployments
```
The command did not specify a namespace, so `default` is used.
# Update
Update a deployment, with `$EDITOR`.
```sh
kubectl edit deployments.apps ${name}
```
This gives us far too much information:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
[ ... ]
creationTimestamp: "2025-08-29T18:13:45Z"
generation: 3
labels:
app: nginx-depl
name: nginx-depl
namespace: default
resourceVersion: "17696"
uid: 8dec2925-5c34-4635-b82c-ba601cb3bef5
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx-depl
[ ... ]
observedGeneration: 3
readyReplicas: 2
replicas: 2
updatedReplicas: 2
```
Pull out the information, without an `$EDITOR`:
```sh
file="webstuff"
kubectl get deployment ${name} -o yaml > ${webstuff}.yaml
```
## Enter the Pod
```bash
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-depl-68c944fcbc-2xbvq 1/1 Running 0 31m
$ pod='nginx-depl-68c944fcbc-2xbvq'
$ kubectl exec -it ${pod} -- bash
root@nginx-depl-68c944fcbc-2xbvq:/# ls
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib media opt root sbin sys usr
root@nginx-depl-68c944fcbc-2xbvq:/#
exit
```
# Delete
Delete a deployment, and watch it leave:
```sh
name=nginx-depl
kubectl delete deployments.apps nginx-depl && kubectl get deployments.apps
kubectl get deployments.apps
```

View File

@@ -0,0 +1,64 @@
---
title: "Kubernetes Docs"
tags: [ "virtualization", "kubernetes", "WTFM", "hosts", "DNS" ]
requires: [ "Kubernetes Basics" ]
---
`kubectl` provides easy high-level overviews:
```sh
kubectl config view
kubectl cluster-info
```
Unfortunately, the documentation commands work less well.
# Kube-Explain
The `kubectl explain` resources cannot use tab-completion.
But you can find the same resources listed with `api-resources`, and use a fuzzy-finder, to get the same effect.
```sh
t="$(kubectl api-resources | fzy | gawk '{print $1}')"
kubectl explain ${t}
```
The documentation is in a classic style, which could only be improved by deletion.
Take this fragment from `kubectl explain namespaces`:
```
DESCRIPTION:
Namespace provides a scope for Names. Use of multiple namespaces is
optional.
```
- Sentence 1: A 'name-space' is a space for names.
- Sentence 2: If you create a namespace, you will not receive an error due to not having a second namespace. This is also the case for deployments, variables, and files which begin with the letter 'P', but the writer was being paid per word.
Continuing...
```
metadata <ObjectMeta>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
```
So a namespace has metadata, which has something in diamond-brackets called `ObjectMeta`.
We should understand this as 'normal metadata for an object', and the author promises us more information.
But only a fool would trust that link, as the author's a hack, without even the flimsy excuse of being left alone with ChatGPT (the docs existed before LLMs became uncool).
Completing this morality tale, entitled '*Why Nobody Reads the Docs*', we arrive at the end of Kubernetes' namespace documentation:
```
status <NamespaceStatus>
Status describes the current status of a Namespace. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
```
Of course this is wrong.
The sentence should read:
```
'Status' describes the current status of a Namespace.
```

View File

@@ -0,0 +1,53 @@
---
title: "Proxy API"
tags: [ "virtualization", "kubernetes" ]
requires: [ "Kubernetes Basics" ]
---
Start the proxy:
```sh
kubectl proxy &
```
Then curl the API server:
```sh
curl http://localhost:8001
```
Create a token:
```sh
export TOKEN=$(kubectl create token default)
kubectl create clusterrole api-access-root \
--verb=get --non-resource-url=/*
kubectl create clusterrolebinding api-access-root \
--clusterrole api-access-root --serviceaccount=default:default
```
Retrieve the API Server endpoint:
```sh
export APISERVER=$(kubectl config view | grep https | \
cut -f 2- -d ":" | tr -d " ")
```
Confirm that the `APISERVER` variable stored the same IP as the Kubernetes control plane IP by issuing the following two commands and comparing their outputs:
```sh
echo $APISERVER
https://192.168.99.100:8443
kubectl cluster-info
```
We can also get the certs straight from the list in `~/.kube/config`.

View File

@@ -0,0 +1,54 @@
---
title: "Kubernetes Setup"
tags: [ "virtualization", "kubernetes", "minikube", "docker" ]
---
# Install `minikube`
Set up a practice environment with `minikube`, using either Docker or VirtualBox.
1. Install the driver (VirtualBox is a good choice).
1. Install `minikube`.
* Debian requires manual installation.[^minideb]
1. Check it works.
The installation takes a long time.
```sh
# driver=docker
driver=virtualbox
minikube start --driver=${driver}
```
## Check `minikube`
Check it's all running:
```sh
minikube kubectl -- get po -A
```
```
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-674b8bbfcf-l7582 1/1 Running 0 2m
kube-system etcd-minikube 1/1 Running 0 2m
kube-system kube-apiserver-minikube 1/1 Running 0 2m
kube-system kube-controller-manager-minikube 1/1 Running 0 2m
kube-system kube-proxy-4q977 1/1 Running 0 2m
kube-system kube-scheduler-minikube 1/1 Running 0 2m
kube-system storage-provisioner 1/1 Running 1 (2m ago) 2m
```
# Uninstall `minikube`
```sh
du -sh ~/.minikube
```
Minikube is huge!
```sh
minikube stop
rm -rf ~/.minikube
```
[^minideb]: https://minikube.sigs.k8s.io/docs/start/