Archiwum kategorii: Aplikacje

logo kubernetes

Kubernetes na Raspberry Pi 4b

Notatki krok po kroku – jak na jednym i więcej Raspbery Pi 4b zainstalować HypriotOS, skonfigurować Dockera i ostatecznie uruchomić klaster Kubernetes.

Do flashowania kart będę używał komputera działającego pod Fedorą, ale kroki są na tyle uniwersalne, że można je spokojnie wykonać na większości innych dystrybucji.

1. HypriotOS

Czemu akurat HypriotOS, a nie Raspbian/Ubuntu/Windows IoT/etc? Z lenistwa 😉
HypriotOS to Debian okrojony gdzie trzeba, a rozbudowany w kierunku bycia hostem dla kontenerów. Dodatkowo jest optymalizowany pod RPi.
Czyli jest dokładnie tym, czego potrzebuję.

1a. Program do flashowania

HypriotOS stworzyło skrypt, który ułatwia flashowanie systemu na kartę sd. Wygodne to to i działa.

https://github.com/hypriot/flash/releases.

Skrypt wykorzystuje hdparm, pv, unzip i curla, także dla świętego spokoju można zacząć od próby doinstalowania braków. Na Fedorze wygląda to tak:

sudo dnf install pv curl unzip hdparm

Teraz ściągamy skrypt. Link do wersji 2.7.0 – przetestowanej i działającej.
Dajemy prawa zapisu i opcjonalnie wrzucamy sobie do /usr/local/bin.

curl -LO https://github.com/hypriot/flash/releases/download/2.7.0/flash
chmod +x flash
sudo mv flash /usr/local/bin/flash

1b. Wstępna konfiguracja

Skrypt ‚flash’ daje możliwość sparametryzowania HypriotOS według własnych potrzeb. Część parametrów można podać używając parametrów, część wymaga stworzenia pliku konfiguracyjnego, który można stworzyć na podstawie dostępnych sampli.

Mój plik konfiguracyjny (myhypriot.yml) wygląda następująco:

Uwaga! Jeżeli skorzystasz z konfiguracji powyżej Malinka dostanie adres z DHCP. Jeżeli adres powinien być statyczny, sprawdź składnię w przykładowych konfigach i wprowadź poprawki w myhypriot.yml.

1c. Flashowanie

Posiadam trzy Raspbery Pi 4. Każde chcę mieć z innym hostname, ale z tym samym plikiem konfiguracyjnym.

W chwili pisania tej notatki, HypriotOS dostępny jest w wersji 1.12.0. Nowsze wersje można znaleźć na stronie https://github.com/hypriot/image-builder-rpi/releases.

Trzykrotnie wkładam więc kartę microsd do laptopa i uruchamiam jako root (za każdym razem z innym hostname):

flash --hostname berta https://github.com/hypriot/image-builder-rpi/releases/download/v1.12.0/hypriotos-rpi-v1.12.0.img.zip
Log z przykładowego wykonania (rozwiń)
# flash --hostname test --userdata myhypriot.yml https://github.com/hypriot/image-builder-rpi/releases/download/v1.12.0/hypriotos-rpi-v1.12.0.img.zip           
Using cached image /tmp/hypriotos-rpi-v1.12.0.img

Is /dev/mmcblk0 correct? y
Unmounting /dev/mmcblk0 ...
Flashing /tmp/hypriotos-rpi-v1.12.0.img to /dev/mmcblk0 ...
1,27GiB 0:00:00 [2,79GiB/s] [============================================================================================================================================================================================>] 100%            
0+20800 records in
0+20800 records out
1363148800 bytes (1,4 GB, 1,3 GiB) copied, 640,081 s, 2,1 MB/s
Waiting for device /dev/mmcblk0

/dev/mmcblk0:
 re-reading partition table
