Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Praktische Anwendungen (Showcase)
    4. Installation Proxmox + Fedora CoreOS (Docker) + Portainer

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    Installation Proxmox + Fedora CoreOS (Docker) + Portainer

    This topic has been deleted. Only users with topic management privileges can see it.
    • Loredo
      Loredo Developer last edited by Loredo

      Hallo Folks,

      ich wollte hier einmal grob festhalten, wie ich mein neues ioBroker Setup vom Grundsatz her aufgebaut habe.
      Da ich damit sehr zufrieden bin und glaube, dass es auch für andere nützlich ist, die vor ähnlichen Fragen stehen, hier ein kleiner Exkurs von mir dazu. Ich gehe nicht auf jedes Detail ein, das "Drumherum" im heimischen Netzwerk (DHCP, DNS, IPv6, etc.) muss jeder selbst hinbekommen.

      0. Voraussetzungen

      1. Proxmox installieren:
        Ich gehe davon aus, dass Proxmox bereits auf einem x86_64 System installiert ist. Das geht so leicht und es gibt so viele Hilfen dazu im Netz, dass ich dazu nicht viel schreiben möchte.
        Für mich war wichtig, dass ich beim Setup auf ZFS im RAID1 Modus als Dateisystem setzen kann. Das geht auch "zu Fuß", aber der Peace of Mind ist höher, wenn man dazu einfach zwei SSD Platten derselben Größe (deshalb idealerweise auch vom gleichen Hersteller und Typ) im System hat. Der Proxmox Installer kümmert sich dann um alles und man kann später den Speicherplatz wesentlich flexibler nutzen, weil man die virtuellen Festplatten großzügig anlegen kann, ohne dass der Speicherplatz blockiert ist oder man später Aufwand hat zu klein geratene Dateisysteme zu vergrößern. RAID1 ist für mich dabei ein netter Nebeneffekt, war aber keine spezielle Anforderung von mir.
        Solch ein System läuft bei mir schon seit fast 10 Jahren, der Intel NUC ist Anno 2013 und schnurrt noch immer gut. Die SSDs habe ich einige Male getauscht, aber die Substanz ist super. Angesichts der hohen Preise für Embedded Systeme habe ich nun zum dritten Mal beide SSDs ersetzt und den NUC auch in ein lüfterloses Gehäuse umgebaut, anstatt den defekten CPU-Lüfter zu tauschen. Vielleicht noch etwas Inspiration am Rande auch für andere als Alternative zu einem überteuerten Raspberry Pi 4. Selbst dieser alte Intel NUC zieht bei mir nur zwischen 3 und 4 Watt, damit kann ich gut leben.
      2. Lokales Docker:
        Du brauchst auf deiner Workstation zur Generierung der Initialisierungsdatei für Fedora CoreOS ein lokales Docker. Damit wird es am einfachsten aus der Butane YAML Konfigurationsdatei die für CoreOS eigentlich notwendige Ignition JSON Datei zu generieren. Damit konfiguriert sich CoreOS beim ersten Start selbst und kann auch während automatischer Updates sicherstellen, dass der gewünschte Zustand danach wieder zur Verfügung steht.
      3. Python 3:
        Damit wir während der Installation die Konfigurationsdatei laden können, muss sie auf einem Webserver bereitgelegt werden. Ich starte dafür einfach einen über Python 3 auf meinem Mac. Für Windows gibt es sicher auch Methoden, einfach mal selbst googlen. Es kann natürlich auch dein eigener Webserver oder ein Hostingpaket im Internet sein, wir brauchen den nur kurz.

      1. Fedora CoreOS Ignition Datei generieren
      Lege eine Textdatei mit dem Namen coreos.bu an und kopiere den folgenden Inhalt als Basis:

      variant: fcos
      version: 1.4.0
      passwd:
        users:
          - name: core
            ssh_authorized_keys:
              - ssh-ed25519 AAAAC3..... me@example.tld
      storage:
        files:
          - path: /etc/hostname
            mode: 0644
            contents:
              inline: |
                iobroker-dockerhost
          - path: /etc/profile.d/systemd-pager.sh
            mode: 0644
            contents:
              inline: |
                # Tell systemd to not use a pager when printing information
                export SYSTEMD_PAGER=cat
          - path: /etc/sysctl.d/20-silence-audit.conf
            mode: 0644
            contents:
              inline: |
                # Raise console message logging level from DEBUG (7) to WARNING (4)
                # to hide audit messages from the interactive console
                kernel.printk=4
          - path: /etc/NetworkManager/system-connections/${interface}.nmconnection
            mode: 0600
            contents:
              inline: |
                [connection]
                id=ens18
                type=ethernet
                interface-name=ens18
                [ipv4]
                address1=192.168.178.10/24,192.168.178.1
                dhcp-hostname=demucvmkp01con
                dns=192.168.178.1;
                dns-search=home.arpa
                may-fail=false
                method=manual
          - path: /etc/systemd/journald.conf
            mode: 0644
            overwrite: true
            contents:
              inline: |
                [Journal]
                SystemMaxUse=200M
                SystemMaxFileSize=20M
          - path: /etc/zincati/config.d/55-updates-strategy.toml
            contents:
              inline: |
                [updates]
                strategy="periodic"
                [[updates.periodic.window]]
                days=[ "Sat", "Sun" ]
                start_time="22:30"
                length_minutes=60
        disks:
        - device: /dev/sdb
          wipe_table: false
          partitions:
          - size_mib: 0
            start_mib: 0
            label: docker-volumes
        filesystems:
          - path: /var/lib/docker/volumes
            device: /dev/disk/by-partlabel/docker-volumes
            format: xfs
            with_mount_unit: true
            mount_options:
                  - noatime
      system:
        units:
          - name: serial-getty@ttyS0.service
            dropins:
            - name: autologin-core.conf
              contents: |
                [Service]
                # Override Execstart in main unit
                ExecStart=
                # Add new Execstart with `-` prefix to ignore failure`
                ExecStart=-/usr/sbin/agetty --autologin core --noclear %I $TERM
          - name: rpm-ostree-install.qemu-guest-agent.service
            enabled: true
            contents: |-
              [Unit]
              Description=Layer qemu-guest-agent with rpm-ostree
              Wants=network-online.target
              After=network-online.target
              # We run before `zincati.service` to avoid conflicting rpm-ostree
              # transactions.
              Before=zincati.service
              ConditionPathExists=!/var/lib/%N.stamp
      
              [Service]
              Type=oneshot
              RemainAfterExit=yes
              # `--allow-inactive` ensures that rpm-ostree does not return an error
              # if the package is already installed. This is useful if the package is
              # added to the root image in a future Fedora CoreOS release as it will
              # prevent the service from failing.
              ExecStart=/usr/bin/rpm-ostree install --apply-live --allow-inactive qemu-guest-agent
              ExecStart=/bin/touch /var/lib/%N.stamp
      
              [Install]
              WantedBy=multi-user.target
          - name: docker.autoheal.service
            enabled: true
            contents: |-
              [Unit]
              Description=Docker Autoheal Container
              After=docker. Service
              Requires=docker.service network.target network-online.target
      
              [Service]
              Type=oneshot
              RemainAfterExit=yes
              TimeoutStartSec=0
              ExecStartPre=-/usr/bin/docker stop %n
              ExecStartPre=-/usr/bin/docker rm %n
              ExecStartPre=-/usr/bin/docker pull willfarrell/autoheal
              # Privileged mode is required for binding to local socket to work due to SELinux
              ExecStart=/usr/bin/docker run --label portainer.hidden="true" --privileged=true -d --name %n --restart always -v /var/run/docker.sock:/var/run/docker.sock --network none willfarrell/autoheal
              ExecStop=/usr/bin/docker stop -t 15 %n
      
              [Install]
              WantedBy=multi-user.target
          - name: docker.portainer-agent.service
            enabled: true
            contents: |-
              [Unit]
              Description=Portainer Agent Container
              After=docker.service
              Requires=docker.service network.target network-online.target
      
              [Service]
              Type=oneshot
              RemainAfterExit=yes
              TimeoutStartSec=0
              ExecStartPre=-/usr/bin/docker network create portainer_agent_network --attachable --internal
              ExecStartPre=-/usr/bin/docker stop %n
              ExecStartPre=-/usr/bin/docker rm %n
              ExecStartPre=-/usr/bin/docker pull portainer/agent
              # Privileged mode is required for binding to local socket to work due to SELinux
              ExecStart=/usr/bin/docker run --label portainer.hidden="true" --privileged=true -d --network portainer_agent_network --name %n --restart always -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/volumes:/var/lib/docker/volumes portainer/agent
              ExecStop=/usr/bin/docker stop -t 15 %n
      
              [Install]
              WantedBy=multi-user.target
          # - name: docker.portainer.service
          #   enabled: true
          #   contents: |-
          #     [Unit]
          #     Description=Portainer Community Edition Container
          #     Requires=docker.portainer-agent.service docker.service network.target network-online.target
          #
          #     [Service]
          #     Type=oneshot
          #     RemainAfterExit=yes
          #     TimeoutStartSec=0
          #     ExecStartPre=-/usr/bin/docker stop %n
          #     ExecStartPre=-/usr/bin/docker rm %n
          #     ExecStartPre=-/usr/bin/docker pull portainer/portainer-ce
          #     ExecStartPre=/usr/bin/docker volume create portainer_data
          #     ExecStart=/usr/bin/docker run --label portainer.hidden="true" -d -p 8800:8000 -p 9443:9443 --name %n --restart always -v portainer_data:/data portainer/portainer-ce
          #     ExecStartPost=-/usr/bin/docker network connect portainer_agent_network %n
          #     ExecStop=/usr/bin/docker stop -t 15 %n
          #
          #     [Install]
          #     WantedBy=multi-user.target
          - name: docker.portainer.service
            enabled: true
            contents: |-
              [Unit]
              Description=Portainer Business Edition Container
              Requires=docker.portainer-agent.service docker.service network.target network-online.target
      
              [Service]
              Type=oneshot
              RemainAfterExit=yes
              TimeoutStartSec=0
              ExecStartPre=-/usr/bin/docker stop %n
              ExecStartPre=-/usr/bin/docker rm %n
              ExecStartPre=-/usr/bin/docker pull portainer/portainer-ee
              ExecStartPre=/usr/bin/docker volume create portainer_data
              ExecStart=/usr/bin/docker run --label portainer.hidden="true" -d -p 8800:8000 -p 9443:9443 --name %n --restart always -v portainer_data:/data portainer/portainer-ee
              ExecStartPost=-/usr/bin/docker network connect portainer_agent_network %n
              ExecStop=/usr/bin/docker stop -t 15 %n
      
              [Install]
              WantedBy=multi-user.target
          - name: docker.builder-prune.service
            enabled: true
            contents: |-
              [Unit]
              Description=Docker Builder Prune
      
              [Service]
              Type=oneshot
              ExecStart=/usr/bin/docker builder prune --all --force --keep-storage 5G
          - name: docker.builder-prune.timer
            enabled: true
            contents: |-
              [Unit]
              Description=Run Docker Builder Prune
      
              [Timer]
              OnCalendar=20:30 Europe/Berlin
      
              [Install]
              WantedBy=multi-user.target
          - name: docker.image-prune.service
            enabled: true
            contents: |-
              [Unit]
              Description=Docker Image Prune
      
              [Service]
              Type=oneshot
              ExecStart=/usr/bin/docker image prune --all --force
          - name: docker.image-prune.timer
            enabled: true
            contents: |-
              [Unit]
              Description=Run Docker Image Prune
      
              [Timer]
              OnCalendar=20:45 Europe/Berlin
      
              [Install]
              WantedBy=multi-user.target
      

      Ich empfehle dir als Editor Visual Studio Code. Dort kannst du manuell auch das Syntax Highlighting für YAML einstellen, so dass die Datei für dich besser les- und editierbar wird.
      Damit du dich später als Benutzer core in der virtuellen Maschine per SSH einloggen kannst, musst du ganz oben zunächst den Public Key deines SSH Schlüssels hinterlegen.
      Auch die Netzwerkeinstellungen wie Hostname, statische IP-Adresse, Gateway, DNS-Search etc. solltest du deinen lokalen Gegebenheiten nach anpassen.

      In der Mitte etwa sind drei systemd-Dienste definiert.

      Der erste Dienst startet einen Docker Autoheal Container, der alle unhealthy Container automatisch neu startet, die das Label autoheal=true tragen.

      Die anderen beiden Dienste sorgen für die Bereitstellung von Portainer als Frontend. Der auskommentierte Dienst ist für die Community Edition. Solltest du diese benutzen wollen, dann musst du diesen Teil wieder einkommentieren und dafür den Dienst für die Enterprise Edition wieder auskommentieren! Ich benutze hier die Enterprise Edition, bei der man problemlos eine kostenfreie Lizenz für bis zu 5 Nodes anfordern kann. Das reicht für mich und ich kann die Komfortfunktion, Images automatisch zu pullen, wieder benutzen, die vor einiger Zeit wohl aus der Community Edition entfernt wurde.

      Portainer wird hier nach draußen über die Ports 8800 statt 8000, 9900 statt 9000 und 9443 erreichbar gemacht. Außerdem wird auch der Portainer Agent installiert, welcher anstelle des Ports 9001 den Port 9901 benutzt. Damit haben wir später keine Kollision mit dem ioBroker und können dort ohne viel Aufwand die Standardeinstellung beibehalten.

      Wenn du die Datei fertig hast, dann öffne ein Terminalfenster und wechsle in das Verzeichnis, wo du die Datei gespeichert hast.
      Dort generierst du dann die Fedora CoreOS Ignition JSON Datei coreos.ign mit dem folgenden Befehl:

      docker run -i --rm quay.io/coreos/butane:release < coreos.bu > coreos.ign
      

      Nun starten wir noch einen temporären Webserver über Python auf meiner Workstation:

      python3 -m http.server
      

      Alternativ kannst du die coreos.ign auch irgendwo anders hochladen. Wir müssen sie später nur über cURL irgendwo runterladen können.

      3. Fedora CoreOS installieren

      1. ISO Image laden:
        Lade das aktuelle Stable Image von Fedora CoreOS auf den Proxmox Server. Das geht inzwischen auch über die GUI auf dem Local Storage unter ISO Images --> Download from URL.
        a73ba2a6-ce25-4d75-b030-ce0b493a7f5b-image.png
        CoreOS ist eine hervorragende Basis, um Docker auf Proxmox zu ergänzen. Es ist sehr wartungsarm, denn es ist dafür gebaut ein Unterbau für Container zu sein und sich selbstständig aktuell zu halten. Die Installation ist etwas umständlich, aber dafür erhalten wir hier auch echte Infrastructure-as-Code, wie man neudeutsch so schön sagt. Das fügt sich super in das Konzept von Docker mit ein, wo Images über das Festtackern an bestimmte Versionen bzw. Tags auch eine verlässliche Reproduzierbarkeit erreicht wird.

      2. Virtuelle Maschine erstellen:
        Auch das Erstellen einer virtuellen Maschine ist wohl kaum der Rede wert. Es gibt nur wenige Punkte zu beachten:

        • Weise der VM 2 Festplatten zu. Bei der ersten Festplatte stellst du ein, dass sie vom Backup ausgenommen ist. Dort liegt später nur das System bzw. die Docker Container und die werden im Falle eines kompletten Restore sehr einfach von Grund auf wiederhergestellt. Du kannst das anders handhaben, aber ich mache das momentan so.
        • Lass den QEMU Guest Agent noch deaktiviert.
        • Gib das Fedora CoreOS ISO Image für die Installationsquelle an.
      3. Fedora Core OS auf die Festplatte kopieren:
        Starte jetzt die VM und Fedora CoreOS wird als Live-Umgebung direkt aus dem ISO Image heraus gestartet. Passe den folgenden Befehl an deine Umgebung an, um die zuvor generierte Fedora CoreOS Ignition Datei zu laden:

        curl -O 192.168.178.100:8000/coreos.ign
        

        Du kannst noch prüfen, ob die Datei auch erfolgreich geladen wurde, indem du kurz hineinschaust:

        cat coreos.ign
        

        Ist alles in Ordnung, dann installierst du CoreOS nun auf der ersten Festplatte /dev/sda und schaltest das System anschließend aus:

        sudo coreos-installer install /dev/sda --ignition-file coreos.ign
        sudo poweroff
        

      Füge nun einen Serial Port zur VM hinzu, entferne das ISO Image aus dem virtuellen CD-Laufwerk der VM in Proxmox, und starte die VM wieder. Wenn du dich jetzt mit der Proxmox Console über xterm.js statt noVNC verbindest, wirst du über den seriellen Port statt über die emulierte Grafikkarte verbunden und direkt als Benutzer core eingeloggt. Mit sudo kannst du lokale Docker befehle ausführen. Das ist eine praktische Alternative zum SSH Login.

      Läuft alles gut, dann sollte auch nach kurzer Zeit auf der von dir eingestellten IP-Adresse und Port 9443 der Portainer zur weiteren Konfiguration erreichbar sein. Unter Environments kannst du dabei auch statt der lokalen Docker Verbindung den Portainer Agent Dienst angeben. Nutze dafür einfach die IP-Adresse deines CoreOS Host und den Port 9901. Damit stehen weitere Funktionen in Portainer zur Verfügung, beispielsweise kannst du auf die Inhalte der Docker Volumes über den Browser zugreifen.

      CoreOS hat auch automatisch die zweite Festplatte eingebunden und dort werden nun die Docker Volumes abgelegt, die wir auch wie oben beschrieben über Proxmox backupen können. Beim ersten Start wird auch der QEMU Guest Agent nachinstalliert, so dass du ihn dann in Proxmox aktivieren kannst. Dafür musst du die Maschine nochmals komplett ausschalten, die Einstellung in Proxmox ändern, und die VM wieder starten.

      Glückwunsch! Wir haben jetzt ein sauberes Docker Basissystem, was sich selbst aktuell hält und wartet, so dass wir uns nun vollkommen auf die eigentlichen Dienste konzentrieren können.

      4. Docker Stack hochladen und starten
      Es gibt bereits unzählige Beschreibungen, wie man seine Docker Umgebung aufbaut. Über Portainer kannst du unter dem Menüpunkt Stacks eine Docker Compose Datei hochladen bzw. dort definieren. Ein Beispiel, wie das im kleinen Ausbaustil aussehen könnte, möchte ich abschließend noch kurz zeigen:

      version: '3.8'
      
      services:
      
        influxdb:
          image: influxdb:2.2-alpine
          restart: always
          container_name: influxdb
          ports:
            - 8086:8086
          environment:
            DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: mySecretInfluxAdminToken
            DOCKER_INFLUXDB_INIT_BUCKET: iobroker
            DOCKER_INFLUXDB_INIT_CLI_CONFIG_NAME: default
            DOCKER_INFLUXDB_INIT_MODE: setup
            DOCKER_INFLUXDB_INIT_ORG: MyHome
            DOCKER_INFLUXDB_INIT_PASSWORD: myEvenMoreSecretInfluxAdminPassword
            DOCKER_INFLUXDB_INIT_RETENTION: 52w
            DOCKER_INFLUXDB_INIT_USERNAME: admin
          volumes:
            - influxdb:/var/lib/influxdb2
            - influxdb_conf:/etc/influxdb2
      
        iobroker:
          image: buanet/iobroker:latest-v7
          restart: always
          container_name: iobroker
          hostname: iobroker
          network_mode: host
          environment:
            AVAHI: "true"
            PACKAGES: avahi-daemon libpam0g-dev
          volumes:
            - iobroker:/opt/iobroker
          labels:
            autoheal: true
      
      volumes:
        influxdb:
        influxdb_conf:
        iobroker:
      

      Ich lasse ioBroker hier im Netzerk Host-Modus laufen, damit es keine Probleme bei den Adaptern Yahka und Sonos gibt. Kann aber auch anders aussehen, wer hätte das gedacht 🙃

      Viel Spaß beim nachkochen!

      —Julian

      Dutchman 1 Reply Last reply Reply Quote 4
      • Dutchman
        Dutchman Developer Most Active Administrators @Loredo last edited by

        @loredo

        Nice danke fürs teilen. Ich setze seit längerem Fedora Core OS ein und bin auch sehr zufrieden

        1 Reply Last reply Reply Quote 0
        • Homoran
          Homoran Global Moderator Administrators last edited by

          Ich denke dass dies kein Einsteigerthema ist.
          Auch wenn, oder gerade weil, das eine gut strukturierte Anleitung ist, verschiebe ich sie mal nach Projektvorstellungen.

          Loredo 1 Reply Last reply Reply Quote 3
          • Loredo
            Loredo Developer @Homoran last edited by

            @homoran alles klar, ich wusste nicht wohin damit, danke 😉

            1 Reply Last reply Reply Quote 0
            • Loredo
              Loredo Developer last edited by Loredo

              An die, die es interessiert:

              Ich habe die Butane Konfiguration erweitert:

              1. Docker Autoheal Container als Dienst hinzugefügt. (docker.autoheal.service)
              2. Größe des Log Journals beschränkt (/etc/systemd/journald.conf)
              3. Zeitfenster für Update von Core OS definiert (/etc/zincati/config.d/55-updates-strategy.toml)
              4. Serielle Console mit Autologin hinzugefügt
              5. docker builder prune und docker image prune als Timer hinzugefügt.
              1 Reply Last reply Reply Quote 0
              • First post
                Last post

              Support us

              ioBroker
              Community Adapters
              Donate

              353
              Online

              31.7k
              Users

              79.8k
              Topics

              1.3m
              Posts

              3
              5
              3118
              Loading More Posts
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes
              Reply
              • Reply as topic
              Log in to reply
              Community
              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
              The ioBroker Community 2014-2023
              logo