Intelligente Lösungen
in neuer Dimension

Logitech-Firmware aktualisieren mit Ubuntu

Hier beschreibe ich, wie ich auf einem Rechner mit Ubuntu-18.04 die Firmware meiner Logitech-Tastatur aktualisiere, die ein Unifying-Dongle verwendet:

1
2
3
4
5
6
7
8
uli@ulivaio:~$ fwupdmgr update
Downloading RQR12.07_B0029 for Unifying Receiver...
Fetching firmware https://fwupd.org/downloads/938fec082652c603a1cdafde7cd25d76baadc70d-Logitech-Unifying-RQR12.07_B0029.cab
Downloading…           [***************************************]
Updating RQR12.07_B0029 on Unifying Receiver...
Decompressing…         [***************************************]
Authenticating…        [***************************************]
Restarting device…     [***************************************]

Also: Mega-einfach, einfach fwdmgr update ausführen und die Welt ist in Ordnung!

Links

Android-UI auf Ubuntu-Desktop spiegeln

Hier beschreibe ich, wie ich auf einem Rechner mit Ubuntu-18.04 die Oberfläche eines Android-Telefons in ein Fenster spiegle. Das Telefon kann anschließend mittels Tastatur und Maus bedient werden:

Android-UI

Vorbereitungen am Handy

Nachfolgendes habe ich an einem Sony Xperia XZ mit Android 8.0 durchgespielt:

  1. Developer-Modus aktivieren
    • Einstellungen
    • System
    • Über das Telefon
    • Build-Nummer: “Oft” draufdrücken (8 mal?)
  2. USB-Debugging aktivieren
    • Einstellungen
    • System
    • Entwickleroptionen
    • USB-Debugging: Aktivieren

Vorbereitung am Linux-Rechner

  • SCRCPY installieren: sudo snap install scrcpy (dauert eine ganze Weile)
  • ADB installieren: sudo apt install adb

Kopplung und Programmstart

  • Handy und Rechner per USB koppeln
  • Handy: “Laden” anwählen
  • Rechner: scrcpy starten
  • Handy: Debugging zulassen
  • Rechner: Die Oberfläche vom Handy erscheint
    • Die Größe kann am Fensterrahmen geändert werden!
    • Wenn man das Handy dreht, dann dreht sich auch das Fenster!
    • Bedienung via Tastatur und Maus klappt!
    • Umlaute per Tastatur funktionieren bei mir im Moment nicht!

Links

Ubuntu-18.04: Bildschirmfilm

Ziel: Ich würde gerne meinen Bildschirm aufzeichnen und als animiertes GIF bereitstellen.

Zusatzprogramme installieren

1
sudo apt install ffmpeg

Ablauf

  • Aufzeichnung starten: ffmpeg -f x11grab -show_region 1 -r 25 -s 640x480 -i :0.0+100,200 -pix_fmt rgb24 recorded.gif
    • -show_region 1: Zeichnet einen Rahmen um die aufzunehmende Region
    • -s 640x480: Größe der auzunehmenden Region
    • -i :0.0+100,200: Erster Bildschirm, 100 Pixel nach rechts, 200 Pixel nach unten
    • -pix_fmt rgb24: Notwendig, wenn Ausgabedateiname auf .gif endet
    • recorded.gif: Ausgabedateiname, legt auch das Aufnahmeformat fest
  • Dateigröße reduzieren: convert -layers Optimize recorded.gif optimized.gif
    • recorded.gif: 86M
    • optimized.gif: 371K
  • Oder auch: convert -resize 640 -coalesce -fuzz 3% +dither -layers Optimize recorded.gif optimized.gif

Interaktive Auswahl der Region

SLOP installieren

1
apt-get install slop

Auswahl und Aufnahme