Mounting Disk
Mounting /dev/mmcblk0 to customize...
total 52604
drwxr-xr-x. 3 root root    16384 sty  1  1970 .
drwxr-xr-x. 3 root root       60 maj  2 22:19 ..
-rwxr-xr-x. 1 root root    23966 wrz 20  2019 bcm2708-rpi-b.dtb
-rwxr-xr-x. 1 root root    24229 wrz 20  2019 bcm2708-rpi-b-plus.dtb
-rwxr-xr-x. 1 root root    23747 wrz 20  2019 bcm2708-rpi-cm.dtb
-rwxr-xr-x. 1 root root    23671 lip  8  2019 bcm2708-rpi-zero.dtb
-rwxr-xr-x. 1 root root    24407 lip  8  2019 bcm2708-rpi-zero-w.dtb
-rwxr-xr-x. 1 root root    25293 lip  8  2019 bcm2709-rpi-2-b.dtb
-rwxr-xr-x. 1 root root    25422 wrz 25  2019 bcm2710-rpi-2-b.dtb
-rwxr-xr-x. 1 root root    26463 lip  8  2019 bcm2710-rpi-3-b.dtb
-rwxr-xr-x. 1 root root    27082 lip  8  2019 bcm2710-rpi-3-b-plus.dtb
-rwxr-xr-x. 1 root root    25277 wrz 20  2019 bcm2710-rpi-cm3.dtb
-rwxr-xr-x. 1 root root    40559 wrz 17  2019 bcm2711-rpi-4-b.dtb
-rwxr-xr-x. 1 root root    52296 wrz 25  2019 bootcode.bin
-rwxr-xr-x. 1 root root      246 sty  7 19:31 cmdline.txt
-rwxr-xr-x. 1 root root      203 sty  7 19:31 config.txt
-rwxr-xr-x. 1 root root    18693 cze 24  2019 COPYING.linux
-rwxr-xr-x. 1 root root       20 sty  7 19:30 fake-hwclock.data
-rwxr-xr-x. 1 root root     3073 wrz 25  2019 fixup4cd.dat
-rwxr-xr-x. 1 root root     6167 wrz 25  2019 fixup4.dat
-rwxr-xr-x. 1 root root     9247 wrz 25  2019 fixup4db.dat
-rwxr-xr-x. 1 root root     9249 wrz 25  2019 fixup4x.dat
-rwxr-xr-x. 1 root root     2657 wrz 25  2019 fixup_cd.dat
-rwxr-xr-x. 1 root root     6736 wrz 25  2019 fixup.dat
-rwxr-xr-x. 1 root root     9808 wrz 25  2019 fixup_db.dat
-rwxr-xr-x. 1 root root     9810 wrz 25  2019 fixup_x.dat
-rwxr-xr-x. 1 root root  5310624 wrz 25  2019 kernel7.img
-rwxr-xr-x. 1 root root  5628040 wrz 25  2019 kernel7l.img
-rwxr-xr-x. 1 root root 13230592 wrz 25  2019 kernel8.img
-rwxr-xr-x. 1 root root  5029176 wrz 25  2019 kernel.img
-rwxr-xr-x. 1 root root     1494 cze 24  2019 LICENCE.broadcom
-rwxr-xr-x. 1 root root       23 sty  7 19:25 meta-data
-rwxr-xr-x. 1 root root      365 sty  7 19:35 os-release
drwxr-xr-x. 2 root root    16384 sty  7 19:30 overlays
-rwxr-xr-x. 1 root root   770816 wrz 25  2019 start4cd.elf
-rwxr-xr-x. 1 root root  4733128 wrz 25  2019 start4db.elf
-rwxr-xr-x. 1 root root  2769540 wrz 25  2019 start4.elf
-rwxr-xr-x. 1 root root  3683816 wrz 25  2019 start4x.elf
-rwxr-xr-x. 1 root root   685668 wrz 25  2019 start_cd.elf
-rwxr-xr-x. 1 root root  4854728 wrz 25  2019 start_db.elf
-rwxr-xr-x. 1 root root  2877988 wrz 25  2019 start.elf
-rwxr-xr-x. 1 root root  3792232 wrz 25  2019 start_x.elf
-rwxr-xr-x. 1 root root     1713 sty  7 19:25 user-data
Copying cloud-init myhypriot.yml to /tmp/0/mnt.477635/user-data ...
Set hostname=test
Unmounting /dev/mmcblk0 ...
Finished.

