


[{"content":"","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/tags/automatic/","section":"Tags","summary":"","title":"Automatic","type":"tags"},{"content":"","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/posts/","section":"Blog","summary":"","title":"Blog","type":"posts"},{"content":"","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/tags/cloud/","section":"Tags","summary":"","title":"Cloud","type":"tags"},{"content":"","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/tags/fedora/","section":"Tags","summary":"","title":"Fedora","type":"tags"},{"content":"","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/tags/hetzner/","section":"Tags","summary":"","title":"Hetzner","type":"tags"},{"content":"","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/tags/kubernetes/","section":"Tags","summary":"","title":"Kubernetes","type":"tags"},{"content":"Die Aufgabe eines System-Maintainers ist es, alles aktuell zu halten. Besonders Security-Updates sollten so schnell wie möglich eingespielt werden.\nFür faule Maintainer wie mich gibt es dnf-automatic, das die Server aktuell hält. Bei einer grossen Zahl von Servern gibt es besser geeignete Lösungen, für meinen Fall reicht dnf-automatic aber.\nInstalliere dnf-automatic mit\ndnf install -y dnf-automatic nun konfigurieren wir dnf-automatic so, dass Security-Updates automatisch installiert werden.\n# set upgrade type to security to only install security updates, # if you\u0026#39;d set it to default it would install all updates. # non-security updates might need you to intervene more often, # so we keep installing them manually sed -i \u0026#39;s/upgrade_type = .*/upgrade_type = security/g\u0026#39; /etc/dnf/automatic.conf # set apply_updates to \u0026#39;yes\u0026#39; otherwise they wouldn\u0026#39;t get installed. sed -i \u0026#39;s/apply_updates = .*/apply_updates = yes/g\u0026#39; /etc/dnf/automatic.conf um Security-Updates in einem definierten Intervall automatisch herunterzuladen und zu installieren.\nJetzt müssen wir nur noch den systemd-Timer aktivieren.\nsystemctl enable --now dnf-automatic-install.timer ","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/posts/kubernetes-hetzner-dnf-automatic/","section":"Blog","summary":"","title":"Kubernetes auf Hetzner Cloud: Automatische Fedora-Updates","type":"posts"},{"content":"","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/tags/security/","section":"Tags","summary":"","title":"Security","type":"tags"},{"content":"","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/tags/server/","section":"Tags","summary":"","title":"Server","type":"tags"},{"content":"Notizen zu Servern, Kubernetes, Cloud-Infrastruktur und dem einen oder anderen macOS-Trick — direkt aus dem Bauen und Betreiben.\n","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/","section":"Startseite","summary":"","title":"Startseite","type":"page"},{"content":"","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"9. Feb. 2020","externalUrl":null,"permalink":"/de/tags/update/","section":"Tags","summary":"","title":"Update","type":"tags"},{"content":"Heute sind die meisten Websites mit TLS (https) gesichert. Mit Let\u0026rsquo;s Encrypt gibt es inzwischen einen sehr günstigen (kostenlosen) Weg zu SSL-Zertifikaten – gerade für uns Privatnutzer.\nWeil Let\u0026rsquo;s Encrypt eine API zum Abrufen und Erneuern von Zertifikaten bereitstellt, können wir unserem Cluster einen automatischen Zertifikatsdienst hinzufügen: CertManager. Mit dieser Komponente erstellen und erneuern wir ein Zertifikat automatisch – allein durch das Deployen einer Ingress-Ressource mit einer bestimmten Annotation cert-manager.io/cluster-issuer.\ncert-manager.io installieren # Zuerst legen wir die Custom Resource Definitions für den cert-manager an:\nkubectl apply --validate=false -f https://raw.githubusercontent.com/jetstack/cert-manager/v0.13.1/deploy/manifests/00-crds.yaml Jetzt erstellen wir einen Namespace, in dem der cert-manager leben kann:\nkubectl create namespace cert-manager Nun deployen wir den cert-manager per Helm in diesen Namespace:\nhelm repo add jetstack https://charts.jetstack.io helm repo update helm install \\ cert-manager \\ --namespace cert-manager \\ --version v0.13.1 \\ --set webhook.enabled=false \\ jetstack/cert-manager Dir ist oben vielleicht webhook.enabled=false aufgefallen. Let\u0026rsquo;s Encrypt braucht eine Art Nachweis, dass dir eine Domain gehört. Zur Verifikation gibt es verschiedene Challenges, die du durchlaufen musst, um das Zertifikat zu erhalten. Das kann die http-01-Challenge sein, die per http auf die Let\u0026rsquo;s-Encrypt-Challenge antwortet. Die interessantere ist aber die dns-01-Challenge, die die Anfrage mit DNS-Einträgen beantwortet. Mit der dns-01-Challenge kannst du Wildcard-Zertifikate für deine Domains erstellen, was mit der http-01-Challenge nicht möglich wäre. Mit Cert-Manager und der Tatsache, dass wir CloudFlare für DNS nutzen, ist das kein Problem. Cert-Manager unterstützt CloudFlare out of the box. Damit Cert-Manager CloudFlare nutzen kann, erstellen wir das Secret mit dem \u0026ldquo;Global API Key\u0026rdquo; von CloudFlare (falls du dich fragst: Nein, das API-Token von CloudFlare funktioniert nicht, auch wenn das die naheliegendere Wahl wäre).\ncat \u0026lt;\u0026lt;EOF | kubectl apply -f- apiVersion: v1 kind: Secret metadata: name: cloudflare-api-key namespace: cert-manager data: api-key: $(echo -n \u0026#39;\u0026lt;your-global-api-key-goes-here\u0026gt;\u0026#39; | base64) EOF Bei Let\u0026rsquo;s Encrypt gibt es RateLimits, die die Zahl der Anfragen und pro Woche erstellbaren Zertifikate begrenzen. Bei einer Fehlkonfiguration in einer Ingress-Ressource oder einem anderen Zertifikatsanforderungs-Objekt (siehe https://cert-manager.io/docs/usage/certificate/) erreichst du dieses Limit ziemlich schnell. Ich empfehle immer, zuerst die Staging-Infrastruktur von Let\u0026rsquo;s Encrypt zu nutzen, um die Konfiguration zu testen, bevor du die Produktions-Infrastruktur verwendest. Darauf gehen wir gleich ein.\nCertManager braucht eine Identität, um Zertifikate bei Let\u0026rsquo;s Encrypt anzufordern und zu erhalten. Wir wollen sowohl die Staging- als auch die Produktions-Infrastruktur von Let\u0026rsquo;s Encrypt nutzen, deshalb erstellen wir je einen ClusterIssuer für Let\u0026rsquo;s Encrypt Produktion und Staging.\ncat \u0026lt;\u0026lt;EOF | kubectl apply -f- apiVersion: cert-manager.io/v1alpha2 kind: ClusterIssuer metadata: name: letsencrypt-staging spec: acme: # You must replace this email address with your own. # Let\u0026#39;s Encrypt will use this to contact you about expiring # certificates, and issues related to your account. email: \u0026lt;your-email\u0026gt; server: https://acme-staging-v02.api.letsencrypt.org/directory privateKeySecretRef: # Secret resource used to store the account\u0026#39;s private key. name: letsencrypt-staging-issuer-private-key # Add a single challenge solver, HTTP01 using nginx solvers: - dns01: cloudflare: email: \u0026lt;cloudflare-account-email\u0026gt; apiKeySecretRef: name: cloudflare-api-key key: api-key --- apiVersion: cert-manager.io/v1alpha2 kind: ClusterIssuer metadata: name: letsencrypt spec: acme: # You must replace this email address with your own. # Let\u0026#39;s Encrypt will use this to contact you about expiring # certificates, and issues related to your account. email: \u0026lt;your-email\u0026gt; server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: # Secret resource used to store the account\u0026#39;s private key. name: letsencrypt-issuer-private-key # Add a single challenge solver, HTTP01 using nginx solvers: - dns01: cloudflare: email: \u0026lt;cloudflare-account-email\u0026gt; apiKeySecretRef: name: cloudflare-api-key key: api-key EOF Das war\u0026rsquo;s! Dein Cluster kann jetzt Zertifikate für Ingress-Ressourcen oder jede andere Zertifikatsanforderung ausstellen. Cert-Manager erneuert Zertifikate, wenn sie kurz vor dem Ablauf stehen.\nEin Beispiel, wie eine Ingress-Ressource automatisch ein Zertifikat konfiguriert, findest du unter https://cert-manager.io/docs/usage/ingress/. Du kannst cert-manager.io/cluster-issuer entweder auf letsencrypt-staging oder letsencrypt setzen, um zwischen beiden Infrastrukturen zu wechseln.\nWie geht\u0026rsquo;s weiter? # Mich stört, dass die Kommunikation zwischen Containern/Nodes nicht verschlüsselt ist. Das private Netzwerk zwischen den Servern ist schon besser als Kommunikation über das Internet. Aber ich migriere vielleicht weg vom privaten Netzwerk hin zu einem verschlüsselten WireGuard-Netzwerk zwischen den Servern.\nEin weiteres Thema wäre das Backup-Problem. Ich sichere den Cluster bzw. das PersistedVolume bisher nur manuell. So will ich das nicht. Ich schreibe einen kleinen Controller für Kubernetes, der den Cluster mit borg auf einen entfernten SSH-Server sichert – so kann ich verschlüsselte Backups auf einem entfernten Server erstellen. Da ich das alles in meiner Freizeit schreibe, brauche ich dafür ein paar Wochen (vielleicht nur wenige (unter 3) Stunden Code pro Woche).\n","date":"8. Feb. 2020","externalUrl":null,"permalink":"/de/posts/kubernetes-hetzner-letsencrypt/","section":"Blog","summary":"","title":"Kubernetes auf Hetzner Cloud: Automatisches SSL/TLS mit Let's Encrypt","type":"posts"},{"content":"","date":"8. Feb. 2020","externalUrl":null,"permalink":"/de/tags/letsencrypt/","section":"Tags","summary":"","title":"Letsencrypt","type":"tags"},{"content":"","date":"8. Feb. 2020","externalUrl":null,"permalink":"/de/tags/network/","section":"Tags","summary":"","title":"Network","type":"tags"},{"content":"","date":"8. Feb. 2020","externalUrl":null,"permalink":"/de/tags/ssl/","section":"Tags","summary":"","title":"Ssl","type":"tags"},{"content":"","date":"8. Feb. 2020","externalUrl":null,"permalink":"/de/tags/tls/","section":"Tags","summary":"","title":"Tls","type":"tags"},{"content":"","date":"20. Jan. 2020","externalUrl":null,"permalink":"/de/tags/flannel/","section":"Tags","summary":"","title":"Flannel","type":"tags"},{"content":"Beim Deployen von Anwendungen in meinen Cluster fiel mir eine Störung auf – ich nutzte PVC, um Volumes zu provisionieren. Manche Volumes liessen sich nicht erstellen oder mounten. Der Container hcloud-csi-driver im hcloud-csi-node-xxxx loggte folgende Fehler:\nGet https://api.hetzner.cloud/v1/volumes/5127341: dial tcp: i/o timeout\u0026#34; Warum sollte eine Verbindung zu api.hetzner.cloud timeouten? Ich untersuchte beide Nodes, und nicht jeder Node hatte diesen Timeout. Warum verhalten sie sich unterschiedlich, obwohl sie exakt gleich konfiguriert sind? Tiefer im Kaninchenbau fand ich diese Art von Fehlermeldungen:\nGet https://api.hetzner.cloud/v1/volumes/5127341: dial tcp: lookup api.hetzner.cloud on 10.96.0.10:53: read udp 10.244.2.70:55772-\u0026gt;10.96.0.10:53: i/o timeout Es sieht so aus, als könne dieser Pod den coredns-Service im Cluster nicht erreichen, api.hetzner.cloud nicht auflösen und daher die Hetzner-API nicht aufrufen, um das Volume zu erstellen und anzuhängen. Als ich diese Pods und sogar Nodes neu startete (vorher kubectl drain \u0026lt;node\u0026gt;), fiel mir auf: Wenn nur ein Node läuft, tritt der Fehler nicht so oft auf. Und nachdem ich die Master-Toleration für coredns vorübergehend entfernt hatte – wodurch alles in der obigen Aufrufkette auf worker-1 lief – war der Fehler komplett weg. Das führte zum Schluss, dass das Netzwerk nicht wie erwartet funktioniert.\nDer erste Satz auf https://github.com/coreos/flannel/blob/master/Documentation/troubleshooting.md:\nIn Docker v1.13 and later, the default iptables forwarding policy was changed to DROP This problem manifests itself as connectivity problems between containers running on different hosts. To resolve it upgrade to the latest version of flannel.\nfiel mir ins Auge. Aber selbst nach dem Upgrade von flannel auf die neueste verfügbare Version half es nicht. Und der Issue-Tracker von flannel zeigt, dass ich mit dem Problem nicht allein bin: https://github.com/coreos/flannel/issues?q=is%3Aissue+is%3Aopen+FORWARD\nAngesichts der MetalLB Network Addon Compatibility musste ich ein Netzwerk-Addon finden, das \u0026ldquo;einfach\u0026rdquo; funktioniert. Mit Calico, Cilium und Weave als grossartigen Alternativen, die nicht auf flannel setzen, gibt es reichlich Auswahl.\nIch entschied mich für Cilium, weil es eine aktive Community und volle MetalLB-Kompatibilität hat. Ich hätte aber auch Calico oder Weave nehmen können – irgendwas musste es sein.\nDer Austausch eines CNI-Plugins/-Addons verursacht eine Downtime für alle Pods im Cluster.\n# delete the flannel network from the cluster kubectl delete -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml # on each node and master rm /etc/cni/net.d/10-flannel.conf # now restart reboot # now deploy Cilium kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/v1.7.1/install/kubernetes/quick-install.yaml # after waiting a few seconds (up to a minute or two) the network and all pods come up again. Ich habe sowohl Cilium als auch WeaveNet getestet, und beide Addons funktionieren, soweit ich das aktuell beurteilen kann.\n","date":"20. Jan. 2020","externalUrl":null,"permalink":"/de/posts/kubernetes-hetzner-move-to-another-network-addon/","section":"Blog","summary":"","title":"Kubernetes auf Hetzner Cloud: Warum ich das Netzwerk-Plugin gewechselt habe","type":"posts"},{"content":"","date":"7. Jan. 2020","externalUrl":null,"permalink":"/de/tags/dns/","section":"Tags","summary":"","title":"Dns","type":"tags"},{"content":"Nachdem ich in meinem vorherigen Beitrag einen LoadBalancer und Ingress eingerichtet habe, kann ich eine Website erfolgreich deployen. Allerdings muss ich die IP des LoadBalancers eingeben, um die Site zu erreichen. Wie bei einem klassischen Setup gibt es dafür DNS. Ja, wir können DNS-Einträge für alle Sites schreiben, die wir auf dem Cluster hosten wollen. Es gibt sogar recht praktische (Web-)Oberflächen dafür.\nAber ich will noch weiter gehen und DNS-Einträge lieber nicht selbst schreiben, sondern Kubernetes sie auf Basis der deployten Ingress-Ressourcen konfigurieren lassen.\nDank der Leute von https://github.com/kubernetes-sigs/external-dns gibt es mehrere Integrationen/Provider, mit denen Kubernetes DNS-Einträge automatisch auf Basis von Services/Ingress-Ressourcen/Annotations konfiguriert.\nMein erster Gedanke war, alles selbst zu machen: den CoreDNS-Provider nutzen und einen ETCD- und CoreDNS-Server konfigurieren, um einen DNS-Dienst umzusetzen. Trotzdem bräuchte ich einen sekundären DNS-Dienst, denn ein Secondary DNS wird bei einem eigenen DNS-Dienst empfohlen. Bisher habe ich https://www.buddyns.com/ genutzt und war mit dem Dienst sehr zufrieden!\nAber der Status \u0026ldquo;alpha\u0026rdquo; dieses Providers hat einen Grund. Er ist ziemlich instabil, lieferte DNS-Einträge für deployte Ingress-Ressourcen aber \u0026hellip; manchmal. Da man in der Config eine ClusterIP nutzen muss – weil Kubernetes-DNS-Auflösung auf einem CoreDNS-Container aus gutem Grund nicht funktioniert – ist er auch gegen Redeploys des ETCD-Dienstes nicht robust. Vielleicht schaue ich mir die Lösung künftig noch einmal an, aber im Moment ist sie zu instabil, um sich darauf zu verlassen.\nEine interessante Lösung ist der Cloudflare DNS-Provider. Cloudflare bietet einen autoritativen DNS-Dienst kostenlos für private Blogs oder Websites wie meine an. Dieser Provider ist im \u0026ldquo;beta\u0026rdquo;-Status, und erste Tests zeigten, dass er deutlich zuverlässiger war als der CoreDNS-Provider.\nCloudflare-Konto erstellen und erste Domain hinzufügen # Zuerst erstellst du ein Cloudflare-Konto und fügst deine erste Domain im DNS-Editor hinzu: https://support.cloudflare.com/hc/en-us/articles/201720164-Step-2-Create-a-Cloudflare-account-and-add-a-website\nCloudflare versucht, deine bestehende DNS-Konfiguration automatisch abzurufen. Das kannst du getrost ignorieren, da wir die Einträge ohnehin neu mit Kubernetes anlegen. Falls Einträge \u0026ldquo;importiert\u0026rdquo; oder \u0026ldquo;proxied\u0026rdquo; werden, solltest du alle Namen entfernen, die du mit Kubernetes konfigurieren willst.\nCloudflare-DNS für deine Domain konfigurieren # Um das Setup vollständig abzuschliessen, musst du die Cloudflare-DNS-Server (in deinem Dashboard auf cloudflare.com unter DNS zu sehen) beim Registrar deiner Domain eintragen. Cloudflare hilft dir dabei.\nDiesen Schritt kannst du überspringen, bis du sicher bist, dass alles eingerichtet ist.\nCloudflare-API-Token erstellen # Der Dienst braucht ein Access-Token, um die DNS-Einträge in deinem Namen zu bearbeiten. Erstelle ein neues API-Token auf https://dash.cloudflare.com/profile/api-tokens. Vergib aber nur folgende Berechtigungen:\nPermissions Zone Zone Read Zone DNS Edit Notiere dir das Token, denn es wird nur einmal angezeigt! Wir brauchen es gleich!\nExternal-DNS-Controller deployen # Endlich können wir den External-DNS-Controller deployen. Ich aktiviere die automatische Konfiguration von Ingress und Services mit den passenden Annotations. Das weicht vom offiziellen Beispiel der Dokumentation ab.\nNamespace für den DNS-Controller anlegen:\nkubectl create ns external-dns Deploye den Controller mit aktiviertem RBAC. Dafür brauchst du das API-Token (ganz unten).\ncat \u0026lt;\u0026lt;EOF | kubectl apply -f- apiVersion: v1 kind: ServiceAccount metadata: name: external-dns namespace: external-dns --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: external-dns namespace: external-dns rules: - apiGroups: [\u0026#34;\u0026#34;] resources: [\u0026#34;services\u0026#34;] verbs: [\u0026#34;get\u0026#34;,\u0026#34;watch\u0026#34;,\u0026#34;list\u0026#34;] - apiGroups: [\u0026#34;\u0026#34;] resources: [\u0026#34;pods\u0026#34;] verbs: [\u0026#34;get\u0026#34;,\u0026#34;watch\u0026#34;,\u0026#34;list\u0026#34;] - apiGroups: [\u0026#34;extensions\u0026#34;] resources: [\u0026#34;ingresses\u0026#34;] verbs: [\u0026#34;get\u0026#34;,\u0026#34;watch\u0026#34;,\u0026#34;list\u0026#34;] - apiGroups: [\u0026#34;\u0026#34;] resources: [\u0026#34;nodes\u0026#34;] verbs: [\u0026#34;list\u0026#34;] --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: external-dns-viewer roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: external-dns subjects: - kind: ServiceAccount name: external-dns namespace: external-dns --- apiVersion: apps/v1 kind: Deployment metadata: name: external-dns namespace: external-dns spec: strategy: type: Recreate selector: matchLabels: app: external-dns template: metadata: labels: app: external-dns spec: serviceAccountName: external-dns containers: - name: external-dns image: eu.gcr.io/k8s-artifacts-prod/external-dns/external-dns:v0.5.18 args: - --source=ingress - --source=service - --provider=cloudflare env: - name: CF_API_TOKEN value: \u0026#34;\u0026lt;your-cloudflare-api-token-goes-here\u0026gt;\u0026#34; EOF Sobald du nun eine Ingress-Ressource mit einem host-Key oder einen Service mit der Annotation external-dns.alpha.kubernetes.io/hostname=nginx.example.org deployst (ersetze nginx.example.org durch einen echten Wert), wird dafür ein DNS-Eintrag erstellt.\nWie geht\u0026rsquo;s weiter? # Du fragst dich vielleicht, wie es weitergeht? Ich will den Cluster so einrichten, dass er für jede deployte Domain automatisch Let\u0026rsquo;s-Encrypt-Zertifikate ausstellt – bleib also dran!\n","date":"7. Jan. 2020","externalUrl":null,"permalink":"/de/posts/kubernetes-hetzner-dns/","section":"Blog","summary":"","title":"Kubernetes auf Hetzner Cloud: Was ist mit DNS?","type":"posts"},{"content":"","date":"4. Jan. 2020","externalUrl":null,"permalink":"/de/tags/bare-metal/","section":"Tags","summary":"","title":"Bare Metal","type":"tags"},{"content":"","date":"4. Jan. 2020","externalUrl":null,"permalink":"/de/tags/ingress/","section":"Tags","summary":"","title":"Ingress","type":"tags"},{"content":"Ein Hauptziel des Servers ist es, Websites/Apps auszuliefern. Um auf Services innerhalb eines Kubernetes-Clusters zuzugreifen, musst du ihn irgendwo öffnen. Das geht über einen NodePort, der aber nur auf dem Node öffnet, der den Pod ausführt. Geht dieser Node down, ist deine Anwendung nicht mehr unter derselben öffentlichen IP erreichbar wie zuvor – was du vielleicht nicht willst.\nLoadBalancer to the rescue. Du brauchst einen LoadBalancer ausserhalb des Kubernetes-Clusters, der eine IP-Adresse hat und den Traffic an alle Nodes weiterleitet, die die Anwendung bereitstellen.\nEin LoadBalancer ist auch Voraussetzung, um eine Ingress-Resource-Implementierung wie NGINX zu deployen, die du für deinen Web-Traffic nutzen willst.\nHetzner bietet leider (noch) keinen LoadBalancer. Deshalb müssen wir mit dem, was wir haben, etwas kreativer werden.\nEin zentraler Aspekt ist die Floating IP, die unsere öffentliche IP-Adresse für den LoadBalancer darstellt. Aber wie richten wir den LoadBalancer ein? Hier betritt MetalLB die Bühne. Es braucht nur ein paar öffentliche IPs zum Verteilen und setzt einen LoadBalancer mit Standard-Routing-Mechanismen um. Hetzner unterstützt aber nicht das Verteilen von IPs ausserhalb seiner Reichweite, sondern nur die Zuweisung an einen Node (Floating IP). Wir nutzen also nur diese eine Floating IP von Hetzner für 1,077 €/Monat. Diese Floating IP lässt sich nur einem Node zuweisen – aber was passiert, wenn dieser Node aus irgendeinem Grund down geht? Ja, alle Anwendungen auf dieser öffentlichen IP sind nicht mehr verfügbar. Mist! Dank C. Beneke gibt es Hoffnung. Der hcloud fip controller prüft, ob ein Node down geht, und weist die Floating IP einem laufenden Node zu – das bewahrt uns vor Downtime!\nMit all dem hast du einen virtuellen LoadBalancer, der sich in die Hetzner-Cloud-Umgebung integriert. Keine ideale Lösung, aber die beste, die wir bisher bekommen. Vielleicht erlaubt uns Hetzner künftig, LoadBalancer zu erstellen?!?\nUnsere neue Lösung sieht so aus:\nJetzt wollen wir das umsetzen und auch die NGINX-Ingress-Resource-Implementierung installieren, um in unserem Cluster Ingress-Ressourcen anlegen zu können – damit wir Websites in unserem Cluster einfach ausliefern!\nVoraussetzungen # Du solltest den Kubernetes-Cluster auf Hetzner Cloud wie in meinem vorherigen Blogbeitrag beschrieben eingerichtet haben. Erstelle eine Floating IP mit hcloud floating-ip create --type ipv4 --home-location nbg1 --name public-ip oder über das Web-Interface – Floating IPs – Floating IP hinzufügen Floating IP auf jedem Node konfigurieren # Um die Floating IP zu nutzen, musst du sie auf jedem Worker-Node separat konfigurieren:\ncat \u0026lt;\u0026lt;EOF \u0026gt; /etc/sysconfig/network-scripts/ifcfg-eth0:1 BOOTPROTO=static DEVICE=eth0:1 IPADDR=\u0026lt;your-floating-ip-goes-here\u0026gt; PREFIX=32 TYPE=Ethernet USERCTL=no ONBOOT=yes EOF danach solltest du die Netzwerkkonfiguration neu starten:\nsystemctl restart network.service MetalLB installieren # Installiere MetalLB, indem du das Manifest anwendest:\nkubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.3/manifests/metallb.yaml Du kannst es auch mit kustomize installieren (Helm wird leider nicht mehr unterstützt); eine Anleitung dazu findest du unter https://metallb.universe.tf/installation/.\nJetzt musst du nur noch deine Floating IP in MetalLB konfigurieren:\ncat \u0026lt;\u0026lt;EOF |kubectl apply -f- apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: default protocol: layer2 addresses: - \u0026lt;your-floating-ip-goes-here\u0026gt;/32 EOF FIP-Controller installieren # Um den automatischen Failover-Mechanismus umzusetzen, installiere den FIP-Controller.\nErstelle einen neuen Namespace und deploye den FIP-Controller hinein.\nkubectl create namespace fip-controller kubectl apply -f https://raw.githubusercontent.com/cbeneke/hcloud-fip-controller/master/deploy/rbac.yaml kubectl apply -f https://raw.githubusercontent.com/cbeneke/hcloud-fip-controller/master/deploy/deployment.yaml Da er auf die Hetzner-Cloud-API zugreifen muss, brauchst du ein weiteres API-Token (oder du nutzt ein bereits erstelltes wieder).\nUm ein Hetzner-Cloud-API-Token zu erstellen, melde dich im Web-Interface an und navigiere zu deinem Projekt -\u0026gt; Access -\u0026gt; API tokens und erstelle ein neues Token.\nJetzt können wir FIP mit diesem Token und unserer Floating IP konfigurieren:\ncat \u0026lt;\u0026lt;EOF | kubectl apply -f - apiVersion: v1 kind: ConfigMap metadata: name: fip-controller-config namespace: fip-controller data: config.json: | { \u0026#34;hcloud_floating_ips\u0026#34;: [ \u0026#34;\u0026lt;your-floating-ip-goes-here\u0026gt;\u0026#34; ] } --- apiVersion: v1 kind: Secret metadata: name: fip-controller-secrets namespace: fip-controller stringData: HCLOUD_API_TOKEN: \u0026#34;\u0026lt;the api token you created just yet\u0026gt;\u0026#34; EOF NGINX Ingress Controller installieren # Zum Ausliefern von Webseiten deployen wir einen NGINX Ingress Controller. Der ist im Grunde ein Service vom Typ LoadBalancer und kann Traffic an mehrere Endpoints/Services routen.\nDu deployst den NGINX Ingress Controller mit\nkubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml und da wir MetalLB nutzen, erstellen wir einen Service, der auf den NGINX Ingress Controller zeigt:\ncat \u0026lt;\u0026lt;EOF | kubectl apply -f - kind: Service apiVersion: v1 metadata: name: ingress-nginx namespace: ingress-nginx annotations: metallb.universe.tf/allow-shared-ip: \u0026#34;floating-ip\u0026#34; labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx spec: type: LoadBalancer selector: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx ports: - name: http port: 80 targetPort: http - name: https port: 443 targetPort: https EOF Jetzt können wir Ingress-Ressourcen deployen, und wenn wir den Browser auf http://\u0026lt;floating-ip-address\u0026gt;/\u0026lt;whatever\u0026gt; richten, sehen wir die deployte Seite/Anwendung.\nAber IP-Adressen in den Browser zu tippen mag niemand – dafür gibt es DNS. Da wir das nicht manuell machen wollen, habe ich etwas im Kopf, worüber ich bald schreibe!\n","date":"4. Jan. 2020","externalUrl":null,"permalink":"/de/posts/kubernetes-hetzner-ingress/","section":"Blog","summary":"","title":"Kubernetes auf Hetzner Cloud: Ingress","type":"posts"},{"content":"","date":"4. Jan. 2020","externalUrl":null,"permalink":"/de/tags/loadbalancer/","section":"Tags","summary":"","title":"Loadbalancer","type":"tags"},{"content":"","date":"4. Jan. 2020","externalUrl":null,"permalink":"/de/tags/metallb/","section":"Tags","summary":"","title":"Metallb","type":"tags"},{"content":"","date":"4. Jan. 2020","externalUrl":null,"permalink":"/de/tags/nginx/","section":"Tags","summary":"","title":"Nginx","type":"tags"},{"content":"Dieser Blogbeitrag zeigt, wie man einen Kubernetes-Cluster auf Hetzner-Cloud-Servern aufsetzt. Der resultierende Cluster ist (noch) nicht vollständig, unterstützt aber bereits Persistent Volumes (Hetzner Block Storage Volumes). Ein Folgebeitrag beschreibt dann, wie wir einen (nginx-)Ingress und LoadBalancer einrichten (den Hetzner noch nicht anbietet).\nIch habe das nicht komplett allein gemacht, sondern konnte mich auf ein paar grossartige Quellen stützen:\nChristian Beneke: https://community.hetzner.com/tutorials/install-kubernetes-cluster blinkeye: https://blinkeye.github.io/post/public/2019-07-25-hetzner-k8s-with-private-network/ Kubernetes-Dokumentation (die sehr gut ist!): https://kubernetes.io/docs/home/ Ich beschreibe die Schritte mit Fedora 31 als Betriebssystem für die Server. Warum Fedora? Mit Ubuntu bin ich nicht mehr so zufrieden wie noch vor ein paar Jahren. Warum also nicht eine andere grosse Distro ausprobieren und ihre Höhen und Tiefen kennenlernen?\nWas wir tun # Kubernetes auf einem Setup mit einem Master und 2 Worker-Nodes aufsetzen, das etwa 13,24 € im Monat kostet (ohne Storage). Storage schlägt mit zusätzlich 4,76 €/100 GB pro Monat zu Buche Die API-Kommunikation läuft über ein privates Netzwerk und nicht über das Internet Du kannst Volumes auf Basis von Hetzner Cloud Block Storage Volumes für Datenspeicherung provisionieren Was wir (noch) nicht tun # Einen Ingress einrichten, um Websites über eine öffentliche IPv4 auszuliefern Einen LoadBalancer einrichten (für Ingress erforderlich) Eine Backup-Strategie für die im Cluster und auf den Volumes gespeicherten Daten einrichten Über diese Themen schreibe ich in ein paar Folgebeiträgen – schau also in ein paar Tagen/Wochen wieder auf meinem Blog vorbei.\nVoraussetzungen # Grundlegendes Linux-Know-how, besonders Shell-Befehle Ein Hetzner-Cloud-Konto Schritt 1 – Das hcloud-CLI-Tool installieren # Beim Arbeiten mit Hetzner Cloud ist es oft praktisch, das meiste in der Shell zu erledigen. Dafür ist das hcloud-CLI-Tool nützlich.\nAuf einem Mac wie meinem reicht:\nbrew install hcloud Bist du nicht auf einem Mac, findest du die Installationsanleitung hier: https://github.com/hetznercloud/cli\nSchritt 2 – Die Ressourcen auf Hetzner Cloud erstellen # Für das Setup brauchen wir mindestens 2–3 Server, die wir mit dem hcloud-Tool erstellen. Wir erstellen und richten ein:\n1 Hetzner Cloud Network 1 Hetzner Cloud CX11 Server 2 Hetzner Cloud CX21 Server Der kleinere CX11-Server dient als Kubernetes-Master, die 2 CX21-Server sind Worker-Nodes.\n2.1a – Ich habe noch keinen SSH-Key # Falls noch nicht geschehen, füge deinen öffentlichen SSH-Key zu Hetzner Cloud hinzu, damit du deine Server per Client-Zertifikat einrichten kannst.\nhcloud ssh-key create --name \u0026lt;whateverthenameyoulike\u0026gt; --public-key-from-file ~/.ssh/id_rsa.pub und notiere dir die Nummer des erstellten Keys, denn die brauchen wir später.\n2.1b – Ich habe bereits einen Hetzner-Cloud-SSH-Key # Falls du schon einen SSH-Key erstellt hast, ermittle jetzt die Nummer/ID dieses Keys, denn die brauchen wir gleich.\nhcloud ssh-key list 2.2 – Netzwerk und Nodes erstellen # Erstelle nun die Ressourcen auf Hetzner Cloud.\n# Create private network (you can alter the ip range of course!. 10.98.0.0 is just a suggestion) hcloud network create --name kubernetes --ip-range 10.98.0.0/16 hcloud network add-subnet kubernetes --network-zone eu-central --type server --ip-range 10.98.0.0/16 # Create Servers (this is where you\u0026#39;ll need that ssh key from step 2.1) hcloud server create --type cx11 --name master --image fedora-31 --ssh-key \u0026lt;ssh key id from 2.1\u0026gt; hcloud server create --type cx21 --name worker-1 --image fedora-31 --ssh-key \u0026lt;ssh key id from 2.1\u0026gt; hcloud server create --type cx21 --name worker-2 --image fedora-31 --ssh-key \u0026lt;ssh key id from 2.1\u0026gt; # Attach the servers to the private network (we will use a easy-to-remember ip for the master, but this is optional) hcloud server attach-to-network --network kubernetes --ip 10.98.0.10 master hcloud server attach-to-network --network kubernetes worker-1 hcloud server attach-to-network --network kubernetes worker-2 Jetzt kannst du dich per SSH auf allen Servern einloggen:\nhcloud server ssh \u0026lt;name-of-server\u0026gt; # Example hcloud server ssh master Schritt 3 – Die Systeme für die Installation vorbereiten # Bevor wir Kubernetes installieren, müssen wir die Systeme vorbereiten. Das gilt nur für Fedora 31. Willst du Ubuntu nutzen, empfehle ich den Beitrag von Christian Beneke.\nWichtig! Diese Schritte musst du auf jedem Server ausführen (Master und die 2 Nodes).\nFedora kommt ohne aktivierte bash-completion. Das lässt sich leicht beheben mit\ndnf install -y nano bash-completion source /etc/profile.d/bash_completion.sh fertig\n3.1 Das System aktualisieren # Vor dem Start empfiehlt es sich, das System zu aktualisieren:\ndnf update -y 3.2 Networking für Kubernetes aktivieren # cat \u0026lt;\u0026lt;EOF \u0026gt; /etc/sysctl.d/k8s.conf # Allow IP forwarding for kubernetes net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1 EOF Erstelle Konfigurationsdateien für Kubernetes und Docker, die wir gleich installieren.\ncat \u0026lt;\u0026lt;EOF \u0026gt; /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS=--cloud-provider=external --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice EOF mkdir -p /etc/systemd/system/docker.service.d/ cat \u0026lt;\u0026lt;EOF \u0026gt; /etc/systemd/system/docker.service.d/00-cgroup-systemd.conf [Service] ExecStart= ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd EOF systemctl daemon-reload 3.3 cgroups v1 statt v2 nutzen # Wenn du die Release Notes von Fedora 31 aufmerksam gelesen hast, ist dir vielleicht der Wechsel zu cgroups v2 aufgefallen. Da Docker und Kubernetes stark auf cgroups setzen, laufen wir definitiv in Probleme, weil sie cgroups v2 (noch) nicht unterstützen.\nAlso müssen wir zurück auf v1:\ndnf install -y grubby grubby --update-kernel=ALL --args=\u0026#34;systemd.unified_cgroup_hierarchy=0\u0026#34; Da es ein Kernel-Parameter ist, müssen wir das System vollständig neu starten:\nreboot 3.4 Docker installieren # Folge https://docs.docker.com/install/linux/docker-ce/fedora/, um Docker zu installieren, im Wesentlichen also:\n# Add Repo dnf config-manager \\ --add-repo \\ https://download.docker.com/linux/fedora/docker-ce.repo # Install packages dnf install -y docker-ce docker-ce-cli containerd.io # Enable the service systemctl enable --now docker 3.5 Kubernetes installieren # Du kannst fast vollständig https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/ folgen, um Kubernetes zu installieren – mit ein paar Ausnahmen.\n# Ensure iptables tooling does not use the nftables backend update-alternatives --set iptables /usr/sbin/iptables-legacy # Add repo (difference to the original is the \u0026#34;exclude=kube*\u0026#34; part, since we should do Kubernetes updates manually) cat \u0026lt;\u0026lt;EOF \u0026gt; /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF # Set SELinux in permissive mode (effectively disabling it) setenforce 0 sed -i \u0026#39;s/^SELINUX=enforcing$/SELINUX=permissive/\u0026#39; /etc/selinux/config # Install the packages for 1.17.3 (difference to the original is the addition of cni, since we we\u0026#39;ll need that for flannel) dnf install -y kubelet-1.17.3-0 kubeadm-1.17.3-0 kubectl-1.17.3-0 kubernetes-cni --disableexcludes=kubernetes # Enable the Kubelet systemctl enable --now kubelet 3.6 Versionen pinnen # Der Befehl dnf upgrade würde auch Docker- und Kubernetes-Pakete upgraden. Das wollen wir vielleicht nicht, denn für jedes Kubernetes-Upgrade gibt es spezifische Schritte: https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/\nEs ist also sinnvoll, die installierte Version festzunageln und diese Pakete manuell zu upgraden. Um dnf am Upgrade aller Pakete zu hindern, kannst du Excludes in der Konfiguration definieren. Es gibt aber einen anderen Weg: dnf-plugin-versionlock. Dieses dnf-Plugin fügt Pakete zu einer Liste hinzu, die bei dnf upgrade nicht aktualisiert werden.\ndnf install -y dnf-plugin-versionlock und dann fügen wir alle installierten Pakete für Kubernetes und Docker zu dieser Lock-Liste hinzu:\ndnf versionlock add kube* docker-* containerd* Wenn wir upgraden müssen, entfernt man einfach den Version-Lock\ndnf versionlock delete \u0026lt;package\u0026gt; und installiert die gewünschte Version\ndnf install -y kubeadm-1.17.3-0 und fügt das Paket danach wieder dem Version-Lock hinzu. Mach das mit jedem Paket entlang der offiziellen Upgrade-Anleitung: https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/\nSchritt 4 – Den Cluster initialisieren – Control Plane installieren # Wenn du bis hierher alle Schritte auf jedem Server befolgt hast, haben wir alles, um den Cluster zu initialisieren. Die folgenden Schritte machst du nur auf dem Master-Node.\nDu brauchst die öffentliche IP-Adresse deines Master-Servers und die Adresse im privaten Netzwerk. Da der API-Server-Traffic zwischen Master und Nodes nicht vollständig gesichert ist (siehe https://kubernetes.io/docs/concepts/architecture/master-node-communication/), will ich das private Netzwerk zwischen allen Servern nutzen. Wir sagen kubeadm also, den API-Server über die private IP (10.98.0.10, erstellt in Schritt 2.2) zu advertisen, aber auch die Authentifizierung über die öffentliche IP des Servers zu erlauben. Denn ich will auch von meinem Mac aus deployen (dieser Traffic ist durch das selbstsignierte Zertifikat in .kube/config verschlüsselt). Das --ignore-preflight-errors=NumCPU brauchen wir nur auf einem CX11-Server, da er nur eine CPU hat. Ein Kubernetes-Master empfiehlt mindestens 2 CPUs.\nkubeadm init \\ --apiserver-advertise-address=10.98.0.10 \\ --service-cidr=10.96.0.0/16 \\ --pod-network-cidr=10.244.0.0/16 \\ --kubernetes-version=v1.17.3 \\ --ignore-preflight-errors=NumCPU \\ --apiserver-cert-extra-sans \u0026lt;public ip of your master server\u0026gt; Jetzt solltest du eine Erfolgsmeldung erhalten wie\nYour 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 \u0026#34;kubectl apply -f [podnetwork].yaml\u0026#34; 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 10.98.0.10:6443 --token 9bsd1v.jl1351231kk53 \\ --discovery-token-ca-cert-hash sha256:aca30f96f58ea1479fe421936e232d5dc46fe19f03fe9d7888821154bb457039 Notiere dir den Join-Befehl in der letzten Zeile, denn den brauchen wir später.\nKopiere die Cluster-Config in dein Home, um mit kubectl auf den Cluster zuzugreifen:\nmkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config Schritt 5 – Ein Container-Netzwerk deployen # Damit die Container/Pods kommunizieren können, brauchen wir ein Container-Netzwerk (CNI). Eine Option ist Cilium, du kannst aber auch ein anderes wählen: https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#pod-network\nUpdate 20. Jan. 2020: Flannel hat auf meinem Cluster Probleme verursacht – warum? Lies hier\nkubectl apply -f https://raw.githubusercontent.com/cilium/cilium/v1.7.1/install/kubernetes/quick-install.yaml Optional\nPrüfe nun, ob das Netzwerk läuft: Du kannst einen gründlichen Connectivity-Test deployen, um zu sehen, ob jeder Container auf jedem Node die anderen über verschiedene Network Policies erreichen kann.\nkubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.7.1/examples/kubernetes/connectivity-check/connectivity-check.yaml # after a while kubectl get pods NAME READY STATUS RESTARTS AGE echo-a-9b85dd869-292s2 1/1 Running 0 8m37s echo-b-c7d9f4686-gdwcs 1/1 Running 0 8m37s host-to-b-multi-node-clusterip-6d496f7cf9-956jb 1/1 Running 0 8m37s host-to-b-multi-node-headless-bd589bbcf-jwbh2 1/1 Running 0 8m37s pod-to-a-7cc4b6c5b8-9jfjb 1/1 Running 0 8m36s pod-to-a-allowed-cnp-6cc776bb4d-2cszk 1/1 Running 0 8m36s pod-to-a-external-1111-5c75bd66db-sxfck 1/1 Running 0 8m35s pod-to-a-l3-denied-cnp-7fdd9975dd-2pp96 1/1 Running 0 8m36s pod-to-b-intra-node-9d9d4d6f9-qccfs 1/1 Running 0 8m35s pod-to-b-multi-node-clusterip-5956c84b7c-hwzfg 1/1 Running 0 8m35s pod-to-b-multi-node-headless-6698899447-xlhfw 1/1 Running 0 8m35s pod-to-external-fqdn-allow-google-cnp-667649bbf6-v6rf8 1/1 Running 0 8m35s Wenn alles im Status ready ist, hast du Glück – alles funktioniert wie erwartet. Du kannst den Check löschen:\nkubectl delete -f https://raw.githubusercontent.com/cilium/cilium/1.7.1/examples/kubernetes/connectivity-check/connectivity-check.yaml Schritt 6 – Worker-Nodes beitreten lassen # Führe den in Schritt 4 ausgegebenen Join-Befehl auf beiden Worker-Nodes aus.\nEtwa so:\nkubeadm join 10.98.0.10:6443 --token 9bsd1v.jl1351231kk53 \\ --discovery-token-ca-cert-hash sha256:aca30f96f58ea1479fe421936e232d5dc46fe19f03fe9d7888821154bb457039 Schritt 7 – Den Hetzner Cloud Controller Manager deployen # Für die Integration mit Hetzner Cloud haben sie einen \u0026ldquo;Kubernetes Cloud Controller Manager\u0026rdquo; entwickelt. Der braucht Zugriff auf die Hetzner Cloud, also erstellen wir ein weiteres API-Token.\nUm ein Hetzner-Cloud-API-Token zu erstellen, melde dich im Web-Interface an und navigiere zu deinem Projekt -\u0026gt; Access -\u0026gt; API tokens und erstelle ein neues Token.\nNun erstellen wir in Kubernetes ein Secret mit diesem Token. Dafür brauchst du die Network-ID, die wir in Schritt 2.2 erstellt haben:\nhcloud network list cat \u0026lt;\u0026lt;EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: hcloud namespace: kube-system stringData: token: \u0026#34;\u0026lt;the api token you created just yet\u0026gt;\u0026#34; network: \u0026#34;\u0026lt;network-id\u0026gt;\u0026#34; EOF Jetzt können wir den Controller deployen:\nkubectl apply -f https://raw.githubusercontent.com/hetznercloud/hcloud-cloud-controller-manager/master/deploy/v1.5.1.yaml Schritt 8 – Hetzner Cloud Storage (CSI) deployen # Um die PVC zu nutzen, die die meisten Anwendungen brauchen, musst du ein CSI deployen. Auch dafür hat Hetzner einen Treiber geschrieben.\nErstelle das API-Token aus dem vorherigen Schritt neu oder nutze es wieder und erstelle ein Secret für den Treiber.\ncat \u0026lt;\u0026lt;EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: hcloud-csi namespace: kube-system stringData: token: \u0026#34;\u0026lt;the api token you created just yet\u0026gt;\u0026#34; EOF Jetzt deploye die API und den Treiber:\nkubectl apply -f https://raw.githubusercontent.com/kubernetes/csi-api/release-1.14/pkg/crd/manifests/csidriver.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes/csi-api/release-1.14/pkg/crd/manifests/csinodeinfo.yaml kubectl apply -f https://raw.githubusercontent.com/hetznercloud/csi-driver/v1.2.3/deploy/kubernetes/hcloud-csi.yml Fazit # Jetzt solltest du neue Anwendungen mit Storage-Fähigkeit (Volumes) deployen können. Um darauf zuzugreifen, bräuchtest du aber einen Einstiegspunkt aus dem Internet wie NodePorts – doch es gibt bereits eine bessere Lösung: LoadBalancer/Ingress.\nDas nächste Thema ist, wie wir auf die in Kubernetes deployten Anwendungen zugreifen können.\n","date":"22. Dez. 2019","externalUrl":null,"permalink":"/de/posts/kubernetes-hetzner-setup/","section":"Blog","summary":"","title":"Kubernetes auf Hetzner Cloud: Einen Kubernetes-Cluster aufsetzen","type":"posts"},{"content":"","date":"7. Dez. 2019","externalUrl":null,"permalink":"/de/tags/docker/","section":"Tags","summary":"","title":"Docker","type":"tags"},{"content":"Ich betreibe diesen Server seit 2017 vollständig auf Docker. Mit einem Git-Commit werden Websites/Apps automatisch gebaut und deployt. Backups laufen regelmässig mit (borg) auf einen Off-Site-Server. Der Reverse Proxy (Caddyserver) steht ganz vorne und kümmert sich um allen webbezogenen Traffic. Er holt Let\u0026rsquo;s Encrypt-Zertifikate und erneuert sie automatisch. Der Reverse Proxy leitet den Traffic an den passenden Docker-Container weiter.\nUm dahin zu kommen, musste ich eine Deployment-Anwendung schreiben, Caddy für jede neue Website oder Anwendung konfigurieren und das DNS entsprechend einrichten. Dazu die Site überwachen (uptimerobot.com) und für jede Anwendung jede Downtime beheben. Meist manuell.\nAll das kostet Zeit, die ich lieber mit meiner Freundin, der Familie und Freunden verbringe.\nBei der Arbeit nutzen wir seit über einem Jahr Kubernetes, und ich habe immer daran gedacht, diese Website auf Kubernetes als Plattform zu betreiben. Kombiniert mit ein paar nützlichen Komponenten könnte es das meiste, was ich manuell mache, automatisch erledigen – und so Zeit sparen.\nGoogle Cloud, AWS oder Azure (um nur einige zu nennen) bieten bereits eine Kubernetes-Plattform, und die sind grossartig (bei der Arbeit nutze ich Google Cloud). Um diese und alle zugehörigen Sites zu betreiben, brauche ich etwa 6–10 GiB RAM. Mit dem Google Cloud Calculator zur Hand kostet ein Setup aus 2 Nodes dieser Leistung – selbst ohne Load Balancing oder IPs – etwa 123.53 € im Monat (Standort: Zürich). Für das Gebotene ist das ein fairer Preis und im Business-Einsatz kaum zu schlagen. Für eine private Website ist es teuer, schliesslich bekommst du einfaches Webhosting schon für 1–3 € im Monat.\nHier kommt Hetzner Cloud ins Spiel. Die Preise sind sowohl für den privaten (Shared CPU) als auch für den Business-Einsatz gut. Mit verfügbarer API und ein paar hilfreichen Komponenten könnte es eine echte Alternative zu Google Cloud werden.\nAber ganz ohne Haken geht es nicht!!!!\nDu musst den harten Weg gehen, einen Kubernetes-Cluster selbst installieren und Dinge wie Load Balancer, DNS oder Ingress selbst integrieren. Ich nehme die Herausforderung an – in der Hoffnung, danach mehr Freizeit zu haben (zumindest hoffe ich das) und unterwegs ein paar neue Skills zu lernen.\n","date":"7. Dez. 2019","externalUrl":null,"permalink":"/de/posts/kubernetes-cluster/","section":"Blog","summary":"","title":"Kubernetes Cluster","type":"posts"},{"content":"","date":"23. Nov. 2019","externalUrl":null,"permalink":"/de/tags/dedicated/","section":"Tags","summary":"","title":"Dedicated","type":"tags"},{"content":"","date":"23. Nov. 2019","externalUrl":null,"permalink":"/de/tags/firewall/","section":"Tags","summary":"","title":"Firewall","type":"tags"},{"content":"Beim Betrieb eines Servers sind zumindest grundlegende Sicherheitsmassnahmen essenziell. Eine der wirksamsten Methoden, deinen Server zu schützen, ist eine Firewall.\nHetzner bietet eine integrierte Firewall auf Netzwerkebene, die den Traffic filtert, bevor er den dedizierten Server überhaupt erreicht. Das blockiert unerwünschte Verbindungen und erhöht die Sicherheit.\nDa ich auf meinem Server Web-, DNS-, Mail- und SSH-Dienste betreibe, habe ich folgende Firewall-Regeln konfiguriert:\nName Source IP Destination IP Source port Destination port Protocol TCP flags Action #1 SSH 22 tcp accept #2 DNS TCP 53 tcp accept #3 DNS UDP 53 udp accept #4 HTTP 80 tcp accept #5 HTTPS 443 tcp accept #6 SMTP 25 tcp accept #7 SMTP TLS 587 tcp accept #8 IMAP TLS 993 tcp accept #9 POP3 TLS 995 tcp accept #10 Out 32768-65535 tcp ack accept Wichtig: Bevor du diese Firewall-Regeln anwendest, stelle sicher, dass du per SSH auf deinen Server zugreifen kannst. Sonst riskierst du, dich selbst auszusperren!\nWarum die letzte Regel wichtig ist # Die letzte Regel (#10: Outbound) ist entscheidend, denn sie erlaubt deinem Server den Internetzugriff für Aufgaben wie Software-Updates. Ohne sie kann es beim Abrufen externer Ressourcen zu Verbindungsproblemen kommen.\nFirewall aktivieren # Da Hetzners Firewall standardmässig eine Deny-Policy hat, müssen wir nur legitimen Traffic erlauben. Sobald du deinen Zugriff geprüft und die Regeln kontrolliert hast, kannst du die Firewall über Hetzners Web-Interface aktivieren. Änderungen greifen nach etwa 30 Sekunden.\nGrenzen der Hetzner Firewall # Beachte: Hetzner begrenzt die Firewall-Konfiguration derzeit auf 10 Regeln. Die Slots sind also schnell aufgebraucht – plane deine Regeln daher sorgfältig, damit sie in diese Grenzen passen.\n","date":"23. Nov. 2019","externalUrl":null,"permalink":"/de/posts/hetzner-firewall/","section":"Blog","summary":"","title":"Hetzner Firewall","type":"posts"},{"content":"Hallo! \u0026#x1f44b;\nHier sammle ich technische Notizen, Erfahrungen und Anleitungen: Softwareentwicklung, Systemarchitektur und Experimente rund um Infrastruktur und Tools.\nIm Grunde ist das ein öffentliches Nachschlagewerk: Lösungen, die ich einmal erarbeitet habe – damit weder du noch ich sie ein zweites Mal recherchieren müssen. \u0026#x1f609;\n","date":"1. Jan. 2019","externalUrl":null,"permalink":"/de/posts/welcome/","section":"Blog","summary":"","title":"Willkommen","type":"posts"},{"content":"Ich hatte Vista mit zwei NTFS-Partitionen (OS und DATA) laufen, dann die erste Partition formatiert und Windows 7 RC installiert. Die zweite Partition (DATA, Laufwerk D) hatte auf einigen Dateien und Ordnern Sicherheitsattribute. Nach der Windows-7-Installation waren manche Dateien auf Laufwerk D nicht mehr zugänglich und ich bekam \u0026ldquo;Access Denied\u0026rdquo;-Fehler. Ich versuchte per Rechtsklick auf die betroffenen Ordner, den Owner zu ändern und die Berechtigungen anzupassen – manche Ordner blieben aber unzugänglich, egal was ich tat. Kurz vor dem Aufgeben erinnerte ich mich: Seit Windows NT gibt es ein Tool namens \u0026ldquo;cacls\u0026rdquo;, mit dem sich ACLs (Access Control Lists) anzeigen oder ändern lassen. Seit Windows 7 heisst es \u0026ldquo;icacls\u0026rdquo;.\nUm Datei-Berechtigungen zurückzusetzen:\n\u0026ldquo;cmd\u0026rdquo; als Administrator ausführen\nZum betreffenden Laufwerk oder Ordner wechseln, zum Beispiel:\nCD /D D: Um alle Ordner-/Datei-Berechtigungen zurückzusetzen, eingeben:\nicacls * /T /Q /C /RESET Und das war\u0026rsquo;s! Danach waren die Berechtigungen der Dateien zurückgesetzt und ich konnte wieder auf sie zugreifen. cacls ist ein praktisches Tool, um Berechtigungen von Dateien und Ordnern zu ändern.\nReferenz: http://support.microsoft.com/kb/318754\n","externalUrl":null,"permalink":"/de/braindump/windows/reset-permissions/","section":"Braindump","summary":"","title":"Alle Berechtigungen auf Windows-Standard zurücksetzen","type":"braindump"},{"content":"Jeder sollte eine regelmässige und getestete Backup-Lösung haben. Datenverlust kann jederzeit passieren, und der Verlust wertvoller Fotos und anderer Erinnerungen kann sehr schmerzhaft sein.\nDas hier ist eine kleine Sammlung von Software, die ich zum Sichern meiner Daten nutze oder genutzt habe.\nborg backup # Als Kommandozeilen-Tool ist es nicht für jeden. Aber es macht seinen Job sehr gut, und einige seiner wichtigsten Features sind:\nplatzsparende Speicherung (speichert unveränderte Daten nicht doppelt) Datenverschlüsselung Kompression Off-Site-Backups (Übertragung über ssh, nfs und vieles mehr) Backups lassen sich als Dateisysteme mounten (FUSE) Open Source Ich nutze es, um meinen Server und meinen Mac (User-Home) vollständig verschlüsselt mit 256-Bit-AES an einen Off-Site-Ort zu sichern.\nborg backup\nMacrium Reflect Free # Macrium Reflect habe ich vor allem zum Imaging von Partitionen oder Festplatten genutzt. Es war unter Microsoft Windows eine zuverlässige Imaging-Lösung.\nMacrium Reflect Free\nEs gibt auch eine kostenpflichtige Variante, die sehr gut ist und mit der du auch inkrementelle oder differenzielle Backups erstellen kannst.\nDriveImage XML # Ein weiteres Tool, um Images von Partitionen oder Festplatten zu erstellen. Vielleicht weniger benutzerfreundlich als Macrium, macht seinen Job aber sehr gut.\nDriveImage XML\n","externalUrl":null,"permalink":"/de/braindump/software/backup-and-imaging/","section":"Braindump","summary":"","title":"Backup \u0026 Imaging","type":"braindump"},{"content":"Um ein Bash-Script zu debuggen, hilft immer:\nbash -x \u0026lt;scriptname\u0026gt; Das schreibt alle Befehle und deren Ausgabe ins Terminal. Mehr Details liefern die guten alten man-Pages man bash oder Beispiele mit tldr bash.\n","externalUrl":null,"permalink":"/de/braindump/unix/debug-shell-script/","section":"Braindump","summary":"","title":"Bash-Script debuggen","type":"braindump"},{"content":"Meine persönliche Wissensbasis: Lösungen und Notizen, die ich einmal erarbeitet habe und griffbereit halte. Die meisten Einträge sind (noch) englisch; deutsche Versionen kommen nach und nach.\nProgramming # Sprachen, Frameworks und die kleinen technischen Stolpersteine, die einen Nachmittag kosten.\nPython # Vergleich von Unicode-Strings funktioniert nicht Computer # Systemnahes: von Kommandozeilen-Tricks bis zur Fehlersuche in Netzwerk und Betriebssystem.\nLinux / Unix / macOS # Systemzeit über HTTP setzen SSH-Port-Tunnel für den Zugriff auf Services Bash-Script debuggen Verbindungen und offene Sockets/Ports anzeigen Ubuntu: Apple-Tastatur erzeugt seltsames Leerzeichen Linux hinter einem HTTP-Proxy nutzen MPlayer im Terminal nutzen In Dateien suchen Leere Verzeichnisse finden HTTP-Traffic mit tcpdump aufzeichnen macOS # CrossOver in einem Shell-Script unter macOS nutzen macOS geht nicht in den Ruhezustand Parallels – prl_disp_service startet nicht VMware Fusion – Netzwerk nicht verfügbar Netzwerk-Bandbreite begrenzen .DS_Store-Dateien auf Netzlaufwerken verhindern Windows # Nicht löschbare Dateien löschen PowerShell: Datei-Encoding ändern PowerShell: Natural Scrolling Berechtigungen auf Windows-Standard zurücksetzen Dateien löschen, die älter als X Tage sind Windows Event Log in MySQL importieren Software # Backup \u0026amp; Imaging Sublime Text Databases # Datenbanken, nützliche Befehle und die wiederkehrenden Aufgaben, die man gern griffbereit hat.\nPostgreSQL # psql: Ein paar nützliche Befehle und Queries PostgreSQL-Datenbanken sichern MS SQL Server # Tabellen mit Präfix versehen oder Präfix entfernen Tabelle kopieren MySQL # Numerische Auto-Increment-ID durch eine andere Reihenfolge ersetzen ","externalUrl":null,"permalink":"/de/braindump/","section":"Braindump","summary":"","title":"Braindump","type":"braindump"},{"content":"","externalUrl":null,"permalink":"/de/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"Manchmal will ich Aufgaben mit Bash-Scripts automatisieren – auch wenn dazu eine Windows-Anwendung ausgeführt werden muss, besonders wenn es sie nur für Windows gibt. Wenn du CrossOver hast und nicht zusätzlich eine wine-Installation (über Homebrew oder MacPorts) einrichten willst, könnte das hier auch für dich funktionieren. Bei mir klappt es mit einer CrossOver-Installation.\nHier die Schritte, die ich für ein Shell-Script gebraucht habe.\n# Start CrossOver, otherwise the X11 server from CrossOver wasn\u0026#39;t found when executing wine (from CrossOver) open -a CrossOver # Now quite a few variables should be set, so wine should find everything it needs. export \u0026#39;DYLD_FALLBACK_LIBRARY_PATH\u0026#39;=\u0026#39;/Applications/CrossOver.app/Contents/SharedSupport/X11/lib:/Users//lib:/lib:/usr/lib:/usr/X11/lib\u0026#39; export \u0026#39;FONTCONFIG_ROOT\u0026#39;=\u0026#39;/Applications/CrossOver.app/Contents/SharedSupport/X11\u0026#39; export \u0026#39;FONTCONFIG_PATH\u0026#39;=\u0026#39;/Applications/CrossOver.app/Contents/SharedSupport/X11/etc/fonts\u0026#39; export \u0026#39;FONT_ENCODINGS_DIRECTORY\u0026#39;=\u0026#39;/Applications/CrossOver.app/Contents/SharedSupport/X11/lib/X11/fonts/encodings/encodings.dir\u0026#39; export \u0026#39;VERSIONER_PERL_PREFER_32_BIT\u0026#39;=\u0026#39;yes\u0026#39; export \u0026#39;CX_BOTTLE_PATH\u0026#39;=\u0026#39;/Users//Library/Application Support/CrossOver/Bottles\u0026#39; export \u0026#39;CX_ROOT\u0026#39;=\u0026#39;/Applications/CrossOver.app/Contents/SharedSupport/CrossOver\u0026#39; export \u0026#39;CX_BOTTLE\u0026#39;=\u0026#39;winxp\u0026#39; # \u0026lt;-- You can set the bottle to execute the .exe in, this is helpful when the .exe has some dependencies! # Determine the DISPLAY variable since this can change sometimes export \u0026#39;DISPLAY\u0026#39;=\u0026#39;:\u0026#39;$(defaults read com.codeweavers.CrossOver Display) # Now we extend the PATH variable and put the bin from CrossOver at the first possible location, to not collide with an # additional wine installation you might have export \u0026#39;PATH\u0026#39;=\u0026#39;/Applications/CrossOver.app/Contents/SharedSupport/CrossOver/bin:\u0026#39;$PATH # Now we can start the application however we ant wine \u0026lt;path to .exe\u0026gt; \u0026lt;parameters\u0026gt; Ersetze einfach die Platzhalter \u0026lt;path to .exe\u0026gt; und \u0026lt;parameters\u0026gt; durch deine Anwendung – fertig.\n","externalUrl":null,"permalink":"/de/braindump/macos/use-crossover-in-shellscript/","section":"Braindump","summary":"","title":"CrossOver in einem Shell-Script unter macOS nutzen","type":"braindump"},{"content":"Vielleicht willst du alte Daten löschen, um Platz zu sparen – zum Beispiel temporäre Dateien. Für solche Fälle gibt es einen einfachen Weg, ganz mit Microsoft-Bordmitteln. Eventuell musst du zuerst das Windows Resource Kit für deine Windows-Version installieren.\nMit dem Befehl forfiles kannst du Dateien nach bestimmten Kriterien auflisten und für jede gefundene Datei einen Befehl ausführen.\nZum Beispiel:\nforfiles -p \u0026#34;C:\\\u0026lt;path\u0026gt;\u0026#34; -s -m *.* /D -\u0026lt;days\u0026gt; /C \u0026#34;cmd /c del @path\u0026#34; löscht alle Dateien in \u0026lt;path\u0026gt;, die älter als \u0026lt;days\u0026gt; sind (beachte das - vor der Anzahl Tage).\n","externalUrl":null,"permalink":"/de/braindump/windows/delete-files-older-than-x-days/","section":"Braindump","summary":"","title":"Dateien löschen, die älter als X Tage sind","type":"braindump"},{"content":"Falls du je SOAP- oder REST-Services debuggen musstest, ohne Zugriff auf den rohen Request/Response, wirst du das hier mögen. Solchen HTTP-Traffic kannst du mit tcpdump aufzeichnen. Das UNIX-Tool tcpdump (Installation mit brew install tcpdump oder apt-get install tcpdump) zeichnet den gesamten Netzwerk-Traffic deines Systems auf. Weil wir aber wissen, dass wir nur HTTP-Traffic brauchen, machen wir es uns etwas leichter!\nHTTP-Traffic inklusive Request-/Response-Header und Message-Body mitschneiden:\ntcpdump -A -s 0 \u0026#39;tcp port 80 and (((ip[2:2] - ((ip[0]\u0026amp;0xf)\u0026lt;\u0026lt;2)) - ((tcp[12]\u0026amp;0xf0)\u0026gt;\u0026gt;2)) != 0)\u0026#39; HTTP-Traffic inklusive Header und Body von einer bestimmten Quelle:\ntcpdump -A -s 0 \u0026#39;src example.com and tcp port 80 and (((ip[2:2] - ((ip[0]\u0026amp;0xf)\u0026lt;\u0026lt;2)) - ((tcp[12]\u0026amp;0xf0)\u0026gt;\u0026gt;2)) != 0)\u0026#39; HTTP-Traffic inklusive Header und Body von localhost zu localhost:\ntcpdump -A -s 0 \u0026#39;tcp port 80 and (((ip[2:2] - ((ip[0]\u0026amp;0xf)\u0026lt;\u0026lt;2)) - ((tcp[12]\u0026amp;0xf0)\u0026gt;\u0026gt;2)) != 0)\u0026#39; -i lo Nur HTTP-Requests: in den Befehlen oben \u0026ldquo;tcp port 80\u0026rdquo; durch \u0026ldquo;tcp dst port 80\u0026rdquo; ersetzen\nTCP-Pakete von localhost zu localhost (Loopback) mitschneiden:\ntcpdump -i lo Quelle: https://sites.google.com/site/jimmyxu101/testing/use-tcpdump-to-monitor-http-traffic\n","externalUrl":null,"permalink":"/de/braindump/unix/record-http-traffic-with-tcpdump/","section":"Braindump","summary":"","title":"HTTP-Traffic mit tcpdump aufzeichnen","type":"braindump"},{"content":"Irgendwann kommt immer der Moment, in dem du Dateien mit einem bestimmten Text finden musst. Auf UNIX-basierten Systemen ist das zum Glück eine leichte Übung.\n\u0026ldquo;foobar\u0026rdquo; in allen Dateien suchen:\nfind . -type f -exec grep -l \u0026#34;foobar\u0026#34; {} \\; Damit suchst du zuerst alle Dateien im aktuellen Verzeichnis und allen Unterverzeichnissen und führst dann mit grep eine Suche innerhalb der Dateien aus.\nMehr Infos findest du auf den man-Pages der beiden Tools:\nfind grep ","externalUrl":null,"permalink":"/de/braindump/unix/search-in-files/","section":"Braindump","summary":"","title":"In Dateien suchen","type":"braindump"},{"content":" Kennst du das? Jede Kubernetes-Datei sieht anders aus – bei der einen steht spec ganz oben, bei der nächsten metadata irgendwo in der Mitte, und im Review scrollst du ewig, bis du findest, wonach du suchst. k8s-yaml-fmt bringt Ordnung rein. Das kleine Python-Tool sortiert die Felder jeder Ressource genau so, wie man es von kubectl, den offiziellen Beispielen und dem täglichen Umgang mit Kubernetes gewohnt ist – nicht alphabetisch, sondern idiomatisch. Einmal eingerichtet, sehen alle Manifeste im Repo gleich aus und deine Diffs bleiben klein und lesbar.\napiVersion, kind, metadata, spec – immer am gewohnten Platz Kennt die passende Reihenfolge für Workloads, Services, RBAC-Ressourcen und mehr Erhält deine YAML-Kommentare und verarbeitet Dateien mit mehreren Manifesten Eigene Ressourcenarten? Einfach in der Projektkonfiguration ergänzen SOPS-verschlüsselte Dateien bleiben unangetastet – deine Secrets bleiben genau so, wie sie sind. Zwei Wege, es zu nutzen:\nKommandozeile Pre-Commit-Hook k8s-yaml-fmt deployment.yaml Eine einzelne Datei oder ein ganzes Verzeichnis auf Zuruf formatieren.\nrepos: - repo: https://github.com/metawave/k8s-yaml-fmt rev: v0.1.0 hooks: - id: k8s-yaml-fmt Jeder Commit hält deine Manifeste sauber – automatisch.\nmetawave/k8s-yaml-fmt A Kubernetes YAML formatter that enforces idiomatic key ordering. Python 0 0 ","externalUrl":null,"permalink":"/de/work/k8s-yaml-fmt/","section":"Projekte","summary":"Schluss mit chaotischen Kubernetes-Manifesten – idiomatische Feldreihenfolge auf Knopfdruck","title":"k8s-yaml-fmt","type":"work"},{"content":"Mit\nfind \u0026lt;path to search\u0026gt; -type d -empty findest du alle leeren Verzeichnisse.\nUnd mit\nfind \u0026lt;path to search\u0026gt; -type d -empty -delete löschst du sie alle.\n","externalUrl":null,"permalink":"/de/braindump/unix/find-empty-directories/","section":"Braindump","summary":"","title":"Leere Verzeichnisse finden","type":"braindump"},{"content":"Ein Proxy ist immer eine Qual, aber in Firmennetzen begegnet er dir ständig. Weil jede Anwendung und jeder Desktop Proxies anders verwaltet, wird es schnell nervig. In den nächsten Abschnitten zeige ich alle Orte für Proxy-Einstellungen, die ich bisher gefunden habe \u0026#x1f604;\nUmgebungsvariablen # Wenn du der einzige Nutzer der Maschine bist oder die Einstellungen systemweit setzen willst, gehören diese Variablen in deine /etc/environment:\nhttp_proxy=http://myproxy.server.com:8080/ https_proxy=http://myproxy.server.com:8080/ ftp_proxy=http://myproxy.server.com:8080/ no_proxy=\u0026#34;localhost,127.0.0.1,localaddress,.localdomain.com\u0026#34; HTTP_PROXY=http://myproxy.server.com:8080/ HTTPS_PROXY=http://myproxy.server.com:8080/ FTP_PROXY=http://myproxy.server.com:8080/ NO_PROXY=\u0026#34;localhost,127.0.0.1,localaddress,.localdomain.com\u0026#34; Warum in Klein- und Grossbuchstaben? Manche Anwendungen nutzen Kleinbuchstaben, andere Grossbuchstaben – und funktionieren nicht, wenn die Variablen nicht wie erwartet definiert sind.\nWillst du die Einstellungen nicht für alle Nutzer, trägst du die Variablen besser in .bashrc, .profile oder .zshrc im Home-Verzeichnis deines Users ein.\nDamit die Variablen auch in sudo-Sessions erhalten bleiben, ergänzen wir folgende Zeilen in /etc/sudoers:\n# Keep Proxy Params in sudo session Defaults env_keep+=\u0026#34;http_proxy\u0026#34; Defaults env_keep+=\u0026#34;HTTP_PROXY\u0026#34; Defaults env_keep+=\u0026#34;https_proxy\u0026#34; Defaults env_keep+=\u0026#34;HTTPS_PROXY\u0026#34; Defaults env_keep+=\u0026#34;ftp_proxy\u0026#34; Defaults env_keep+=\u0026#34;FTP_PROXY\u0026#34; Defaults env_keep+=\u0026#34;no_proxy\u0026#34; Defaults env_keep+=\u0026#34;NO_PROXY\u0026#34; sonst sind die Variablen in sudo-Sessions nicht gesetzt und du bekommst \u0026ldquo;Connection refused\u0026rdquo;-Fehler.\nAPT # Auf Debian/Ubuntu-basierten Distributionen nutzten ältere apt-Versionen einen anderen Weg für Proxy-Einstellungen. Selbst Variablen in /etc/environment werden von älteren apt-get-Versionen nicht verwendet.\nUm ältere apt-Versionen mit Proxy zu nutzen, lege eine neue Datei /etc/apt/apt.conf.d/95proxies an:\nAcquire::http::proxy \u0026#34;http://myproxy.server.com:8080/\u0026#34;; Acquire::https::proxy \u0026#34;https://myproxy.server.com:8080/\u0026#34;; Acquire::ftp::proxy \u0026#34;ftp://myproxy.server.com:8080/\u0026#34;; GTK3-Programme # GTK-3-Programme wie Rhythmbox nutzen eigene Einstellungen, die du so setzt:\ngsettings set org.gnome.system.proxy mode \u0026#39;manual\u0026#39; gsettings set org.gnome.system.proxy.http host \u0026#39;myproxy.server.com\u0026#39; gsettings set org.gnome.system.proxy.http port 8080 Docker # Auf einem Linux-System mit systemd kannst du die systemd-Definition von Docker bearbeiten und die Variablen zum Service hinzufügen:\nsudo systemctl edit docker nun ergänzen:\n[Service] Environment=\u0026#34;HTTP_PROXY=http://myproxy.server.com:8080/\u0026#34; Environment=\u0026#34;HTTPS_PROXY=http://myproxy.server.com:8080/\u0026#34; und je nach gesetztem EDITOR ein :wq oder Ctrl+O, Ctrl+X, dann den Service neu starten:\nsudo systemctl restart docker Update 2. Feb. 2019: Docker hat eine eigene Seite zum Setzen von Proxies: Docker Daemon - HTTP Proxy\n","externalUrl":null,"permalink":"/de/braindump/unix/use-linux-behind-a-proxy/","section":"Braindump","summary":"","title":"Linux hinter einem HTTP-Proxy nutzen","type":"braindump"},{"content":"Manchmal willst du, dass macOS in den Ruhezustand geht – und es tut es nicht. Um herauszufinden, was den Schlaf verhindert, hilft dieser Befehl:\nsudo pmset -g assertions das liefert etwa so etwas:\n2015-11-17 08:04:25 +0100 Assertion status system-wide: BackgroundTask 0 ApplePushServiceTask 0 UserIsActive 0 PreventUserIdleDisplaySleep 0 PreventSystemSleep 0 ExternalMedia 1 PreventUserIdleSystemSleep 1 NetworkClientActive 1 Listed by owning process: pid 58(powerd): [0x000000040008012c] 10:43:06 ExternalMedia named: \u0026#34;com.apple.powermanagement.externalmediamounted\u0026#34; pid 92548(AddressBookSourceSync): [0x000096a700010b0f] 00:00:06 PreventUserIdleSystemSleep named: \u0026#34;Address Book Source Sync\u0026#34; Timeout will fire in 1793 secs Action=TimeoutActionTurnOff pid 92546(cupsd): [0x000096a800110b11] 00:00:05 NetworkClientActive named: \u0026#34;org.cups.cupsd\u0026#34; Kernel Assertions: 0x4=USB id=500 level=255 0x4=USB mod=01.01.70, 01:00 description=com.apple.usb.externaldevice.fd140000 owner=USB Receiver id=501 level=255 0x4=USB mod=01.01.70, 01:00 description=com.apple.usb.externaldevice.fa140000 owner=My Passport 0820 Idle sleep preventers: IODisplayWrangler Im ersten Abschnitt siehst du, welche Arten von Anwendungen den verdienten Schlaf verhindern. Im zweiten Teil siehst du, welche Anwendungen das konkret tun. Führe den Befehl ruhig mehrmals aus – einige Anwendungen verschwinden, weil sie fertig sind; in meinem Fall ist die Adressbuch-Synchronisation bald durch. Interessanter finde ich den cupsd-Prozess. Warum verhindert der macOS-/Linux-Druckdienst den Schlaf meines Macs? Ein Blick auf die Druckwarteschlange zeigt: Ein Druckauftrag wurde nicht fertig, weil dem Drucker das Papier ausging. Nachdem ich den Job beendet hatte, verschwand die cupsd-Assertion und der Mac schlief ein wie ein Baby \u0026#x1f604;.\n","externalUrl":null,"permalink":"/de/braindump/macos/what-prevents-macos-from-sleep/","section":"Braindump","summary":"","title":"macOS geht nicht in den Ruhezustand","type":"braindump"},{"content":" Kennst du das? Du willst ein Fest auf die Beine stellen – und schon versinkst du in Terminumfragen, endlosen Chat-Nachrichten und einer Liste, in der trotzdem niemand einträgt, wer den Salat mitbringt. Mit meinfest ist damit Schluss. Kostenlos Kein Login Kein Account Du erstellst dein Event in einer Minute, schlägst ein paar mögliche Termine vor und teilst einen Link – mehr braucht es nicht. Deine Gäste tragen sich mit wenigen Klicks ein, stimmen über den Termin ab und wählen aus, was sie mitbringen. Alle sehen jederzeit denselben Stand: wer kann wann, was ist schon reserviert und was fehlt noch.\nDen passenden Termin finden – ganz ohne endloses Nachfragen Mitbringsel abstimmen, damit niemand mit dem dritten Kartoffelsalat auftaucht Sofort loslegen, ganz ohne Login und Account Ein Link für deine Gäste, ein eigener zum Verwalten für dich In Sekunden geteilt – über Messenger oder Copy-Link Kalendereintrag für den bestätigten Termin, damit ihn keiner vergisst meinfest ausprobieren ","externalUrl":null,"permalink":"/de/work/meinfest/","section":"Projekte","summary":"Kostenlos, ohne Login, in Sekunden geteilt: Mit meinfest planst du dein privates Fest ganz entspannt.","title":"meinfest","type":"work"},{"content":" MPlayer verwenden und anpassen # MPlayer startest du als Kommandozeilen-Programm mit mplayer, die GUI mit gmplayer. Die GUI ist weitgehend selbsterklärend, die Kommandozeilen-Optionen brauchen dagegen etwas Erklärung.\nDatei öffnen: mplayer filename Datei mit Untertiteln öffnen (z. B. bei DivX): mplayer filename -subfile filename.sub VCD-Track öffnen: mplayer -vcd \u0026lt;trackno\u0026gt; DVD in praktisch jeder Umgebung abspielen (Vesa-Modus): mplayer -o vesa -cache 8192 -fs -dvd \u0026lt;trackno\u0026gt; Wenn die Hardware nicht schnell genug ist und der Film ruckelt: mplayer -framedrop Verfügbare Codecs auflisten: mplayer -vc help Die zentrale Konfigurationsdatei ist ~/.mplayer/config. Sie enthält Kommentare zu jeder Funktion. Die Defaults passen meist, ein paar Dinge lassen sich aber anpassen. Tastenbelegungen liegen in ~/.mplayer/input.conf und lassen sich ausgiebig ändern – aber erst ein Backup, dann spielen. Die Syntax ist simpel und selbsterklärend.\nMPlayer hat zudem einige Spezial-Optionen für Mediendateien, die sich seltsam verhalten. Angenommen, du hast einen DivX auf Japanisch, aber die Untertitel-Spur läuft nicht synchron zum Bild: eine hat 25 fps, die andere 23, der Film folgt also den Untertiteln. Dieser Befehl löst das:\nmplayer \u0026lt;filename\u0026gt; -subfile \u0026lt;filenmame.sub\u0026gt; -subfps 25 Schlimmer wird es, wenn der Film schlecht kodiert ist und der Ton das Bild nie einholt. Dieser lästige Fall könnte dir den Sonntagnachmittag ruinieren – gäbe es MPlayer nicht. Verzögere das Bild einfach ein wenig:\nmplayer \u0026lt;filename\u0026gt; -delay \u0026lt;secs\u0026gt; Beide Verzögerungen dürfen auch negativ sein.\nAngenommen, eine Datei ist mit Codec X kodiert, MPlayer will sie aber mit Codec Y abspielen. Du kannst einen bestimmten Codec erzwingen:\nmplayer \u0026lt;filename\u0026gt; -vc \u0026lt;codec\u0026gt; Angenommen, du hast gerade angefangen, eine Konferenz-Aufzeichnung herunterzuladen, und willst die Qualität kennen, bevor du dich auf 700 MB einlässt – oder du hast schlicht einen kaputten DivX. Dieser Befehl baut den DivX-Index neu auf, sodass du in der defekten AVI vor- und zurückspringen kannst:\nmplayer \u0026lt;filename\u0026gt; -idx Zeigt die AVI immer noch nichts an, probiere diese Optionen in verschiedenen Kombinationen:\n-nobps -ni -mc0 -forceidx -nocache\nMEncoder # Ein anständiger Media-Player gehört zu einem guten Desktop. Manchmal willst du aber mehr. Vielleicht hast du die schwer erhältliche Robotech-Serie ins .rm-Format gesichert, willst sie jetzt aber auf dem VCD-Player schauen. Auch dafür hat MPlayer eine Lösung: Es kann fast alle Mediendateien crosscoden. Wenn du das MPlayer-Paket kompiliert hast, ist MEncoder bereits dabei.\nDie Syntax ist sehr einfach. Diese Befehlszeile kodiert die Datei basket.rm mit dem libav-Codec (dem besten DivX-Codec für Performance und Qualität) und die Tonspur mit mp3lame.\nmencoder -ovc lavc basket.rm -oac mp3lame -o basket.avi Erinnerst du dich an die AVI mit dem kaputten Index? Statt jedes Mal den Workaround zu nutzen, kannst du sie mit MEncoder dauerhaft reparieren. Der folgende Befehl baut den Index neu auf und kopiert den gesamten Audio- und Video-Stream unverändert in die Ausgabedatei.\nmencoder -idx input.avi -ovc copy -oac copy -o output.avi Vielleicht willst du mehrere AVI-Dateien zu einer einzigen zusammenfügen. Solange sie denselben Codec und dieselbe Bitrate haben, ist auch das einfach. Zurück zu den Unix-Wurzeln:\ncat 1.avi 2.avi | mencoder -noidx -ovc copy -oac copy -o output.avi - Ich gehe hier nicht weiter ins Detail, denn MPlayer und MEncoder haben mehr Optionen, als ich in einem Artikel beschreiben kann. Viel Spass mit diesen mächtigen Programmen – und experimentiere mit den Einstellungen.\n","externalUrl":null,"permalink":"/de/braindump/unix/mplayer-in-terminal/","section":"Braindump","summary":"","title":"MPlayer im Terminal nutzen","type":"braindump"},{"content":"Wenn es dir geht wie mir – zu Hause Mac, bei der Arbeit Windows – hast du dich wahrscheinlich schon gefragt: \u0026ldquo;Wo kann ich Natural Scrolling aktivieren?\u0026rdquo;. Es gibt keine Einstellung, um das Mausrad wie am Mac auf \u0026ldquo;Natural Scrolling\u0026rdquo; umzustellen.\nBeim Googeln findest du einen Registry-Key (FlipFlopWheel), der dieses Verhalten ändert. Aber wenn du wie ich die Mäuse wechselst – eine bei der Arbeit, eine zu Hause und noch eine woanders – musst du die Einstellung für jede Maus und jeden USB-Port ändern, was mühsam ist.\nUm \u0026ldquo;Natural Scrolling\u0026rdquo; für alle Mäuse zu aktivieren, lässt du PowerShell die Arbeit machen.\nStarte PowerShell als Administrator und führe den Befehl aus:\nGet-ItemProperty HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\HID\\*\\*\\Device` Parameters FlipFlopWheel -EA 0 | ForEach-Object { Set-ItemProperty $_.PSPath FlipFlopWheel 1 } Damit die Änderung wirkt, verbinde die Maus neu. Bei USB- oder Logitech-Unifying-Geräten das USB-Kabel bzw. den Receiver aus- und wieder einstecken. Ein Neustart tut es auch.\nQuelle: https://www.michaelcrump.net/invert-mouse-bootcamp-win10/\n","externalUrl":null,"permalink":"/de/braindump/windows/powershell-natural-scrolling/","section":"Braindump","summary":"","title":"Natural Scrolling in Windows 10","type":"braindump"},{"content":"Update 13. Februar 2019: Das funktioniert nur bis OSX Yosemite (10.10). Ab Yosemite wurde ipfw durch pf ersetzt.\nIn OSX lässt sich die Netzwerk-Bandbreite mit ipfw-Regeln begrenzen. Das gilt allerdings für die ganze Maschine, nicht nur für einzelne Anwendungen.\nUm die Bandbreite für alle Ziele zu begrenzen:\nsudo ipfw pipe 1 config bw [Speed] sudo ipfw add pipe 1 dst-ip 0.0.0.0/0 zum Beispiel:\nsudo ipfw pipe 1 config bw 300kbit/s sudo ipfw add pipe 1 dst-ip 0.0.0.0/0 Wenn du nicht alle Verbindungen begrenzen willst, sondern nur bestimmte IP-Adressen oder Ports:\nsudo ipfw add pipe 1 dst-ip 192.168.1.0/24 sudo ipfw add pipe 1 dst-port http sudo ipfw add pipe 1 dst-port https sudo ipfw add pipe 1 dst-port pop3 sudo ipfw add pipe 1 dst-port pop3s sudo ipfw add pipe 1 dst-port imap sudo ipfw add pipe 1 dst-port imaps Alle Regeln entfernst du einfach mit sudo ipfw flush. Ein Neustart entfernt sie ebenfalls.\nMehr Infos liefert die man-Page zu ipfw. Wer nicht gern Befehle tippt, kann sich auch WaterRoof ansehen.\n","externalUrl":null,"permalink":"/de/braindump/macos/limit-network-bandwidth/","section":"Braindump","summary":"","title":"Netzwerk-Bandbreite begrenzen","type":"braindump"},{"content":" Versteckte Datei oder reservierter Name # Es kann vorkommen, dass du Dateien auf einem NTFS-Volume nicht löschen kannst, selbst als Mitglied der Administratoren-Gruppe.\nDas kann verschiedene Ursachen haben. Einige sind unter http://support.microsoft.com/kb/320081/en-us beschrieben.\nCause 5: The file name includes a reserved name in the Win32 name space\nDiese Ursache hatte ich schon mehrfach, sie lässt sich aber beheben mit\ndel \\\\?\\C:\\path_to_file\\file.dat um genau diese Datei trotzdem zu löschen.\nDer Dateiname oder die Erweiterung ist zu lang. # Das passiert bei sehr tiefen Ordnerstrukturen, danach lassen sich Dateien oder Ordner nicht mehr löschen. Beheben lässt sich das mit einem kleinen Trick, den ich gelernt habe. Ziel ist es, die Pfadlänge so weit zu reduzieren, dass Windows sie wieder handhaben kann. Der passende Befehl ist subst.\nC:\\\u0026gt;subst /? Associates a path with a drive letter. SUBST [drive1: [drive2:]path] SUBST drive1: /D drive1: Specifies a virtual drive to which you want to assign a path. [drive2:]path Specifies a physical drive and path you want to assign to a virtual drive. /D Deletes a substituted (virtual) drive. Type SUBST with no parameters to display a list of current virtual drives. Ein Beispiel:\nC:\\\u0026gt;subst G: C:\\Documents and Settings\\user\\Desktop\\One Folder\\A Subfolder\\A Subsubfolder\\ Jetzt ist der Inhalt von \u0026ldquo;C:\\Documents and Settings\\user\\Desktop\\One Folder\\A Subfolder\\A Subsubfolder\u0026quot; als Laufwerk G: erreichbar, was die Pfadlänge reduziert – und das Löschen einer Datei ist kein Problem mehr.\nOrdner löschen, für die ich keine Berechtigung habe (Vista/Windows 7) # Starte eine Administrator-Konsole (cmd.exe mit Administratorrechten) und wechsle in den betreffenden Ordner. Führe den folgenden Befehl aus, um die Berechtigungen zu ändern und deinem Benutzer Zugriff zu geben.\nC:\\\u0026gt;icacls \u0026#34;\u0026lt;path to folder or file\u0026gt;\u0026#34; /grant \u0026lt;username\u0026gt;:(D,WDAC) /t Der Befehl gibt dem Benutzer \u0026lt;username\u0026gt; Schreib- und Löschrechte für diese Datei/diesen Ordner und alle Unterordner und Dateien.\nEin Beispiel:\nC:\\\u0026gt;icacls \u0026#34;C:\\FolderIwantAccessTo\u0026#34; /grant metawave:(D,WDAC) /t ","externalUrl":null,"permalink":"/de/braindump/windows/delete-undeletable-files/","section":"Braindump","summary":"","title":"Nicht löschbare Dateien löschen","type":"braindump"},{"content":"Das war eine ziemlich seltsame Anfrage. Eine Tabelle hatte Auto-Increment-IDs – bei MySQL ganz üblich.\nDie Anfrage war dann aber, den Inhalt nach Datum neu zu sortieren und diese Reihenfolge in der ID-Spalte abzubilden.\nVorher:\nID Date 1 2017-01-04 2 2018-02-06 3 2016-12-24 Nachher:\nID Date 1 2016-12-24 2 2017-01-04 3 2018-02-06 Tabelle für die Reihenfolge vorbereiten # Füge der bestehenden Tabelle eine neue Spalte hinzu, die die sortierte Position aufnimmt.\nalter table mytable add column orderid int Neue ID generieren # Jetzt sortieren wir den Inhalt der Tabelle und speichern die Position im sortierten Ergebnis in der neuen Spalte. Im Beispiel sortieren wir nach Datum.\nSET @rownum=0; UPDATE mytable AS i, (SELECT @rownum:=@rownum+1 rownum, id FROM mytable order by mytable.date asc) AS r SET i.orderid = r.rownum WHERE i.id = r.id; Alte ID durch die neue ersetzen # Nun bereiten wir die ID-Spalte auf die neue ID vor, indem wir die ID über den letzten Eintrag hinaus verschieben. Das ist nötig, weil MySQL zeilenweise aktualisiert und beim Überschreiben der ID mit der neuen orderID sonst ID-Kollisionen entstünden.\nUPDATE mytable SET id = id+(select max(id) from mytable); jetzt können wir die ID überschreiben mit\nUPDATE mytable SET id = orderid; nun bildet die ID die Reihenfolge nach Datum ab.\nAufräumen # Da wir die ID erfolgreich aktualisiert haben, können wir unsere Hilfsspalte orderid löschen\nALTER TABLE mytable DROP COLUMN orderid; Mein Rat # Meiner Meinung nach ist das nicht wirklich, wie man eine Datenbank nutzen sollte – das klingt eher nach einer Anfrage von jemandem, der Excel gewohnt ist.\n","externalUrl":null,"permalink":"/de/braindump/db/mysql/replace-id-with-another-order/","section":"Braindump","summary":"","title":"Numerische Auto-Increment-ID durch eine andere Reihenfolge ersetzen","type":"braindump"},{"content":" Das Problem # Beim Start von Parallels 5 erscheint eine Fehlermeldung wie: \u0026ldquo;Service prl_disp_service could not be started or connected to\u0026rdquo;. Den genauen Wortlaut weiss ich nicht mehr. Das passiert bei jedem Start von Parallels, und selbst ein Neustart hilft nicht.\nAnalyse # Im \u0026ldquo;Activity Monitor\u0026rdquo; ist der Prozess nicht zu finden. Manche Anwendungen nutzen ein StartupItem oder eine launchd-Konfiguration, um einen Service-Prozess zu starten – Parallels gehört dazu.\nIn diesem Fall sollte launchd bei jedem Boot des Macs diesen Befehl ausführen:\n/Library/Parallels/Parallels Service.app/Contents/Resources/ParallelsDispatcherService start Das ist ein Shell-Script, das wir debuggen können. Wie man Shell-Scripts debuggt, steht unter Bash-Script debuggen.\nAlso starten wir das Shell-Script im Debug-Modus bash -x:\nsudo bash -x /Library/Parallels/Parallels\\ Service.app/Contents/Resources/ParallelsDispatcherService start und schauen uns die Debug-Ausgabe genau an:\n+ RunService start + case $1 in + StartService + \u0026#39;[\u0026#39; $\u0026#39;-YES-\\r\u0026#39; \u0026#39;!=\u0026#39; -YES- \u0026#39;]\u0026#39; + return diese Ausgabe entsteht in diesen Zeilen:\n# The start subroutine StartService () { # Check if service is enabled [ \u0026#34;${PARALLELS:=-YES-}\u0026#34; != \u0026#34;-YES-\u0026#34; ] \u0026amp;\u0026amp; return das heisst: Sobald die Property PARALLELS in /etc/hostconfig nicht auf\nPARALLELS=-YES- gesetzt ist, soll der Service nicht starten.\nIn der Ausgabe oben wirkt der Vergleich mit -YES- aber etwas seltsam. Warum steht dieses \\r (Carriage-Return) direkt nach -YES-? Das scheint das Problem zu sein – der Vergleich schlägt jedes Mal fehl.\nParallels hat die /etc/hostconfig irgendwie beschädigt und DOS-Zeilenenden (\\r\\n) statt UNIX-Zeilenenden (\\n) eingeführt.\nSogar\nfile /etc/hostconfig sagt dir\n/etc/hostconfig: ASCII text, with CRLF line terminators Lösung # Das lässt sich beheben, indem man die \\r aus /etc/hostconfig entfernt:\nsudo sed -i \u0026#39;s/\\r//g\u0026#39; /etc/hostconfig Nach einem Neustart oder\nsudo launchctl start com.parallels.desktop.launchdaemon sollte Parallels wie erwartet laufen.\nEine Kopie dieses Artikels habe ich auch im Parallels-Forum veröffentlicht: http://forum.parallels.com/showthread.php?t=99054\n","externalUrl":null,"permalink":"/de/braindump/macos/parallels-prl-disp-service-wont-start/","section":"Braindump","summary":"","title":"Parallels – prl_disp_service startet nicht","type":"braindump"},{"content":"Vor dem Upgraden oder Verändern von Datenbanken empfiehlt es sich, zuerst ein Backup anzulegen. Der Befehl pg_dumpall schreibt alles in eine einzige Plain-Datei. Das ist etwas old-school, seit es das flexiblere Custom-Format für Backups gibt.\nMein Ziel ist eine Custom-Format-Datei pro Datenbank.\npsql -AtU postgres -c \u0026#34;SELECT datname FROM pg_database WHERE NOT datistemplate\u0026#34;| \\ while read f; do pg_dump -Upostgres --format=c --file=$f.sqlc $f; done; Das erzeugt einen Custom-Format-Dump pro Datenbank. Damit kannst du jede Datenbank einzeln wiederherstellen.\npg_restore -d postgres --clean --create db.sqlc --clean löscht eine bestehende Datenbank gleichen Namens und --create legt dieselbe Datenbank wie im Backup an.\nWenn du alles auf einmal wiederherstellen willst, ist pg_dumpall vielleicht besser für dich geeignet.\n","externalUrl":null,"permalink":"/de/braindump/db/postgresql/backup-databases/","section":"Braindump","summary":"","title":"PostgreSQL-Datenbanken sichern","type":"braindump"},{"content":"Manchmal steht man vor dem Problem, dass Dateien das falsche Encoding haben. Wenn auf deiner Maschine PowerShell installiert ist – was oft der Fall ist – geht das ganz einfach.\nBeispiel: Du willst das Encoding jeder .java-Datei im aktuellen Verzeichnis und allen Unterverzeichnissen von utf-8 nach iso-8859-1 ändern:\nGet-ChildItem . -include *.java -recurse | ForEach-Object { $inputEncoding = [System.Text.Encoding]::GetEncoding(\u0026#34;utf-8\u0026#34;) $outputEncoding = [System.Text.Encoding]::GetEncoding(\u0026#34;iso-8859-1\u0026#34;) $content = [System.IO.File]::ReadAllText($_.Fullname, $inputEncoding) [System.IO.File]::WriteAllText($_.Fullname, $content, $outputEncoding) } In der Variable $inputEncoding setzen wir das Encoding aller Quelldateien. Mit $outputEncoding setzt du das Ziel-Encoding, in das konvertiert werden soll. Gültige Encoding-Namen findest du in dieser Tabelle: http://msdn.microsoft.com/en-us/library/86hf4sb8.aspx.\nGet-ChildItem ähnelt dem find-Befehl unter Unix. Mit Get-Help Get-ChildItem siehst du weitere Infos, wie du Dateien gezielter findest.\n","externalUrl":null,"permalink":"/de/braindump/windows/powershell-change-encoding/","section":"Braindump","summary":"","title":"PowerShell – Datei-Encoding (rekursiv) ändern","type":"braindump"},{"content":"Kleinere Projekte, die nebenbei entstanden sind – meist aus einem „das muss doch einfacher gehen\u0026quot;.\n","externalUrl":null,"permalink":"/de/work/","section":"Projekte","summary":"","title":"Projekte","type":"work"},{"content":" Kennst du das? Du brauchst schnell ein Passwort, öffnest die Proton-Pass-App, suchst, kopierst, wechselst zurück – jedes Mal ein paar Sekunden zu viel. Dieser Alfred-Workflow holt deine Proton Pass Vaults direkt in die Alfred-Suche. Tippen, Eintrag finden, kopieren – ohne die Hände von der Tastatur zu nehmen. Im Hintergrund arbeitet das offizielle pass-cli.\nAlle Vaults auf einmal durchsuchen Passwort, Benutzername oder TOTP-Code mit einem Tastendruck kopieren URLs direkt aus den Suchresultaten öffnen Zwischenablage leert sich nach 30 Sekunden von selbst Secrets werden nie zwischengespeichert – niemals. Das offizielle pass-cli holt sie bei Bedarf, nichts landet je auf der Platte. metawave/proton-pass-alfred Alfred workflow for searching and copying credentials from Proton Pass vaults Python 2 1 Workflow herunterladen ","externalUrl":null,"permalink":"/de/work/proton-pass-alfred/","section":"Projekte","summary":"Deine Proton-Pass-Zugangsdaten direkt aus Alfred – suchen, kopieren, weiter geht’s","title":"Proton Pass for Alfred","type":"work"},{"content":" Was du kennen solltest # Dieser Abschnitt sammelt Befehle, die du beim Arbeiten mit PostgreSQLs psql kennen solltest!\nAn fast jeden Befehl kannst du ein S anhängen, um auch System-Objekte anzuzeigen, und ein +, um mehr Informationen zu sehen!\nDatenbank # \\l Alle Datenbanken auflisten \\c databasename Mit der Datenbank databasename verbinden Tabellen/Relationen/Views # \\d Alle Tabellen, Views und Sequences auflisten \\d tablename Definition der Tabelle tablename anzeigen \\dt Nur Tabellen auflisten \\dv Nur Views auflisten \\ds Nur Sequences auflisten \\dp Berechtigungen für Tabellen, Views und Sequences auflisten Benutzer # \\du Alle Benutzer auflisten Aufgaben im Alltag # Ein paar Queries für alltägliche Aufgaben an einem PostgreSQL-Server.\nNeuen Benutzer mit Passwort anlegen # create user myuser with password \u0026#39;very-secure-password\u0026#39;; Datenbank für einen Benutzer anlegen (der zugleich Owner ist) # create database newdatabase with owner myuser; Statistiken wie Tabellengrössen, Zeilenanzahl und Index-Grösse anzeigen # SELECT t.tablename, foo.indexname, c.reltuples AS num_rows, pg_size_pretty(pg_relation_size(quote_ident(t.tablename::text)::regclass)) AS table_size, pg_size_pretty(pg_total_relation_size(s.relid::regclass)) AS table_total_size, pg_size_pretty(pg_total_relation_size(s.relid::regclass) - pg_relation_size(s.relid::regclass)) AS table_external_size, pg_size_pretty(pg_relation_size(quote_ident(foo.indexrelname::text)::regclass)) AS index_size, CASE WHEN foo.indisunique THEN \u0026#39;Y\u0026#39;::text ELSE \u0026#39;N\u0026#39;::text END AS \u0026#34;index_unique\u0026#34;, foo.idx_scan AS number_of_scans, foo.idx_tup_read AS tuples_read, foo.idx_tup_fetch AS tuples_fetched FROM pg_tables t LEFT JOIN pg_class c ON t.tablename = c.relname LEFT JOIN pg_statio_user_tables s ON s.relname = t.tablename LEFT JOIN ( SELECT c_1.relname AS ctablename, ipg.relname AS indexname, x.indnatts AS number_of_columns, psai.idx_scan, psai.idx_tup_read, psai.idx_tup_fetch, psai.indexrelname, x.indisunique FROM pg_index x JOIN pg_class c_1 ON c_1.oid = x.indrelid JOIN pg_class ipg ON ipg.oid = x.indexrelid JOIN pg_stat_all_indexes psai ON x.indexrelid = psai.indexrelid) foo ON t.tablename = foo.ctablename WHERE t.schemaname = \u0026#39;public\u0026#39;::name ORDER BY t.tablename, foo.indexname Owner für Tabellen/Funktionen/Sequences ändern # Mit diesen Statements generierst du nur das SQL, um den Owner dieser Objekte zu ändern. Das generierte SQL musst du danach selbst ausführen. In den Beispielen wird das public-Schema verwendet, passe es nach Bedarf an.\nTabellen\nselect \u0026#39;ALTER TABLE \u0026#39;|| tablename ||\u0026#39; OWNER TO {newOwner};\u0026#39; FROM pg_tables WHERE schemaname = \u0026#39;public\u0026#39;; Funktionen\nSELECT \u0026#39;ALTER FUNCTION \u0026#39; || quote_ident(n.nspname) || \u0026#39;.\u0026#39; || quote_ident(p.proname) || \u0026#39;(\u0026#39; || pg_catalog.pg_get_function_identity_arguments(p.oid) || \u0026#39;) OWNER TO {newOwner};\u0026#39; , E\u0026#39;\\n\u0026#39; AS _sql FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname = \u0026#39;public\u0026#39;; Sequences\nSELECT \u0026#39;ALTER SEQUENCE \u0026#39; || quote_ident(n.nspname) || \u0026#39;.\u0026#39; || quote_ident(c.relname) || \u0026#39; OWNER TO {newOwner};\u0026#39; FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = \u0026#39;public\u0026#39; AND c.relkind = \u0026#39;S\u0026#39;; ","externalUrl":null,"permalink":"/de/braindump/db/postgresql/useful-commands-queries/","section":"Braindump","summary":"","title":"psql: Ein paar nützliche Befehle und Queries","type":"braindump"},{"content":".DS_Store-Dateien sind versteckte Dateien, die macOS in Ordnern anlegt, um eigene Attribute des Ordnerinhalts zu speichern – etwa Icon-Positionen, Ansichtsoptionen und Metadaten zur Darstellung. Sie sind für den Gebrauch an einer einzelnen Workstation gedacht, können aber freigegebene Verzeichnisse zumüllen und beim Verschieben oder Löschen von Dateien Berechtigungsfehler verursachen. Um das Anlegen von .DS_Store-Dateien auf Netzlaufwerken zu verhindern, folge diesen einfachen Schritten:\nTerminal öffnen: Öffne zunächst die Terminal-App auf deinem Mac. Du findest sie im Ordner Programme unter Dienstprogramme, oder per Spotlight mit Command + Space und der Eingabe \u0026ldquo;Terminal\u0026rdquo;.\nBefehl eingeben: Tippe im Terminal-Fenster folgenden Befehl ein und drücke Enter:\ndefaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE Abmelden oder neu starten: Nach der Eingabe musst du dich entweder von deinem macOS-Benutzerkonto abmelden und wieder anmelden oder die Workstation neu starten. Erst dann greift die Änderung.\nEinstellung prüfen: Um zu bestätigen, dass .DS_Store-Dateien auf Netzlaufwerken deaktiviert sind, kannst du die aktuelle Einstellung mit folgendem Befehl prüfen:\ndefaults read com.apple.desktopservices Wenn die .DS_Store-Dateien für Netzlaufwerke erfolgreich deaktiviert sind, sollte im Terminal \u0026ldquo;DSDontWriteNetworkStores = 1\u0026rdquo; erscheinen.\nEinstellung entfernen (optional): Willst du irgendwann zum Standardverhalten zurück und .DS_Store-Dateien auf Netzlaufwerken wieder zulassen, entfernst du die Einstellung mit:\ndefaults delete com.apple.desktopservices DSDontWriteNetworkStores Mit diesen Schritten unterbindest du das Anlegen von .DS_Store-Dateien auf Netzlaufwerken zuverlässig. Diese kleine Anpassung verbessert die Performance beim Durchsuchen von Verzeichnissen und verhindert unnötigen Ballast und Fehler in geteilten Speicherumgebungen wie einem NAS.\n","externalUrl":null,"permalink":"/de/braindump/macos/disable-ds-store-on-network-drives/","section":"Braindump","summary":"","title":"So verhinderst du .DS_Store-Dateien auf Netzlaufwerken unter macOS","type":"braindump"},{"content":"Oft ist es sehr praktisch, per Tunnel auf Services zu Hause oder auf einem Server zuzugreifen.\nBeispiel: Du betreibst auf einem Server, den du per SSH verwaltest, eine MySQL-Instanz. Sie ist nicht ins Internet exponiert und lauscht nur auf localhost. Jetzt willst du mit deinem SQL-Lieblingstool auf die Datenbank zugreifen.\nKlar, das ginge per VPN – aber die sind nicht leicht korrekt einzurichten. Da du den Server ohnehin über SSH verwaltest, hast du bereits ein einfaches Werkzeug zur Hand: einen Port-Tunnel durch SSH. Das ähnelt dem Port-Forwarding, das du vielleicht vom Heim-Router kennst. Ziel ist ein Port auf deiner Maschine, der auf einen Port einer entfernten Maschine weitergeleitet wird.\nDas geht so:\n$ ssh -f user@mydomain.com -L \u0026lt;port\u0026gt;:\u0026lt;remote host\u0026gt;:\u0026lt;remote port\u0026gt; -N Parameter: -f Führt den Befehl im Hintergrund aus, blockiert deine Terminal-Session also nicht. Achtung: Der Tunnel bleibt offen, solange du das Netzwerk nicht trennst oder den SSH-Prozess killst. Ohne diesen Parameter schliesst du die Verbindung mit \u0026lt;Ctrl\u0026gt;+C und beendest damit den SSH-Tunnel. user@mydomain.com Benutzername und Host deines SSH-Servers. -L Erzeugt den Tunnel statt einer normalen SSH-Session. \u0026lt;port\u0026gt; Lokaler Port auf deiner Maschine, der aufs entfernte System weitergeleitet wird. \u0026lt;remote host\u0026gt; Host des Services, mit dem du dich verbinden willst; kann der SSH-Host sein, meist aber der Host der MySQL-Instanz. \u0026lt;remote port\u0026gt; Port auf dem entfernten Host, zu dem der Tunnel verbindet. Bei MySQL wäre das 3306. -N Wir wollen auf dem entfernten System nichts ausführen, nur einen Tunnel aufbauen. Für einen PostgreSQL-Server sähe das so aus:\n$ ssh -f marcel@metawave.ch -L 5432:localhost:5432 -N und bei einem MySQL-Server:\n$ ssh -f marcel@metawave.ch -L 3306:localhost:3306 -N Nach Eingabe des Passworts steht die Tunnel-Verbindung. Jetzt greifst du auf den entfernten Service zu, als liefe er auf deiner lokalen Maschine. In deinem SQL-Tool gibst du als Hostname localhost ein und verbindest dich wie auf dem entfernten System.\nNebenbei verbessert das die Server-Sicherheit: Statt zu viel nach aussen zu exponieren, verbindest du dich über einen sicheren SSH-Tunnel und greifst von dort auf deine Services zu.\n","externalUrl":null,"permalink":"/de/braindump/unix/ssh-port-tunnel/","section":"Braindump","summary":"","title":"SSH-Port-Tunnel für den Zugriff auf Services","type":"braindump"},{"content":"Sublime ist ein schneller, grossartiger Editor mit vielen nützlichen Features. Zu den besten gehören:\nColumn Mode # Column Mode / Selection ist eines meiner Lieblingsfeatures und macht das Editieren viel schneller und einfacher:\nmacOS: Option + linke Maustaste / mittlere Maustaste Windows/Linux: Shift + rechte Maustaste ","externalUrl":null,"permalink":"/de/braindump/software/sublime/","section":"Braindump","summary":"","title":"Sublime Text","type":"braindump"},{"content":"Es gibt Fälle, in denen du deine lokale Zeit nicht per NTP mit einem Zeitserver synchronisieren kannst – besonders hinter einem HTTP-Proxy.\nDafür gibt es eine einfache Lösung, um die lokale Zeit korrekt zu setzen. Sie ist natürlich nicht so genau wie NTP; wenn du eine exakte Zeit brauchst, führt an NTP kein Weg vorbei. Für die meisten Zwecke ist sie aber genau genug.\nsudo date -s \u0026#34;$(curl -sD - google.com | grep \u0026#39;^Date:\u0026#39; | cut -d\u0026#39; \u0026#39; -f3-6)Z\u0026#34; Das holt einen Timestamp von Google und setzt ihn als GMT-Zeit. Bei korrekten Zeitzonen-Einstellungen zeigt dein Betriebssystem danach die richtige lokale Zeit an.\n","externalUrl":null,"permalink":"/de/braindump/unix/sync-system-time-http/","section":"Braindump","summary":"","title":"Systemzeit über HTTP setzen","type":"braindump"},{"content":"Du kannst jede Tabelle (samt Daten) kopieren mit:\nSELECT * INTO [NewTableName] FROM [TableName] ein Beispiel:\nSELECT * INTO adress_backup FROM adress ","externalUrl":null,"permalink":"/de/braindump/db/mssql/copy-table/","section":"Braindump","summary":"","title":"Tabelle kopieren","type":"braindump"},{"content":"Tabellennamen zu präfixen halte ich für keine gute Idee. In manchen Altsystemen wurde das aber aus welchen Gründen auch immer ausgiebig gemacht.\nMS SQL Server kann nicht alles in einer Query umbenennen, aber wir können die Queries zum (Ent-)Präfixen generieren und danach ausführen.\nTabellen präfixen # SELECT \u0026#39;EXECUTE sp_rename \u0026#39;\u0026#39;\u0026#39; + schema_name(schema_id) + \u0026#39;.\u0026#39; + name + \u0026#39;\u0026#39;\u0026#39;,\u0026#39;\u0026#39;myprefix_\u0026#39; + name + \u0026#39;\u0026#39;\u0026#39;;\u0026#39; FROM sys.tables T WHERE type = \u0026#39;U\u0026#39; Ersetze myprefix_ durch das Gewünschte und führe alle/einige der angezeigten Queries aus, um alle Tabellen umzubenennen.\nPräfix von Tabellen entfernen # Zum Entfernen des Präfixes brauchen wir ein leicht abgewandeltes SQL-Script.\nSELECT \u0026#39;EXECUTE sp_rename \u0026#39;\u0026#39;\u0026#39; + schema_name(schema_id) + \u0026#39;.\u0026#39; + name + \u0026#39;\u0026#39;\u0026#39;,\u0026#39;\u0026#39;\u0026#39; + replace(name, \u0026#39;myprefix_\u0026#39;, \u0026#39;\u0026#39;) + \u0026#39;\u0026#39;\u0026#39;;\u0026#39; FROM sys.tables T WHERE type = \u0026#39;U\u0026#39; Führe alle/einige der angezeigten Queries aus, um das Präfix zu entfernen.\n","externalUrl":null,"permalink":"/de/braindump/db/mssql/de-prefix-tables/","section":"Braindump","summary":"","title":"Tabellen mit Präfix versehen oder Präfix entfernen","type":"braindump"},{"content":"Softwarearchitekt aus Bern. Mich interessiert Software, die verständlich bleibt: einfache Architektur, klare Verantwortlichkeiten und Technik, die dem Problem dient. Skalierung, Microservices und verteilte Systeme sind Werkzeuge, keine Ziele – ich setze sie ein, wenn Aufwand und Nutzen zusammenpassen, nicht weil sie im Konferenz-Talk gut klangen.\nAbseits vom Rechner: Velo, Gitarre und das gelegentliche Wochenendprojekt, das nie ganz fertig wird.\n","externalUrl":null,"permalink":"/de/about/","section":"Startseite","summary":"","title":"Über mich","type":"page"},{"content":"Ich nutze bei der Arbeit ein Apple Magic Keyboard an einer Linux-Maschine. Von Zeit zu Zeit bekomme ich beim Arbeiten seltsame Fehler. In IntelliJ passiert das sogar bei manchen Completions – dann wird ein Leerzeichen mit roter Wellenlinie unterstrichen.\nBeim Kompilieren kann diese Warnung auftauchen:\nError:(38, 31) java: illegal character: \u0026#39;\\u00a0\u0026#39; oder sogar Bash-Befehle werden nicht mehr erkannt:\n$ echo \u0026#34;test\u0026#34; zsh: command not found: echo test Mit bless ~/Documents/myfile.md wollte ich wissen, wie das so durcheinandergerät. Nach Auswahl des Leerzeichens in bless zeigte sich die Hex-Darstellung C2 A0. Nach etwas Recherche war klar: Das ist ein non-breaking space, der je nach Encoding der Datei als 00 A0 oder C2 A0 dargestellt wird.\nAber warum? Wie kam dieses geschützte Leerzeichen überhaupt herein?\nIch öffnete ein Terminal und führte sudo showkey -a aus, um alle Tastendrücke zu beobachten. Dann probierte ich diverse Kombinationen mit der Leertaste, bis diese Ausgabe kam:\n194 0302 0xc2 160 0240 0xa0 – beim Drücken von Shift+Space. Erwischt! Auf meinem Schweizerdeutschen Apple-Tastaturlayout entsteht der non-breaking space also mit Shift+Space. Ich kannte dieses Zeichen bislang nur von Option+Space auf dem Mac.\nDas ist ausgesprochen nervig für alle, die Shift drücken, weil nach dem nächsten Leerzeichen ein Grossbuchstabe kommen soll.\nDie Einstellung dafür ist nicht in den Standard-Gnome-Preferences enthalten. Um sie zu ändern, musst du gnome-tweaks installieren:\nsudo apt install gnome-tweaks Starte Gnome Tweaks und finde unter \u0026ldquo;Keyboard \u0026amp; Mouse\u0026rdquo; -\u0026gt; \u0026ldquo;Additional Layout Options\u0026rdquo; die Einstellung \u0026ldquo;Using space key to input non-breaking space\u0026rdquo;. Bei mir funktioniert \u0026ldquo;Usual space at any level\u0026rdquo; bestens, da ich noch nie einen non-breaking space gebraucht habe. Und das Problem ist weg!\nLinux Mint: Für Linux Mint gibt es dafür bereits eine GUI, gnome-tweaks brauchst du nicht. Gehe zu Settings -\u0026gt; Keyboard -\u0026gt; Tab \u0026ldquo;Layouts\u0026rdquo; -\u0026gt; rechts unten \u0026ldquo;Options\u0026hellip;\u0026rdquo;. Dort gibt es eine Liste mit dem Eintrag \u0026ldquo;Using space key to input non-breaking space\u0026rdquo;.\n","externalUrl":null,"permalink":"/de/braindump/unix/ubuntu-apple-keyboard-nbsp-combination/","section":"Braindump","summary":"","title":"Ubuntu: Apple-Tastatur erzeugt seltsames Leerzeichen","type":"braindump"},{"content":"Beim Entwickeln oder Nutzen von Services ist es oft praktisch, alle lauschenden Sockets oder Verbindungen der Maschine aufzulisten. Auf den meisten Distributionen gibt es dafür ein praktisches Tool:\nAuf älteren Distributionen gab es netstat, auf neueren wurde es durch ss ersetzt.\n$ ss Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port u_seq ESTAB 0 0 @0001f 101956 * 101957 u_seq ESTAB 0 0 @0001c 36327 * 36328 u_str ESTAB 0 0 * 605506 * 605507 u_str ESTAB 0 0 /var/run/dbus/system_bus_socket 40972 * 39126 u_str ESTAB 0 0 * 39939 * 39938 u_str ESTAB 0 0 * 29377 * 27430 u_str ESTAB 0 0 * 620557 * 620556 u_str ESTAB 0 0 * 602348 * 602349 u_str ESTAB 0 0 * 34852 * 32327 u_str ESTAB 0 0 @/tmp/.X11-unix/X0 27347 * 33301 u_str ESTAB 0 0 /run/user/1000/bus 34057 * 34056 u_str ESTAB 0 0 @/tmp/dbus-RiJ4OUll 1096107 * 1100088 u_str ESTAB 0 0 * 681622 * 681621 u_str ESTAB 0 0 * 107612 * 106793 u_str ESTAB 0 0 * 36029 * 34234 u_str ESTAB 0 0 /run/systemd/journal/stdout 30269 * 35283 u_str ESTAB 0 0 * 35859 * 32413 .... ein paar meiner meistgenutzten Optionen:\n-n, --numeric Do not try to resolve service names. -a, --all Display both listening and non-listening (for TCP this means established connections) sockets. -l, --listening Display only listening sockets (these are omitted by default). -p, --processes Show process using socket. -t, --tcp Display TCP sockets. -u, --udp Display UDP sockets. -x, --unix Display Unix domain sockets (alias for -f unix). Beispiele:\nAlle lauschenden TCP-Sockets anzeigen (Ports numerisch statt als Service-Namen):\nss -altn Alle Prozesse mit lauschenden TCP-Sockets anzeigen (Ports numerisch statt als Service-Namen):\nss -altnp Beachte: Für manche Operationen – etwa das Anzeigen von Prozessen – musst du mit sudo ausführen.\n","externalUrl":null,"permalink":"/de/braindump/unix/show-connections-and-sockets/","section":"Braindump","summary":"","title":"Verbindungen und offene Sockets/Ports anzeigen","type":"braindump"},{"content":"Wenn man in Python 2 mit Unicode-Strings arbeitet, kann der Vergleich zweier Strings manchmal unerwartet ausgehen. Zwei Strings können gleich aussehen, Python meldet aber das Gegenteil. Wie ist das möglich? Wie kann das deutsche Wort \u0026ldquo;Glück\u0026rdquo; nicht dasselbe sein wie \u0026ldquo;Glück\u0026rdquo;?\nIn Unicode gibt es zwei Arten, den deutschen Umlaut zu kodieren. Mehr dazu: https://en.wikipedia.org/wiki/Unicode_equivalence\nIm Fall von \u0026ldquo;Glück\u0026rdquo; lässt sich der ü-Umlaut kodieren als\nvollständiges Zeichen U+00fc Zeichen \u0026ldquo;u\u0026rdquo; gefolgt von einem non-spacing mark bzw. Akzentzeichen, das für sich kein eigenes Zeichen ist, sondern das vorangehende Zeichen modifiziert/überlagert. Das wird als ASCII-\u0026ldquo;u\u0026rdquo; (U+0075) gefolgt von \u0026quot; (U+0308) kodiert. Code zum Umwandeln zwischen beiden:\n\u0026gt;\u0026gt;\u0026gt; import unicodedata \u0026gt;\u0026gt;\u0026gt; unicodedata.normalize(\u0026#34;NFD\u0026#34;, u\u0026#34;ü\u0026#34;) u\u0026#39;u\\u0308\u0026#39; \u0026gt;\u0026gt;\u0026gt; unicodedata.normalize(\u0026#34;NFC\u0026#34;, u\u0026#34;u\\u0308\u0026#34;) u\u0026#39;\\xfc\u0026#39; Behalte das im Kopf, wenn du in Python Strings vergleichst – und beachte, dass Python 2 und 3 sie nicht exakt gleich behandeln.\n","externalUrl":null,"permalink":"/de/braindump/programming/python/compare-unicode-string-doesnt-work/","section":"Braindump","summary":"","title":"Vergleich von Unicode-Strings funktioniert nicht","type":"braindump"},{"content":" Problem # Selten kommt es vor, dass in VMware Fusion das Netzwerk nicht verfügbar ist.\nLösung # Mit\nsudo /Library/Application\\ Support/VMware\\ Fusion/boot.sh --start im Terminal startest du die VMware-Fusion-Dienste, inklusive Netzwerk. Danach startest du VMware Fusion.app wie gewohnt.\n","externalUrl":null,"permalink":"/de/braindump/macos/vmware-fusion-network-not-available/","section":"Braindump","summary":"","title":"VMware Fusion – Netzwerk nicht verfügbar","type":"braindump"},{"content":"Manchmal ist es praktisch, Windows Events in eine SQL-Datenbank zu importieren. Das lässt sich auf jede Datenbank als Ziel übertragen (MySQL dient hier nur als Beispiel).\nIn diesem Beispiel importieren wir das Security-Log in die Datenbank.\nUpdate 13. Februar 2019: Ich weiss nicht, ob das mit neueren Windows-Versionen als XP oder 7 noch funktioniert.\nVoraussetzungen # Logparser von Microsoft installieren: https://www.microsoft.com/en-us/download/details.aspx?id=24659 Eine installierte MySQL-Version Installierte 32-Bit-Version des MySQL-ODBC-Treibers https://dev.mysql.com/downloads/connector/odbc/ Vorgehen # Stelle sicher, dass du alle Voraussetzungen erfüllst\nLege eine neue Datenbank in MySQL an, oder nutze bei Bedarf eine bestehende.\nLege diese Datenbankverbindung im 32-Bit-ODBC-Manager (c:\\windows\\SysWOW64\\odbcad32.exe) als Datenquelle an (hier nennen wir sie WindowsLog32). Achtung: Nutze auf 64-Bit-Systemen nicht den ODBC-Manager aus den Systemtools, das würde Probleme geben.\nVersuche nun, die Daten zu importieren mit\nlogparser \u0026#34;SELECT * FROM Security TO seclog\u0026#34; -i:EVT -o:SQL -createTable:ON -dsn:WindowsLog32 -server:localhost Mit dem Parameter -createTable:ON versucht Logparser, das Tabellen-Schema anzulegen; manchmal sind die erzeugten Spalten aber zu kurz, weil Logparser MySQL nicht kennt. Dann bekommst du Fehler wie \u0026ldquo;Data too long for column \u0026lsquo;Strings\u0026rsquo; at row 1\u0026rdquo;. Du musst dann selbst ein paar ALTER TABLE ausführen, um die Spalten lang genug zu machen.\nDa die Tabelle nun in deiner Datenbank existiert, kannst du den Parameter -createTable:ON weglassen, und der Import sollte gelingen. Diesen Parameter brauchst du nur beim ersten Mal, spätere Importe kommen ohne ihn aus.\n","externalUrl":null,"permalink":"/de/braindump/windows/import-windows-events-into-db/","section":"Braindump","summary":"","title":"Windows Event Log in MySQL importieren","type":"braindump"}]