1
2
3
eval $(slop)
ffmpeg -f x11grab -s "$W"x"$H" -i :0.0+$X,$Y -pix_fmt rgb24 ~/recorded.gif
convert -layers Optimize ~/recorded.gif ~/optimized.gif`

Ubuntu-18.04 installieren

Hier beschreibe ich, wie ich einen Rechner mit Ubuntu-18.04 einrichte.

ISO herunterladen

USB-Stick erzeugen

1
2
3
# Ermitteln: Welche /dev/sdX-Datei gehört zum USB-Stick?
# -> Bei mir: /dev/sdb [WICHTIG! NICHT "RATEN"!]
dd if=ubuntu-18.04.2-...iso of=/dev/sdb

Installation durchführen

  • Von USB starten
  • Bei UEFI-PCs: “Textoberfläche” muß sichtbar sein für das Boot-Menü! Wenn’s grafisch aussieht, dann startet der USB-Stick im BIOS-Modus, das sorgt für Probleme!
  • Installation – Komplette Platte mit verschlüsseltem LVM Hinweis: Die Platte vom ASUS-Laptop wurde “frühzeitig” überschrieben, also nicht erst nach “Änderungen auf die Festplatten schreiben?”

Benutzer anlegen

1
2
3
sudo useradd -m {benutzername}
sudo passwd {benutzername}
sudo -a -G adm,cdrom,sudo,dip,plugdev,lpadmin,sambashare {benutzername}

Partitionierung korrigieren

  • Von USB-Stick booten – Try ubuntu without installing…
  • sudo -s
  • cryptsetup luksOpen /dev/sda5 cheer
  • vgscan
  • vgchange -a y
  • lvscan
  • lvresize --resizefs --size 20G /dev/ubuntu-vg/root (… dauert eine ganze Weile, knapp 2 Minuten)

Die nachfolgenden Kommandos scheinen unnötig zu sein, ich habe sie auf einem Rechner ausgeführt, auf diversen anderen nicht:

  • mount /dev/neon-vg/root /mnt
  • for dir in /dev /dev/pts /proc /sys /run; do sudo mount --bind $dir /mnt/$dir; done
  • chroot /mnt /bin/bash
  • grub-install /dev/sda
  • update-grub

Neustart:

  • exit
  • reboot

Pakete aktualisieren

1
2
3
4
sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade
sudo apt-get clean

Zusatzpakete installieren

1
2
sudo apt-get install joe openconnect openvpn git emacs
sudo apt-get install net-tools sshuttle chromium-browser

Alte Kernel löschen

1
2
dpkg --get-selections linux* # -> 4.18.0-15
sudo apt-get purge `dpkg --get-selections linux*-15*|cut -f1`

Partitionen anlegen

1
2
3
sudo lvcreate -n root2 -L 20G ubuntu-vg
sudo lvcreate -n home -L 20G ubuntu-vg
sudo mkfs.ext4 /dev/ubuntu-vg/home

Home-Partition umziehen

1
2
3
4
5
6
sudo -s
mount /dev/ubuntu-vg/home /mnt
cd /mnt
cp -a /home/* .
# /etc/fstab editieren
reboot

Wechsel der Loginshell auf bash-Shell

Auswahl der bash-Shell als Standard-Loginshell (z.B. damit im Terminal History und Pfad vervollständigen funktionieren)
* chsh * PW eingeben * aktuelle Shell wird vorgeschlagen, neue Shell angeben mit /bin/bash * Benutzer abmelden und komplett neu anmelden

Touchpad: Rechte Ecke aktivieren

damit re Mausklick durch Auswahl der re Ecke des kleinen Touchpads möglich ist

1
2
sudo apt-get install gnome-tweaks
gnome-tweaks

–> Dort Einstellungen > Tastatur und Maus > “Bereich” auswählen

Ubuntu-18.04: Homeverzeichnis nachträglich anlegen

Manchmal passiert es mir, dass ich einen Benutzer mit den falschen Aufrufoptionen anlege und dieser so kein Home-Verzeichnis angelegt bekommt:

1
2
3
4
$ sudo useradd {benutzername}
  # Option "-m" vergessen
$ ls /home/{benutzername}
ls: Zugriff auf /home/{benutzername} nicht möglich: Datei oder Verzeichnis nicht gefunden

Das kann man leicht korrigieren mit dem Skript “mkhomedir_helper”:

1
$ sudo mkhomedir_helper {benutzername}

Git: Fehler bei dpkg-buildpackage

Bei der Aktualisierung auf Version 2.22.0 scheitert das Bauen meines Git-Paketes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ cd git-2.21.0
$ uupdate -u ../git-2.22.0.tar.xz
uupdate: New Release will be 1:2.22.0-0ubuntu1.
uupdate: Untarring the new sourcecode archive ../git-2.22.0.tar.xz
uupdate: Unpacking the debian/ directory from version 1:2.21.0-0dp07~xenial1 worked fine.
uupdate: Remember: Your current directory is the OLD sourcearchive!
uupdate: Do a "cd ../git-2.22.0" to see the new package
$ cd ../git-2.22.0
$ dpkg-buildpackage
...
dpkg-source: info: using source format '3.0 (quilt)'
dpkg-source: info: building git using existing ./git_2.22.0.orig.tar.xz
patching file Documentation/Makefile
Hunk #1 succeeded at 436 (offset 46 lines).
Hunk #2 FAILED at 401.
1 out of 2 hunks FAILED
patching file Documentation/technical/api-index.sh
dpkg-source: info: the patch has fuzz which is not allowed, or is malformed
dpkg-source: info: if patch 'Normalize-generated-asciidoc-timestamps-with-SOURCE_D.diff' is correctly applied by quilt, use 'quilt refresh' to update it
dpkg-source: error: LC_ALL=C patch -t -F 0 -N -p1 -u -V never -E -b -B .pc/Normalize-generated-asciidoc-timestamps-with-SOURCE_D.diff/ --reject-file=- < git-2.22.0.orig.RiMq1I/debian/patches/Normalize-generated-asciidoc-timestamps-with-SOURCE_D.diff gave error exit status 1
dpkg-buildpackage: error: dpkg-source -b git-2.22.0 gave error exit status 2
$

Nachfolgend beschreibe ich, wie ich das Problem korrigiere.

Sichtung der Fehlermeldung

Die Fehlermeldung sieht grob so aus:

1
dpkg-source: info: the patch has fuzz which is not allowed, or is malformed

Ich gehe davon aus, dass der Patch möglicherweise funktionieren kann, sofern man ihn “unscharf” anwendet. Das verbietet QUILT üblicherweise!

Quilt initialisieren

1
$ export QUILT_PATCHES=debian/patches

Patch unscharf anwenden

1
2
3
4
5
6
7
8
$ quilt push
Applying patch debian/patches/Normalize-generated-asciidoc-timestamps-with-SOURCE_D.diff
patching file Documentation/Makefile
Hunk #1 succeeded at 436 (offset 46 lines).
Hunk #2 succeeded at 447 with fuzz 2 (offset 46 lines).
patching file Documentation/technical/api-index.sh

Now at patch debian/patches/Normalize-generated-asciidoc-timestamps-with-SOURCE_D.diff

Patch festschreiben

1
2
$ quilt refresh
Refreshed patch debian/patches/Normalize-generated-asciidoc-timestamps-with-SOURCE_D.diff

Paket bauen

1
2
3
4
5
$ dpkg-buildpackage
dpkg-buildpackage: source package git
dpkg-buildpackage: source version 1:2.22.0-0dp08~xenial1
dpkg-buildpackage: source distribution xenial
...

Läuft nun durch, Problem scheint korrigiert!

Bamboo: Wert einer Passwort-Variablen ermitteln

Bei Bamboo kann man eine oder mehrere Passwort-Variable (=Variable, die im Namen “password” enthält) setzen. Im Build-Log von Bamboo wird der Wert dieser Variablen dann maskiert, Werte von “normalen” Variablen sieht man:

1
2
3
4
5
6
7
8
...
command   23-May-2019 17:15:23    Substituting variable: ${bamboo.BUILD_USER} with my.build.user
command   23-May-2019 17:15:23    Substituting password variable: ${bamboo.BUILD_PASSWORD}
...
command   23-May-2019 17:15:23    Beginning to execute external process for build....
running command line:
../gradlew -Puser=my.build.user -Ppassword=********
...

Wenn man in einem Build-Skript den Wert einfach ausgibt, so erscheint dies zwar im Log, leider ist der Wert aber auch dort maskiert. Das soll vermutlich verhindern, dass man einfach an den Wert herankommt.

Manchmal braucht man ihn aber doch, bspw. wenn die ursprüngliche Bamboo-Job-Einrichtung nicht vernünftig dokumentiert und der “Einrichter” nicht mehr erreichbar ist.

Abhilfe:

1
2
echo "Password (maskiert): ${bamboo_BUILD_USER} - ${bamboo_BUILD_PASSWORD}"
echo "Password (base64):   ${bamboo_BUILD_USER} - $(echo "${bamboo_BUILD_PASSWORD}"|base64)"

Die Ausgabe im Build-Log sieht dann grob so aus:

1
2
Password (maskiert): my.build.user - ********
Password (base64):   my.build.user - MTIzNDU2Cg==

Den richtigen Wert des Kennwortes ermittelt man dann mit:

1
2
$ echo "MTIzNDU2Cg=="|base64 -d
123456

In unserem Fall hat das Kennwort also den Wert “123456”.

DB2: Probleme mit SSL-Verbindungen und Java7

Viele unserer Kunden setzen DB2 als Datenbank ein. DB2 kann JDBC-Verbindungen mittels TLS verschlüsseln. Leider treten dabei gelegentlich Probleme auf, die “Anwender” melden dann idR. Zertifikatsprobleme unabhängig vom tatsächlichen Problem.

Ausgangslage

Zugriff auf die DB2 klappt für alle Programme, die Java8 oder neuer verwenden. Bei Java7 gibt es eine “SSLHandshakeException”:

1
2
3
4
5
6
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
  at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
  at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
  at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1991)
  at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1098)
...

Oberflächlich ist klar:

  • Entweder ist das DB2-Zertifikat abgelaufen
  • … oder von einer merkwürdigen CA ausgestellt
  • … oder die CA nicht im “cacerts” eingetragen (das ist “was spezielles” für diesen Kunden, er ändert diese gerne)

Analyse DB2-Zertifikat

Sichtung des Zertifikats mit OPENSSL:

1
2
3
$ openssl s_client -connect db2.internal.biz:62000
CONNECTED(00000003)
13795:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:610:

… scheint nicht zu klappen. Liegt an der veralteten Version von OPENSSL:

1
2
$ openssl version
OpenSSL 0.9.8j-fips 07 Jan 2009

Neuer Versuch mit neuerer Version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ openssl version
OpenSSL 1.0.1g 7 Apr 2014
$ openssl s_client -connect db2.internal.biz:62000
CONNECTED(00000003)
depth=2 DC = biz, DC = ios, DC = iosPKI, CN = IOS-CA-ROOT-42
verify return:1
depth=1 DC = biz, DC = ios, DC = iosPKI, CN = IOS-CA-PROC-43
verify return:1
depth=0 C = DE, O = IOS GmbH, OU = DB2ADM, CN = db2.internal.biz, L = Stuttgart, ST = Baden-Wuerttemberg
...
$ openssl s_client -connect db2.internal.biz:62000|openssl x509 -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 3899571 (0x3b80b3)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: DC=biz, DC=ios, DC=iosPKI, CN=IOS-CA-PROC-43
        Validity
            Not Before: Mar 22 12:17:19 2019 GMT
            Not After : Mar 22 00:00:00 2023 GMT
        Subject: C=DE, O=IOS GmbH, OU=DB2ADM, CN=db2.internal.biz, L=Stuttgart, ST=Baden-Wuerttemberg
...
            X509v3 Subject Alternative Name: 
                DNS:gateway001.internal.biz, DNS:gateway002.internal.biz
...

Man sieht: * das Zertifikat ist gültig * … und von der richtigen CA ausgestellt * … und auf die richtigen Namen ausgestellt

Am Zertifikat gibt es nichts zu bemängeln!

Abstimmung mit dem DB2-Team – Ciphers

Das DB2-Team hat die BSI-Empfehlung zu TLS umgesetzt und die darin enthaltenen Ciphers als zulässig konfiguriert.

Also Quercheck mit unserer Java7-Version: Gibt es da Überlappungen? Unterstützt unsere Java7-Version einen der hinterlegten Ciphers? Die unterstützten Ciphers kann man sich leicht anzeigen lassen mit Ciphers.java:

1
2
3
4
5
6
7
8
9
10
11
12
$ javac Ciphers.java
$ java Ciphers
Default   Cipher
  SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
* SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
  SSL_DHE_DSS_WITH_DES_CBC_SHA
...
* TLS_RSA_WITH_AES_128_CBC_SHA
* TLS_RSA_WITH_AES_128_CBC_SHA256
* TLS_RSA_WITH_AES_256_CBC_SHA
* TLS_RSA_WITH_AES_256_CBC_SHA256
  TLS_RSA_WITH_NULL_SHA256

Das “Sternchen” bedeutet hier, dass es sich um einen “Default Cipher” handelt. Es gibt beispielsweise den Cipher TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, der in der Liste der Default Ciphers enthalten ist und auch in der BSI-Liste. “Eigentlich müßte es funktionieren”.

Analyse mit SSLPoke

Mit SSLPoke kann man weitere Erkenntnisse sammeln:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ javac SSLPoke.java
$ /java8/bin/java SSLPoke db2.internal.biz 62000
Successfully connected
$ java SSLPoke db2.internal.biz 62000
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
  at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
  at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
  at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1991)
  at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1098)
  at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1344)
  at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:721)
  at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
  at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:136)
  at SSLPoke.main(SSLPoke.java:31)

SSLPoke verhält sich ähnlich zu den Java-Programmen: Mit Java8 funktioniert alles, mit Java7 gibt’s Probleme!

Also: SSL-Debugging aktivieren und nochmal probieren:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ java -Djavax.net.debug=all SSLPoke db2.internal.biz 62000
keyStore is : 
keyStore type is : jks
keyStore provider is : 
init keystore
...
trigger seeding of SecureRandom
done seeding SecureRandom
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Allow unsafe renegotiation: false
Allow legacy hello messages: true
...

Viele Ciphers werden also ignoriert! Das sind insbesondere alle, die in der Cipher-Liste vom DB2-Team enthalten sind.

Es stellt sich heraus, dass Java7 per Default kein TLSv1.2 aktiviert und die Ciphers sind nur für TLSv1.2 oder neuer zulässig!

Lösung

Die Lösung des Problems sieht für uns so aus, dass wir TLSv1.2 für die JavaVM aktivieren.

Test mit SSLPoke:

1
2
$ java -Djdk.tls.client.protocols=TLSv1.1,TLSv1.2 SSLPoke db2.internal.biz 62000
Successfully connected

Sieht gut aus!

Wir bauen den Parameter -Djdk.tls.client.protocols=TLSv1.1,TLSv1.2 auch in die Start-Skripte von unseren Tomcats ein und damit ist das Thema erledigt.

Links

LXD/LXC: Installation auf KDE Neon 18.04

Hier beschreibe ich, wie ich LXD/LXC auf KDE Neon 18.04 in Betrieb nehme. Die ganze Aktion dauert grob 1 Stunde, wenn man halbwegs weiß, was man zu erledigen hat.

Aktualisieren

1
sudo pkcon update

LXD installieren

1
sudo snap install lxd

Plattenbereich für LXC anlegen

1
2
3
4
5
6
7
8
9
10
11
12
$ sudo vgdisplay
  --- Volume group ---
  VG Name               neon-vg
...
  VG Size               <465,04 GiB
  PE Size               4,00 MiB
  Total PE              119050
  Alloc PE / Size       61684 / 240,95 GiB
  Free  PE / Size       57366 / <224,09 GiB
  VG UUID               CZfxss-UeDu-s1pZ-dwb6-Iffa-pOuO-84otnm
$ sudo lvcreate -n lxclv -L 50G neon-vg
 Logical volume "lxclv" created.

LXD initialisieren

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$ sudo lxd init
Would you like to use LXD clustering? (yes/no) [default=no]: 
Do you want to configure a new storage pool? (yes/no) [default=yes]: 
Name of the new storage pool [default=default]: 
Name of the storage backend to use (btrfs, ceph, dir, lvm, zfs) [default=zfs]: btrfs
Create a new BTRFS pool? (yes/no) [default=yes]: yes
Would you like to use an existing block device? (yes/no) [default=no]: yes
Path to the existing block device: /dev/mapper/neon--vg-lxclv
Would you like to connect to a MAAS server? (yes/no) [default=no]: no
Would you like to create a new local network bridge? (yes/no) [default=yes]: 
What should the new bridge be called? [default=lxdbr0]: 
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
Would you like LXD to be available over the network? (yes/no) [default=no]: no
Would you like stale cached images to be updated automatically? (yes/no) [default=yes] 
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: yes
config: {}
networks: []
storage_pools:
- config:
    source: /dev/mapper/neon--vg-lxclv
  description: ""
  name: default
  driver: btrfs
profiles:
- config: {}
  description: ""
  devices:
    eth0:
      name: eth0
      nictype: bridged
      parent: lxdbr0
      type: nic
    root:
      path: /
      pool: default
      type: disk
  name: default
cluster: null

Container anlegen

1
2
3
4
$ sudo lxc launch ubuntu:18.04 ubuntu-1804
Creating ubuntu-1804
Retrieving image: Unpack: 100% (2.14GB/s)   
Starting ubuntu-1804                        

Container sichten

1
2
3
4
5
6
$ sudo lxc list
+-------------+---------+-----------------------+----------------------------------------------+------------+-----------+
|    NAME     |  STATE  |         IPV4          |                     IPV6                     |    TYPE    | SNAPSHOTS |
+-------------+---------+-----------------------+----------------------------------------------+------------+-----------+
| ubuntu-1804 | RUNNING | 10.239.106.134 (eth0) | fd42:cc27:326:facd:216:3eff:fef6:251f (eth0) | PERSISTENT |           |
+-------------+---------+-----------------------+----------------------------------------------+------------+-----------+

Container-Kommandos ohne SUDO

1
2
3
4
sudo usermod -aG lxd ${USER}
# Abmelden und wieder anmelden falls ${USER} dein eigenes Benutzerkonto ist
# Nachkontrolle - muß "lxd" ausgeben
id ${USER}|grep -o lxd

Basisimage für Uli

Prompt vom Container holen mit sudo lxc exec ubuntu-1804 /bin/bash und dann im Container:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# Aktualisieren
apt-get -y update
apt-get -y upgrade
apt-get -y dist-upgrade
apt-get -y autoremove
apt-get -y clean
# Zusatzpakete
apt-get -y install joe
apt-get -y install apt-transport-https
apt-get -y install openssh-server
apt-get -y install net-tools # ... provides ifconfig and netstat
apt-get -y clean
# Autostart für SSH
systemctl enable ssh
# PubKey eintragen
mkdir /root/.ssh
chmod 700 /root/.ssh
touch /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
cat >>/root/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA1cd... Uli's SSH Key
^D
cat >>/etc/bash.bashrc
HISTFILESIZE=
HISTSIZE=
HISTTIMEFORMAT="[%F %T] "
# Change the file location because certain bash sessions truncate .bash_history file upon close.
# http://superuser.com/questions/575479/bash-history-truncated-to-500-lines-on-each-login
HISTFILE=~/.bash_eternal_history
# Force prompt to write history after every command.
# http://superuser.com/questions/20900/bash-history-loss
PROMPT_COMMAND="history -a; ${PROMPT_COMMAND:-true}"
# Log last command to syslog
log_command () {
 echo "${USER} $(HISTTIMEFORMAT='' builtin history 1|cut -c8-)" |  logger -t shell -p user.info
}
PROMPT_COMMAND="${PROMPT_COMMAND:-true};log_command"
^D
for f in /etc/skel/.bashrc /root/.bashrc /home/ubuntu/.bashrc; do\
  sed -i 's/^\(HISTSIZE\|HISTFILESIZE\)/#\1/' "${f}"
done
timedatectl set-timezone Europe/Berlin

Schlusstests

Nach einem Reboot teste ich dies:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ lxc list
+-------------+---------+------+------+------------+-----------+
|    NAME     |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |
+-------------+---------+------+------+------------+-----------+
| ubuntu-1804 | STOPPED |      |      | PERSISTENT |           |
+-------------+---------+------+------+------------+-----------+
$ lxc start ubuntu-1804
$ lxc list
+-------------+---------+-----------------------+----------------------------------------------+------------+-----------+
|    NAME     |  STATE  |         IPV4          |                     IPV6                     |    TYPE    | SNAPSHOTS |
+-------------+---------+-----------------------+----------------------------------------------+------------+-----------+
| ubuntu-1804 | RUNNING | 10.239.106.134 (eth0) | fd42:cc27:326:facd:216:3eff:fef6:251f (eth0) | PERSISTENT |           |
+-------------+---------+-----------------------+----------------------------------------------+------------+-----------+
$ lxc stop ubuntu-1804
$ lxc list
+-------------+---------+------+------+------------+-----------+
|    NAME     |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |
+-------------+---------+------+------+------------+-----------+
| ubuntu-1804 | STOPPED |      |      | PERSISTENT |           |
+-------------+---------+------+------+------------+-----------+

Offene Punkte

  • Ansprechen der Container via Containername, d.h. ich hätte gerne mit ssh ubuntu-1804 eine SSH-Session in den Container hinein
  • Separierung: Container mit und ohne Internet-Zugriff

Links

Änderungen

  • 2019-05-24: Offene Punkte hinzugefügt
  • 2019-05-20: Erste Version

LXC: Too many open files

In einem meiner LXC-Container erscheint beim Stoppen und Starten vom Apache HTTPD plötzlich die Fehlermeldung “Failed to allocate directory watch: Too many open files”:

1
2
3
4
container# service apache2 stop
Failed to allocate directory watch: Too many open files
container# service apache2 start
Failed to allocate directory watch: Too many open files

Im ProxMox-Forum gibt’s Hinweise auf die Lösung…

Sichten der INOTIFY-Limits am Host

1
2
3
4
host# sysctl fs.inotify
fs.inotify.max_queued_events = 16384
fs.inotify.max_user_instances = 128
fs.inotify.max_user_watches = 65536

Erhöhen von fs.inotify.max_user_instances

1
host# sysctl fs.inotify.max_user_instances=512

Apache-HTTPD-Start-Test im Container

1
2
3
container# service apache2 stop
container# service apache2 start
container#

Es erscheint keine Fehlermeldung!

Festschreiben im Host

Datei: /etc/sysctl.d/20-lxc.conf

/etc/sysctl.d/20-lxc.conf
1
fs.inotify.max_user_instances=512

Danach: Host durchstarten mit reboot

Nachkontrolle

1
2
host# sysctl fs.inotify.max_user_instances
fs.inotify.max_user_instances = 512

Finaler Apache-HTTPD-Start-Test im Container

1
2
3
container# service apache2 stop
container# service apache2 start
container#

Es erscheint keine Fehlermeldung!