Przekładamy kartę do RPi, podpinamy do sieci i odpalamy. Po kilku minutach potrzebnych na pierwotną autokonfigurację, HypriotOS powinien być dostępny po ssh.

2. OS & Docker

Kroki do wykonania na wszystkich maszynach!

Zaktualizuj i zrestartuj system

$ sudo -i
# apt update && apt upgrade && reboot

Popraw konfigurację Dockera tak, aby:

  • do zarządzania cgroup’ami używał systemd
  • logi tworzył w formacie json
  • zajmował do 100MiB na logi
  • używał sterownika storage w wersji overlay2
$ sudo -i
# cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": { "max-size": "100m" },
  "storage-driver": "overlay2"
}
EOF

(opcjonalnie) Tworzymy katalog na parametry serwisu Docker i restartujemy go

# mkdir -p /etc/systemd/system/docker.service.d
# systemctl daemon-reload
# systemctl restart docker

Ustawiamy parametry kernela pozwalające iptables poprawnie widzieć ruch w bridge’ach.

# cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# sysctl --system

Tworzymy katalog /etc/cnt/net.d. Wymagany jest przez kubelet.service, a niestety instalator go nie przygotowuje. Brak katalogu skutkuje błędami NetworkPluginNotReady.

# mkdir -p /etc/cnt/net.d

3. Instalacja kubernetesa

Kroki do wykonania na wszystkich maszynach!

Dodaj oficjalne repozytorium Kubernetes

# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
# echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list
# apt update

Zainstaluj!

# apt install -y kubeadm

4. To ja tu rządzę!

Wybierz jedną z maszyn do zarządzania klastrem. Wydaj na niej komendę:

# kubeadm init --pod-network-cidr 10.244.0.0/16
Log z wykonania (rozwiń)
# kubeadm init --pod-network-cidr 10.244.0.0/16
W0503 10:39:57.299688 32439 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[init] Using Kubernetes version: v1.18.2
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [elsa kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.88.16]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [elsa localhost] and IPs [192.168.88.16 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [elsa localhost] and IPs [192.168.88.16 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
W0503 10:42:11.343155 32439 manifests.go:225] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[control-plane] Creating static Pod manifest for "kube-scheduler"
W0503 10:42:11.346581 32439 manifests.go:225] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 38.015489 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.18" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node elsa as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node elsa as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: zuqc0t.xyq5i6lzbf9jarlb
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[kubelet-check] Initial timeout of 40s passed.
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.88.16:6443 --token asdfgh.12qaz2wsx3edc4rf \
--discovery-token-ca-cert-hash sha256:1qaz2wsx3edc4rfv5tgb6yhn7ujm8ikk9oll0ppp1qaz2wsx3edc4rfv5t

Na koniec komendy inicjalizacyjnej dostajemy zestaw zaleceń do zrealizowania:

  1. Wykonaj na userze na którym będziesz standardowo pracować poniższe komendy. Zarządzanie kubernetesem z roota jest mało sexi.
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

2. Skopiuj sobie gdzieś na bok komendę zawierającą token i klucz. Nie wykonuj jej jeszcze na workerach! Chodzi o coś wyglądającego w ten sposób:

kubeadm join 192.168.88.16:6443 --token asdfgh.12qaz2wsx3edc4rf \
--discovery-token-ca-cert-hash sha256:1qaz2wsx3edc4rfv5tgb6yhn7ujm8ikk9oll0ppp1qaz2wsx3edc4rfv5t

Na naszej głównej maszynie przenosimy się na usera ‚zarządzającego’. Czyli tego dla którego przygotowaliśmy punkt 1 powyżej.

3. Flannel

Czyli wirtualna sieć, która udostępnia odpowiednie podsieci każdemu z hostów klastra.

Instalacja:

$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/k8s-manifests/kube-flannel-rbac.yml
Log z wykonania (rozwiń)

$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel configured
clusterrolebinding.rbac.authorization.k8s.io/flannel unchanged
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds-amd64 created
daemonset.apps/kube-flannel-ds-arm64 created
daemonset.apps/kube-flannel-ds-arm created
daemonset.apps/kube-flannel-ds-ppc64le created
daemonset.apps/kube-flannel-ds-s390x created

4. Dołącz hosty do klastra

(opcjonalnie) Zezwól na swojej głównej maszynie na uruchamianie na niej PODów.
Standardowo, z powodów bezpieczeństwa, host na którym odpalamy kubeadm init, jest wyłączony z klastra. Służy tylko do jego zarządzania. W warunkach domowego laba, to często marnotrawstwo zasobów.
Uwaga! Jeżeli robisz ten tutorial na pojedynczej maszynie, to poniższa komenda nie jest opcjonalna.

kubectl taint nodes --all node-role.kubernetes.io/master-

Nie zanotowałeś sobie tokena?
Minęło ponad 24h od uruchomienia komendy kubeadm init? To nic strasznego. Skorzystaj z instrukcji we wpisie o zarządzaniu tokenami w kubernetesie.

Uruchom na wszystkich workerach komendę wymusząjącą dołączenie do klastra:

# kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>
Log z przykładowego uruchomienia (rozwiń)
kubeadm join 192.168.88.16:6443 --token 3fs9sd.z4di8tmrxdskitl4 --discovery-token-ca-cert-hash sha256:c4d361fb1bd7a4511ab398b3e99d950dfac3b1235ae981628c79ac0c5110c156
W0516 14:24:09.006377 21168 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster…
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.18" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap…
This node has joined the cluster:
Certificate signing request was sent to apiserver and a response was received.
The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

5. Weryfikacja

Zweryfikuj na głównej maszynie listę hostów w klastrze:

$ kubectl get nodes

Przykładowo, może wyglądać to tak:

$ kubectl get nodes
NAME     STATUS     ROLES    AGE     VERSION
berta    NotReady   <none>   4s      v1.18.2
elsa     Ready      master   13d     v1.18.2
ingrid   Ready      <none>   3m13s   v1.18.2

$ kubectl get nodes
NAME     STATUS   ROLES    AGE   VERSION
berta    Ready    <none>   12m   v1.18.2
elsa     Ready    master   13d   v1.18.2
ingrid   Ready    <none>   15m   v1.18.2

Spróbujmy uruchomić na naszym klastrze mały serwis testowy

kubectl run hypriot --image=hypriot/rpi-busybox-httpd --port=80

Działa?

$ kubectl get pods
HypriotOS/armv7: szydell@elsa in ~
$ kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
hypriot   1/1     Running   0          96s

Udostępnijmy teraz port 80 i sprawdźmy pod jakim ip, oraz na którym node kubernetes serwuje nasz serwis.

$ kubectl expose po hypriot --port 80
$ kubectl get endpoints hypriot
$ kubectl describe pods/hypriot | grep Node:

Przykładowo:

$ kubectl expose po hypriot --port 80
service/hypriot exposed
$ kubectl get endpoints hypriot
NAME ENDPOINTS AGE
hypriot 10.244.1.2:80 17s
$ kubectl describe pods/hypriot | grep Node:
Node: ingrid/192.168.88.15

Wchodzimy na hosta zwróconego przez ostatnią komendę. I jeżeli wszystko jest ok, powinniśmy móc lokalnie pobrać zawartość działającej strony:

$ curl 10.244.1.2:80
<html>
<head><title>Pi armed with Docker by Hypriot</title>
  <body style="width: 100%; background-color: black;">
    <div id="main" style="margin: 100px auto 0 auto; width: 800px;">
      <img src="pi_armed_with_docker.jpg" alt="pi armed with docker" style="width: 800px">
    </div>
  </body>
</html>

Jak widać wersja minimum działa. Wywalmy jeszcze dla sportu poda hypriot i sprawdzamy czy zniknął.

$ kubectl delete pod hypriot --now
$ kubectl get pods

Kubernetes w wersji minimum jest zainstalowany i działa. Teraz dopiero zaczną się schody. 😉

logo kubernetes

Kubernetes, dołączanie nowego hosta i zarzadzanie tokenami

Standardowo token potrzebny do dołączenia do klastra ważny jest 24 godziny. Poza tym, notatki giną. 😉

Komenda pozwalająca na dołączenia hosta do klastra

# kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>

Wylistowanie aktywnych tokenów

kubeadm token list

Pusto? Znaczy się, nie masz żadnego aktywnego tokena.

Wygeneruj nowy token

kubeadm token create

Odzyskaj ‚discovery token ca cert’

Poza tokenem, do komendy kubeadm join potrzeba też hasha certyfikatu. Żeby go ‚odzyskać’, wykonaj:

openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

Centos 7 + apache httpd >=2.4 + mod_wsgi + Python 3 + falcon

Odpalałem ostatnio prostą aplikacyjkę napisaną w pythonie 3 z wykorzystaniem frameworka falcon. Troszkę było kombinowania.
Nie poruszam tutaj kompletnie kwestii uprawnień, selinuxa itd. Zakładam też działające apache httpd i skonfigurowanego vhosta.

  1. Dodaj repozytorium IUS do Centosa 7

    yum install https://centos7.iuscommunity.org/ius-release.rpm
  2. Zainstaluj Python 3.6, mod_wsgi i pip.

    yum install python36u-mod_wsgi python36u-pip
  3. Stwórz środowisko wirtualne ‚app1’ potrzebne do uruchomienia aplikacji. Ścieżka przykładowa.

    sudo mkdir -p /srv/pythonenvs
    cd /srv/pythonenvs
    python3.6 -m venv app1
  4. Aktywuj venv dla swojej sesji

    source app1/bin/activate
  5. Zainstaluj falcona i wszystkie inne zależności

    (app1)$ pip install falcon
  6. Zakładam, że aplikację masz w katalogu /srv/app1/www, a ‚entry point’ to main.py. Bardzo ważne! Aplikacja musi się przedstawiać serwerowi wsgi jako ‚application’. To znaczy, że w kodzie falcon musi być odpalony w następujący sposób:

    api = application = falcon.API()
  7. Dodaj do konfiguracji vhosta:

    WSGIDaemonProcess app1 python-path=/srv/app1/www/ python-home=/srv/pythonenvs/app1
    WSGIProcessGroup app1
    WSGIScriptAlias / /srv/app1/www/main.py
    <Directory /srv/app1/www/>
    Require all granted
    </Directory>
  8. Teraz tylko restart httpd:

    systemctl restart httpd

Ochłap zaginął, Fallout 4

Może trochę nie na temat, ale… takie drobne ułatwienie dla graczy.

  1. Odpal konsolę (~)
  2. Wpisz ‚prid 0001d162’, enter
  3. Wpisz ‚moveto player’, enter
  4. Wyjdź z konsoli (~)

Ochłap powinien stać tuż obok 😉

Lista pozostałych towarzyszy, których można odzyskać w ten sam sposób:

  1. Cait: Human, Trigger Rush, Combat Zone, ID: 00079305
  2. Codsworth: Mister Handy (Robot), Robot Sympathy, Sanctuary Hills, ID: 0001ca7d
  3. Curie: Miss Nanny/Synth, Combat Medic, Vault81, ID: 00102249
  4. Paladin Danse: Human, Know Your Enemy, Cambridge Police Station, ID: 0005de4d
  5. Deacon: Human, Cloak & Dagger, Old North Church, ID: 00045ac9
  6. Dogmeat: Dog, Attack Dog, Red Rocket Truck Stop, ID: 0001d162
  7. John Hancock: Ghoul, Isodoped, Goodneighbor, ID: 00022615
  8. Robert MacCready: Human, Killshot, Goodneighbor, ID: 0002a8a7
  9. Nick Valentine: Synth, Close to Metal, Valut 114, ID: 00002f25
  10. Piper: Human, Gift of Gab, Diamond City, ID: 0002f1f
  11. Preston Garvey: Human, United We Stand, Concord, ID: 0001a4d7
  12. Strong: Super Mutant, Berserk, Trinity Tower, ID: 0003f2bb
  13. X6-88: Synth, Shield Harmonics, The Institute, ID: 0002e210a

 

Skradzione stąd: https://www.gameskinny.com/03cw4/fallout-4-companion-list-perks-locations-ids/

Zdalna edycja kodu

Zazwyczaj pracuję na Windowsie. A piszę programiki i skrypty stricte dla Linuxa.
VIMa kocham niezmiernie, ale są fajniejsze zabawki do takiej pracy. Na przykład Visual Studio Code, które mi wyjątkowo podpasowało.
VSCode ma fajną wtyczkę, dzięki której można po ssh edytować pliki na zdalnej maszynie ‚w locie’. Nie jest to może najwygodniejsza w konfiguracji metoda, ale z pomocą putty da się ogarnąć temat dość prosto 🙂
Wtyczka korzysta z rmate. Najrozsądniejsza wydaje mi się implementacja w bashu (ale jak ktoś lubi to jest też w RUBY, Pythonie, C i pewnie w kilku innych językach)

  1. Zainstaluj w VSCode dodatek Remote VSCode:
    ctrl+p wklej ext install remote-vscode
  2. Na zdalnej maszynie instalujemy ‚rmate’:
    sudo wget -O /usr/local/bin/rmate https://raw.github.com/aurora/rmate/master/rmate
    chmod a+x /usr/local/bin/rmate

    Wydaje mi się, że można bez żadnego uszczerbku na fajności, zaciągnąć sobie skrypt na lokalnego usera. System wide nie powinno być konieczne (aczkolwiek nie testowałem).
  3. Zestaw w putty tunel do maszyny na której chcesz edytować pliki. ‚Główna’ strona standardowo, natomiast Connection->SSH->Tunnels ustaw tak:
  4. CTRL-C „Remote: Start server”, następnie w VSCode -> Naciśnij F1, wklej i ENTER
  5. Na zdalnej maszynie wydaj komendę ‚rmate <plik_do_edycji>’. Pliczek powinien się automagicznie otworzyć w VSCode

W codziennej pracy odpalamy tylko punkty 3,4,5.

Plusy? Chyba widać. Da się ładnie edytować zdalnie zlokalizowane pliki ‚on-line’.

Minusy? Jeszcze nie rozgryzłem jak odpalać zdalnie zabawki typu golint. Na razie walidacja kodu robi mi się w pełni lokalnie (a to mi się nie do końca podoba).

Chapeau bas Certbot!

Skończył mi się certyfikat SSL dla tego bloga. StartSSL podpadł wszystkim dookoła, trzeba było zrobić z tym porządek.
Z pomocą przyszła inicjatywa Let’s Encrypt, Electronic Frontier Foundation i rewelacyjny skrypt certbot 🙂

Co zrobiłem, żeby mieć nowy certyfikat:

# cd /opt
# mkdir certbot
# chmod 700 certbot
# cd certbot/
# wget https://dl.eff.org/certbot-auto
# chmod 700 certbot-auto
# ./certbot-auto --nginx

Certbot wyświetlił mi wszystkie skonfigurowane na nginxie domeny i poprosił o wybranie tej odpowiedniej.
Podałem maila, zgodziłem się na otrzymanie wiadomości w momencie gdy certyfikat się będzie miał ku końcowi.
Certbot poprawił config dla podanej domeny, wygenerował podpisany przez Let’s Encrypt certyfikat, zrobił reload nginxa.
Koniec.

Wow?!

PS
Certbot dostępny jest też w repozytorium EPEL ale jest tam starsza wersja, która jeszcze nie kuma nginxa. Za to dla fanów Apache – polecam 🙂

PS2
Pisałem już, że certbot i generowane przez Let’s Encrypt certyfikaty są darmowe?

PS3
Co do jakości samego certyfikatu:
https://www.ssllabs.com/ssltest/analyze.html?d=marcin.szydelscy.pl