LabCodeHub öffentliche Ansicht
Anmelden
Küpper / Quildrop öffentlich

fix: first release

R Rüdiger Küpper <rpr@9it.de> committete am 19.02.2026 07:08
3cf7ed24ddf94544a67670efb018d3405263ce1a
260 geänderte Datei(en) +0 −13249
Kontextzeilen: 0 1 2 3 10
gelöscht .github/workflows/release-images.yml
+0 −102
@@ -1,102 +0,0 @@
1 -
# ==============================================================================
2 -
# Example: Caller workflow for test-image
3 -
# Lives in: 9it-full-service/shared-workflows/.github/workflows/build.yml
4 -
#
5 -
# This shows how to use the shared workflows with a dynamic architecture matrix.
6 -
# Adjust the matrix.include array to control which architectures are built.
7 -
# ==============================================================================
8 -
9 -
name: Build Images Image
10 -
11 -
on:
12 -
  workflow_dispatch:
13 -
    inputs:
14 -
      version:
15 -
        description: 'Version tag for the image'
16 -
        required: false
17 -
        default: 'dev'
18 -
        type: string
19 -
  # push:
20 -
  #   branches:
21 -
  #     - main
22 -
  #     - develop
23 -
  #     - 'release/*'
24 -
    # paths:
25 -
    #   - 'operator/**'
26 -
    #   - 'src/**'
27 -
    #   - 'go.mod'
28 -
    #   - 'go.sum'
29 -
    #   - 'main.go'
30 -
    #   - 'Dockerfile'
31 -
32 -
jobs:
33 -
  # ============================================================================
34 -
  # 1. Prepare - Get version info
35 -
  # ============================================================================
36 -
  prepare:
37 -
    uses: 9it-full-service/shared-workflows/.github/workflows/prepare.yml@main
38 -
    with:
39 -
      version_override: ${{ github.event.inputs.version || '' }}
40 -
      default_version: 'dev'
41 -
42 -
  # ============================================================================
43 -
  # 2. Build - Matrix over architectures
44 -
  #
45 -
  #    ⚡ This is where the magic happens:
46 -
  #    - Add/remove entries from matrix.include to control which archs are built
47 -
  #    - Each project defines its own runner labels and builder images
48 -
  #    - needs_qemu: true triggers QEMU setup for cross-compilation
49 -
  # ============================================================================
50 -
  build:
51 -
    needs: [prepare]
52 -
    strategy:
53 -
      fail-fast: false
54 -
      matrix:
55 -
        include:
56 -
          # ── ARM64 (native) ──
57 -
          - arch: arm64
58 -
            runner: arc-runner-set
59 -
            needs_qemu: false
60 -
            build_args: ""
61 -
62 -
          # ── ARMv7 (cross-compiled via QEMU on amd64) ──
63 -
          # - arch: armv7
64 -
          #   runner: arc-runner-set
65 -
          #   needs_qemu: false
66 -
          #   build_args: |
67 -
          #     #   GO_BUILDER_IMAGE=ghcr.io/mogenius/go-builder:latest-amd64
68 -
          #     #   RUST_BUILDER_IMAGE=ghcr.io/mogenius/rust-builder:latest-amd64
69 -
          #     #   BPFTOOL_IMAGE=ghcr.io/mogenius/bpftool:latest-armv7
70 -
          #     #   SNOOPY_IMAGE=ghcr.io/mogenius/snoopy:latest-armv7
71 -
          #     #   RUNTIME_IMAGE=ghcr.io/mogenius/runtime:latest-armv7
72 -
73 -
    uses: 9it-full-service/shared-workflows/.github/workflows/build-image.yml@main
74 -
    with:
75 -
      image_name: ghcr.io/9it-full-service/quilldrop
76 -
      dockerfile: ./Dockerfile-images
77 -
      context: .
78 -
      arch: ${{ matrix.arch }}
79 -
      runner: ${{ matrix.runner }}
80 -
      needs_qemu: ${{ matrix.needs_qemu }}
81 -
      version: ${{ needs.prepare.outputs.version }}-images
82 -
      commit_hash: ${{ needs.prepare.outputs.commit_hash }}
83 -
      git_branch: ${{ needs.prepare.outputs.git_branch }}
84 -
      build_timestamp: ${{ needs.prepare.outputs.build_timestamp }}
85 -
      build_args: ${{ matrix.build_args }}
86 -
87 -
  # ============================================================================
88 -
  # 3. Manifest - Combine all arch images into one multi-arch manifest
89 -
  #
90 -
  #    The architectures array MUST match the archs built above.
91 -
  # ============================================================================
92 -
  manifest:
93 -
    needs: [build]
94 -
    uses: 9it-full-service/shared-workflows/.github/workflows/create-manifest.yml@main
95 -
    with:
96 -
      image_name: ghcr.io/9it-full-service/quilldrop
97 -
      version: ${{ needs.prepare.outputs.version }}-images
98 -
      architectures: '["arm64"]'
99 -
      tag_latest: ${{ github.ref_name == 'main' && needs.prepare.outputs.is_release == 'true' }}
100 -
      tag_sha: true
101 -
      tag_branch: true
102 -
      runner: arc-runner-set
gelöscht .github/workflows/release-quilldrop.yml
+0 −335
@@ -1,335 +0,0 @@
1 -
name: build-and-release
2 -
3 -
on:
4 -
  # push:
5 -
  #   branches: [main]
6 -
  workflow_dispatch:
7 -
    # tags:
8 -
    #   - 'v*' # z.B. v1.2.3
9 -
10 -
permissions:
11 -
  contents: write
12 -
  packages: write
13 -
  id-token: write
14 -
  issues: write
15 -
  pull-requests: write
16 -
17 -
env:
18 -
  # Hier kannst du einen Default-Name definieren, der in die Artefakte wandert
19 -
  APP_VERSION: ${{ github.ref_name }}
20 -
  GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
21 -
  TARGET_REPO: owner/target-repo
22 -
  TAG: ${{ github.ref_name }}
23 -
  REGISTRY: ghcr.io
24 -
  IMAGE_NAME: ${{ github.repository }}-2
25 -
26 -
jobs:
27 -
28 -
  # Job 1: Automatisches Semver Tagging
29 -
  # create-version-tag:
30 -
  #   name: Create Version Tag
31 -
  #   # runs-on: ubuntu-latest
32 -
  #   # runs-on: [self-hosted, macbook]
33 -
  #   runs-on: [self-hosted]
34 -
  #   outputs:
35 -
  #     new_tag: ${{ steps.tag_version.outputs.new_tag }}
36 -
  #     changelog: ${{ steps.tag_version.outputs.changelog }}
37 -
  #   permissions:
38 -
  #     contents: write
39 -
  #   steps:
40 -
  #     - name: Checkout
41 -
  #       uses: actions/checkout@v6
42 -
  #       with:
43 -
  #         fetch-depth: 0
44 -
45 -
  #     - name: Bump version and push tag
46 -
  #       id: tag_version
47 -
  #       uses: mathieudutour/github-tag-action@v6.2
48 -
  #       with:
49 -
  #         github_token: ${{ secrets.GITHUB_TOKEN }}
50 -
  #         default_bump: patch
51 -
  #         release_branches: main
52 -
  #         # fix: = patch (0.0.1)
53 -
  #         # feat: = minor (0.1.0)
54 -
  #         # BREAKING CHANGE: = major (1.0.0)
55 -
56 -
  #     - name: Show new version
57 -
  #       run: |
58 -
  #         echo "New version: ${{ steps.tag_version.outputs.new_tag }}"
59 -
  #         echo "Changelog: ${{ steps.tag_version.outputs.changelog }}"
60 -
61 -
  create-version-tag:
62 -
    uses: 9it-full-service/shared-workflows/.github/workflows/prepare.yml@main
63 -
    with:
64 -
      version_override: ${{ github.event.inputs.version || '' }}
65 -
      default_version: 'dev'
66 -
67 -
  build:
68 -
    runs-on: [ arc-runner-set-arm64 ]
69 -
    # runs-on: [ self-hosted ]
70 -
    needs: [ "create-version-tag" ]
71 -
    strategy:
72 -
      fail-fast: false
73 -
      matrix:
74 -
        # goos: [linux,]
75 -
        # goarch: [arm64]
76 -
        goos: [linux, darwin]
77 -
        goarch: [amd64, arm64]
78 -
        # goos: [linux, darwin, windows]
79 -
        # goarch: [amd64, arm64,arm]
80 -
        # exclude:
81 -
        #   # ARM 32-bit ist nur für Linux sinnvoll
82 -
        #   - goos: darwin
83 -
        #     goarch: arm
84 -
        #   - goos: windows
85 -
        #     goarch: arm
86 -
87 -
    steps:
88 -
      - uses: actions/checkout@v6
89 -
90 -
      - name: Setup Go
91 -
        uses: actions/setup-go@v6
92 -
        with:
93 -
          go-version: '1.25'
94 -
          cache: true
95 -
96 -
      # - name: Print build matrix
97 -
      #   run: |
98 -
      #     echo "GOOS=${{ matrix.goos }}"
99 -
      #     echo "GOARCH=${{ matrix.goarch }}"
100 -
      #     echo "TAG=${{ github.ref_name }}"
101 -
102 -
      - name: Set build timestamp
103 -
        id: timestamp
104 -
        run: echo "BUILD_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_OUTPUT
105 -
106 -
      - name: Print build matrix
107 -
        run: |
108 -
          echo "GOOS=${{ matrix.goos }}"
109 -
          echo "GOARCH=${{ matrix.goarch }}"
110 -
          echo "TAG=${{ needs.create-version-tag.outputs.version }}"
111 -
          echo "VERSION=${{ needs.create-version-tag.outputs.version }}"
112 -
          echo "COMMIT=${{ github.sha }}"
113 -
          echo "BUILD_TIMESTAMP=${{ steps.timestamp.outputs.BUILD_TIMESTAMP }}"
114 -
115 -
      - name: Build quilldrop
116 -
        env:
117 -
          GOOS: ${{ matrix.goos }}
118 -
          GOARCH: ${{ matrix.goarch }}
119 -
          VERSION: ${{ needs.create-version-tag.outputs.version }}
120 -
          COMMIT: ${{ github.sha }}
121 -
          BUILD_TIMESTAMP: ${{ steps.timestamp.outputs.BUILD_TIMESTAMP }}
122 -
        run: |
123 -
          set -euo pipefail
124 -
          mkdir -p dist
125 -
          BIN_NAME="quilldrop-${GOOS}-${GOARCH}"
126 -
          OUT="dist/${BIN_NAME}"
127 -
          # Windows: .exe
128 -
          if [ "${GOOS}" = "windows" ]; then OUT="${OUT}.exe"; fi
129 -
          # Build (im Unterordner)
130 -
          (cd . && CGO_ENABLED=0 go build -trimpath -ldflags="-s -w \
131 -
          -X 'main.version=${VERSION}' \
132 -
          -X 'main.commit=${COMMIT}' \
133 -
          -X 'main.date=${BUILD_TIMESTAMP}'" -o "../${OUT}")
134 -
          # go mod init quilldrop && go mod tidy && \
135 -
          go mod tidy && \
136 -
          # CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo \
137 -
          # -ldflags="-s -w \
138 -
          #   -X 'main.version=${VERSION}' \
139 -
          #   -X 'main.commit=${COMMIT}' \
140 -
          #   -X 'main.date=${BUILD_TIMESTAMP}'" \
141 -
          # -o vm-tracker-api main.go
142 -
          # Paket
143 -
          if [[ "${OUT}" == *.exe ]]; then
144 -
            (cd dist && zip "${BIN_NAME}.zip" "${BIN_NAME}.exe")
145 -
          else
146 -
            (cd dist && tar -czf "${BIN_NAME}.tar.gz" "${BIN_NAME}")
147 -
          fi
148 -
149 -
      - name: Build vm-tracker-client
150 -
        env:
151 -
          GOOS: ${{ matrix.goos }}
152 -
          GOARCH: ${{ matrix.goarch }}
153 -
          VERSION: ${{ needs.create-version-tag.outputs.version }}  # ← hinzufügen
154 -
          COMMIT: ${{ github.sha }}                                  # ← hinzufügen
155 -
          # BUILD_TIMESTAMP: ${{ github.event.head_commit.timestamp }}
156 -
          BUILD_TIMESTAMP: $(date -u +%Y-%m-%dT%H:%M:%SZ)
157 -
        run: |
158 -
          set -euo pipefail
159 -
          mkdir -p dist
160 -
          BIN_NAME="quilldrop-${GOOS}-${GOARCH}"
161 -
          OUT="dist/${BIN_NAME}"
162 -
          if [ "${GOOS}" = "windows" ]; then OUT="${OUT}.exe"; fi
163 -
          (cd . && CGO_ENABLED=0 go build -trimpath -ldflags="-s -w \
164 -
          -X 'main.version=${VERSION}' \
165 -
          -X 'main.commit=${COMMIT}' \
166 -
          -X 'main.date=${BUILD_TIMESTAMP}'" -o "../${OUT}")
167 -
          if [[ "${OUT}" == *.exe ]]; then
168 -
            (cd dist && zip "${BIN_NAME}.zip" "${BIN_NAME}.exe")
169 -
          else
170 -
            (cd dist && tar -czf "${BIN_NAME}.tar.gz" "${BIN_NAME}")
171 -
          fi
172 -
173 -
      - name: Checksums erzeugen
174 -
        run: |
175 -
          set -euo pipefail
176 -
          cd dist
177 -
          # Ein Checksum-File pro Matrix-Kombination
178 -
          # FILE="CHECKSUMS-${{ env.APP_VERSION }}-${{ matrix.goos }}-${{ matrix.goarch }}.txt"
179 -
          FILE="CHECKSUMS-${{ needs.create-version-tag.outputs.version }}-${{ matrix.goos }}-${{ matrix.goarch }}.txt"
180 -
          shopt -s nullglob
181 -
          for f in *.tar.gz *.zip; do
182 -
            sha256sum "$f" >> "$FILE"
183 -
          done
184 -
          cat "$FILE"
185 -
186 -
      - name: Upload artifacts (unique per matrix)
187 -
        uses: actions/upload-artifact@v5
188 -
        with:
189 -
          name: release-bundles-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.run_attempt }}
190 -
          path: |
191 -
            dist/*.tar.gz
192 -
            dist/*.zip
193 -
            dist/CHECKSUMS-*.txt
194 -
          if-no-files-found: error
195 -
          compression-level: 6
196 -
197 -
  release:
198 -
    needs: [ "build", "create-version-tag" ]
199 -
    runs-on: ubuntu-latest
200 -
    steps:
201 -
      - name: Download all build artifacts (merged)
202 -
        uses: actions/download-artifact@v6
203 -
        with:
204 -
          pattern: release-bundles-*
205 -
          merge-multiple: true
206 -
          path: dist
207 -
208 -
      - name: Übersicht
209 -
        run: ls -la dist
210 -
211 -
      # --- Option A: Release in anderes Repo via gh CLI ---
212 -
      - name: Create release in target repo
213 -
        env:
214 -
          GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}   # 👈 wichtig: GH_TOKEN, nicht RELEASE_TOKEN
215 -
          TARGET_REPO: 9it-full-service/quilldrop
216 -
          TAG: ${{ needs.create-version-tag.outputs.version }}
217 -
          # TAG: ${{ github.ref_name }}
218 -
        run: |
219 -
          set -euo pipefail
220 -
          gh release create "$TAG" \
221 -
            --repo "$TARGET_REPO" \
222 -
            --title "$TAG" \
223 -
            --notes "Automated release from ${GITHUB_REPOSITORY}@${GITHUB_SHA}" \
224 -
          || echo "Release exists, continue to upload assets."
225 -
226 -
          gh release upload "$TAG" dist/* --repo "$TARGET_REPO" --clobber
227 -
228 -
  # build-and-push-docker:
229 -
  #   name: Build Multi-arch Docker
230 -
  #   needs: [create-version-tag, build]
231 -
  #   runs-on: [self-hosted]
232 -
  #   permissions:
233 -
  #     contents: read
234 -
  #     packages: write
235 -
  #   steps:
236 -
  #     - name: Checkout repository
237 -
  #       uses: actions/checkout@v6
238 -
239 -
  #     # Alle Artifacts herunterladen
240 -
  #     - name: Download build artifacts
241 -
  #       uses: actions/download-artifact@v6
242 -
  #       with:
243 -
  #         path: ./artifacts
244 -
245 -
  #     # Übersicht was heruntergeladen wurde
246 -
  #     - name: List downloaded artifacts
247 -
  #       run: |
248 -
  #         echo "=== Downloaded artifacts ==="
249 -
  #         ls -laR artifacts/
250 -
251 -
  #     # Binaries für Docker vorbereiten
252 -
  #     - name: Prepare binaries for Docker
253 -
  #       run: |
254 -
  #         set -euo pipefail
255 -
  #         mkdir -p docker-bin/{amd64,arm64}
256 -
          
257 -
  #         # Suche und extrahiere amd64 binary
258 -
  #         echo "Searching for amd64 binary..."
259 -
  #         AMD64_TAR=$(find artifacts -name "vm-tracker-api-linux-amd64.tar.gz" -type f | head -1)
260 -
  #         if [ -n "$AMD64_TAR" ]; then
261 -
  #           echo "Found: $AMD64_TAR"
262 -
  #           tar -xzf "$AMD64_TAR" -C docker-bin/amd64/
263 -
  #           mv docker-bin/amd64/vm-tracker-api-linux-amd64 docker-bin/amd64/vm-tracker-api
264 -
  #           chmod +x docker-bin/amd64/vm-tracker-api
265 -
  #         else
266 -
  #           echo "ERROR: amd64 binary not found!"
267 -
  #           exit 1
268 -
  #         fi
269 -
          
270 -
  #         # Suche und extrahiere arm64 binary
271 -
  #         echo "Searching for arm64 binary..."
272 -
  #         ARM64_TAR=$(find artifacts -name "vm-tracker-api-linux-arm64.tar.gz" -type f | head -1)
273 -
  #         if [ -n "$ARM64_TAR" ]; then
274 -
  #           echo "Found: $ARM64_TAR"
275 -
  #           tar -xzf "$ARM64_TAR" -C docker-bin/arm64/
276 -
  #           mv docker-bin/arm64/vm-tracker-api-linux-arm64 docker-bin/arm64/vm-tracker-api
277 -
  #           chmod +x docker-bin/arm64/vm-tracker-api
278 -
  #         else
279 -
  #           echo "ERROR: arm64 binary not found!"
280 -
  #           exit 1
281 -
  #         fi
282 -
          
283 -
  #         echo "=== Prepared binaries ==="
284 -
  #         ls -la docker-bin/*/
285 -
  #         file docker-bin/*/vm-tracker-api
286 -
287 -
  #     - name: Set up QEMU
288 -
  #       uses: docker/setup-qemu-action@v3
289 -
290 -
  #     - name: Set up Docker Buildx
291 -
  #       uses: docker/setup-buildx-action@v3
292 -
293 -
  #     - name: Log in to Container Registry
294 -
  #       uses: docker/login-action@v3
295 -
  #       with:
296 -
  #         registry: ${{ env.REGISTRY }}
297 -
  #         username: ${{ github.actor }}
298 -
  #         password: ${{ secrets.GITHUB_TOKEN }}
299 -
300 -
  #     - name: Set build metadata
301 -
  #       id: meta
302 -
  #       run: |
303 -
  #         echo "VERSION=${{ needs.create-version-tag.outputs.new_tag }}" >> $GITHUB_ENV
304 -
  #         echo "COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
305 -
  #         echo "BUILD_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_ENV
306 -
307 -
  #     - name: Build and push Docker image
308 -
  #       uses: docker/build-push-action@v6
309 -
  #       with:
310 -
  #         context: .
311 -
  #         platforms: linux/amd64,linux/arm64
312 -
  #         push: true
313 -
  #         tags: |
314 -
  #           ghcr.io/9it-full-service/vm-tracker-api:${{ needs.create-version-tag.outputs.new_tag }}
315 -
  #           ghcr.io/9it-full-service/vm-tracker-api:latest
316 -
  #         labels: |
317 -
  #           org.opencontainers.image.version=${{ needs.create-version-tag.outputs.new_tag }}
318 -
  #           org.opencontainers.image.created=${{ env.BUILD_TIMESTAMP }}
319 -
  #           org.opencontainers.image.revision=${{ github.sha }}
320 -
  #         build-args: |
321 -
  #           VERSION=${{ env.VERSION }}
322 -
  #           COMMIT=${{ env.COMMIT }}
323 -
  #           BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
324 -
  #         # cache-from: type=gha
325 -
  #         # cache-to: type=gha,mode=max
326 -
  #         provenance: false
327 -
328 -
  #     # - name: Clean up Docker images
329 -
  #     #   if: always()  # Also run in case of errors
330 -
  #     #   run: |
331 -
  #     #     # remove dangling images
332 -
  #     #     docker rmi ghcr.io/9it-full-service/vm-tracker-api:${{ needs.create-version-tag.outputs.new_tag }}
333 -
  #     #     docker rmi ghcr.io/9it-full-service/vm-tracker-api:latest
334 -
  #     #     # docker image prune -f
335 -
gelöscht .github/workflows/release.yml
+0 −102
@@ -1,102 +0,0 @@
1 -
# ==============================================================================
2 -
# Example: Caller workflow for test-image
3 -
# Lives in: 9it-full-service/shared-workflows/.github/workflows/build.yml
4 -
#
5 -
# This shows how to use the shared workflows with a dynamic architecture matrix.
6 -
# Adjust the matrix.include array to control which architectures are built.
7 -
# ==============================================================================
8 -
9 -
name: Build Image
10 -
11 -
on:
12 -
  workflow_dispatch:
13 -
    inputs:
14 -
      version:
15 -
        description: 'Version tag for the image'
16 -
        required: false
17 -
        default: 'dev'
18 -
        type: string
19 -
  push:
20 -
    branches:
21 -
      - main
22 -
      - develop
23 -
      - 'release/*'
24 -
    # paths:
25 -
    #   - 'operator/**'
26 -
    #   - 'src/**'
27 -
    #   - 'go.mod'
28 -
    #   - 'go.sum'
29 -
    #   - 'main.go'
30 -
    #   - 'Dockerfile'
31 -
32 -
jobs:
33 -
  # ============================================================================
34 -
  # 1. Prepare - Get version info
35 -
  # ============================================================================
36 -
  prepare:
37 -
    uses: 9it-full-service/shared-workflows/.github/workflows/prepare.yml@main
38 -
    with:
39 -
      version_override: ${{ github.event.inputs.version || '' }}
40 -
      default_version: 'dev'
41 -
42 -
  # ============================================================================
43 -
  # 2. Build - Matrix over architectures
44 -
  #
45 -
  #    ⚡ This is where the magic happens:
46 -
  #    - Add/remove entries from matrix.include to control which archs are built
47 -
  #    - Each project defines its own runner labels and builder images
48 -
  #    - needs_qemu: true triggers QEMU setup for cross-compilation
49 -
  # ============================================================================
50 -
  build:
51 -
    needs: [prepare]
52 -
    strategy:
53 -
      fail-fast: false
54 -
      matrix:
55 -
        include:
56 -
          # ── ARM64 (native) ──
57 -
          - arch: arm64
58 -
            runner: arc-runner-set
59 -
            needs_qemu: false
60 -
            build_args: ""
61 -
62 -
          # ── ARMv7 (cross-compiled via QEMU on amd64) ──
63 -
          # - arch: armv7
64 -
          #   runner: arc-runner-set
65 -
          #   needs_qemu: false
66 -
          #   build_args: |
67 -
          #     #   GO_BUILDER_IMAGE=ghcr.io/mogenius/go-builder:latest-amd64
68 -
          #     #   RUST_BUILDER_IMAGE=ghcr.io/mogenius/rust-builder:latest-amd64
69 -
          #     #   BPFTOOL_IMAGE=ghcr.io/mogenius/bpftool:latest-armv7
70 -
          #     #   SNOOPY_IMAGE=ghcr.io/mogenius/snoopy:latest-armv7
71 -
          #     #   RUNTIME_IMAGE=ghcr.io/mogenius/runtime:latest-armv7
72 -
73 -
    uses: 9it-full-service/shared-workflows/.github/workflows/build-image.yml@main
74 -
    with:
75 -
      image_name: ghcr.io/9it-full-service/quilldrop
76 -
      dockerfile: ./Dockerfile-static
77 -
      context: .
78 -
      arch: ${{ matrix.arch }}
79 -
      runner: ${{ matrix.runner }}
80 -
      needs_qemu: ${{ matrix.needs_qemu }}
81 -
      version: ${{ needs.prepare.outputs.version }}
82 -
      commit_hash: ${{ needs.prepare.outputs.commit_hash }}
83 -
      git_branch: ${{ needs.prepare.outputs.git_branch }}
84 -
      build_timestamp: ${{ needs.prepare.outputs.build_timestamp }}
85 -
      build_args: ${{ matrix.build_args }}
86 -
87 -
  # ============================================================================
88 -
  # 3. Manifest - Combine all arch images into one multi-arch manifest
89 -
  #
90 -
  #    The architectures array MUST match the archs built above.
91 -
  # ============================================================================
92 -
  manifest:
93 -
    needs: [prepare, build]
94 -
    uses: 9it-full-service/shared-workflows/.github/workflows/create-manifest.yml@main
95 -
    with:
96 -
      image_name: ghcr.io/9it-full-service/quilldrop
97 -
      version: ${{ needs.prepare.outputs.version }}
98 -
      architectures: '["arm64"]'
99 -
      tag_latest: ${{ github.ref_name == 'main' && needs.prepare.outputs.is_release == 'true' }}
100 -
      tag_sha: true
101 -
      tag_branch: true
102 -
      runner: arc-runner-set
\ No newline at end of file
gelöscht content/2016-01-07-defekt-ice-wifi-nicht-immer-db-schuld.md
+0 −38
@@ -1,38 +0,0 @@
1 -
---
2 -
title: 'Wer hat das ICE WiFi kaputt gemacht?'
3 -
date: 2016-01-16 14:00:23
4 -
update: 2016-01-16 14:00:23
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - Internet
9 -
    - WiFi
10 -
preview: "Die Deutsche Bahn bietet auf mittlerweilen vielen Strecken WLAN an. In der 1. Klasse kostenlos, in der 2. Klasse kostenpflichtig."
11 -
categories: 
12 -
    - Internet
13 -
toc: false
14 -
hide: false
15 -
type: post
16 -
---
17 -
18 -
19 -
Die Deutsche Bahn bietet auf mittlerweilen vielen Strecken WLAN an. In der 1. Klasse kostenlos, in der 2. Klasse kostenpflichtig. Wenn es funktioniert ist alles gut. Aber leider ist das nicht immer der Fall. Ein Störfaktor ist aber öfters zu erkennen. Andere WLAN Accespoints. Entweder hat jemand sein Smartphone asl Accespoint für einen Laptop oder neuerdings benutzen andere reisende im ICE immer mehr einen UMTS Accesspoint. 
20 -
21 -
<!--more-->
22 -
23 -
Anderes Problem sind die Telekom eigenen Accesspoints. Das kann jeder selbst checken wenn der ICE in den nächsten Bahnhof fährt.  Das Problem ist der Country Code. In den ICE Zügen ist dieser in den Accesspoints auf den Ländercode für Frankreich (FR) gestellt. Für die Telekom Hotspots in den Bahnhöfen auf Deutschland (DE).  Nur was passiert in solchen Momenten. Alle Accesspoints arbeiten mit 2,4 GHz, da sollte es ja kein Problem geben. Doch 811.2 hat die Eigenschaft das man auch die Frequenzen der jeweiligen Länder damit beachten kann. In einigen gibt es z.B. den Kanal 13, in anderen ist dieser nicht vorhanden. Weil der Frequenzbereich anderweitig benutzt wird.
24 -
25 -
![Wlan Konfikt Country Code](/images/posts/DB-Wifi-1.webp)
26 -
27 -
![Länderkennung FR](/images/posts/DB-Wifi-2.webp)
28 -
29 -
![Länderkennung FR](/images/posts/DB-Wifi-3.webp)
30 -
31 -
```
32 -
Dec 31 15:46:40 rprMacBookAir kernel[0]: en0: 802.11d country code set to 'FR'.
33 -
Dec 31 15:46:40 rprMacBookAir kernel[0]: en0: Supported channels 1 2 3 4 5 6
34 -
7 8 9 10 11 12 13 36 40 44 48 52 56 60 64 100 104 108 112 116 120 124 128 132
35 -
136 140 149 153 157 161 165
36 -
Dec 31 15:46:40 rprMacBookAir locationd[86]: NETWORK: no response from server,
37 -
reachability, 2, queryRetries, 5
38 -
```
gelöscht content/2016-01-08-e-mails-verwalten.md
+0 −212
@@ -1,212 +0,0 @@
1 -
---
2 -
title: 'E-Mails verwalten'
3 -
date: 2016-01-08 02:00:51
4 -
update: 2016-01-08 02:00:51
5 -
author: ruediger
6 -
cover: "/images/cat/organisation.webp"
7 -
tags:
8 -
    - E-Mail
9 -
    - Feed
10 -
    - Filter
11 -
    - IMAP
12 -
    - imapdir
13 -
    - Internet
14 -
    - Maildir
15 -
    - Organisation
16 -
    - Organisieren
17 -
    - RSS
18 -
    - Rule
19 -
    - Sieve
20 -
preview: "In diesem [Google+](https://plus.google.com/+RüdigerPretzlaff/posts/9v1WyUG1NM5) Post hatte ich das Thema ja mal anschnitten und jetzt endlich mal angefangen genauer zu beschreiben. Hier aber erst noch mal das von Google+"
21 -
categories: 
22 -
    - Organisation
23 -
toc: false
24 -
hide: false
25 -
type: post
26 -
---
27 -
28 -
In diesem [Google+](https://plus.google.com/+RüdigerPretzlaff/posts/9v1WyUG1NM5) Post hatte ich das Thema ja mal anschnitten und jetzt endlich mal angefangen genauer zu beschreiben. Hier aber erst noch mal das von Google+:
29 -
30 -
> A: wie viele Mail bekommst du eigentlich so am Tag.
31 -
32 -
> Ich: puh, kann ich gar nicht sagen. Müsste ich mal über eines der Logfiles das Script jagen.
33 -
<!--more-->
34 -
> A: ähm Moment, wieso sind das bei dir so vielen Ordner im Postfach. Äh, wie viele sind das denn?
35 -
36 -
> Ich: puh, kann ich gar nicht sagen. Letzte Woche waren es noch etwas über 140. Aber die werden
37 -
automatisch angelegt, je nachdem was für eine Mail reinkommt
38 -
39 -
> A: wie hast Du für alles Regeln angelegt?
40 -
41 -
> Ich: nein, aber eine richtige. Das zu erklären dauert aber etwas länger. Ich will das aber eh mal
42 -
aufschreiben.Auch weil schon andere gefragt haben, weil viele schon mit viel weniger Mails
43 -
überfordert sind.Mit diesem Mailsetup ist mir auch eine Funktion bei iOS aufgefallen die
44 -
richtig schick ist. Es gibt Ordner die werden zwar per Notification angezeigt. Aber nicht
45 -
als Zahl auf dem Homescreen. Wichtige Mail aus der Inbox fallen auf, da die Anzahl zusehen
46 -
ist. Nicht wichtige, aber gut wenn du sie mal wahrgenommen hast werden notifiziert, aber
47 -
sonst nichts. Alles andere ist unwichtig und man sieht sie unterwegs nur wenn man in einen
48 -
Mailordner gehen würde. Aber genauer dann wenn ich alles fertig gesammelt und geschrieben habe.
49 -
50 -
51 -
Als ersten einmal die Anzahl der Mails: ca. 700 bis 1200 pro Tag.
52 -
53 -
Davon gelangen in den Posteingangsordnern gerade mal ca. 30-50 Mails pro Tag. Alle anderen Mails sind in verschiedene Ordner schon auf dem Mailserver sortiert worden. Dabei gibt es mehrere Kategorien.
54 -
55 -
1.  AutoSort
56 -
    1.  Accounts
57 -
    2.  Dienste (Serverzeug)
58 -
    3.  Shops
59 -
    4.  Verträge
60 -
    5.  Soziale Netzwerke
61 -
    6.  Fritzboxen
62 -
2.  Feeds \*(Dazu später mehr \[rss2mail\])
63 -
3.  Office \*(Shared Folders)
64 -
65 -
_**Feeds**_ Fangen wir als erstes mit den einfachen Dingen an. Als erstes etwas zu der Kategorie **Feeds**. Diese E-Mails kommen nicht von externen Server, sondern werden auf dem Server selbst erstellt. Dazu verwende ich [rss2email](http://www.allthingsrss.com/rss2email/) und habe in der Konfiguration RSS-**Feeds** von Newsseiten und Blogs eingetragen, die an verschiedene Accounts gesendet werden. Unterkategorien sind:
66 -
67 -
1.  Apple
68 -
2.  Blogs
69 -
3.  News
70 -
4.  Städte
71 -
72 -
In den beiten Kategorien "**News**" und Städte sind z.B. die News Feeds von DW (Deutsche Welle) und bei Städte die Feeds von der-westen.de (Stadt Essen), Ka-news.de und Karlsruhe-insider.de. Die entsprechenden Feeds werden dann per Mail an folgende E-Mailadressen gesendet:
73 -
74 -
*   feeds+News.DW@example.net sortiert den Feed von dw.com in den Mailordner "Feeds.News.DW" (maildir ~/.Feeds.News.DW/)
75 -
*   feeds+Städte.Essen@example.net
76 -
*   feeds+Städte.Karlsruhe@example.net
77 -
78 -
Das ganze sortiert jetzt erst einmal überhaupt nichts. Der Server muss den Delimiter "+" unterstützen. Sollte er das nicht machen hat man trotzdem noch die Möglichkeit dies mit einem "Sieve-Filter" auf dem Server zu machen und einem Catch-All Account. Dazu und den Regeln auf dem Mailserver aber erst später. Vorher noch kurz zu den Kategorieren "**Office**" und "**AutoSort**". **AutoSort** ist die Kategorie um die es hier eigentlich geht. _**Office**_ Die Kategorie "**Office**" ist eigentlich am schnellsten erklärt. In dieser befinden sich nur Shared Folders. Also Ordner die man zwischen verschiedenen Accounts einfach freigeben kann. Das sind entweder Ordner für alle meine Accounts, damit ich z.B. alle Rechnungen, Bestellungen usw. von allen Account nach dem lesen in den jeweiligen Ordner verschiebe um alle Rechnungen von jedem Account aus schnell erreichen zu können. Die anderen Ordner sind dann auch für andere User auf dem Server freigeben. Projekte mit anderen werden damit organisiert, Daten ausgetauscht, archiviert usw. _**AutoSort**_ Im Google Post vom 30.10.2015 wurde eine Ordnerzahl von 140 genannt. Aktuell sind es jetzt 275 Ordner. Zur Erinnerung noch einmal die Liste der Unterkategorien:
79 -
80 -
1.  Accounts
81 -
2.  Dienste (Serverzeug)
82 -
3.  Shops
83 -
4.  Verträge
84 -
5.  Soziale Netzwerke
85 -
6.  Fritzboxen
86 -
87 -
In den Beispielen wird immer "user+\*@example.net" genannte. Die eigentliche Adresse ist user@example.net. "User" ist der Localpart der Mailadresse, bei den meisten also der Benutzername: cmueller@example.net.
88 -
89 -
_Hinweis:_
90 -
91 -
_Bei den Beispielen hier benutze ich bei den einzelnen Ordnernamen immer einen Grossbuchstaben am Anfang. Dies dient hier nur der besseren Lesbarkeit. Man kann das auch so machen, sollte sich aber bewusst sein das manche Anbieter das zwar so annehmen beim eintragen einer E-Mailadresse, teilweise auch in Einstellungen auch wieder so anzeigen, aber beim versenden der E-Mail alles in Kleinbuchstaben umwandeln. Das könnte dazu führen das auf einmal zwei Ordner für Onlineshops vorhanfen sind. "Shops" und "shops". Daher benutze ich nur noch Kleinbuchstaben._
92 -
93 -
In **Accounts** werden alle Accounts für alles mögliche gefiltert. Zum Beispiel dort in den Kategorien "Foren", "Musik", "Software", usw.
94 -
95 -
Melde ich mich in einem Forum an für Musik, landet es auch in Musik. Für die Anmeldung benutzt man z.B. die Mailadresse:
96 -
97 -
"user+Accounts.Foren.Gitarrenforum@example.com" -> landen im Mailordner "AutoSort.Foren.Musik.Gitarrenforum"
98 -
99 -
"user+Foren.Musik.BandsInNrw@example.net" -> Mailordner:   AutoSort.Foren.Musik.BandsInNrw
100 -
101 -
usw.
102 -
103 -
Für unseren Beispiel Kai wäre das dann: cmueller+Foren.Musik.BandsInNrw@example.net. In den weitern Beispielen werde ich für die Übersichtlichkeit immer "user+...." benutzen.
104 -
105 -
Bei **Dienste** filter ich alles in verschiedene Ordner für z.B.: "Cron", "Certs" (noch weiter unterteilt für die einzelnen Anbieter), SA-Learn (Spamlernen), usw.
106 -
107 -
Cronjobs auf dem dem Server werden an "user+AutoSort.Server.Cron@example.net" geschickt. Wenn man mehrere Server betreibt oder Mails aus verschiednen Jobs noch weiter filtern möchte hängt man einfach dementsprechend ".ServerA", ".ServerB" oder ".Backups", "Updates" an die Adresse an.
108 -
109 -
*   user+Server.Cron@example.net
110 -
*   user+Server.Cron.ServerA@example.net
111 -
*   user+Server.Cron.ServerA@example.net
112 -
*   user+Server.Cron.Backups@example.net
113 -
*   user+Server.Cron.Updates@example.net
114 -
115 -
Immer wird in den Cron oder den Unterordner in Cron gespeichert. Wem nur Cron reicht, der benutzt halt nur die erste Adresse. Falls man später merkt das dieser Ordner nicht reicht ändert man nur die Adresse für einen Server oder Job in der Konfiguration und schon werden die nächsten Mails neu sortiert eintreffen.
116 -
117 -
Dazu muss man keinen Filter anpassen. Zu den Filtern kommen wir aber später. Erst noch ein paar Beispiele um verständlich zu machen wie der Aufbau der E-Mailadressen sind.
118 -
119 -
**Shops** und **Soziale Netzwerke**
120 -
121 -
Amazon, Ebay, Wein Müller, Musikladen Mustermann. Alles Shops bei denen man sich so anmeldet. Die ersten beiden kennt jeder, die letzten beiden existieren glaube ich gar nicht. Aber sind ja auch nur Beispiele.
122 -
123 -
Bei allen Diensten meldet man sich ab jetzt nur noch mit Extraadressen für jeden Shop an. Oder man ändert die Mailadressen dort ab.
124 -
125 -
*   Amazon: user+Shops.Amazon@example.net
126 -
*   Ebay: user+Shops.Ebay@example.net
127 -
*   Wein Müller: user+Shops.WeinMueller@example.net
128 -
*   Musikladen Mustermann: user+Shops.MusikMustermann@example.net
129 -
130 -
Wer jetzt viele Musikläden und Getränkelieferanten in der Liste hat kann auch hier wieder unterteilen und sortieren:
131 -
132 -
*   user+Shops.Musik."AnbieterA"@....
133 -
*   user+Shops.Musik."AnbieterB"@....
134 -
*   usw.
135 -
136 -
Auch hier gilt wieder: Weitere Untergliederung ist immer möglich. Einfach die Mailadresse beim Shop/Anbieter ändern auf die neue (hier ".Musik." dazwischen packen) Adresse und fertig. Keine Änderungen am Mailfilter nötig. Die **Sozialen Netzwerke** landen bei mit im Ordner "**SN**", ich bin ab und zu Tippfaul und lange Ordnernamen will ich auch nicht. Aber auch noch ein anderer Punkt hat gerade bei den sozialen Netzwerken zu einer Verkürzung bei der Ordnerbezeichnung geführt. Es gab da einen Anbieter der nur einen nicht gerade lange localpart vor dem @-Zeichen oder die komplette Adresse nicht zu lang sein durfte. Es war ausgerechnet ein nicht mal alter Dienst. Eher ein neue Fancy Service, so ein Hipsterzeugs. Da fand ich es sehr lächerlich nur sehr kurze Adressen zulässig waren. Da wurde sehr wahrscheinlich das Formular schnell zusammen kopiert und Hipstermässig ohne richtiger QA gearbeitet. **Fritzboxen** und **Vertäge** Für die einzelnen Fritzboxen in der Familie bekomme ich die Mails für Updates, Fehler beim DynDNS, VPN Status usw. Verträge werden für Gas, Strom, Internetanschluss, Handytarife usw. angelegt. Hier jetzt nur noch die Beispiele dazu:
137 -
138 -
*   user+Fritzbox.Karlsruhe.rs32@example.net
139 -
*   user+Fritzbox.Essen.FS371@example.net
140 -
*   user+Fritzbox.Essen.FB39@example.net
141 -
*   user+Fritzbox.Essen.BS206@example.net
142 -
*   user+Contracts.Strom@example.net
143 -
*   user+Contracts.Gas@example.net
144 -
*   user+Contracts.Telekom@example.net
145 -
*   user+Contracts.T-Mobile@example.net
146 -
147 -
**Lists** Bei Mailinglisten wird genau das gleiche gemacht:
148 -
149 -
*   user+Lists.debian@example.net
150 -
*   user+Lists.debian.updates@example.net
151 -
*   user+Lists.debian.security@example.net
152 -
*   user+Lists.redhat@example.net
153 -
*   user+Lists.linuxkernel@example.net
154 -
155 -
**_Die Filterregel(n)_** Damit das ganze funktioniert braucht man nur noch den/die Filter anlegen. Eigentlich benötigt man nur einen Filter. Aber in bestimmten Situationen sind 3 oder 4 Filter sinnvoll. Dazu gleich aber noch mehr. Als erstes benötigt man im Sieve Filter einen weiteren Eintrag ("variables") bei "require".
156 -
157 -
```
158 -
require ["reject","fileinto","imap4flags","body","vacation","copy","variables"];
159 -
```
160 -
161 -
Jetzt fügt man nur eine Regel im Filter dazu:
162 -
163 -
```
164 -
rule:[AutoSort1]
165 -
if header :matches "X-Original-To" "user+\*@example.net" { fileinto "AS.${1}"; stop; }
166 -
```
167 -
168 -
Diese Regel bewirkt:
169 -
170 -
1.  alles was zwischen "user+" und dem "@" steht wird in eine Variable gespeichert.
171 -
2.  Als Zielordner wird beim fileinto die Variable an den AutoSort Ordner (AS) gehangen.
172 -
173 -
Mail an "user+Shops.Amazon@example.net" wird zu: fileinto "AS.Shops.Amazon"; **Jetzt die Ausnahmen,** falls man noch weitere "Probleme" umgehen oder Anforderungen haben sollte. _Probleme:_ Es gibt Anbieter die kein "+"-Zeichen in der E-Mailadresse zulassen. Entweder können sie im Backend damit nicht umgehen oder wie ich bei einigen erfahren konnte, können sie das speichern und auch benutzen. Nur ist der Check im Onlineformular nicht dafür ausgelegt und zeigt einfach einen Fehler an. Wer eine Domain alleine benutz kann einfach einen Catch-All Account auf seine Mailadresse anlegen. Oder er nicht die komplette Domain als Catch-All benutzen möchte kann je nach Mailserver und Konfiguration auch einen Catch-All auf den User anlegen: "user%@example.net" weitergeleitet auf "user@example.net" Anschliessen kann man anstatt "user+Shops.Shopname@example.net" die Adresse "userShops.Shopname@example.net" benutzen. Als Filter dafür fügt man dann folgendes dazu:
174 -
175 -
```
176 -
rule:[AutoSort2]
177 -
if header :matches "X-Original-To" "user\*@example.net" { fileinto "AS.${1}"; stop; }
178 -
```
179 -
180 -
Wer mehrere verschiedene Domains auf einen Account zusammenfügt kann folgende Regel benutzen: \[cc lang=c\]
181 -
182 -
```
183 -
rule:[delimiter1]
184 -
if header :matches "X-Original-To" "user+_@_" { fileinto "AS.${1}"; stop; }
185 -
```
186 -
**Die Feeds** Vor den AutoSort Regeln habe ich noch die letzte Rule eingetragen. Da ich die RSS-Feeds nicht mit im Ordner AutoSort haben möchte filter ich diese vorher schon weg. Beispiel von oben: "feeds+News.DW@example.net"
187 -
188 -
```
189 -
rule:[feeds]
190 -
if header :matches "X-Original-To" "feeds+\*@example.net" { fileinto "Feeds.${1}"; stop; }
191 -
```
192 -
Damit ist auch schon alles erledigt. Ich muss nie wieder einen Filter anlegen für neuen Accounts, Shops, Servermails o.a. Ich muss nur die richtige Mailadresse bei der Anmeldung/Einrichtung eintragen. Alle wichtigen Mails kann ich weiter auf der Hauptadresse eintreffen lassen und sehe sie direkt im Posteingang. Der Rest bei Bedarf. Ich kann mir auch so sehr gut meine Zeit planen wann ich welche Mails lese. Foren, Shops, Feeds stehen bei mir ganz hinten auf der Todo. Die sieht ungefähr so aus, variiert aber immer mal ein wenig. Wobei auch nicht alle Kategorieren hier nicht aufgelistet sind.
193 -
194 -
1.  Posteingang
195 -
2.  Fritzbox
196 -
3.  Server
197 -
4.  Mailinglisten
198 -
5.  Soziale Netzwerke
199 -
6.  Foren
200 -
7.  Feeds
201 -
202 -
_**Benachrichtigungen am iPhone**_ Im Google+ Beitrag hatte ich die Notifikationen am iPhone erwähnt. Wenn alles weggefiltert wird sieht man die Mails erst wenn man in einen der vielen Ordner guckt. Bei iOS kann man in der Liste mit der "Inbox", "Papierkorb", "Entwürfe" usw. auf "Bearbeiten" und ganz unten auf "Ordner hinzufügen" tippen. In der Ordnerliste kann man jetzt die gewünschten Ordner auswählen. Bei mir sind das ein paar News und Blog Feeds, der Nagios Monitoring Ordner und alles was wichtig ist. Insgesamt maximal 10 Ordner. Der schöne Nebeneffekt ist die Notifizierung und die Anzeige der neuen Mails bei geschlossener Mail.App. Alle Mails die in der Inbox und den gerade hinzufügten Ordnern werden per iOS Notifikation auf dem iPhone und der Apple Watch angezeigt. In der Mitteilungszentrale sieht man sie auch. Aber bei der geschlossenen Mail.app werden nur die E-Mails aus der Inbox angezeigt. So bekomme ich mit wenn Nagios Dienste alarmiert, sehe sie und kann sie zu Kenntnis nehmen und reagieren. Kommt dann eine wichtige Mail in die Inbox und gucke nur auf den den entsperrten Homescreen, sehe ich an der Mail.app nur eine "1" und nicht auch noch alle ungelesenen Nagios Meldungen. Genau das gleiche gilt für alle hinzugefügten Ordner News, Blogs u.a., sie werden zwar benachrichtigt, aber stören nicht mehr. Damit sind das schon mal 2 Stufen der Benachrichtigung. Aber wir haben ja jetzt auch noch die Ordner die nicht in der Liste hinzugefügt wurden. Damit sind es jetzt also 3 Stufen was die Priorisierung der E-Mails angeht.
203 -
204 -
1.  Inbox = wichtig
205 -
2.  Ordner mit Benachrichtigung
206 -
3.  Ordner ohne, die werden gelesen wenn die Zeit dafür übrig ist.
207 -
208 -
Die grosse Anzahl der Ordner wirkt erst einmal Heftig. Ich benutze das jetzt aber schon etwas länger und kann sagen der Arbeitsablauf "E-Mails lesen" hat sich dadurch erleichtert. Ich kann mich einfach, sinnvoll und mich dann um die Sachen kümmern wie es gerade passend ist. Im Zug schnell die Inbox checken, danach ist Zeit für News und Blogs. Nach dem dort der erste Überlick über neue Artikel gemacht wurde kommen kurz Server Mails dran. Nichts auffälliges oder aktuell nichts machen kann, aber weiß was ich im Büro dann als erstes mache, geht es dann erst einmal zurück zu den Artikeln. Man ist einfach schnell in die einzelnen Bereiche der Kategorien gesprungen, checken, reagieren, planen, konsumieren usw.
209 -
210 -
**Kurz zu rss2email**
211 -
212 -
Ich benutze [rss2email](http://www.allthingsrss.com/rss2email/) (früher auch mal [feed2imap](http://home.gna.org/feed2imap/)) gerne für RSS-Feeds, da ich mit RSS-Readern nie so richtig warm geworden bin. RSS-Reader gibt es zwar auch richtig gute. Aber immer wenn ich mich gerade an einen gewohnt habe wurde die Entwicklung eingestampft. Wieder einen neuen suchen. Kurz drauf wurde die Entwicklung eingestellt. Das war mir dann irgend wann zu lästig. Dabei waren dann auch mal RSS-Reader die zwar von anderen Readern importieren konnten, aber nicht exportieren. Das war dann richtig übel, weil man die Feeds dann einzeln da raus kopieren musste und im neuen Eintragen. Wer also einen RSS-Reader sucht, eh gerne mit einem Mailclient arbeitet und dort auch viel mit Mailordnern macht sollte sich [rss2email](http://www.allthingsrss.com/rss2email/) oder [feed2imap](http://home.gna.org/feed2imap/) einmal angucken.
gelöscht content/2016-01-14-rock-solo-guitar-new-version.md
+0 −18
@@ -1,18 +0,0 @@
1 -
---
2 -
title: 'Rock - Solo Guitar (New Version)'
3 -
date: 2016-01-14 23:00:56
4 -
update: 2016-01-14 23:00:56
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags: [Alle Beiträge, Guitar, Musik, Solo, Song, Track]
8 -
preview: "Rock - Solo Guitar (New Version)"
9 -
categories: 
10 -
    - Internet
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
17 -
18 -
<iframe width="100%" height="166" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/235962771&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true"></iframe><div style="font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;"><a href="https://soundcloud.com/rpr-3" title="rpr_" target="_blank" style="color: #cccccc; text-decoration: none;">rpr_</a> · <a href="https://soundcloud.com/rpr-3/rock-solo-guitar-new-version" title="Rock - Solo Guitar (New Version)" target="_blank" style="color: #cccccc; text-decoration: none;">Rock - Solo Guitar (New Version)</a></div>
\ No newline at end of file
gelöscht content/2016-01-15-nightly-session-part-1-blues-in-a-minor.md
+0 −17
@@ -1,17 +0,0 @@
1 -
---
2 -
title: 'Nightly Session Part 1 Blues In A Minor'
3 -
date: 2016-01-15 00:38:56 +0000
4 -
update: 2016-01-15 00:38:56 +0000
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags: [Guitar, Musik, Solo, Song, Track]
8 -
preview: "Nightly Session Part 1 Blues In A Minor"
9 -
categories: 
10 -
    - Musik
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
17 -
<iframe width="100%" height="166" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/242004759&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true"></iframe><div style="font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;"><a href="https://soundcloud.com/rpr-3" title="rpr_" target="_blank" style="color: #cccccc; text-decoration: none;">rpr_</a> · <a href="https://soundcloud.com/rpr-3/nightly-session-part-1-blues-in-a-minor" title="Nightly Session Part 1 Blues In A Minor" target="_blank" style="color: #cccccc; text-decoration: none;">Nightly Session Part 1 Blues In A Minor</a></div>
\ No newline at end of file
gelöscht content/2016-01-15-nightly-session-part-2-rock-power-ballade.md
+0 −17
@@ -1,17 +0,0 @@
1 -
---
2 -
title: 'Nightly Session Part 2 Rock Power Ballade'
3 -
date: 2016-01-15 00:39:43 +0000
4 -
update: 2016-01-15 00:39:43 +0000
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags: [Guitar, Musik, Solo, Song, Track]
8 -
preview: "Nightly Session Part 1 Blues In A Minor"
9 -
categories: 
10 -
    - Musik
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
17 -
<iframe width="100%" height="166" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/242004962&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true"></iframe><div style="font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;"><a href="https://soundcloud.com/rpr-3" title="rpr_" target="_blank" style="color: #cccccc; text-decoration: none;">rpr_</a> · <a href="https://soundcloud.com/rpr-3/nightly-session-part-2-rock-power-ballade" title="Nightly Session Part 2 Rock Power Ballade" target="_blank" style="color: #cccccc; text-decoration: none;">Nightly Session Part 2 Rock Power Ballade</a></div>
\ No newline at end of file
gelöscht content/2016-01-16-bausatzprojekt-1-fuzz.md
+0 −30
@@ -1,30 +0,0 @@
1 -
---
2 -
title: 'Bastelprojekt 1 Bender Mk3 Fuzz fast fertig.'
3 -
date: 2016-01-16 14:00:23
4 -
update: 2016-01-16 14:00:23
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags:
8 -
    - Bausatz
9 -
    - Effektgeräte
10 -
    - Guitar
11 -
    - Musik
12 -
preview: "Im Frühjahr 2015 habe ich bei Mike seine ersten Effektgerätbausätze gesehen. Recht günstig diese kleinen Dinger."
13 -
categories: 
14 -
    - Musik
15 -
toc: false
16 -
hide: false
17 -
type: post
18 -
---
19 -
20 -
Im Frühjahr 2015 habe ich bei Mike seine ersten Effektgerätbausätze gesehen. Recht günstig diese kleinen Dinger. Platine, Schalter, Buchsen und weitere Kleinteile für kleines Geld. Dazu kann man direkt die passenden Gehäuse bestellen. Auch gleich mit vorgebohrten Löchern wenn man nicht selbst bohren möchte. Blank oder farbig. Je nachdem wie man es möchte. Also ist der Selbstgestaltung keine Grenze gesetzt. Mike war von Fuzz sehr begeistert. Bei einer Session letzen Sommer meinte er:
21 -
<!--more-->
22 -
23 -
> Ich habe mich in den Fuzz verliebt.
24 -
25 -
Er hörte sich auch sehr gut an. Also nicht Mike, der Fuzz. Auf der Internetseite von [Musikding.de](http://www.musikding.de) sind auch Soundbespiele bei den Bausätzen zu hören.
26 -
27 -
![Fuzzy](/images/posts/fuzzy.webp)
28 -
29 -
30 -
[Der Bender Mk3 - Germanium Fuzz Bausatz](http://www.musikding.de/Der-Bender-Mk3-Germanium-Fuzz-Bausatz) 26,- € + Gehäuse insgesamt 38,50 €. Ich habe mich für das vorgebohrte Gehäuse entschieden. Zusätzlich habe ich noch 5 rote Regler bestellt. Die restlichen werde ich für den zweiten Bausatz benutzen. Da ich später noch weitere Bausätze bestellen möchte kann ich auch später noch die Farben variieren. Später werde ich noch einen Artikel zum Compressor schreiben. Wenn beide dann da sind gehe ich noch etwas mehr auf Details zu den Bausätzen ein. Dann auch mit mehr Bildern von der Lieferung, auspacken und vom basteln.
gelöscht content/2016-01-16-lieferung-fuzz-und-compressor.md
+0 −32
@@ -1,32 +0,0 @@
1 -
---
2 -
title: 'Lieferung Fuzz und Compressor'
3 -
date: 2016-01-16 15:09:31
4 -
update: 2016-01-16 15:09:31
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags:
8 -
    - Bausatz
9 -
    - Effektgeräte
10 -
    - Guitar
11 -
    - Musik
12 -
preview: 'Die ersten beiden Bausätze sind eingetroffen. Der Compressor-Dyna und der "Der Bender Mk3 Fuzz".'
13 -
categories: 
14 -
    - Musik
15 -
toc: false
16 -
hide: false
17 -
type: post
18 -
---
19 -
20 -
Die ersten beiden Bausätze sind eingetroffen. Der Compressor-Dyna und der "Der Bender Mk3 Fuzz". Bei der Bestellung hatte ich meinen Namen mit angegen und den Firmenname. Da wir uns auch privates Zeug in die Firma schicken lassen dürfen ging auch dieses Päckle an unsere Poststelle. Auf dem Etikett stand nur der Firmenname mit der Adresse. Der Versender [Musikding.de](http://musikding.de) hat aber das fehlen des Empfängernamen bemerkt und handschriftlich noch mit drauf gepackt.
21 -
<!--more-->
22 -
23 -
24 -
![Der Compressor Dyna Compressor Bausatz](/images/posts/Der-Compressor-Dyna-Compressor-Bausatz.jpg.webp)
25 -
26 -
![Der Compressor Dyna Compressor Bausatz](/images/posts/Der-Compressor-Dyna-Compressor-Bausatz.jpg.webp)
27 -
28 -
29 -
Das hatte ich bei anderen schon mal anders erlebt und Pakete konnten nicht zugeordnet werden und mussten wieder zurück an den Absender gehen. Lob an den Absender.
30 -
In dem Packet lagen die beiden Bausätze, 2 Gehäuse und ein kleines Tütchen mit den Reglern.
31 -
32 -
Als erstes werde ich den Fuzz zusammen bauen. Nachher als erstes den Lötkolben bereitlegen und anfangen.
gelöscht content/2016-01-19-bausatzprojekt-2-compressor-dyna.md
+0 −29
@@ -1,29 +0,0 @@
1 -
---
2 -
title: 'Bausatzprojekt 2 Compressor-Dyna'
3 -
date: 2016-01-19 12:10:43
4 -
update: 2016-01-19 12:10:43
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags:
8 -
    - Bausatz
9 -
    - Effektgeräte
10 -
    - Guitar
11 -
    - Musik
12 -
preview: "Das 2. Bausatzprojekt wird ein Compressor."
13 -
categories: 
14 -
    - Musik
15 -
toc: false
16 -
hide: false
17 -
type: post
18 -
---
19 -
20 -
Das 2. Bausatzprojekt wird ein Compressor. [Der Compressor Dyna - Compressor Bausatz](http://www.musikding.de/Der-Compressor-Dyna-Compressor-Bausatz) + Gehäuse kostet der Bausatz bei [musikding.de](http://www.musikding.de) 35,- €
21 -
<!--more-->
22 -
23 -
24 -
![Der Compressor Dyna Compressor Bausatz](/images/posts/Der-Compressor-Dyna-Compressor-Bausatz.jpg.webp)
25 -
26 -
27 -
Der Compressor Dyna Compressor Bausatz (Bildquelle: Musikding.de)
28 -
29 -
Der Compressor und der Fuzz wurden heute geliefert. Dazu später mehr, Bilder und noch ein paar Worte zum Versender.
gelöscht content/2016-01-21-bausatzprojekt-3-volume-schalter.md
+0 −30
@@ -1,30 +0,0 @@
1 -
---
2 -
title: 'Bausatzprojekt 3 Volume Schalter'
3 -
date: 2016-01-21 15:00:43
4 -
update: 2016-01-21 15:00:43
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags:
8 -
    - Bausatz
9 -
    - Effektgeräte
10 -
    - Guitar
11 -
    - Musik
12 -
preview: "Die ersten beiden Bausätze sind gerade da, da habe ich die nächsten zwei bestellt."
13 -
categories: 
14 -
    - Musik
15 -
toc: false
16 -
hide: false
17 -
type: post
18 -
---
19 -
20 -
Die ersten beiden Bausätze sind gerade da, da habe ich die nächsten zwei bestellt. Da ich mir ein nettes Board zusammenstellen möchte habe ich noch einmal durch den Shop gestöbert und eine Volume Schalter, so wie den Bluelay - Delay Bausatz.  
21 -
<!--more-->
22 -
23 -
![Volume Schalter Bausatz](/images/posts/img_1074.webp)
24 -
25 -
Den Volume Schalter habe ich aus zwei Gründen gewählt.
26 -
27 -
1.  Bei Solos mit leisem Part kann ich gezielt an diesen Stellen auf eine bestimmte Lautstärke per Fußschalter umschalten.
28 -
2.  Anders herum möchte ich meine gewünschte Lautstärke haben und bei Bedarf schnell noch etwas drauf drehen. Wenn die anderen mal lauter wurden oder meine Einstellung an manchen Stellen nicht laut genug ist schnell noch eine Schüppe drauf legen zu können.
29 -
30 -
Das mache ich aktuell direkt am Volumeregler an der Gitarre. Bei manchen Songs muss das sehr schnell gehen, da die Übergänge sehr kurz sind. Dabei genau die richtige Lautstärke zu treffen geht auch mal schief. Mal ist man zu laut oder mal zu leise. Einen weiteren Vorteil bei diesen Volume Schalter, gegen über dem Regler an der Gitarre, ist der parallel geschaltete Kondensator, durch dem zu keinem  Höhenklau kommt. Der Bausatz kostet 8,50 € + 12,00 € für das Gehäuse.
gelöscht content/2016-01-21-bausatzprojekt-4-bluelay-delay.md
+0 −25
@@ -1,25 +0,0 @@
1 -
---
2 -
title: 'Bausatzprojekt 4 Bluelay - Delay'
3 -
date: 2016-01-21 15:00:38
4 -
update: 2016-01-21 15:00:38
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags:
8 -
    - Bausatz
9 -
    - Effektgeräte
10 -
    - Guitar
11 -
    - Musik
12 -
preview: "Die ersten beiden Bausätze sind gerade da, da habe ich die nächsten zwei bestellt."
13 -
categories: 
14 -
    - Musik
15 -
toc: false
16 -
hide: false
17 -
type: post
18 -
---
19 -
20 -
Die letzte Tretmiene ist ein Delay. Das Bluelay ist ein digitales Delay, welches laut Beschreibung analog klingen soll. Auf der Artikelseite sind zwei Soundbeispiele. Genau was ich gesucht habe und mir zusagt.
21 -
22 -
![Das Bluelay Delay](/images/posts/img_1075.webp)
23 -
24 -
25 -
Auch hier der Preis: 22,50 € + Gehäuse 11,50 €. Das war dann der letzte Bausatz der neuen Effektgeräte. Jetzt fängt der Bastelspass bald an. Die nächsten Tage werden alle Schaltpläne ausgedruckt und erst einmal das Bastelprojekt 3 (Volume Schalter) gemacht, oder auch nicht. Die beiden zuletzt bestellten sind ja noch gar nicht da. Also doch am Wochenende eine der anderen Tretminen. Das ist von den vier Bausätzen der leichteste. Genau das richtige um nach so langer Zeit langsam mit dem Löten anzufangen.
gelöscht content/2016-01-23-mpow-magneto-headset.md
+0 −42
@@ -1,42 +0,0 @@
1 -
---
2 -
title: 'MPOW Magneto Headset'
3 -
date: 2016-01-23 00:03:31
4 -
update: 2016-01-23 00:03:31
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags: [Bluetooth, Musik, Technik, Telefon, Zubehör]
8 -
preview: "Die In-Ear Headphones Earpods wurden am 12 September 2012 von Apple vorgestellt. Wie üblich bei Apple wurden Zahlen genannt und dramatisch darüber berichtet wie schwer es ist einen solchen Kopfhörer zu entwickeln."
9 -
categories: 
10 -
    - Technik
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
Die In-Ear Headphones Earpods wurden am 12 September 2012 von Apple vorgestellt. Wie üblich bei Apple wurden Zahlen genannt und dramatisch darüber berichtet wie schwer es ist einen solchen Kopfhörer zu entwickeln. Aber Apple rettet ja die Welt und hat drei Jahre Entwicklung in einen Kopfhörer gesteckt, um den Ultimativen Kopfhörer herzustellen. Apple hat dafür tausende von Ohrformen analysiert. So entstanden dann die Earpods, die fast jedem passen sollten.
17 -
<!--more-->
18 -
19 -
![Earpods](/images/posts/earpods-2-300x300.webp)
20 -
21 -
22 -
Mir passen diese Kopfhörer überhaupt nicht. Sie fallen nicht nur beim laufen alle paar Meter runter, nein selbst im stehen rutscht mir dieser Kopfhörer alle paar Minuten oder auch Sekunden aus dem Ohr. Ich benutze ein Headset um die Hände frei zu haben. Nicht um andauernd hingreifen zu müssen, damit es nicht komplett raus rutscht.
23 -
24 -
![Earpods](/images/posts/earpods-1-300x225.webp)
25 -
26 -
27 -
In letzer Zeit habe ich sie noch ein paar mal ausprobiert. Wir werden wohl nie Freunde werden. Also habe ich vor ein paar Tagen ein wenig nach einem neuen Headset gesucht. Schnell war klar, ein In-Ear wird es werden. Irgendwann viel mir das Headset von MPOW auf. Die Artikel und Videos über das MPOW Magneto waren durchweg sehr positiv. Dieses Headset ist ein Bluetooth Headset, hat kleine Bügel (Stabilisatoren) in verschiedenen Grössen zur weiteren Fixierung im Ohr.
28 -
29 -
![Mpow-Magneto](/images/posts/Mpow-Magneto-2-300x169.webp)
30 -
31 -
32 -
Interessant ist die Magnetfunktion des Headsets. Sie hält nicht nur die beiden Seiten zusammen beim Tragen um den Hals, damit werden auch Anrufe angenommen/beendet oder Musik gestartet/gestoppt.
33 -
34 -
![Mpow-Magneto](/images/posts/Mpow-Magneto-3-300x288.webp)
35 -
36 -
37 -
Wie üblich sind mehrere Ohrstöpsel in verschiedenen Grössen im Lieferumfang enthalten. Zusätzlich sorgen Stabilisatoren für einen besseren Halt im Ohr. Auch hier in unterschiedlichen Grössen. Die Kopfhörer sitzen ohne den Stabilisator sehr gut im Ohr, mit diesen ist aber noch ein weiterer Punkt im Ohr vorhanden der für halt sorgt. Sonst wird ein In-EarKopfhörer durch das Kabel meistens nach unten gezogen, sitzt dann schief im Ohr, was die Ursache für ein rausrutschen. Genau das verhindern die Stabilisatoren. In der ersten Zeit sind sie noch ungewohnt, aber man gewöhnt sich sehr schnell an sie und bemerkt sie nicht mehr.
38 -
39 -
![Mpow-Magneto](/images/posts/Mpow-Magneto-1-300x180.webp)
40 -
41 -
42 -
Die Ohrstöpsel selbst sitzen sehr fest am Gehäuse. Beim austauschen für die passende Grösse musste man schon etwas ziehen. Das aufstecken der anderen war auch mit etwas fummeln verbunden. Sie werden aber wohl nie einfach abgehen und im Ohr stecken bleiben wenn man die Kopfhörer aus dem Ohr zieht. Das ist mir bei anderen In-Ears schon ein paar mal passiert. Bis jetzt wurde das Headset nur ein paar mal getestet. Die nächste Zeit wird zeigen wie es sich im Alltag bewährt. Da man sie einfach um den Nacken herumführen kann und bei nicht benutzen vorne durch die Magenete zusammen schnappen lassen kann, können sie auch nicht verloren gehen. Bei einem Anruf einfach auseinander ziehen und in die Ohren stecken. Wie erwähnt ist dies auch beim Musik hören benutzt werden. Wer bei der Arbeit Musik hört kennt die Unterbrechungen durch die Kollegen. Kopfhörer aus den Ohren ziehen und einfach zusammen schnappen lassen. Musik stoppt. Auseinanderziehen, in die Ohren stecken und die Musik spielt weiter. Neben den anderen Funktionen sind diese beiden für mich das Argument für den Kauf gewesen. Jetzt heisst es erst einmal testen.
gelöscht content/2016-02-01-da-liegt-mxr-m102-dyna-comp-auf-dem-tisch.md
+0 −29
@@ -1,29 +0,0 @@
1 -
---
2 -
title: 'Da liegt MXR M102 "dyna comp" auf dem Tisch'
3 -
date: 2016-02-01 15:24:59
4 -
update: 2016-02-01 15:24:59
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags:
8 -
    - Effektgeräte
9 -
    - Guitar
10 -
    - Musik
11 -
preview: "Vor ein paar Wochen habe ich für einen Arbeitskollegen einen Bass mit nach Essen genommen. Fahre ja eh jedes Wochenende nach Essen. Da bietet sich das an für jemanden etwas mit zunehmen."
12 -
categories: 
13 -
    - Musik
14 -
toc: false
15 -
hide: false
16 -
type: post
17 -
---
18 -
19 -
Vor ein paar Wochen habe ich für einen Arbeitskollegen einen Bass mit nach Essen genommen. Fahre ja eh jedes Wochenende nach Essen. Da bietet sich das an für jemanden etwas mit zunehmen. Der Käufer hat sich für seinen Bass entschieden und ich habe das Gigbag wieder mit zurück nach Karlsruhe genommen. Gehe in sein Büro um es wieder abzuliefern. Liegt da eine kleine schwarze Box mit rotem Aufkleber.
20 -
<!--more-->
21 -
22 -
![MXR M102 Dyna Comp](/images/posts/IMG_9117-e1454339397491-1024x768.webp)
23 -
24 -
MXR M102 "Dyna Comp" steht drauf. Er hat sich den bestellt und mit seinem Bass getestet. Ihm klaut der Dyna zu viele Bässe von seinem Bass. Ein anderer Kollege hat das Teil an seiner Stratocaster getestet und fand es dafür genau richtig. Das Angebot den "Dyna Comp" auch mal anzuspielen konnte ich natürlich nicht ausschlagen. Also die Box unter dem Arm geklempt und nachher dann mal antesten.
25 -
26 -
![MXR M102 dyna comp](/images/posts/IMG_7260-e1454339420251-225x300.webp)
27 -
28 -
29 -
Soundbeispiele werden folgen. Da ich dieses Wochenende mal das Zoom mit Audiointerface in Essen gelassen habe, kann ich auch gleich Aufnahmen mit dem Samson C-03 U Studio Großmembran Kondensator Mikrofon testen. Dank integrierten USB Audiointerface komme ich damit auch ohne Probleme für die Aufnahmen in den Rechner.
gelöscht content/2016-02-02-gsm-codes.md
+0 −24
@@ -1,24 +0,0 @@
1 -
---
2 -
title: 'GSM Codes'
3 -
date: 2016-02-02 14:42:56
4 -
update: 2016-02-02 14:42:56
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
    - GSM
9 -
    - Codes
10 -
preview: "Aktuell offline. Tabelle muss nach der Migration angepasst werden."
11 -
categories: 
12 -
    - Technik
13 -
toc: false
14 -
hide: false
15 -
type: post
16 -
---
17 -
18 -
19 -
Aktuell offline. Tabelle muss nach der Migration angepasst werden.
20 -
21 -
22 -
<!--
23 -
\[\["Rufumleitung auf Voicemail","",""\],\["\*\*67\*3311#","Rufumleitung auf Voicemail, wenn besetzt, aktivieren",""\],\["\*\*62\*3311#","Rufumleitung auf Voicemail, wenn nicht erreichbar, aktivieren",""\],\["\*\*61\*3311#","Rufumleitung auf Voicemail nach 15 Sekunden",""\],\["\*\*61\*3311\*11\*ZEIT#","Rufumleitung auf Voicemail nach 5, 10, 15, 25 oder 30 Sekunden (Zahl anstelle von ZEIT eingeben)",""\],\["\*\*004\*3311#","Aktivieren aller bedingten Umleitungen auf Voicemail",""\],\["\*\*21\*3311#","Sofortige Rufumleitung auf Voicemail f\\u00fcr alle Anrufe",""\],\["","",""\],\["Voicemail-Umleitung deaktivieren","",""\],\["##67#","Rufumleitung, wenn besetzt, deaktivieren",""\],\["##62#","Rufumleitung, wenn nicht erreichbar, deaktivieren",""\],\["##61#","Verz\\u00f6gerte Rufumleitung deaktivieren",""\],\["##004#","Alle bedingten Rufumleitungen deaktivieren",""\],\["##002#","Alle Rufumleitungen deaktivieren",""\],\["","",""\],\["Status f\\u00fcr bedingte Rufumleitung abfragen","",""\],\["\*#67#","Zeigt an, ob die Rufumleitung im Besetztfall aktiv ist",""\],\["\*#62#","Zeigt an, ob die Rufumleitung bei Nichterreichbarkeit aktiv ist",""\],\["\*#61#","Zeigt an, ob die verz\\u00f6gerte Rufumleitung aktiv ist",""\],\["","",""\],\["N\\u00fctzliche Codes","",""\],\["\*#06#","Abfrage der IMEI des iPhone",""\],\["\*135#","Eigene Rufnummer bei T-Mobile abfragen",""\],\["\*#5005\*74663#","Eigene Rufnummer von SIM-Karte lesen",""\],\["","",""\],\["SIM-Karten anderer Anbieter nutzen","",""\],\["\*#5005\*86#","Anzeige der Rufnummer der Mailbox",""\],\["\*5005\*86\*MAILBOX#","Setzen der Mailbox-Nummer (statt MAILBOX eintragen)",""\],\["##5005\*86#","L\\u00f6schen der Mailbox-Nummer",""\],\["\*#5005\*7672#","Aktuelle Nummer der SMS-Zentrale anzeigen",""\],\["\*5005\*7672\*SMS#","Setzen der Nummer der SMS-Zentrale (statt SMS eingeben)",""\],\["##5005\*7672#","L\\u00f6schen der Nummer der SMS-Zentrale",""\],\["","",""\],\["Allgemeine Rufumleitung konfigurieren","",""\],\["\*\*21\*ZIEL#","oder Festnetz) programmieren",""\],\["\*21#","Umleitung zur gespeicherten Nummer aktivieren",""\],\["#21#","Rufumleitung ausschalten",""\],\["##21#","Nummer f\\u00fcr Rufumleitung l\\u00f6schen",""\],\["","",""\],\["\\u00dcbermittlung der eigenen Nummer einstellen","",""\],\["\*31#ZIEL","Nummer ZIEL anrufen, dabei eigene Nummer zeigen",""\],\["#31#ZIEL","Nummer ZIEL anrufen, dabei eigene Nummer unterdr\\u00fccken",""\],\["\*#31#","Status der Rufnummer\\u00fcbermittlung anzeigen",""\],\["","",""\],\["Verhalten bei Anruf im laufenden Gespr\\u00e4ch","",""\],\["\*43#","Anklopfen erlauben (Voraussetzung f\\u00fcr Konferenzen)",""\],\["#43#","Anklopfen nicht erlauben",""\],\["\*#43#","Status f\\u00fcr Funktion Anklopfen anzeigen",""\],\["","",""\],\["Verhalten von Zweitkarten (Multi-SIM)","",""\],\["\*222#","Diese Karte f\\u00fcr SMS\\/MMS Empfang aktivieren (T-Mobile)",""\],\["\*221#","Status f\\u00fcr SMS\\/MMS-Empfang anzeigen (T-Mobile)",""\],\["\*125#","SMS-Empfang mit dieser Karte (O2)",""\],\["\*126#","MMS-Empfang mit dieser Karte (O2)",""\],\["","",""\],\["PINs \\u00e4ndern und mit PUK entsperren","",""\],\["\*\*04\*PIN\*NEUE\_PIN\*NEUE\_PIN#","PIN in NEUE\_PIN \\u00e4ndern",""\],\["\*\*05\*PUK\*NEUE\_PIN\*NEUE\_PIN#","PIN mit PUK entsperren",""\],\["\*\*042\*PIN2\*NEUE\_PIN2\*NEUE\_PIN2#","PIN 2 in NEUE\_PIN2 \\u00e4ndern",""\],\["\*\*052\*PUK2\*NEUE\_PIN2\*NEUE\_PIN2#","PIN 2 mit PUK 2 entsperren",""\],\["","",""\],\["### Wichtige Mailbox-Nummern","",""\],\["Anbieter","Kennzahl","Kurzwahl im eigenen Netz"\],\["T-Mobile","13","3311"\],\["Vodafone","50","5500"\],\["O2","33","333"\],\["E-Plus","99","9911"\],\["","",""\]\]
24 -
-->
gelöscht content/2016-02-02-iphone-ios-gsm-codes.md
+0 −29
@@ -1,29 +0,0 @@
1 -
---
2 -
title: 'iPhone iOS GSM Codes'
3 -
date: 2016-02-02 15:49:36
4 -
update: 2016-02-02 15:49:36
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
    - Codes
9 -
    - GSM
10 -
    - iOS
11 -
    - iPhone
12 -
    - Mailbox
13 -
    - Rufumleitung
14 -
    - Technik
15 -
    - Telefon,
16 -
    - Weiterleitung
17 -
preview: ""
18 -
categories: 
19 -
    - Technik
20 -
toc: false
21 -
hide: true
22 -
draft: true
23 -
type: post
24 -
---
25 -
26 -
27 -
\[table id=1 /\] 
28 -
29 -
Philip Tusch von Apfelpage erwähnt in [einem Artikel](http://www.apfelpage.de/2016/02/04/ueberbleibsel-mit-funktionen-67-nuetzliche-gsm-codes-fuer-das-iphone/ ) noch das hier der Feldtestmodus erwähnt werden könnte: "Ergänzen könnte man die Liste noch um den Code für den Feldtestmodus, der beispielsweise genau in Dezibel anzeigt, wie stark euer Mobilfunkempfang aktuell wirklich ist: _3001#12345#_. Diese Funktion gibt es übrigens auch schon seit 2007."
gelöscht content/2016-02-03-bausatzprojekt-3-volume-switch-fertig.md
+0 −30
@@ -1,30 +0,0 @@
1 -
---
2 -
title: 'Bausatzprojekt 3 Volume Switch fertig.'
3 -
date: 2016-02-03 00:03:32
4 -
update: 2016-02-03 00:03:32
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags:
8 -
    - Bausatz
9 -
    - Effektgeräte
10 -
    - Guitar
11 -
    - Musik
12 -
preview: "Wie schon erwähnt ist der 3. Bausatz der erste der zusammen gebaut wurde. Der Volume Switch ist vorhin fertig geworden."
13 -
categories: 
14 -
    - Musik
15 -
toc: false
16 -
hide: false
17 -
type: post
18 -
---
19 -
20 -
Wie schon erwähnt ist der 3. Bausatz der erste der zusammen gebaut wurde. Der Volume Switch ist vorhin fertig geworden. Die Wahl war genau richtig. Die Zeit in denen der Lötkolben zuletzt an war ist schon etwas länger her. Da war dieser Bausatz genau richtig um wieder damit anzufangen. Zum Schluss lief es dann auch wieder richtig gut. Die zwei kleinen Fehler wurden schnell korrigiert.  Am Poti hatte ich links und rechts vertauscht und bei der LED war auch vertauscht. Kleine blöde Fehler, aber das kann ja mal passieren.
21 -
<!--more--> 
22 -
Die waren dann auch schnell gefunden und jetzt funktioniert der Volume Switch wie er soll.  Beim testen fällt auf das die Höhen wirklich bei Aktivierung konstant bleiben. Genau wie in der Beschreibung beschrieben. Leise Passagen im Song können mit dem gleichen Sound gespielt werden und es klingt nicht wie üblich dumpfer. Außerdem treffe ich bei manchen Songs am Regler der Gitarre oft nicht genau die richtige Lautstärke. Gerade wenn der Übergang sehr kurz ist.
23 -
24 -
![Volume Switch](/images/posts/IMG_1121-1-e1454456497787-1024x768.webp)
25 -
26 -
27 -
![Volume Switch](/images/posts/IMG_1122-e1454456449498-1024x768.webp)
28 -
29 -
30 -
Also fertig ist die erste Tretmine, macht Spaß beim Spielen und beim zusammen löten. Ich habe ja noch drei Stück hier liegen. Der nächste wird der Fuzz. Manche Sachen werde ich die Tage schon anfangen. Die schwierigen Sachen beim Fuzz werde ich aber erst machen wenn die 3. bzw 4. Hand da ist. Den diese netten kleinen klemmen fehlen in manchen Situationen schon. Daher habe ich bei Amazon vorhin eine bestellt. Dieses Mal ging es zwar auch ohne, aber sollte man sich lieber gleich mit bestellen. Kostet auch nur 9 €.
gelöscht content/2016-02-10-bastelprojekt-1-bender-mk3-fuzz-fast-fertig.md
+0 −42
@@ -1,42 +0,0 @@
1 -
---
2 -
title: 'Bastelprojekt 1 Bender Mk3 Fuzz fast fertig.'
3 -
date: 2016-02-10 21:28:27
4 -
update: 2016-02-10 21:28:27
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/04/programming.webp"
7 -
tags:
8 -
    - Bausatz
9 -
    - Effektgeräte
10 -
    - Guitar
11 -
    - Musik
12 -
preview: "Nachdem der Volume Switch letzte Woche fertig zusammmen gebaut hatte wurde gleich als erstes die 3. Hand bestellt."
13 -
categories: 
14 -
    - Musik
15 -
toc: false
16 -
hide: false
17 -
type: post
18 -
---
19 -
20 -
21 -
Nachdem der Volume Switch letzte Woche fertig zusammmen gebaut hatte wurde gleich als erstes die 3. Hand bestellt. Bei dem Effektgerät war es ohne kein Problem. Aber das nächste hat eine Platine, auf die ein paar Widerstände, Kondensatoren usw draufgelötet werden wollen. Trotzdem wollte ich letzte Woche auch schon einmal mit dem Fuzz anfangen. Die Potis, Klinkestecker, LED und Schalter schon mal verdrahten ist als Entspannung neben dem TV auch etwas für Grobmotoriker. Da geht nichts bei schief. Schief ging er später etwas. Aber nur eine Kleinigkeit. Als ich sehr schnell mit der Verkabelung der oben genannten Teile fertig war und die Platine in der Hand halte geht mir der Gedanke durch den Kopf:
22 -
<!--more-->
23 -
24 -
> Ach komm schon. Die Wiederstände sind kein Problem.
25 -
26 -
Gedacht getan und schon waren sie auf der Platine verlötet. Das gleiche spielte sich dann nach einander mit Kondensatoren, Transostoren, Dioden und allem anderen ab.
27 -
28 -
> Ach komm schon. Die ... sind kein Problem.
29 -
30 -
![Bender MK3 FUZZ](/images/posts/IMG_1435-e1455138449549-1024x768.webp)
31 -
32 -
33 -
Bis zur vorletzen Diode hat auch alles sehr gut geklappt. Ok, mit der 3. Hand wären manche Löststellen besser geworden. Die kam aber erst am nächsten Tag an. Die vorletzte Diode war eine A1108. Wie bei allen anderen Teilen wollte ich die Kontakte zurecht biegen um sie passend auf die Platine zu bekommen. Da machte es dann einmal knack und die war hin. Dafür klappte dann aber die letzte besser.
34 -
35 -
![Bender MK3 FUZZ 2](/images/posts/IMG_7208-e1455138417739-1024x768.webp)
36 -
37 -
38 -
Direkt einmal 5 Stück als Ersatz bestellt. Sicher ist sicher. Die sind auch die Tage angekommen. Am Samstag werde ich dann die letzte Diode einbauen und sehen ob alles andere richtig zusammen gebaut wurde. Hier noch kurz die Info zur 3. Hand von Amazon.
39 -
40 -
<!--
41 -
\[AMAZONPRODUCTS asin="B000T9UCHI" features="1" desc="1" locale="de" public\_key="AKIAJDRNJ6O997HKGXW" private\_key="Nzg499eVysc5yjcZwrIV3bhDti/OGyRHEYOWO005" partner\_id="blogpretzlaff-21"\]
42 -
-->
gelöscht content/2016-02-12-vox-v847a-wah-wah-pedal.md
+0 −37
@@ -1,37 +0,0 @@
1 -
---
2 -
title: 'VOX V847A Wah Wah Pedal'
3 -
date: 2016-02-12 10:00:38
4 -
update: 2016-02-12 10:00:38
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags: [Effektgeräte, Guitar, Musik, Test, VOX, Wah-Wah, Zubehör]
8 -
preview: "Um im BGP manche Netze nicht zu erlauben:"
9 -
categories: 
10 -
    - Musik
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
17 -
Dieses mal nicht selbst gelötet, dafür aber selbst gekauft. Da ich noch kein Wah-Wah habe, aber in Zukunft eins brauche, musste ein Wah-Wah her. Irgendwie stehen Effektgerätehersteller alle aktuell auf rot. Der Karton von VOX ist genau so rot wie der von dem Compressor den ich letztens getestet habe. Sieht nicht schlecht aus, wirkt stylisch. Wird aber trotzdem im schrank landen, denn das VOX Wah V847A wird mit einer Tasche geliefert.
18 -
<!--more-->
19 -
20 -
![VOX V847A Wah Wah Pedal](/images/posts/IMG_1127-e1455234520305-150x150.webp)
21 -
22 -
23 -
![VOX V847A Wah Wah Pedal](/images/posts/IMG_1128-e1455234629727-768x1024.webp)
24 -
25 -
Die sehr wahr scheinlich im gleichen Schrank landen wird wie der Karton. Außer das Pedal passt nachher mal nicht mehr auf das Pedalboard. Vom Sound her ist es ähnlich wie das Cry-Baby von VOX. Man muss aber schon genau hinhören um wirklich einen Unterschied feststellen zu können. Beim "nur mal beide testen" ist es schwer diesen Unterschied wirklich zu hören.
26 -
27 -
![VOX V847A Wah Wah Pedal](/images/posts/IMG_1129-e1455234758942-150x150.webp)
28 -
29 -
30 -
Gitarristen die ein Cry-Baby regelmässig spielen werden es sehr wahrscheinlich hören. Was am Anfang sehr gewöhnungsbedürftig war, ist der starke Druckpunkt um es zu aktivieren. Man muss das Pedal schon sehr feste nach vorne kippen. Im sitzen sehr schwer, aber im stehen geht es sehr gut. Ein brauchbares Wah-Wah Pedal für eine sehr guten Preis.
31 -
32 -
![VOX V847A Wah Wah Pedal](/images/posts/IMG_1131-e1455234812127-150x150.webp)
33 -
34 -
35 -
Vom Sound her nicht zu extrem und eher ein weichers Wah-Wah. Eben der Klassiker unter den Wah-Pedalen.
36 -
37 -
<!-- Unten im Player sind 4 Soundbeispiele mit dem VOX V847A. Zwei davon Clean und zwei verzerrte.     \[playlist artists="false" ids="518,517,516,515"\] -->
gelöscht content/2016-02-24-wordpress-slack-com-telegram-icinga.md
+0 −78
@@ -1,78 +0,0 @@
1 -
---
2 -
title: 'Wordpress, Slack.com, Telegram, Icinga'
3 -
date: 2016-02-24 11:40:56
4 -
update: 2016-02-24 11:40:56
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags: [Internet, Wordpress, Icinga, Slack, Telegram]
8 -
preview: "Eher durch Zufall bin ich auf Slack.com gestoßen. Ich hatte nach einer Chatlösung für Seiten gesucht. Dabei bin ich auf Chatlio gestossen. Damit wurden die Anfragen per Chat in Slack gesendet. Antworten musste man dann aber leider über den Adminbereich vom Wordpress."
9 -
categories: 
10 -
    - internet
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
17 -
Eher durch Zufall bin ich auf Slack.com gestoßen. Ich hatte nach einer Chatlösung für Seiten gesucht. Dabei bin ich auf Chatlio gestossen. Damit wurden die Anfragen per Chat in Slack gesendet. Antworten musste man dann aber leider über den Adminbereich vom Wordpress. Dabei ist mir aber die Nagios/Icinga App im Slack aufgefallen. Installiert und im Icinga konfiguriert schickt es jetzt die Alarme in einen Slack Raum. slack\_nagios.cfg
18 -
19 -
<!--more-->
20 -
21 -
```
22 -
define contact {
23 -
      contact\_name                             slack
24 -
      alias                                    Slack
25 -
      service\_notification\_period              24x7
26 -
      host\_notification\_period                 24x7
27 -
      service\_notification\_options             w,u,c,r
28 -
      host\_notification\_options                d,r
29 -
      service\_notification\_commands            notify-service-by-slack
30 -
      host\_notification\_commands               notify-host-by-slack
31 -
}
32 -
33 -
define command {
34 -
      command\_name notify-service-by-slack
35 -
      command\_line /usr/local/bin/slack\_nagios.pl -field slack\_channel=#alerts -field HOSTALIAS="$HOSTNAME$" -field SERVICEDESC="$SERVICEDESC$" -field SERVICESTATE="$SERVICESTATE$" -field SERVICEOUTPUT="$SERVICEOUTPUT$" -field NOTIFICATIONTYPE="$NOTIFICATIONTYPE$"
36 -
}
37 -
38 -
define command {
39 -
      command\_name notify-host-by-slack
40 -
      command\_line /usr/local/bin/slack\_nagios.pl -field slack\_channel=#ops -field HOSTALIAS="$HOSTNAME$" -field HOSTSTATE="$HOSTSTATE$" -field HOSTOUTPUT="$HOSTOUTPUT$" -field NOTIFICATIONTYPE="$NOTIFICATIONTYPE$"
41 -
}
42 -
```
43 -
44 -
Das benötigte Pakete installieren:
45 -
46 -
```
47 -
sudo apt-get install libwww-perl libcrypt-ssleay-perl
48 -
```
49 -
50 -
In den Einstellungen auf Slack.com den Token erstellen. Das Skript für die Notifizierung über Slack.com herunterladen, ausführbar machen und den Token, sowie die Slack Team URL eintragen.
51 -
52 -
```
53 -
wget https://raw.github.com/tinyspeck/services-examples/master/nagios.pl
54 -
cp nagios.pl /usr/local/bin/slack\_nagios.pl
55 -
chmod 755 /usr/local/bin/slack\_nagios.pl
56 -
57 -
```
58 -
59 -
Team und Token in nagios.pl anpassen:
60 -
61 -
```
62 -
my $opt\_domain = "DeinSlackTeam.slack.com"; # Your team's domain
63 -
my $opt\_token = "HKhwerKJ72Kghhj23gsJG8"; # The token from your Nagios services page
64 -
```
65 -
66 -
Icinga neustarten und die nächsten Alarme landen im Slack Team Channel. Ich habe dafür einen neuen Raum #alerts im Slack angelegt.
67 -
68 -
### Chat auf der Homepage.
69 -
70 -
Chatlio war jetzt nicht so super. Man kann nur antworten wenn man selbst online im Desktop ist. Für Leute die unterwegs auch mit Kunden Kontakt aufnehmen wollen nicht brauchbar. Slack hat im App Verzeichnis einen Chatbot. Linked-Chat im Slack installieren und einfach Schritt für Schritt die angebenen Schritte durch gehen. Als erstes verbinden man einfach einen Raum im Slack mit Linked-Chat. Anschliessend noch Telegram. Bei beiden gibt es nur wenige Schritte um dies zu bewerkstelligen.
71 -
72 -
1.  Slack bzw. Telegram Link anklicken.
73 -
2.  Raum wählen
74 -
3.  den Befehl /link <linked-Chat-ID> senden.
75 -
76 -
Das war es dann auch schon. Jetzt kann man noch den Titel der Chatbox anpassen (Online/Offline). Farbe anpassen, Position des Chats auf der Seite und die Arbeitszeiten angeben. Durch die Arbeitszeiten wird festgelegt wann der Chat erreichbar ist und wann die Nachrichten nur mit angegebener E-Mailadresse gesendet werden. So kann man auch Nachts Anfragen annehmen und dem Kunden später auch noch antworten. Das ganze dann speichern und auf der Homepage einfach nur diesen Code mit einbauen:
77 -
78 -
Jetzt erscheint sofort auf der Internetseite unten eine kleine Box mit dem Chat und Besucher der Seite können schnell Anfragen stellen. Das ganze werde ich jetzt mal mit zwei Bekannten testen die schon mal genau wegen so etwas gefragt haben.
gelöscht content/2017-01-31-libstdc-so-6-version-glibcxx_3-4-20-not-found.md
+0 −62
@@ -1,62 +0,0 @@
1 -
---
2 -
title: 'libstdc++.so.6: version `GLIBCXX_3.4.20'' not found'
3 -
date: 2017-01-31 21:07:03
4 -
update: 2017-01-31 21:07:03
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
    - Arm
9 -
    - Fhem
10 -
    - Homekit
11 -
    - Libc6
12 -
    - Linux
13 -
    - nodeJS
14 -
    - npm
15 -
    - RaspberryPi
16 -
    - Technik
17 -
preview: "Da will man einmal kurz was neues installieren und dann das:"
18 -
categories: 
19 -
    - Technik
20 -
toc: false
21 -
hide: false
22 -
type: post
23 -
---
24 -
25 -
Da will man einmal kurz was neues installieren und dann das:
26 -
27 -
```
28 -
foo@pi01:~# node -v
29 -
foo@pi01:~# node: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version
30 -
`GLIBCXX_3.4.20' not found (required by node)
31 -
foo@pi01:~# node: /lib/arm-linux-gnueabihf/libc.so.6: version `GLIBC_2.16'
32 -
not found (required by node)
33 -
```
34 -
<!--more-->
35 -
36 -
Na dann fixt man es halt eben schnell:
37 -
38 -
```
39 -
foo@pi01:~# sudo apt-get update
40 -
foo@pi01:~# sudo apt-get install gcc-4.8 g++-4.8
41 -
foo@pi01:~# sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 20
42 -
foo@pi01:~# sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
43 -
foo@pi01:~# sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.6 20
44 -
foo@pi01:~# sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50
45 -
```
46 -
Da zum testen ein alter RaspberryPI B im Einsatz ist:
47 -
48 -
```
49 -
foo@pi01:~# apt-get purge node
50 -
foo@pi01:~# wget https://nodejs.org/download/release/v0.10.0/node-v0.10.0-linux-arm-pi.tar.gz
51 -
foo@pi01:~# cd /usr/local
52 -
foo@pi01:/usr/local# tar xzvf ~/node-v0.10.0-linux-arm-pi.tar.gz --strip=1
53 -
```
54 -
55 -
Fertig und weiter machen mit dem was man eigentlich vor hatte. ;-)
56 -
57 -
```
58 -
foo@pi01:/usr/local# node -v
59 -
v0.10.0
60 -
foo@pi01:/usr/local# npm -v
61 -
1.2.14
62 -
```
gelöscht content/2017-02-15-linux-auf-z83-mini-pc-installieren.md
+0 −154
@@ -1,154 +0,0 @@
1 -
---
2 -
title: Linux auf Z83 Mini PC installieren
3 -
date: 2017-02-15 15:09:31
4 -
update: 2017-02-15 15:09:31
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
    - Atom
9 -
    - Backup
10 -
    - Fhem
11 -
    - Homebridge
12 -
    - Homekit
13 -
    - Installation
14 -
    - Intel
15 -
    - Linux
16 -
    - Mini-PC
17 -
    - Restore
18 -
    - Smart-Home
19 -
    - Technik
20 -
    - UEFI
21 -
    - USB-Stick
22 -
    - Z5
23 -
    - Z5-8300
24 -
    - Z83
25 -
preview: "Der Raspberry PI zuhause ist noch ein altes 1er Model. Für FHEM und Homebridge für Apple HomeKit musste eigentlich ein neuer Raspberry her. Denn Homebridge auf dem alten Schätzchen installieren klappt nicht. Vielleicht hätte man das mit einigen Stunts hinbekommen. Aber es soll ja Stabil laufen."
26 -
categories: 
27 -
    - Technik
28 -
toc: false
29 -
hide: false
30 -
type: post
31 -
---
32 -
33 -
Der Raspberry PI zuhause ist noch ein altes 1er Model. Für FHEM und Homebridge für Apple HomeKit musste eigentlich ein neuer Raspberry her. Denn Homebridge auf dem alten Schätzchen installieren klappt nicht. Vielleicht hätte man das mit einigen Stunts hinbekommen. Aber es soll ja Stabil laufen.
34 -
<!--more-->
35 -
36 -
Wie der Zufall will hatten ich mit ein paar Kollegen eine Schulung und einer der Kollegen erzählte sehr begeistert von seinem neuen Spielzeug. Er hatte sich für knapp 100 € den Z83 Mini PC gekauft und Linux drauf laufen. Hörte sich interressant an. Kurz überlegt und entschlossen den auch zu bestellen. Raspberry + Gehäuse + Netzteil + SD Card, da ist der Z83 leistungsfähiger und vom Preis daher günstiger. Am nächsten Tag kam das Teil auch schon an und abends wurde der USB Stick erstellt. Der dann prompt nicht installieren wollte. Google, Google, Google ... ein paar Sachen schnell ausprobiert. Nix. Da das Teil am TV hing konnte auch nur in den Werbepausen getestet werden. Neben bei den Sohn bespassen, füttern und ins Bett bringen, da bleibt nicht viel Zeit für Frickeln am Rechner. Ok, abbrechen und morgen weiter machen.
37 -
38 -
Am nächsten Tag auch nicht wirklich dazu gekommen. Irgendwie ist mit Arbeit, Kind und Renovierungen wenig Zeit für so etwas. Also den Kollegen im Xing angeschrieben ob er seinen Stick mitbringen kann. Damit funktionierte das dann auch prompt. Falls ich den noch einmal brauche direkt einmal eine Sicherung gemacht und auf einen Stick geschrieben. Das Image kommt jetzt auch noch ins Netz für mich und wenn es jemand auch einmal gebrauchen kann. Hier also die Info zu der Hardware, Sichern und Wiederherstellen des Sticks und zur Installation. btw: Homebridge ist direkt installiert und läuft mit Eve und FHEM zusammen perfekt. Endlich SmartHome per Siri.
39 -
40 -
Die Hardware
41 -
------------
42 -
43 -
Z83 Mini PC Intel Atom x5-Z8300 Processor (2M Cache, up to 1.84 GHz)
44 -
45 -
*   Product model:Z83 Mini PC
46 -
*   Dimension:119.5_119.5_24mm
47 -
*   Processor Number:x5-Z8350
48 -
*   Cache:2 MB
49 -
*   Instruction Set:64-bit
50 -
*   System config
51 -
*   OS:Support Windows10
52 -
*   Language :Multi -language
53 -
*   Intel CPU:Intel Atom x5-Z8350 Processor (2M Cache, up to 1.84 GHz)
54 -
*   Processor Graphics:Intel HD Graphics
55 -
*   Installed RAM:DDR3 2GB
56 -
*   System Disk:Windows(C:) 32GB
57 -
*   Ethernet: 1000Mbps LAN
58 -
*   WIFI: IEEE 802.11a/b/g/n,2.4G+5.8G
59 -
*   Bluetooth: BT 4.0
60 -
*   Antenna: Built-in antenna for WIFI
61 -
*   Expand Memory:SD Card (Support 128GB)
62 -
*   \# of Cores:4
63 -
*   \# of Threads:4
64 -
*   Processor Base Frequency:1.44 GHz
65 -
*   Burst Frequency:1.84 GHz
66 -
*   Scenario Design Power (SDP):2 W
67 -
*   Cache:2 MB
68 -
*   Instruction Set:64-bit
69 -
*   Button&ports Button:1\*Power Button
70 -
*   DC-in:1\*DC in Port
71 -
*   USB3.0:1\* Standard USB Port
72 -
*   HD:1\*HD A Type Port
73 -
*   RJ45:1\*RJ45 (1000Mbps network connection)
74 -
*   Headphone microphone:1\*Headphone microphone jack
75 -
*   SD Card:1\* SD card slot
76 -
*   USB2.0:2\* Standard USB Port
77 -
78 -
Stick Backup
79 -
============
80 -
81 -
Den Stick mit der funktionierden Installation einstecken und sichern.
82 -
83 -
```
84 -
#> dmesg| grep -A 10 "USB device" | tail -n 15
85 -
[ 2512.633014] usb 2-1.7: new high-speed USB device number 8 using ehci-pci
86 -
[ 2512.728550] usb 2-1.7: New USB device found, idVendor=090c, idProduct=1000
87 -
[ 2512.728558] usb 2-1.7: New USB device strings: Mfr=1, Product=2, SerialNumber=3
88 -
[ 2512.728562] usb 2-1.7: Product: USB DISK
89 -
[ 2512.728566] usb 2-1.7: Manufacturer: SMI Corporation
90 -
[ 2512.728569] usb 2-1.7: SerialNumber: AA04012700007674
91 -
[ 2512.729344] usb-storage 2-1.7:1.0: USB Mass Storage device detected
92 -
[ 2512.730417] scsi host8: usb-storage 2-1.7:1.0
93 -
[ 2513.734712] scsi 8:0:0:0: Direct-Access     USB      Stick 2.0 ME     1100 PQ: 0 ANSI: 0 CCS
94 -
[ 2513.735369] sd 8:0:0:0: Attached scsi generic sg2 type 0
95 -
[ 2513.738041] sd 8:0:0:0: [sdc] 1981440 512-byte logical blocks: (1.01 GB/968 MiB)
96 -
[ 2513.739134] sd 8:0:0:0: [sdc] Write Protect is off
97 -
[ 2513.739143] sd 8:0:0:0: [sdc] Mode Sense: 43 00 00 00
98 -
```
99 -
In diesem Fall ist es das Device /dev/sdb und hat 1GB.
100 -
101 -
```
102 -
#> dd if=/dev/sdb of=z83\_install.iso
103 -
1981440+0 Datensätze ein
104 -
1981440+0 Datensätze aus
105 -
1014497280 bytes (1,0 GB, 968 MiB) copied, 88,4281 s, 11,5 MB/s
106 -
```
107 -
108 -
Stick Restore
109 -
=============
110 -
111 -
Neuen Stick einstecken und das Image auf den Stick mit `dd` kopieren: Darauf achten das richtige Device zu wählen:
112 -
113 -
```
114 -
#> dmesg | grep -A 10 "Attached"
115 -
[1452.680096] sd 7:0:0:0: Attached scsi generic sg2 type 0
116 -
[1452.680659] sd 7:0:0:0: [sdb] 3948544 512-byte logical blocks: (2.02 GB/1.88 GiB)
117 -
[1452.681279] sd 7:0:0:0: [sdb] Write Protect is off
118 -
[1452.681282] sd 7:0:0:0: [sdb] Mode Sense: 00 00 00 00
119 -
[1452.681907] sd 7:0:0:0: [sdb] Asking for cache data failed
120 -
[1452.681911] sd 7:0:0:0: [sdb] Assuming drive cache: write through
121 -
[1452.823221] sdb: sdb1
122 -
[1452.826012] sd 7:0:0:0: [sdb] Attached SCSI removable disk
123 -
```
124 -
125 -
In diesem Fall ist es /dev/sdb. Wenn noch Daten auf dem Stick sind müssen diese nicht gelöscht werden. Sie werden eh gleich überschrieben. Aber man kann sie gut dafür nutzen um sicher zugehen ob es wirklich das richtige Device ist.
126 -
127 -
```
128 -
#> dd if=z83_install.iso of=/dev/sdb
129 -
1981440+0 Datensätze ein
130 -
1981440+0 Datensätze aus
131 -
1014497280 bytes (1,0 GB, 968 MiB) copied, 439,406 s, 2,3 MB/s
132 -
```
133 -
Überprüfen ob alles auf dem Stick ist:
134 -
135 -
```
136 -
#> fdisk -l /dev/sdb
137 -
Medium /dev/sdb: 1,9 GiB, 2021654528 Bytes, 3948544 Sektoren
138 -
Einheiten: sectors von 1 \* 512 = 512 Bytes
139 -
Sektorengröße (logisch/physisch): 512 Bytes / 512 Bytes
140 -
I/O Größe (minimal/optimal): 512 Bytes / 512 Bytes
141 -
Typ der Medienbezeichnung: dos
142 -
Medienkennung: 0x4455395b
143 -
144 -
Gerät      Boot  Start    Ende Sektoren Größe Id Typ
145 -
/dev/sdb1  \*         0 1482751  1482752  724M  0 Leer
146 -
/dev/sdb2       139820  144555     4736  2,3M ef EFI (FAT-12/16/32)
147 -
```
148 -
149 -
Z83 Mini PC starten und installieren
150 -
====================================
151 -
152 -
Jetzt den Stick einfach in den Z83 stecken und einschalten. Direkt nach dem drücken des Power-Buttons die Taste F7 gedrückt halten. Nach kurzer Zeit sollte die Auswahl des Boot Medium erscheinen. Dort den USB Stick auswählen und die Installation sollte starten. Have Fun.
153 -
154 -
Image des Installtions Sticks [https://drive.google.com/open?id=0B4MeHQoJL4f9bWFZa3pxTjZNUnc](https://drive.google.com/open?id=0B4MeHQoJL4f9bWFZa3pxTjZNUnc) 1 GB
gelöscht content/2017-02-24-free-book-latex-beginners-guide.md
+0 −24
@@ -1,24 +0,0 @@
1 -
---
2 -
title: 'Free Book: LaTeX Beginner''s Guide'
3 -
date: 2017-02-24 08:58:20
4 -
update: 2017-02-24 08:58:20
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - Beginner
9 -
    - Book
10 -
    - epub
11 -
    - Free
12 -
    - Internet
13 -
    - Latex
14 -
    - Mobi
15 -
    - PDF
16 -
preview: "LaTeX Beginner's Guide Get to grips with LaTeX with this accessible guide for beginners, and experience its versatility for yourself."
17 -
categories: 
18 -
    - Internet
19 -
toc: false
20 -
hide: false
21 -
type: post
22 -
---
23 -
24 -
> LaTeX Beginner's Guide Get to grips with LaTeX with this accessible guide for beginners, and experience its versatility for yourself. Explore its extensive range of features to gain confidence with its impressive functionality using the step by step guidance, demonstrations and examples included throughout the book. Covering everything from basic formatting to typing complex mathematics formulas, LaTeX Beginner’s Guide is at once accessible and comprehensive, making LaTeX simple and easy to use. https://www.packtpub.com/packt/offers/free-learning
gelöscht content/2017-03-30-learning-data-mining-with-python-ebook-for-free.md
+0 −27
@@ -1,27 +0,0 @@
1 -
---
2 -
title: 'Learning Data Mining with Python Ebook for free'
3 -
date: 2017-03-30 08:07:34
4 -
update: 2017-03-30 08:07:34
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - data mining
9 -
    - Ebook
10 -
    - Epub
11 -
    - Internet
12 -
    - Mobi
13 -
    - PDF
14 -
    - Programming
15 -
    - Python
16 -
preview: 'Heute gibt es das Buch "Learning Data Mining with Python" bei [PacktPub](https://www.packtpub.com/packt/offers/free-learning) kostenlos.'
17 -
categories: 
18 -
    - Internet
19 -
toc: false
20 -
hide: false
21 -
type: post
22 -
---
23 -
24 -
Heute gibt es das Buch "Learning Data Mining with Python" bei [PacktPub](https://www.packtpub.com/packt/offers/free-learning) kostenlos.
25 -
<!--more-->
26 -
27 -
> Data is the new oil in this information age and today's free eBook will show you how to apply data mining concepts to real-world problems. Python is one of the most popular languages for data mining because it's powerful and flexible when it comes to analysis. Deep dive into the libraries available in Python for data mining and learn new algorithms and techniques for turning raw data into insight.
gelöscht content/2017-05-12-practical-linux-security-cookbook.md
+0 −21
@@ -1,21 +0,0 @@
1 -
---
2 -
title: 'Practical Linux Security Cookbook'
3 -
date: 2017-05-12 07:53:20
4 -
update: 2017-05-12 07:53:20
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags: [E-Book, epub, Internet, Internet, Linux, Network, Security]
8 -
preview: 'Bei [packtpub.com](https://www.packtpub.com/packt/offers/free-learning) gibt es wieder das tägliche kostenlose E-Book. "Practical Linux Security Cookbook" heißt das heutige Buch und könnte für einige interessant sein.'
9 -
categories: 
10 -
    - Internet
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
17 -
Bei [packtpub.com](https://www.packtpub.com/packt/offers/free-learning) gibt es wieder das tägliche kostenlose E-Book. "Practical Linux Security Cookbook" heißt das heutige Buch und könnte für einige interessant sein.
18 -
19 -
<!--more-->
20 -
21 -
> As more and more organizations adopt Linux for their networks and servers, the number of security threats grows and grows. As a sysadmin, you'll be the first point of call when hackers threaten your network - and this free eBook will be your bible for building and maintaining a secure Linux system. Whether you are new to Linux administration or an experienced admin, this book will make your system secure. Walk through customizing the Linux kernel and securing local files, manage user authentication locally and remotely, patch bash vulnerability and more.
gelöscht content/2017-05-29-gpn17-mammut-statt-vogel-das-verteilte-soziale-netzwerk-mastodon.md
+0 −25
@@ -1,25 +0,0 @@
1 -
---
2 -
title: "GPN17 Mammut statt Vogel Das verteilte soziale Netzwerk Mastodon"
3 -
date: 2017-05-29 10:45:24
4 -
update: 2017-05-29 10:45:24
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - Dezentral
9 -
    - Gulaschprogrammiernacht 2017
10 -
    - Internet
11 -
    - Mastodon
12 -
    - Social Network
13 -
preview: "Mastodon ist ein neues soziales Netzwerk, das dezentral funktioniert und OStatus implementiert (wie auch zB GNUSocial)."
14 -
categories: 
15 -
    - Internet
16 -
toc: false
17 -
hide: false
18 -
type: post
19 -
---
20 -
21 -
Mastodon ist ein neues soziales Netzwerk, das dezentral funktioniert und OStatus implementiert (wie auch zB GNUSocial).
22 -
Hier soll erklärt werden, wie Mastodon funktioniert, welche Eigendynamik sich auf Instanzen entwickelt und Statistiken über die Nutzung der ersten Monate nach dem Abheben vorgestellt werden.
23 -
<!--more-->
24 -
25 -
Quelle: [Media.ccc.de GPN17 Mammut statt Vogel](https://media.ccc.de/v/gpn17-8575-mammut_statt_vogel)
gelöscht content/2017-06-06-macos-high-sierra-usb-installer-benutzen.md
+0 −22
@@ -1,22 +0,0 @@
1 -
---
2 -
title: 'macOS High Sierra USB installer benutzen'
3 -
date: 2017-06-06 12:06:05
4 -
update: 2017-06-06 12:06:05
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags: [Apple, Beta, Boot, High Sierra, Installation, Internet, MacOS, Partition, USB-Stick]
8 -
preview: 'Um den USB-Installer zu benutzen, einfach den Mac booten, während dessen die Option / alt (⌥) drücken. Das Laufwerk mit dem Titel "Install macOS 10.13 Beta" auswählen.'
9 -
categories: 
10 -
    - Technik
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
Um den USB-Installer zu benutzen, einfach den Mac booten, während dessen die Option / alt (⌥) drücken. Das Laufwerk mit dem Titel "Install macOS 10.13 Beta" auswählen.
17 -
<!--more-->
18 -
19 -
![High Sierra install screen](/images/posts/high-sierra-install-screen.webp)
20 -
21 -
22 -
Der Computer wird dann auf die MacOS 10.13 High Sierra Beta Installation booten und die Installation kann durchgeführt werden.
gelöscht content/2017-06-09-macos-high-sierra-beta-usb-boot-stick-erstellen.md
+0 −35
@@ -1,35 +0,0 @@
1 -
---
2 -
title: 'MacOs High Sierra Beta USB Boot-Stick erstellen'
3 -
date: 2017-06-09 11:52:17
4 -
update: 2017-06-09 11:52:17
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags: 
8 -
    - Apple
9 -
    - Application
10 -
    - Boot
11 -
    - High Sierra
12 -
    - Installation
13 -
    - Internet
14 -
    - MacOS
15 -
    - mount
16 -
    - Partition
17 -
    - USB-Stick
18 -
preview: 'MacOs High Sierra Beta USB Boot-Stick erstellen'
19 -
categories: 
20 -
    - Technik
21 -
toc: false
22 -
hide: false
23 -
type: post
24 -
---
25 -
26 -
27 -
   * Lade das High Sierra Beta-Installationsprogramm herunter und stell sicher, dass es sich im / Applications-Ordner befindet. Dies ist der Standard-Download-Ort vom Mac App Store.
28 -
   * Einen >=8GB USB-Stick einstecken. Wenn der Stick nicht bereits als GUID Partition Map und Mac OS Extended (Journaled) formatiert ist, starte die Festplatten-Utility-Anwendung und formatiere den Stick. Dadurch werden alle Daten vom Laufwerk gelöscht. 
29 -
   <!--more-->
30 -
   * Öffne ein Terminal-Fenster und füge folgenden Befehl ein, um den Beta-Installer auf den USB zu verschieben und ihn bootfähig zu machen: 
31 -
   
32 -
```
33 -
sudo /Applications/Install\ macOS\ 10.13\ Beta.app/Contents/Resources/createinstallmedia --volume /Volumes/USB --applicationpath /Applications/Install\ macOS\ 10.13\ Beta.app --nointeraction
34 -
```
35 -
   * Gebe dein Ihr Benutzer-Passwort ein, wenn dazu aufgefordert wird. Das kopieren wird gestartet. Das USB-Laufwerk wird während des gesamten Prozesses aus gehangen und wird nicht auf dem Desktop angezeigt. Auf dem Terminal wird der Fortschritt angezeigt. Sobald die Dateien kopiert wurden und das Laufwerk bootfähig gemacht wurde, wird das Laufwerk wieder auf dem Desktop erscheinen und das Terminal wird angezeigt, dass der Prozess abgeschlossen ist.
gelöscht content/2017-06-14-mastodon-social-pretzlaff-co.md
+0 −20
@@ -1,20 +0,0 @@
1 -
---
2 -
title: 'Mastodon: social.pretzlaff.co'
3 -
date: 2017-06-14 12:25:34
4 -
update: 2017-06-14 12:25:34
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags: [dezentral, Facebook, free, Internet, Mastodon, OpenSource, Social Network, Twitter]
8 -
preview: 'Auf [social.pretzlaff.co](https://social.pretzlaff.co) läuft seit ein paar Tagen eine Mastodon Instanz. Mein User ist dort: [rpr](https://social.pretzlaff.co/@rpr).'
9 -
categories: 
10 -
    - Technik
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
Auf [social.pretzlaff.co](https://social.pretzlaff.co) läuft seit ein paar Tagen eine Mastodon Instanz. Mein User ist dort: [rpr](https://social.pretzlaff.co/@rpr). Registration ist dort aktiviert. Alternativ kann man sich auch einen Account auf einer [der vielen anderen Mastodon Instanzen](https://instances.mastodon.xyz/list) anlegen. Die Kommunikation funktioniert ja schließlich zwischen den Instanzen und ist ja auch der Sinn von Mastodon und dem dezentralem Aufbau. Quelle: [Wikipedia](https://de.wikipedia.org/wiki/Mastodon_(Software))
17 -
18 -
<!--more-->
19 -
20 -
> Mastodon ist ein verteilter Mikrobloggingdienst, der 2016 von Eugen Rochko entwickelt wurde; einem deutschen Programmierer aus Jena. Im Gegensatz zu großen Plattformen wie Twitter ist Mastodon als dezentrales Netzwerk konzipiert. Benutzer können einer beliebigen Instanz beitreten oder selbst eine eigene betreiben. Mastodon ist kompatibel zu GNU Social sowie allen OStatus-Diensten. Das Projekt ist Freie Software und steht mit seinem Quelltext unter der GNU Affero General Public License zur Verfügung. Entwicklung und Betrieb der Instanz mastodon.social werden durch Spenden finanziert. Auf Mastodon können angemeldete Nutzer telegrammartige Kurznachrichten verbreiten. Diese Nachrichten werden „Toots“ oder übersetzt „Tröts“ genannt. Mastodon erlaubt pro Post (Toot) 500 Zeichen.
gelöscht content/2017-07-19-git-version-control-for-everyone-ebook.md
+0 −37
@@ -1,37 +0,0 @@
1 -
---
2 -
title: 'Git: Version Control for Everyone eBook'
3 -
date: 2017-07-19 08:52:27
4 -
update: 2017-07-19 08:52:27
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - Codes
9 -
    - Dev
10 -
    - DevOps
11 -
    - Ebook
12 -
    - epub
13 -
    - Git
14 -
    - Github
15 -
    - Gitlab
16 -
    - Internet
17 -
    - Linux
18 -
    - MacOS
19 -
    - Mobi
20 -
    - PDF
21 -
    - Programming
22 -
    - Versioncontrol
23 -
preview: 'Heute gibt es bei [packtpub.com](https://www.packtpub.com) "Git: Version Control for Everyone" kostenlos zum [herunterladen](https://www.packtpub.com/packt/offers/free-learning). Controlling different versions of files is an efficient process with Git, and this book makes it a snap to learn too! A practical tutorial, it hard-wires the lessons through hands-on exercises throughout the course.'
24 -
categories: 
25 -
    - Internet
26 -
toc: false
27 -
hide: false
28 -
type: post
29 -
---
30 -
31 -
Heute gibt es bei [packtpub.com](https://www.packtpub.com) "Git: Version Control for Everyone" kostenlos zum [herunterladen](https://www.packtpub.com/packt/offers/free-learning). Controlling different versions of files is an efficient process with Git, and this book makes it a snap to learn too! A practical tutorial, it hard-wires the lessons through hands-on exercises throughout the course.
32 -
<!--more-->
33 -
34 -
*   A complete beginner's workflow for version control of common documents and content
35 -
*   Examples used are from non-techie, day to day computing activities we all engage in
36 -
*   Learn through multiple modes – readers learn theory to understand the concept and reinforce it by practical tutorials.
37 -
*   Ideal for users on Windows, Linux, and Mac OS X
gelöscht content/2017-08-16-serverless-computing-what.md
+0 −20
@@ -1,20 +0,0 @@
1 -
---
2 -
title: 'Serverless Computing. What?'
3 -
date: 2017-08-16 11:17:54
4 -
update: 2017-08-16 11:17:54
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags: [Cloud, Computing, Infrastructure, Internet, Internet, Linux, programming, Social Network]
8 -
preview: 'René Büst erklärt in [seinem Artikel](https://www.computerwoche.de/a/serverless-infrastructure-erleichtert-die-cloud-nutzung,3314756) was "Serverless Infrastruktur" bzw. "Serverless Computing" ist.'
9 -
categories: 
10 -
    - Internet
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
René Büst erklärt in [seinem Artikel](https://www.computerwoche.de/a/serverless-infrastructure-erleichtert-die-cloud-nutzung,3314756) was "Serverless Infrastruktur" bzw. "Serverless Computing" ist.
17 -
18 -
<!--more-->
19 -
20 -
> Im Prinzip ist es nichts Besonderes, wenn Cloud-Anbieter ständig eine neue Sau durchs Dorf treiben. Die aktuelle Sau hört auf den Namen "Serverless Infrastructure" oder auch "Serverless Computing". Das Außergewöhnliche daran ist jedoch, dass sie einige Verwirrung stiftet. Ist nun das Ende der Server angebrochen? Bei weitem nicht - viel mehr verschiebt sich innerhalb des Cloud-Stacks mal wieder etwas weiter nach oben.
gelöscht content/2017-08-16-textcraft-pocket-aktuell-kostenlos.md
+0 −25
@@ -1,25 +0,0 @@
1 -
---
2 -
title: 'Textcraft Pocket aktuell kostenlos'
3 -
date: 2017-08-16 09:40:26
4 -
update: 2017-08-16 09:40:26
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags: [Apple, Application, Editor, iOS, Markdown, Organisation, pdf, Text, Textverarbeitung]
8 -
preview: "Um im BGP manche Netze nicht zu erlauben:"
9 -
categories: 
10 -
    - Organisation
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
Lesen, schreiben, korrigieren, recherchieren und teilen! [Textkraft Pocket](https://itunes.apple.com/de/app/textkraft-pocket/id909848112?mt=8) für iPhone und Apple Watch ist eine professionelle Schreib-App und komfortabler Dokumenten-Reader.
17 -
18 -
Das Besondere an Textkraft ist, dass du alle Dokumente für dein Projekt in einer App hast, Seite an Seite, ohne Ladezeit zugriffsbereit. Mit einer Wischgeste oder der Dokumentenübersicht wechselst du vor und zurück durch Texte, Notizen, Office-Dokumente, PDF-Dateien und andere Vorlagen, die du für deine Textarbeit benötigst
19 -
<!--more-->
20 -
21 -
Erweiterte Offline-Wörterbücher mit Synonymen und viele integrierte Online-Nachschlagewerke helfen dir bei Rechtschreibung, Sprache, Ausdruck, Grammatik, Definition und Übersetzung. Präzise Cursornavigation, schnelle Textauswahl und viele zusätzliche Tastaturfunktionen optimieren das Schreiben.
22 -
23 -
24 -
![textcraft_pocket_screen](/images/posts/textcraft_pocket_screen.webp)
25 -
gelöscht content/2017-09-14-aws-lambda-serverless-tool-plus-erverless-offline.md
+0 −245
@@ -1,245 +0,0 @@
1 -
---
2 -
title: 'AWS Lambda serverless Framework und serverless-offline'
3 -
date: 2017-09-14 09:53:46
4 -
update: 2017-09-14 09:53:46
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - AWS
9 -
    - Cloud
10 -
    - Internet
11 -
    - Javascript
12 -
    - NodeJS
13 -
    - npm
14 -
    - Programming
15 -
    - Serverless
16 -
preview: "nodejs, npm, serverless und serverless-offline installieren"
17 -
categories: 
18 -
    - Internet
19 -
toc: false
20 -
hide: false
21 -
type: post
22 -
---
23 -
24 -
25 -
nodejs, npm, serverless und serverless-offline installieren
26 -
===========================================================
27 -
28 -
*   [serverless](https://github.com/serverless/serverless)
29 -
*   [serverless-offline](https://github.com/dherault/serverless-offline)
30 -
*   [NodeJS](https://nodejs.org/en/)
31 -
32 -
Installation nodejs
33 -
-------------------
34 -
<!--more-->
35 -
36 -
```
37 -
$ sudo apt-get install curl python-software-properties
38 -
$ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
39 -
$ sudo apt-get install nodejs
40 -
$ node -v
41 -
42 -
v8.2.1
43 -
44 -
$ npm -v
45 -
46 -
5.3.0
47 -
```
48 -
49 -
Installation serverless
50 -
-----------------------
51 -
52 -
```
53 -
npm install -g serverless
54 -
```
55 -
56 -
serverless service erstellen
57 -
============================
58 -
59 -
Project erstellen
60 -
-----------------
61 -
62 -
```
63 -
# Ein neues Serverless Service/Project erstellen
64 -
serverless create --template aws-nodejs --path my-service
65 -
# In das neue Verzeichnis wechseln
66 -
cd my-service
67 -
```
68 -
69 -
AWS Access-Key und Secret
70 -
-------------------------
71 -
72 -
```
73 -
export AWS_ACCESS_KEY_ID=<your-key-here>
74 -
export AWS_SECRET_ACCESS_KEY=<your-secret-key-here>
75 -
serverless deploy
76 -
```
77 -
oder
78 -
```
79 -
serverless config credentials --provider aws --key AKIAIOSFODNN7EXAMPLE --secret wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
80 -
```
81 -
82 -
Deploy Service
83 -
--------------
84 -
85 -
```
86 -
serverless deploy -v
87 -
```
88 -
89 -
Die Logs der Function abrufen:
90 -
------------------------------
91 -
92 -
```
93 -
serverless invoke -f hello -l
94 -
```
95 -
96 -
Service in AWS entfernen
97 -
------------------------
98 -
99 -
```
100 -
serverless remove
101 -
```
102 -
103 -
mysql RSD DB mit NodeJS in Lambda benutzen
104 -
==========================================
105 -
106 -
Als erstes im Projectverzeichnis (my-project) das mysql plugin installieren
107 -
```
108 -
npm install mysql
109 -
```
110 -
Im Code mysql hinzufügen und den restlichen mysql java-script Code:
111 -
```
112 -
var mysql = require('mysql');
113 -
module.exports.view = (event, context, callback) => {
114 -
  const ip = event.requestContext.identity.sourceIp;
115 -
  var connection = mysql.createConnection({
116 -
    host: 'YourRdsDB.xxxxxxx.eu-central-1.rds.amazonaws.com',
117 -
    user: 'DBUser',
118 -
    password: 'DBPass',
119 -
    database: 'DBname'
120 -
  });
121 -
  connection.connect();
122 -
  // ....
123 -
}
124 -
```
125 -
126 -
Serverless offline ohne AWS benutzen
127 -
====================================
128 -
129 -
Serverless-offline installieren
130 -
-------------------------------
131 -
132 -
```
133 -
npm install serverless-offline --save-dev
134 -
```
135 -
136 -
### Hinter einem Cooperate-Proxy ggf. auch noch mit Auth?
137 -
138 -
Einfach npm mit config set die Parameter für https-proxy und proxy setzen.
139 -
```
140 -
npm config set proxy http://"username:gehe\!m"@proxy.example.com:3128
141 -
npm config set https-proxy http://"username:gehe\!m"@proxy.example.com:3128
142 -
```
143 -
Sonderzeichen wie das '!' hier im Beispiel müssen escaped werden. Und Benutzer und Password müssen komplett in " gesetzt werden. Das Verzeichnis "node\_modules" sollte jetzt ungefähr so aussehen und unter anderem serverless-offline auflisten:
144 -
145 -
```
146 -
ls node_modules/
147 -
accept            babel-helpers   balanced-match   content               esutils            home-or-tmp  json5             mimos          os-homedir           serverless-offline  supports-color
148 -
ammo              babel-messages  boom             convert-source-map    globals            invariant    jsonpath-plus     minimatch      os-tmpdir            shot                to-fast-properties
149 -
ansi-regex        babel-register  brace-expansion  core-js               h2o2               iron         js-string-escape  minimist       path-is-absolute     slash               topo
150 -
ansi-styles       babel-runtime   call             cryptiles             hapi               isemail      js-tokens         mkdirp         peekaboo             source-map          trim-right
151 -
b64               babel-template  catbox           crypto                hapi-cors-headers  is-finite    kilt              moment         pez                  source-map-support  velocityjs
152 -
babel-code-frame  babel-traverse  catbox-memory    debug                 has-ansi           items        lodash            ms             private              statehood           vise
153 -
babel-core        babel-types     chalk            detect-indent         heavy              joi          loose-envify      nigel          regenerator-runtime  strip-ansi          wreck
154 -
babel-generator   babylon         concat-map       escape-string-regexp  hoek               jsesc        mime-db           number-is-nan  repeating            subtext
155 -
```
156 -
157 -
PlugIn in der serverless.yml hinzufügen
158 -
---------------------------------------
159 -
160 -
```
161 -
plugins:
162 -
  - serverless-offline
163 -
```
164 -
165 -
Überprüfen ob das PlugIn verfügbar ist
166 -
--------------------------------------
167 -
168 -
```
169 -
serverless
170 -
```
171 -
Die Ausgabe sollte unter commands jetzt zusätzlich "offline" und "offline-start" auflisten
172 -
```
173 -
...
174 -
logs .......................... Output the logs of a deployed function
175 -
metrics ....................... Show metrics for a specific function
176 -
offline ....................... Simulates API Gateway to call your lambda functions offline.
177 -
offline start ................. Simulates API Gateway to call your lambda functions offline using backward compatible initialization.
178 -
package ....................... Packages a Serverless service
179 -
remove ........................ Remove Serverless service and all resources
180 -
...
181 -
```
182 -
183 -
In der letzten Zeile werden alle verfügbaren PlugIns aufgelistet und "Offline" sollte dort auch aufgelistet werden.
184 -
```
185 -
Plugins
186 -
AwsCommon, AwsCompileAlexaSkillEvents, AwsCompileApigEvents, AwsCompileCloudWatchEventEvents, AwsCompileCloudWatchLogEvents, AwsCompileCognitoUserPoolEvents, AwsCompileFunctions, AwsCompileIoTEvents, AwsCompileS3Events, AwsCompileSNSEvents, AwsCompileScheduledEvents, AwsCompileStreamEvents, AwsConfigCredentials, AwsDeploy, AwsDeployFunction, AwsDeployList, AwsInfo, AwsInvoke, AwsInvokeLocal, AwsLogs, AwsMetrics, AwsPackage, AwsProvider, AwsRemove, AwsRollback, AwsRollbackFunction, Config, Create, Deploy, Emit, Info, Install, Invoke, Login, Logout, Logs, Metrics, Offline, Package, Platform, Remove, Rollback, Run, SlStats
187 -
```
188 -
189 -
Projekt offline starten
190 -
-----------------------
191 -
192 -
`serverless offline start` or `sls offline start`.
193 -
```
194 -
serverless offline start
195 -
Serverless: Starting Offline: dev/us-east-1.
196 -
197 -
Serverless: Routes for hello:
198 -
Serverless: (none)
199 -
200 -
Serverless: Offline listening on http://localhost:3000
201 -
```
202 -
203 -
Service testen
204 -
--------------
205 -
206 -
Dabei an den Proxy denken und den Parameter `--noproxy` setzen:
207 -
```
208 -
curl --noproxy "127.0.0.1, localhost" http://localhost:3000
209 -
```
210 -
211 -
Parameter von serverless-offline
212 -
--------------------------------
213 -
214 -
```
215 -
serverless offline --help
216 -
--prefix                -p  Adds a prefix to every path, to send your requests to http://localhost:3000/[prefix]/[your_path] instead. E.g. -p dev
217 -
--location              -l  The root location of the handlers' files. Defaults to the current directory
218 -
--host                  -o  Host name to listen on. Default: localhost
219 -
--port                  -P  Port to listen on. Default: 3000
220 -
--stage                 -s  The stage used to populate your templates. Default: the first stage found in your project.
221 -
--region                -r  The region used to populate your templates. Default: the first region for the first stage found.
222 -
--noTimeout             -t  Disables the timeout feature.
223 -
--noEnvironment             Turns off loading of your environment variables from serverless.yml. Allows the usage of tools such as PM2 or docker-compose.
224 -
--resourceRoutes            Turns on loading of your HTTP proxy settings from serverless.yml.
225 -
--dontPrintOutput           Turns off logging of your lambda outputs in the terminal.
226 -
--httpsProtocol         -H  To enable HTTPS, specify directory (relative to your cwd, typically your project dir) for both cert.pem and key.pem files.
227 -
--skipCacheInvalidation -c  Tells the plugin to skip require cache invalidation. A script reloading tool like Nodemon might then be needed.
228 -
--corsAllowOrigin           Used as default Access-Control-Allow-Origin header value for responses. Delimit multiple values with commas. Default: '*'
229 -
--corsAllowHeaders          Used as default Access-Control-Allow-Headers header value for responses. Delimit multiple values with commas. Default: 'accept,content-type,x-api-key'
230 -
--corsDisallowCredentials   When provided, the default Access-Control-Allow-Credentials header value will be passed as 'false'. Default: true
231 -
--exec "<script>"           When provided, a shell script is executed when the server starts up, and the server will shut domn after handling this command.
232 -
```
233 -
234 -
Parameter in der serverless.yml setzen
235 -
--------------------------------------
236 -
237 -
Beispiel:
238 -
```
239 -
custom:
240 -
  serverless-offline:
241 -
    httpsProtocol: "dev-certs"
242 -
    port: 4000
243 -
    prefix: "dev"
244 -
    stage: "dev"
245 -
```
gelöscht content/2017-09-18-atom-editor-hinter-proxy.md
+0 −32
@@ -1,32 +0,0 @@
1 -
---
2 -
title: 'Atom Editor hinter Proxy'
3 -
date: 2017-09-18 16:35:03
4 -
update: 2017-09-18 16:35:03
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - Free
9 -
    - Installation
10 -
    - Internet
11 -
    - Internet
12 -
    - Linux
13 -
    - MacOS
14 -
    - Programming
15 -
preview: "Da will man sich im [Atom Editor](https://atom.io) mal eben das Package script installieren, um Code zum testen direkt im Atom auszuführen, da stellt sich der Proxy mal wieder in den Weg."
16 -
categories: 
17 -
    - Internet
18 -
toc: false
19 -
hide: false
20 -
type: post
21 -
---
22 -
23 -
Da will man sich im [Atom Editor](https://atom.io) mal eben das Package "script" installieren, um Code zum testen direkt im Atom auszuführen, da stellt sich der Proxy mal wieder in den Weg.
24 -
25 -
<!--more-->
26 -
27 -
```
28 -
apm config set https-proxy http://proxy.example.com:3128
29 -
apm config set http-proxy http://proxy.example.com:3128
30 -
```
31 -
32 -
Atom wieder öffnen und Package installieren.
gelöscht content/2017-09-19-php-in-aws-lambda-function-ausfuehren.md
+0 −102
@@ -1,102 +0,0 @@
1 -
---
2 -
title: 'PHP in AWS Lambda Function ausführen'
3 -
date: 2017-09-19 12:30:14
4 -
update: 2017-09-19 12:30:14
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags: [Application, aws, Azure, Cloud, Google Cloud Computing, Internet, Internet, nodeJS, perl, php, programming]
8 -
preview: "Bei der Transformation in der Cloud möchte man manchmal schnell kleine Scripts in die Cloud bringen ohne erst Server oder Container in der Cloud zu installieren. In vielen Fällen reichen Funktionen wie AWS-Lambda-Functions, Azure Functions oder Google Cloud Functions."
9 -
categories: 
10 -
    - Internet
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
Bei der Transformation in der Cloud möchte man manchmal schnell kleine Scripts in die Cloud bringen ohne erst Server oder Container in der Cloud zu installieren. In vielen Fällen reichen Funktionen wie AWS-Lambda-Functions, Azure Functions oder Google Cloud Functions. AWS Lambda bietet dafür in Lambda folgende (Script)-Sprachen an:
17 -
<!--more-->
18 -
19 -
*   C#
20 -
*   Java
21 -
*   python
22 -
*   nodejs
23 -
24 -
Gerade in älteren Umgebungen werden oft Perl und PHP für kleinere Webscripte, die Applikationen zum Austausch von Informationen benutzen eingesetzt. Klar, diese Scripte sollte man teilweise überdenken und erneuern. Das kostet zum einen Geld, jemand muss es machen und manche sollen auch nur noch bei dem Sprung in die Cloud helfen und dann eh das zeitliche segnen. Daher wäre es nicht schlecht diese Tools schnell mit in die Cloud zu nehmen um andere Software so in die Cloud zu bekommen und die Tools nicht als Spassbremse zu haben.
25 -
26 -
nodejs und statisch kompliliertes php
27 -
-------------------------------------
28 -
29 -
Da Lambda nodejs anbietet kann man es auch dazu nötigen PHP auszuführen. Ja, würde ich es jetzt auch lesen oder es von jemanden hören, ich würde mich jetzt genau so schütteln. Aber es soll ja nur den Sprung in die Cloud ermöglichen und zeigen wie man solche Probleme umgehen kann.
30 -
31 -
PHP Binary erstellen
32 -
--------------------
33 -
34 -
Um das PHP statisch als ein Binary vorliegen zu haben bietet sich Docker an. build\_php\_7.sh
35 -
```
36 -
#!/bin/sh
37 -
PHP_VERSION_GIT_BRANCH=PHP-7.1.1
38 -
echo "Build PHP Binary from current branch '$PHP_VERSION_GIT_BRANCH' on https://github.com/php/php-src"
39 -
docker build --build-arg PHP_VERSION=$PHP_VERSION_GIT_BRANCH -t php-build -f Dockerfile.BuildPHP .
40 -
container=$(docker create php-build)
41 -
docker -D cp $container:/root/php7/usr/bin/php ./php
42 -
docker rm $container
43 -
```
44 -
Das stellt einen Container der PHP 7.7.1 zusammensetzt und anschliessend das fertige Binary aus den Docker Container kopiert. Wer eine andere Version benötigt kann die Version mit PHP\_VERSION\_GIT\_BRANCH setzen.
45 -
46 -
PHP Script
47 -
----------
48 -
49 -
```
50 -
<?php
51 -
echo "Hello world!";
52 -
var_dump($argv);
53 -
?>
54 -
```
55 -
56 -
index.js spawn für php
57 -
----------------------
58 -
59 -
Damit der PHP Interpreter und ein Script aufgerufen werden benötigt man nur noch etwas JavaScript:
60 -
```
61 -
'use strict';
62 -
var child_process = require('child_process');
63 -
exports.handler = function(event, context) {
64 -
  var strToReturn = '';
65 -
  var proc = child_process.spawn('./php', [ "index.php", JSON.stringify(event), { stdio: 'inherit' } ]);
66 -
  proc.stdout.on('data', function (data) {
67 -
    var dataStr = data.toString()
68 -
    console.log('stdout: ' + dataStr);
69 -
    strToReturn += dataStr
70 -
  });
71 -
72 -
  proc.on('close', function(code) {
73 -
    if(code !== 0) {
74 -
      return context.done(new Error("Process exited with non-zero status code"));
75 -
    }
76 -
    context.succeed(strToReturn);
77 -
  });
78 -
}
79 -
```
80 -
81 -
Alles einpacken und verschiffen
82 -
-------------------------------
83 -
84 -
Jetzt nur noch ein Zip-File `aws-lambda-php-example.zip` erstellen mit den Dateien:
85 -
86 -
*   index.js
87 -
*   index.php
88 -
*   php zip aws-lambda-php-example.zip index.js index.php php
89 -
90 -
91 -
In AWS eine neue Lambda Function erstellen mit folgenden Parametern:
92 -
93 -
*   Type: nodeJS
94 -
*   RAM: 128mb
95 -
*   Timeout: 3 seconds
96 -
97 -
Den JavaScript Code nicht in den Online Editor kopieren, sondern Upload auswählen und das komplette ZIP-File hochladen und an der Lambda Function anhängen. Alternativ im S3 ablegen und aus dem Bucket heraus laden lassen Benötigt man die Schnittstelle per HTTP von extern und/oder anderen Instanzen kann man auch noch das API-Gateway von Amazon hinzuziehen.
98 -
99 -
Spassbremse umgangen
100 -
--------------------
101 -
102 -
Das Script stört nicht mehr die weitere Transformation und alle anderen Softwarebrocken können ihren Weg in die Cloud beschreiten. Die Teams, die solche Softwarestückchen einmal in schön abliefern müssen, können dies dann noch später nachholen. Haben aber auch erst einmal Zeit für die grösseren Cloud-Projekte. Wer aus "Gründen" nicht sofort eine komplette Software in die Cloud bringen kann sollte sich das API-Gateway einmal genauer angucken. Path und Method lassen sich damit sehr gut trennen. Einzelne Aufrufe lassen sich so auf die alte Software oder die neue Software leiten. Natürlich nur, so lange so etwas mit einer Software möglich ist und intern keine Abhängigkeiten bestehen. Ist es möglich steht einer Migration einzelner Funktionen nichts im Wege. Rollback inklusive.
gelöscht content/2018-01-02-dsl-graph-mit-python.md
+0 −71
@@ -1,71 +0,0 @@
1 -
---
2 -
title: 'DSL Graph mit Python'
3 -
date: 2018-01-02 16:14:52
4 -
update: 2018-01-02 16:14:52
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - Internet
9 -
    - Linux
10 -
    - MacOS
11 -
    - Programming
12 -
    - Python
13 -
preview: "Da heute ja [hier](https://blog.pretzlaff.info/2018/01/02/dsl-traffic-2017/) Graphen zum Traffic im Jahr 2016 veröffentlicht wurde hier auch gleich eines der Scripts."
14 -
categories: 
15 -
    - Technik
16 -
toc: false
17 -
hide: false
18 -
draft: false
19 -
type: post
20 -
---
21 -
22 -
Da heute ja [hier](https://blog.pretzlaff.info/2018/01/02/dsl-traffic-2017/) Graphen zum Traffic im Jahr 2016 veröffentlicht wurde hier auch gleich eines der Scripts.
23 -
Datenquelle: fb.csv
24 -
25 -
<!--more-->
26 -
27 -
```
28 -
Monat;Gesendet;Empfangen;Gesamt 
29 -
Jan;4124;16815;20939 
30 -
Feb;1078;403;1481 
31 -
Mar;1199;446;1645 
32 -
Apr;2464;36476;38940 
33 -
Mai;92979;615268;708247 
34 -
Jun;138402;664743;803145 
35 -
Jul;116406;507155;623561 
36 -
Aug;35654;471810;507464 
37 -
Sep;31362;428400;459762 
38 -
Okt;24072;549927;573999 
39 -
Nov;44095;914362;958457 
40 -
Dez;57889;1141699;1199588 
41 -
Gesamt:;549724;5347504;5897228
42 -
```
43 -
44 -
Benötigte python Pakete:
45 -
46 -
*   pygal
47 -
*   cairosvg
48 -
49 -
`pip install pygal pip install cairosvg` bzw. `apt-get install -y python-cairosvg python-pygal` Script welches die Daten ausliest und die Grafik erstellt:
50 -
51 -
```
52 -
#!/bin/bash
53 -
OUT=`for i in $(tail -n 13 fb.csv | head -n 12 | awk -F";" {'print $2'} ); do echo -n "$i "; done | sed -e 's/\ $//' | sed -e 's/\ /, /g'`
54 -
IN=`for i in $(tail -n 13 fb.csv | head -n 12 | awk -F";" {'print $3'} ); do echo -n "$i "; done | sed -e 's/\ $//' | sed -e 's/\ /, /g'`
55 -
SUM=`for i in $(tail -n 13 fb.csv | head -n 12 | awk -F";" {'print $4'} ); do echo -n "$i "; done | sed -e 's/\ $//' | sed -e 's/\ /, /g'`
56 -
57 -
echo " import pygal bar_chart = pygal.Bar() bar_chart.x_labels = 'Jan', 'Feb', 'Mar', 'Apr', 'Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez' bar_chart.add('Eingehend', [$IN ]) bar_chart.add('Ausgehend', [$OUT ]) bar_chart.add('Gesamt', [$SUM ]) bar_chart.render_to_file('output.svg') " > generate.py
58 -
```
59 -
Ausführen:
60 -
```
61 -
/usr/bin/python generate.py
62 -
```
63 -
64 -
oder ausführbar machen und ausführen:
65 -
66 -
```
67 -
chmod +x generate.sh
68 -
./generate.sh
69 -
```
70 -
71 -
Ergebnis: [![PyGal output](/images/posts/output.svg)](-/imgages/posts/output.svg)
gelöscht content/2018-01-02-dsl-traffic-2017.md
+0 −75
@@ -1,75 +0,0 @@
1 -
---
2 -
title: 'DSL Traffic 2017'
3 -
date: 2018-01-02 13:03:29
4 -
update: 2018-01-02 13:03:29
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - Internet
9 -
    - Traffic
10 -
    - 2017
11 -
preview: Unser DSL-Traffik 2017 Angabe in Megabytes 
12 -
categories: 
13 -
    - Technik
14 -
toc: false
15 -
hide: false
16 -
draft: false
17 -
type: post
18 -
---
19 -
20 -
Unser DSL-Traffik 2017 Angabe in Megabytes
21 -
22 -
Monat   | Gesendet |   Empfangen | Gesamt
23 -
--------|----------|-------------|-------
24 -
Jan	    | 4124	   | 16815	     | 20939
25 -
Feb	    | 1078	   | 403	       | 1481
26 -
Mär	    | 1199	   | 446	       | 1645
27 -
Apr	    | 2464	   | 36476	     | 38940
28 -
Mai	    | 92979	   | 615268	     | 708247
29 -
Jun	    | 138402	 | 664743	     | 803145
30 -
Jul	    | 116406	 | 507155	     | 623561
31 -
Aug	    | 35654	   | 471810	     | 507464
32 -
Sep	    | 31362	   | 428400	     | 459762
33 -
Okt	    | 24072	   | 549927	     | 573999
34 -
Nov	    | 44095	   | 914362	     | 958457
35 -
Dez	    | 57889	   | 1141699     | 1199588
36 -
Gesamt:	| 549724   | 5347504     | 5897228
37 -
<!--more-->
38 -
39 -
Anfang des Jahres war der Traffik hauptsächlich über den anderen Anschluss und taucht hier in der Statistik nicht auf.
40 -
Im März und April war noch Renovierungszeit und es wurde weniger gestreamt. Wir haben uns nach der Arbeit eher selbst
41 -
nur noch in Bett gestreamt. Im Oktober wurde das 1. OG mit aufgeklemmt und gepatched. Daher dann ab Ende Oktober der
42 -
Anstieg des Traffiks.
43 -
44 -
In den nächsten Tagen kommt noch das EG mit dazu, dann ist das Netzwerk endlich komplett. Im 2. und 3. OG ist schon
45 -
alles fertig. 2. und 3. OG haben jeweils 2 x 16 Port Switche. Beide Etagen sind mit 4 Gigabit (LAG) verbunden.
46 -
Im 2. OG ist dann noch der AccessPoint und ein Cisco 10 Port für Layer 3, der die unteren Etagen mit anbindet.
47 -
Das 1. OG ist über den Cisco Switch mit 2 Leitungen (LAG) zum dort verbauten Cisco Switch verbunden.
48 -
Das gleiche wird dann bald auch noch jeweils aus dem 1. und 2. OG in das EG gemacht. So das 4 Leitungen (LAG) 4 Gigabit
49 -
theoretisch im ganzen Haus können.
50 -
51 -
Wenn das gemacht ist werden alle Geräte über 2 Leitungen ins Internet gehen und die Jahresstatistik nächstes Jahr wird beide Anschlüsse beinhalten. Aber hier jetzt erst einmal die Graphen von 2017 mit nur einem Anschluss.
52 -
Ein- und ausgehender Traffic:
53 -
54 -
![In/Out Stacked](/images/posts/inoutstacked.svg)
55 -
56 -
Ein- und ausgehender Traffic (Summe)
57 -
58 -
![Traffic](/images/posts/sum.svg)
59 -
60 -
61 -
Ein- und ausgehender Traffic:
62 -
63 -
![In/Outgoing Traffic](/images/posts/inout.svg)
64 -
65 -
66 -
Ausgehender Traffic:
67 -
68 -
![Outgoing Traffic](/images/posts/outgoing.svg)
69 -
70 -
Eingehender Traffic:
71 -
72 -
![Incoming Traffic](/images/posts/incomming.svg)
73 -
74 -
75 -
Danke an Dennis für [den Hinweis](https://instant-thinking.de/2018/01/02/2017-in-vdsl-zahlen/) das ein Jahr wieder rum ist.
gelöscht content/2018-03-09-bbq-sose.md
+0 −36
@@ -1,36 +0,0 @@
1 -
---
2 -
title: 'Leckere BBQ-Soße einfach selbst gemacht.'
3 -
date: 2018-03-09 22:01:19
4 -
update: 2018-03-09 22:01:19
5 -
author: ruediger
6 -
cover: "/images/cat/essen.webp"
7 -
tags:
8 -
    - BBQ
9 -
    - Essen
10 -
    - Grillen
11 -
    - Kochen
12 -
    - Soße
13 -
preview: "Leckere BBQ-Soße einfach selbst gemacht."
14 -
categories: 
15 -
    - Essen
16 -
toc: false
17 -
hide: false
18 -
type: post
19 -
---
20 -
21 -
Leckere BBQ-Soße einfach selbst gemacht.
22 -
23 -
*   1 Knoblauchzehe
24 -
*   50 ml Apfelessig
25 -
*   200 ml Apfelsaft
26 -
*   200 g Tomatenketchup
27 -
*   1 EL Sojasauce
28 -
*   1 TL Worcestersauce
29 -
*   4 EL Ahornsirup
30 -
*   1-2 TL geräuchertes Paprikapulver
31 -
*   1 EL Whiskey (Ich nehme immer gerne einen rauchigen/torfigen Whiskey)
32 -
*   Salz, Pfeffer
33 -
34 -
<!--more-->
35 -
36 -
Alle Zutaten ausser den Ahornsirup in einen Topf und 20 Minuten leicht köcheln lassen. Anschließend den Ahornsirup dazugeben und abschmecken. Das war es eigentlich schon. Jetzt muss sie Soße einfach nur noch weiter auf kleiner Stufe offen kochen. Keinen Deckel auf den Topf, da sonst das kondensierte Wasser wieder in die Soße tropft. Die Soße soll jetzt reduzieren und eine zähflüssige BBQ-Soße werden.
gelöscht content/2018-03-09-burger-buns.md
+0 −61
@@ -1,61 +0,0 @@
1 -
---
2 -
title: 'Burger Buns'
3 -
date: 2018-03-09 21:35:13
4 -
update: 2018-03-09 21:35:13
5 -
author: ruediger
6 -
cover: "/images/cat/essen.webp"
7 -
tags:
8 -
    - Backen
9 -
    - Burger Buns
10 -
    - Essen
11 -
    - Hamburgerbrötchen
12 -
    - Ofen
13 -
preview: "Zutaten für Hamburgerbrötchen / Burger Buns"
14 -
categories: 
15 -
    - Essen
16 -
toc: false
17 -
hide: false
18 -
type: post
19 -
---
20 -
21 -
Zutaten für Hamburgerbrötchen / Burger Buns
22 -
23 -
*   200 ml warmes Wasser
24 -
*   4 EL Milch
25 -
*   1 Würfel Hefe
26 -
*   35 g Zucker
27 -
*   8 g Salz
28 -
*   80 g Butter
29 -
*   500 g Mehl Typ 550
30 -
*   1 Ei
31 -
32 -
<!--more-->
33 -
34 -
![Burger Buns](/images/posts/img_0150.webp)
35 -
36 -
37 -
Wasser und Zucker in eine Schüssel geben. Die Hefe zerbröselt dazugeben. Alles verrühren und für 5 Minuten ruhen lassen. Jetzt alle restlichen Zutaten dazu geben, gut vermischen und durchkneten. Kann auch in der Maschine gemacht werden. Nach ca. 5 Minuten sollte es einen geschmeidigen Teig.
38 -
39 -
40 -
![Burger Buns](/images/posts/img_0154.webp)
41 -
42 -
Den Teig für eine Stunde an einem warmen Ort ruhen lassen. In dieser Zeit mache ich immer den "Klebstoff" für den Sesam. Dieser sollte Zimmertemperatur haben, da sonst die Buns beim bepinseln zusammen fallen könnten.
43 -
44 -
*   1 Ei
45 -
*   2 EL Milch
46 -
*   2 EL Wasser
47 -
*   Sesam
48 -
49 -
Ei, Wasser und Milch in einer kleinen Schale gut mit dem Schneebesen vermengen. Abdecken und beiseite stellen bis kurz bevor die Buns in den Ofen können. Nach einer Stunde ist der Teig gut aufgegangen und kann weiter verarbeitet werden.
50 -
51 -
![Burger Buns](/images/posts/img_0156.webp)
52 -
53 -
Man nimmt jetzt ca 80-90 Gramm und formt den Teig in der Hand zu einer Kugel. Dabei ruhig ordentlich arbeiten. Das lässt die Buns nachher perfekt aussehen. Die Kugel auf das Blech legen und leicht herunter drücken. Aus dem Teig bekommt man zwischen 10 und 12 Buns.
54 -
55 -
![Burger Buns](/images/posts/img_0157-1.webp)
56 -
57 -
Da diese Buns nicht für Burger gewesen sind, sondern für das [Pulled Pork](https://blog.pretzlaff.info/2018/03/09/pulled-pork/) sind sie nicht alle gleich gross und nicht perfekt auf 10 cm Durchmesser getrimmt. Alles darf jetzt wieder eine Stunde ruhen. Und werden jetzt wieder ein wenig wachsen. Daher nicht zu sparsam mit dem Platz sein. Später im Ofen werden sie dann auch noch grösser. Daher nicht zu eng auf das Blech legen. Ist die Stunde rum nimmt man das Ei-, Wasser- und Milchgemisch und verteilt mit einem Pinsel es auf die Buns. Jetzt noch Sesam auf die Buns und ab in den Ofen damit. Der Ofen wird auf 200 Grad Ober-/Unterhitze vorgeheizt. Die Buns bleiben für 15-20 Minuten im Ofen. Sie sollten oben Goldbraun sein.
58 -
59 -
![Burger Buns](/images/posts/img_0159.webp)
60 -
61 -
Die fertigen Buns sind super lecker und schön fluffig.
gelöscht content/2018-03-09-pulled-pork.md
+0 −61
@@ -1,61 +0,0 @@
1 -
---
2 -
title: 'Pulled Pork'
3 -
date: 2018-03-09 20:38:05
4 -
update: 2018-03-09 20:38:05
5 -
author: ruediger
6 -
cover: "/images/cat/essen.webp"
7 -
tags: [Alle Beiträge, BBQ, Essen, Essen, Grillen, Kochen, Ofen, Pulled Pork]
8 -
preview: "Pulled Pork"
9 -
categories: 
10 -
    - Essen
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
#### Zutaten
17 -
18 -
* 2,5 Kilo Schweinenacken ohne Knochen
19 -
* ca. 250 ml Ananassaft
20 -
* ca. 250 ml kräftige Gemüsebrühe
21 -
* 3 EL brauner Zucker
22 -
* 4 EL Senf
23 -
* 3 EL Paprikapulver, edelsüß
24 -
* 1,5 EL Salz
25 -
* 1,5 EL Puderzucker
26 -
* 1 EL Pfeffer
27 -
* 1,5 EL Kreuzkümmel
28 -
* 1,5 EL Knoblauchgranulat
29 -
* 1,5 EL Cayennepfeffer
30 -
31 -
<!--more-->
32 -
33 -
#### Zubereitung
34 -
35 -
1.  Alle Gewürze von Paprikapulver miteinander vermischen.
36 -
2.  Fleisch mit dem Senf einreiben.
37 -
3.  Anschliessend der trockenen Gewürzmischung sorgfälltig einreiben. Je sorgfältiger desto Besser wird es nachher schmecken.
38 -
4.  Das Fleisch in einen Beutel packen Luft heraussaugen oder drücken, luftdicht verschliessen und für 24 Stunden in den Kühlschrank.
39 -
40 -
![Pulled Pork](/images/posts/img_5073-300x225.webp)
41 -
42 -
43 -
Am nächsten Tag rechtzeitig das Fleisch aus dem Kühlschrank nehmen und bevor es in den Ofen kommt die Zimmertemperatur annehmen lassen.
44 -
45 -
1.  Ofen auf 110 Grad vorheizen. Ober-/Unterhitze auf keinen Fall Umluft.
46 -
2.  Ein Auflaufform oder Bräter der unter das Rost passt mit 250 ml Annanassaft, 250 ml Orangensaft ud 250 ml Brühe und den 3 EL braunen Zucker füllen.
47 -
3.  Bräter/Auflauform in den Ofen und auf dem Gitter darüber das Fleisch legen.
48 -
4.  Jetzt heisst es warten, warten, warten.
49 -
5.  Wenn das Fleisch ein Kerntempertur von 65-70 Grad hat mit dem Sud aus dem Bräter mit einem Pinsel bestreichen. Wenn nötig ruhig Annanas und Co nachschütten.
50 -
51 -
Wichtig. Immer Ruhe bewaren. Das Fleisch wird am anfang recht schnell hoch gehen. Wird dann aber Plateaus haben in denen nichts mehr passiert. Meistens bei ca. 65 Grad. Es kommt auch vor das später auch noch mal bei ca 75-78 Grad ein zweites Plateau kommt. Die Plateaus können auch schon mal bis zu 2 Stunden dauern bis es weiter geht. Also abwarten und nicht die Temperatur hoch drehen. Das wird schon.
52 -
53 -
![Pulled Pork](/images/posts/img_5078-1024x768.webp)
54 -
55 -
56 -
Wenn 20-21 Stunden rum sind kann man auch schon einmal mit der [BBQ-Sosse](https://blog.pretzlaff.info/2018/03/09/bbq-sosse/) beginnen. Wer zum Pulled Pork auch [Buns](https://blog.pretzlaff.info/2018/03/09/burger-buns/) haben möchte auch diese. Beides dauert 2-3 Stunden. Aber reine Arbeitszeit ist fast gar keine. Dabei heisst es auch die meiste Zeit warten, warten, warten. Wird aber auch beides genau so belohnt wie das Pulled Pork. Unverschämt lecker. Wenn das Fleisch 95 Grad hat ist es fertig. Es kann jetzt aus dem Ofen genommen werden und auseinander gezupft werden. Es sollte jetzt aber schon von selbst auseinder fallen. Dafür nehme ich immer ein Backofenblech und lege das Fleisch drauf. Einfach mit 2 Gabeln  auseinander ziehen. Anschliessend gibt man noch etwas vom Sud und etwas von der [BBQ-Sosse](https://blog.pretzlaff.info/2018/03/09/bbq-sosse/) dazu. Fertig ist das Pulled Pork und kann gegessen werden.
57 -
58 -
![Pulled Pork](/images/posts/img_0161.webp)
59 -
60 -
61 -
Beim schreiben dieses Artikels ist aufgefallen das vom fertigen Pulled Pork bis jetzt nur das Bild existiert wo die Schale schon fast leer war. Beim nächsten mal muss ich die hunrige Meute davon fern halten. Die fahren halt alle voll drauf ab.
gelöscht content/2018-06-06-fender-squier-bullet-strat-rw-aw.md
+0 −30
@@ -1,30 +0,0 @@
1 -
---
2 -
title: 'Fender Squier Bullet Strat RW AW'
3 -
date: 2018-06-06 20:28:10
4 -
update: 2018-07-18 20:28:10
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags:
8 -
    - Guitar
9 -
    - Musik
10 -
    - Fender
11 -
preview: "Neue Gitarre"
12 -
categories: 
13 -
    - Musik
14 -
toc: false
15 -
hide: false
16 -
type: post
17 -
---
18 -
19 -
### Neue Gitarre
20 -
21 -
22 -
![Fender Squier Bullet Strat RW AW](/images/posts/IMG_1116.webp)
23 -
24 -
25 -
![Fender Squier Bullet Strat RW AW](/images/posts/IMG_1123-e1455287450903-150x150.webp)
26 -
27 -
28 -
### Video
29 -
30 -
<iframe width="560" height="315" src="https://www.youtube.com/embed/2Bsp62SjnGo?si=r-SG305DWIQRgcp7" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
\ No newline at end of file
gelöscht content/2018-06-08-twitter-und-youtube-vimeo-videos-datenschutzgerecht-eingebunden.md
+0 −68
@@ -1,68 +0,0 @@
1 -
---
2 -
title: 'Twitter und Youtube/Vimeo Videos datenschutzgerecht  eingebunden'
3 -
date: 2018-06-06 21:10:02
4 -
update: 2018-06-06 21:10:02
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags: [datenschutz, dsgvo, Facebook, Internet, Social Network, Technik, Twitter, vimeo, wordpress, youtube]
8 -
preview: "Hier werden jetzt Videos von Youtube, Vimeo (Facebook würde auch gehen), sowie Tweets von Twitter datenschutzgerecht eingebunden."
9 -
categories: 
10 -
    - Technik
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
Hier werden jetzt Videos von Youtube, Vimeo (Facebook würde auch gehen), sowie Tweets von Twitter datenschutzgerecht eingebunden.  
17 -
[Heise.de](https://www.heise.de/newsticker/meldung/Embetty-Social-Media-Inhalte-datenschutzgerecht-einbinden-4060362.html) hat dafür [Embetty](https://github.com/heiseonline/embetty) und [Embetty Server](https://github.com/heiseonline/embetty-server) veröffentlicht.
18 -
19 -
<!--more-->
20 -
21 -
Beim Aufruf der Artikel werden die Videovorschau jetzt nicht mehr direkt bei Google und Co mit der IP der Besucher dieser Seite der abgerufen.
22 -
Das wird jetzt alles über den Embetty Server gemacht. Embetty hängt also als Proxy zwischen euch und Youtube, Vimeo, Facebook und Twitter.
23 -
Erst wenn ein Video angeklickt wird werden Daten an die Server der Anbieter gesendet.
24 -
Im Wordpress Header wurde jetzt einfach der embetty Server hinzugefügt und im Webroot der Seite das embetty.js abgelegt:
25 -
26 -
```
27 -
<meta data-embetty-server="https://blog.pretzlaff.info:8089">
28 -
<script async src="/embetty.js"></script>
29 -
```
30 -
31 -
Tweet im Artikel einbinden:
32 -
```
33 -
<embetty-tweet status="1000738984253943811"></embetty-tweet>
34 -
```
35 -
36 -
Ergebnis:
37 -
38 -
```
39 -
<embetty-video type="vimeo" video-id="91085172"></embetty-video>
40 -
```
41 -
42 -
Ergebnis:
43 -
44 -
```
45 -
git clone https://github.com/heiseonline/embetty-server.git
46 -
cd embetty-server
47 -
```
48 -
49 -
docker-compose.yml
50 -
51 -
```
52 -
version: '3.1'
53 -
services:
54 -
  server:
55 -
    image: heiseonline/embetty-server:latest
56 -
    ports:
57 -
      - 8089:8080
58 -
    environment:
59 -
      - VALID_ORIGINS=http://localhost
60 -
      - TWITTER_ACCESS_TOKEN_KEY=<YOURTOKENKEY>
61 -
      - TWITTER_ACCESS_TOKEN_SECRET=<YOURSECTRETKEY>
62 -
      - TWITTER_CONSUMER_KEY=<YOURCUNSOMERKEY>
63 -
      - TWITTER_CONSUMER_SECRET=<YOURCONSUMERSECRET>
64 -
```
65 -
66 -
 Speichern ..
67 -
68 -
```docker-compose up -d``` und der Server rennt.
gelöscht content/2018-07-19-boris-brejcha-musik-fuers-buero.md
+0 −24
@@ -1,24 +0,0 @@
1 -
---
2 -
title: 'Boris Brejcha Musik fürs Büro'
3 -
date: 2018-07-19 16:32:23
4 -
update: 2018-07-19 16:32:23
5 -
author: ruediger
6 -
cover: "/images/cat/musik.webp"
7 -
tags:
8 -
    - BORIS BREJCHA
9 -
    - High-Tech Minimal
10 -
    - Mix
11 -
    - Mixed
12 -
    - Musik
13 -
    - Track
14 -
preview: "[Carsten](https://blog.zn80.net/) hat heute eine Track von [Boris Brejcha](http://www.borisbrejcha.de) [im Blog gepostet](https://blog.zn80.net/2018/07/19/boris-brejcha-au-main-square-festival-2018/). Und ja, der ist schon was ganz feines während der Arbeit. Der Track und andere von ihm werden jetzt öfters laufen."
15 -
categories: 
16 -
    - Musik
17 -
toc: false
18 -
hide: true
19 -
type: post
20 -
---
21 -
22 -
[Carsten](https://blog.zn80.net/) hat heute eine Track von [Boris Brejcha](http://www.borisbrejcha.de) [im Blog gepostet](https://blog.zn80.net/2018/07/19/boris-brejcha-au-main-square-festival-2018/). Und ja, der ist schon was ganz feines während der Arbeit. Der Track und andere von ihm werden jetzt öfters laufen.
23 -
<!--more-->
24 -
{{< youtube juhEm_J1r70 >}}
gelöscht content/2018-07-19-ebook-react-and-react-native-kostenlos.md
+0 −35
@@ -1,35 +0,0 @@
1 -
---
2 -
title: 'eBook React and React Native kostenlos'
3 -
date: 2018-07-18 09:42:20
4 -
update: 2018-07-18 09:42:20
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - Application
9 -
    - Build-React
10 -
    - E-Book
11 -
    - epub
12 -
    - Facebooks-Relay
13 -
    - GraphQL 
14 -
    - technologies
15 -
    - Internet
16 -
    - Platform
17 -
    - React
18 -
    - React-Native
19 -
    - Routing
20 -
    - Unified-Architecture
21 -
    - Web-Application
22 -
preview: 'Bei [packtpub.com](https://www.packtpub.com/packt/offers/free-learning) gibt es wieder das tägliche kostenlose E-Book. "React and React Native" heißt das heutige Buch und könnte für einige interessant sein.'
23 -
categories: 
24 -
    - Musik
25 -
toc: false
26 -
hide: false
27 -
type: post
28 -
---
29 -
30 -
31 -
Bei [packtpub.com](https://www.packtpub.com/packt/offers/free-learning) gibt es wieder das tägliche kostenlose E-Book. "React and React Native" heißt das heutige Buch und könnte für einige interessant sein.
32 -
33 -
<!--more-->
34 -
35 -
> React and React Native Use React and React Native to build applications for desktop browsers, mobile browsers, and even as native mobile apps Build React and React Native applications using familiar component concepts Dive deep into each platform, from routing in React to creating native mobile applications that can run offline Use Facebook's Relay, React and GraphQL technologies, to create a unified architecture that powers both web and native applications
gelöscht content/2018-07-19-the-iphone-x-index.md
+0 −17
@@ -1,17 +0,0 @@
1 -
---
2 -
title: 'The iPhone X Index'
3 -
date: 2018-07-19 14:37:37
4 -
update: 2018-07-19 14:37:37
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags: [Buy, Internet, iPhone, money, UBS]
8 -
preview: "Wer einfach mal wissen möchte wie lange er für ein iPhone arbeiten müsste. Oder sich einfach mal bewusst machen wie viel Glück die meisten von uns eigentlich haben ein Smartphone überhaupt zu haben."
9 -
categories: 
10 -
    - Internet
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
Wer einfach mal wissen möchte wie lange er für ein iPhone arbeiten müsste. Oder sich einfach mal bewusst machen wie viel Glück die meisten von uns eigentlich haben ein Smartphone überhaupt zu haben. [howmuch.net](https://howmuch.net/articles/hours-work-buy-iphone)
17 -
<!--more-->
gelöscht content/2018-07-20-good-mans-burger-trucks.md
+0 −31
@@ -1,31 +0,0 @@
1 -
---
2 -
title: 'Good Mans Burger Trucks'
3 -
date: 2018-07-20 11:12:54
4 -
update: 2018-07-20 11:12:54
5 -
author: ruediger
6 -
cover: "/images/posts/essen.webp"
7 -
tags:
8 -
    - Beef
9 -
    - Burger
10 -
    - Düsseldorf
11 -
    - Essen
12 -
    - Köln
13 -
    - Ratingen
14 -
    - Truck
15 -
preview: "Ein Kollege hat uns vor ein paar Wochen einmal mit zum [Burgertruck](https://www.goodmansburgertruck.de) genommen, der ab und an in der Nähe vom Büro steht."
16 -
categories: 
17 -
    - Essen
18 -
toc: false
19 -
hide: true
20 -
draft: true
21 -
type: post
22 -
---
23 -
24 -
Ein Kollege hat uns vor ein paar Wochen einmal mit zum [Burgertruck](https://www.goodmansburgertruck.de) genommen, der ab und an in der Nähe vom Büro steht. Seit dem waren wir jedes mal Burger holen wenn der Truck da war. Super lecker und Preise sind auch noch sehr angenehm. Heute war wieder der Burger Tag und es war wieder ein Genuss. Sie sind mit 6 Trucks und in bis zu 10 Städten pro Woche.
25 -
<!--more-->
26 -
27 -
28 -
![Goodman's Burger Truck](/images/posts/burger-n-truck.webp)
29 -
30 -
31 -
Einen Wochenplan mit allen Adressen findest Du hier: [http://www.facebook.com/Burgertruck/](http://www.facebook.com/Burgertruck/) Lohnt sich.
gelöscht content/2018-07-23-dsgvo-temporaere-speicherung-der-ip-adressen-bei-kommentaren.md
+0 −42
@@ -1,42 +0,0 @@
1 -
---
2 -
title: 'DSGVO: temporäre Speicherung der IP Adressen bei Kommentaren'
3 -
date: 2018-07-23 12:15:41
4 -
update: 2018-07-23 12:15:41
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - Blog
9 -
    - DSGvO
10 -
    - Internet
11 -
    - IP
12 -
    - IP-Adresse
13 -
    - Kommentare
14 -
    - Spam
15 -
    - Wordpress
16 -
preview: "Mit der DSGVO ist die IP-Adresse zu schützen. Vorher wurde die IP auch nur temporär gespeichert."
17 -
categories: 
18 -
    - Technik
19 -
toc: false
20 -
hide: false
21 -
draft: false
22 -
type: post
23 -
---
24 -
25 -
Mit der DSGVO ist die IP-Adresse zu schützen. Vorher wurde die IP auch nur temporär gespeichert. Nach der Freischaltung eines Kommentars wurden die IP Adressen bei den Kommentaren gelöscht. Mit der DSGVO habe ich einfach mal die IP-Adresse bei den Kommentaren komplett eliminiert und jetzt knapp 2 Monate versucht ohne auszukommen. Ergebnis: Scheisse. Früher war es so das Spammer versucht haben ihre Scheisse los zu werden. Dabei sind sie meistens wie folgt vorgegangen:
26 -
<!--more-->
27 -
1.  Kommentar gesendet. (z.B. von 123.123.123.123)
28 -
2.  Minuten oder Stunden später kam dann der nächste Spam-Kommentar. wieder mit der gleichen IP Adresse.
29 -
3.  Einige Zeit später ein weiterer Kommentar.
30 -
4.  Spätestens jetzt habe ich dann die IP genommen, gegen ein Tool von mir geworfen und die IP landete in direkt in der Firewall in einer Blacklist.
31 -
5.  Ruhe
32 -
6.  Ohne geht das jetzt weiter bis dann 30 und mehr Spam-Kommentare das Blog zu müllen.
33 -
34 -
Daher werden hier jetzt bei den Kommentaren die IP-Adressen wieder gespeichert und nach Freigabe oder Löschung der Kommentare die IP-Adressen aus der Datenbank entfernt. Das ganze ist natürlich in der Datenschutzerklärung abgedeckt.
35 -
36 -
> ### Kommentare und Beiträge
37 -
>
38 -
> Wenn Nutzer Kommentare oder sonstige Beiträge hinterlassen, können ihre IP-Adressen auf Grundlage unserer berechtigten Interessen im Sinne des Art. 6 Abs. 1 lit. f. DSGVO für 7 Tage gespeichert werden.
39 -
40 -
Zusätzlich werden Besucher beim Schreiben der Kommentare auf die Speicherung der IP-Adresse hingewiesen. 
41 -
42 -
Icons made by [Freepik](http://www.freepik.com "Freepik") from [www.flaticon.com](https://www.flaticon.com/ "Flaticon") is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/ "Creative Commons BY 3.0")
gelöscht content/2018-12-18-mpow-bluetooth-headset-reset.md
+0 −24
@@ -1,24 +0,0 @@
1 -
---
2 -
title: 'MPOW Bluetooth Headset Reset'
3 -
date: 2018-12-18 18:42:05
4 -
update: 2018-12-18 18:42:05
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags: ["Bluetooth", "iPhone", "Musik", "Restore", "Technik", "Telefon", "Zubehör"]
8 -
preview: "Ich hatte 2016 ja [hier berichtet](https://blog.kuepper.nrw/2016/01/23/mpow-magneto-headset/): ich habe jetzt das MPOW Bluethoth Headset. Das benutze ich immer noch."
9 -
categories: 
10 -
    - Technik
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
17 -
Ich hatte 2016 ja [hier berichtet](https://blog.kuepper.nrw/2016/01/23/mpow-magneto-headset/): ich habe jetzt das MPOW Bluethoth Headset. Das benutze ich immer noch.
18 -
19 -
<!--more-->
20 -
21 -
![MPOW Bluetooth Headset Reset](/images/posts/Mpow-Magneto-1.webp)
22 -
23 -
24 -
Aus gegebenen Anlass mal ein Update zu dem Gerät. Funktioniert immer noch super und ich bin damit immer noch zufrieden. Vorgestern habe ich es einfach in den Rucksack geworfen und irgend etwas muss auf die Knöpfe gedrückt haben. Er blinkte nur noch wild. Gerade wollte ich einen Podcast hören und das Headset war nicht mehr gekoppelt. Mehrfach aus- und einschalten hat nicht geholfen. Wie Reset durchführen? Google wirft nur zig Anleitungen zum koppeln. Reset ist nirgendwo beschrieben. Ich hatte das Headset aber schon mal neu verbinden müssen. Aber erst einmal und das ist lange her und es war nur wegen neuem iDevice und nicht wegen einem Fehler. Es war etwas mit lange drücken. Also Power gedrückt, nichts. Die Taste für lauter ist es auch nicht. Es war die Leisetaste. Die einfach bei wild blinken 10 Sekunden gedrückt halten. Danach hört das blinken auf. Aber koppeln ging noch nicht. Dafür dann einfach ausschalten und wieder einschalten. Das Headset befindet sich dann im Pearingmodus. Am anderen Device taucht es dann auf, antippen und wird gekoppelt.
gelöscht content/2019-01-04-dsl-traffic-2018.md
+0 −46
@@ -1,46 +0,0 @@
1 -
---
2 -
title: 'DSL Traffic 2018'
3 -
date: 2019-01-04 13:03:29
4 -
update: 2019-01-04 13:03:29
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags:
8 -
    - Internet
9 -
    - Traffic
10 -
    - 2018
11 -
preview: Unser DSL-Traffik 2018 Angabe in Terrabytes 
12 -
categories: 
13 -
    - Technik
14 -
toc: false
15 -
hide: false
16 -
draft: false
17 -
type: post
18 -
---
19 -
20 -
Unser DSL-Traffik 2018 Angabe in Terabytes
21 -
22 -
Monat   | Gesendet   |   Empfangen | Gesamt
23 -
--------|----------|-----------|-------
24 -
Jan	    | 0.07	   | 1.20	     | 1.30
25 -
Feb	    | 0.07	   | 0.95	     | 1.05
26 -
Mär	    | 0.73	   | 0.92	     | 1.02
27 -
Apr	    | 0.06	   | 0.81	     | 0.87
28 -
Mai	    | 0.08	   | 1.28	     | 1.36
29 -
Jun	    | 0.07	   | 0.71	     | 0.78
30 -
Jul	    | 0.10	   | 0.82	     | 0.92
31 -
Aug	    | 0.06	   | 1.01	     | 1.07
32 -
Sep	    | 0.08	   | 1.09	     | 1.18
33 -
Okt	    | 0.86	   | 1.01	     | 1.10
34 -
Nov	    | 0.04	   | 1.17	     | 1.21
35 -
Dez	    | 0.04	   | 1.11	     | 1.16
36 -
Gesamt:	| 2.26     | 12.08     | 13.02
37 -
38 -
<!--more-->
39 -
![DSL Traffic IN/OUT/Summe](/images/posts/traffic_2018.webp)
40 -
41 -
42 -
Wie auch schon im [letzten Jahr](https://blog.kuepper.nrw/2018/01/02/dsl-traffic-2017/) auch dieses Jahr wieder die DSL Traffik Statistik.
43 -
44 -
Der Dennis hat seine [auch schon online](https://instant-thinking.de/2019/01/02/2018-in-vdsl-zahlen/).
45 -
46 -
Und [Michel](https://pixelscheucher.de/vdsl-nutzung-2018/) so wie so. Die Grafiken dazu werden später noch nachgereicht.
gelöscht content/2019-01-28-kopieren-mit-dd-und-progressbar.md
+0 −41
@@ -1,41 +0,0 @@
1 -
---
2 -
title: "Kopieren mit dd und Progressbar"
3 -
date: 2019-01-28 19:07:53
4 -
update: 2019-01-28 19:07:53
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
    - Boot
9 -
    - CleanInstall
10 -
    - Installation
11 -
    - Linux
12 -
    - MacOS
13 -
    - Partition
14 -
    - Restore
15 -
    - Technik
16 -
    - USB-Stick
17 -
preview: "Wer einen Rescue USB Stick erstellen will kann mit Hilfe von dd das .iso auf den Stick schreiben."
18 -
categories: 
19 -
    - Technik
20 -
toc: false
21 -
hide: false
22 -
type: post
23 -
---
24 -
25 -
Wer einen Rescue USB Stick erstellen will kann mit Hilfe von dd das .iso auf den Stick schreiben.
26 -
27 -
```
28 -
dd if=~/rescue.iso of=/dev/disk3 bs=1m
29 -
```
30 -
31 -
Dabei wird aber nicht angezeigt wie weit der Kopiervorgang ist. Bei den heutigen Betriebsystemen ist das Image aber mehrere Gigabytes groß und es dauert bei einem langsamen Stick sehr lange. Es könnte aber auch sein das ein Problem aufgetreten ist und man sieht nicht ob noch weiter kopiert wird. Daher kann man zwischen dem if (InputFile) und of (OutputFile) das Programm pv getrennt durch ein pipe setzen.
32 -
<!--more-->
33 -
```
34 -
dd if=~/rescue.iso | pv | dd of=/dev/disk3 bs=1m mb-rp# dd if=snow\ leopard\ install.iso | pv | dd of=/dev/disk3 bs=1m
35 -
731MiB 0:28:30 [   0 B/s] [             <=>            ]
36 -
```
37 -
So sieht man wie viel MB/GB schon kopiert wurden und wird nach Stunden warten nicht nervös und bricht das kopieren nicht vor lauter Verzweiflung auch noch unwissend bei 98% ab. ;-) **DMG to ISO umwandeln** Da ich selbst auch immer suchen muss halte ich hier auch gleich das dmg zu iso Image umwandeln fest.
38 -
39 -
```
40 -
hdiutil convert /path/imagefile.dmg -format UDTO -o /path/convertedimage.iso
41 -
```
gelöscht content/2019-03-30-roundcube-webmail-mit-zwei-faktor-authentifizierung.md
+0 −43
@@ -1,43 +0,0 @@
1 -
---
2 -
title: "Roundcube Webmail mit Zwei-Faktor Authentifizierung"
3 -
date: 2019-03-30 21:35:05
4 -
update: 2019-03-30 21:35:05
5 -
author: ruediger
6 -
cover: "/images/cat/internet.webp"
7 -
tags: ["Alle Beiträge", "Authentication", "Authentifizierung", "E-Mail", "Internet", "Internet", "Security", "Two-Factor", "Two-Factor Authentication", "Webmail", "Zwei-Faktor"]
8 -
preview: "Um die Sicherheit zu erhöhen habe ich vor ein paar Wochen das Two-Factor Gauthenticator Modul im Roundcube Webmail hinzugefügt. Damit können die User sich nicht mehr nur mit Benutzer und Passwort einloggen, sondern brauchen einen zweiten Faktor. Das ist dann ein 6-stelliger Code aus dem Google Authenticator auf dem Smartphone. Die Installation ist recht einfach."
9 -
categories: 
10 -
    - Internet
11 -
toc: false
12 -
hide: false
13 -
type: post
14 -
---
15 -
16 -
Um die Sicherheit zu erhöhen habe ich vor ein paar Wochen das Two-Factor Gauthenticator Modul im Roundcube Webmail hinzugefügt. Damit können die User sich nicht mehr nur mit Benutzer und Passwort einloggen, sondern brauchen einen zweiten Faktor. Das ist dann ein 6-stelliger Code aus dem Google Authenticator auf dem Smartphone. Die Installation ist recht einfach. Das Module wird in das Webverzeichnis in dem Roundcube installiert ist im Ordner "**plugins**" gespeichert. z.B. "**/var/www/webmail/plugins**"
17 -
18 -
<!--more-->
19 -
> ```
20 -
> cd /var/www/webmail/plugins
21 -
> git clone https://github.com/alexandregz/twofactor\_gauthenticator.git
22 -
> ```
23 -
24 -
Um das PlugIn zu aktiveren öffnet man die Roundcube Konfigurationsdatei und fügt das PlugIn in der Liste hinzu:
25 -
26 -
> ```
27 -
> $config\[‘plugins’\] = array(‘plugin1’, ‘plugin2’, ‘twofactor\_gauthenticator’);
28 -
> ```
29 -
30 -
Anschliessend kann man sich im Roundcube einloggen und in die Einstellungen unter dem Punkt "**Zwei-Faktor Authentifizierung**" die Einstellungen vornehmen und den Goolge Authenticator einrichten.
31 -
32 -
![Roundcube Webmail mit Two-Factor Authentication](/images/posts/2factor-1024x312.webp)
33 -
34 -
35 -
1.  Auf speichern klicken.
36 -
2.  Es erscheint eine Meldung das nicht alle Felder ausgefüllt sind.
37 -
3.  OK Bestätigen und es erscheint ein QR-Code.
38 -
4.  Den Google Authenticator öffnen.
39 -
5.  Hinzufügen auswählen und Barcode scannen.
40 -
6.  Den 6 stelligen Code aus der App eingeben und prüfen anklicken.
41 -
7.  Auf "Speichern" klicken.
42 -
43 -
Ab jetzt wird nach dem Login im Webmail nach dem zweiten Faktor gefragt. Die Wiederherstellungscodes sollte man speichern und sicher aufbewahren. Diese werden benötigt wenn man das Smartphone verliert oder wenn der Google Authenticator zum Beispiel bei einem defekten Gerät nicht mehr zur Verfügung stehen sollte.
gelöscht content/2019-07-13-hugo-cms-migration.md
+0 −246
@@ -1,246 +0,0 @@
1 -
---
2 -
title: 'Hugo CMS migration'
3 -
date: 2019-07-13 17:03:03
4 -
update: 2019-07-13 17:03:03
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/04/programming.webp"
7 -
tags:
8 -
    - Webpage
9 -
    - CMS
10 -
    - Hugo
11 -
    - Generator
12 -
    - Pipeline
13 -
    - Deployment
14 -
    - Automatisierung
15 -
preview: "*Notiz an mich, um nich noch einmal suchen zu müssen*  Um im BGP manche Netze nicht zu erlauben:"
16 -
categories: 
17 -
    - Technik
18 -
toc: false
19 -
hide: false
20 -
type: post
21 -
---
22 -
23 -
24 -
## Migration nach Hugo CMS
25 -
26 -
Die Seite ist jetzt zu einem Hugo CMS migriert worden. Hugo ist ein Static Page Generator.
27 -
Im gegensatz zu Wordpress werden die Seiten nicht bei jedem Aufruf neu generiert, sondern nur nach Änderungen.
28 -
Die fertig Seiten werden dann auf dem Server bereitgestellt.
29 -
30 -
Das macht die Seite sehr schell und ich kann sie in Zukunft auch auf sehr vielen Servern, in Docker oder Kubernetes Clustern verteilen.
31 -
Also auch sehr grosse Lastspitzen locker abfangen.
32 -
<!--more-->
33 -
## Hugo - CMS
34 -
35 -
> Als statischer Websitegenerator werden von Hugo die HTML-Dateien – im Gegensatz zu dynamischen Websitegeneratoren – nicht jedes Mal, wenn die Webseite aufgerufen wird, neu generiert, sondern nur, wenn sich der Inhalt der jeweiligen Seite ändert. Insbesondere ermöglicht es Hugo, dass nur diejenigen HTML-Dokumente der jeweiligen Webseite neu gebaut werden müssen, in denen Änderungen auftraten. Hierdurch sollen die Ressourcen des Servers geschont und eine hohe Effizienz von diesem erreicht werden.[3] Nach einer nicht-repräsentativen Benchmark generiert Hugo Webseiten 75-mal schneller als der ebenfalls statische Websitegenerator Middleman.[4]
36 -
37 -
> Hugo unterstützt nativ neben HTML auch die Darstellung von Texten, die in Markdown verfasst wurden. Mit Hilfe externer Anwendungen kann diese Unterstützung auf AsciiDoc und reStructuredText erweitert werden. Auch YAML, JSON und TOML werden unterstützt. Mittels der sogenannten „LiveReload“-Funktion können Änderungen an den Dokumenten zeitgleich auf der Webseite übernommen werden. Die graphische Darstellung der Inhalte kann mittels verschiedener Themenvorlagen geregelt werden.[4][5] Dabei wird zwischen drei verschiedenen Grundtypen unterschieden: Single, List und Homepage. Die Nutzung der Themen erfolgt mittels der Template-Engine von Go. Hugo ermöglicht es zusätzlich, Inhalte der Webseiten mittels Schlüsselwörtern zu kategorisieren.
38 -
39 -
> Eine Besonderheit von Hugo ist, dass es einen eigenen HTTP-Server mitliefert. Hierdurch sind Anwender nicht auf z. B. nginx oder den Apache HTTP Server angewiesen, wodurch Abhängigkeiten verhindert werden. Auch bestimmte Laufzeitumgebungen und Datenbanken wie Ruby, PHP oder MySQL werden zur Nutzung nicht benötigt.
40 -
41 -
## Format von manchen Blog Artikeln noch defekt
42 -
43 -
In manchen Artikeln wurden Plugins für Tabellen, Soundcloud einbindung und andere benutzt.
44 -
Daher können manche der Artikel aktuell noch nicht richtig angezeigt werden.
45 -
Bei den Artikeln muss ich noch etwas nacharbeiten.
46 -
47 -
## Seite generieren auf GitLab
48 -
49 -
Beschreibung wie die Seite mit Gitlab Pipeline generiert wird ...
50 -
51 -
Um die Seite neu zu generieren werden Änderungen in den Master Branch gepushed.
52 -
Dadurch wird eine Pipeline getriggert die sich ein Hugo Docker Image holt und die Seite wird damit generiert (build).
53 -
Ist der Build fertig und ok wird ein ssh+rsync Docker Image geladen und die Seite wird auf den/die Webserver kopiert (deploy).
54 -
55 -
Die Konfiguration `.gitlab-ci.yml` der Pipeline sieht so aus:
56 -
57 -
```
58 -
stages:
59 -
  - build
60 -
  - deploy
61 -
build:
62 -
  stage: build
63 -
  image: registry.gitlab.com/ruedigerp/hugoci:latest
64 -
  script:
65 -
  - git submodule update --init --recursive
66 -
  - hugo -b "${BLOG_URL}"
67 -
  artifacts:
68 -
    paths:
69 -
    - public
70 -
    expire_in: 1 hour
71 -
  only:
72 -
  - master
73 -
build:
74 -
  stage: build
75 -
  image: registry.gitlab.com/ruedigerp/hugoci:latest
76 -
  script:
77 -
  - git submodule update --init --recursive
78 -
  - hugo -b "${BLOG_URL}"
79 -
  artifacts:
80 -
    paths:
81 -
    - public
82 -
    expire_in: 1 hour
83 -
  only:
84 -
  - master
85 -
deploy:
86 -
  stage: deploy
87 -
  image: registry.gitlab.com/ruedigerp/ci-deploy-rsync-ssh
88 -
  script:
89 -
  - echo "${SSH_PRIVATE_KEY}" > ${HOME}/id_rsa
90 -
  - chmod 400 ${HOME}/id_rsa
91 -
  - mkdir "${HOME}/.ssh"
92 -
  - echo "${SSH_KNOWN_HOSTS}" > "${HOME}/.ssh/known_hosts"
93 -
  - rsync -at --quiet --delete --delete-delay --delay-updates --exclude=_ --include=.well-known -e "ssh -i ~/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${DEPLOY_PORT}" public/ ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_DIR}
94 -
  variables:
95 -
    GIT_STRATEGY: none
96 -
  only:
97 -
  - master
98 -
```
99 -
100 -
Beim Build wird Die Seite  nach `./Public` generiert und als Artifakt für 1 Stunde gespeichert.
101 -
Das wird im Deploy Schritt dann wieder abgerufen und kann so dann in diesem Schritt benutzt werden.
102 -
103 -
Damit die Pipeline funktioniert müssen in den Settings noch die Variabeln hinterlegt werden.
104 -
105 -
* BLOG_URL
106 -
* SSH_PRIVATE_KEY
107 -
* SSH_KNOWN_HOSTS
108 -
* DEPLOY_PORT
109 -
* DEPLOY_USER
110 -
* DEPLOY_HOST
111 -
* DEPLOY_DIR
112 -
113 -
Den SSH Host Key bekommt man mit:
114 -
115 -
    ssh-keyscan -p $PORT dein.ssh.host.de
116 -
117 -
Wer noch keinen `ssh-key` hat oder einen neuen genieren will:
118 -
119 -
    ssh-keygen -t rsa -b 4096 [-f output_keyfile] [-C ci-cd-deploment]
120 -
121 -
122 -
~~Geplant sind noch weitere Stages um die Seite nicht nur lokal zu testen, sondern bevor sie Live jetzt auch im Internet in einer Testumgebung testen zu können.~~
123 -
Gerade wenn man Seiten mit mehreren Leuten betreut kann auf `staging` deployed werden und alle können überprüfen ob alles ok ist.
124 -
Erst danach wird `staging` in `master` gemerged und automatisch in `PROD` deployed.
125 -
126 -
Das ist jetzt auch umgesetzt mit folgender `.gitlab-ci.yml`.
127 -
128 -
```
129 -
stages:
130 -
  - build
131 -
  - deploy-dev
132 -
  - deploy
133 -
build:
134 -
  stage: build
135 -
  image: registry.gitlab.com/ruedigerp/hugoci:latest
136 -
  script:
137 -
  - git submodule update --init --recursive
138 -
  - hugo -b "${BLOG_URL}"
139 -
  artifacts:
140 -
    paths:
141 -
    - public
142 -
    expire_in: 1 hour
143 -
  only:
144 -
  - master
145 -
  - dev
146 -
147 -
dev:
148 -
  stage: deploy-dev
149 -
  image: registry.gitlab.com/ruedigerp/ci-deploy-rsync-ssh
150 -
  script:
151 -
  - echo "${SSH_PRIVATE_KEY}" > ${HOME}/id_rsa
152 -
  - chmod 400 ${HOME}/id_rsa
153 -
  - mkdir "${HOME}/.ssh"
154 -
  - echo "${SSH_KNOWN_HOSTS}" > "${HOME}/.ssh/known_hosts"
155 -
  - rsync -at --quiet --delete --delete-delay --delay-updates --exclude=_ --include=.well-known -e "ssh -i ~/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${DEPLOY_PORT}" public/ ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_DIR}dev
156 -
  variables:
157 -
    GIT_STRATEGY: none
158 -
  only:
159 -
  - dev
160 -
161 -
deploy:
162 -
  stage: deploy
163 -
  image: registry.gitlab.com/ruedigerp/ci-deploy-rsync-ssh
164 -
  script:
165 -
  - echo "${SSH_PRIVATE_KEY}" > ${HOME}/id_rsa
166 -
  - chmod 400 ${HOME}/id_rsa
167 -
  - mkdir "${HOME}/.ssh"
168 -
  - echo "${SSH_KNOWN_HOSTS}" > "${HOME}/.ssh/known_hosts"
169 -
  - rsync -at --quiet --delete --delete-delay --delay-updates --exclude=_ --include=.well-known -e "ssh -i ~/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${DEPLOY_PORT}" public/ ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_DIR}dev
170 -
  variables:
171 -
    GIT_STRATEGY: none
172 -
  only:
173 -
  - master
174 -
  - dev
175 -
  when: manual
176 -
177 -
```
178 -
179 -
Push in `dev` triggert die Pipeline. Die macht den Build und das Deploy dann in die Testumgebung.
180 -
Danach hält die Pipeline an und man kann alles testen. Wenn man dann nach `live` deployen will klickt man in der Pipeline und sie läuft weiter.
181 -
182 -
### Hugo Docker Image für GitLab Pipeline
183 -
184 -
Um die Seiten zu generieren ....
185 -
186 -
hugoci
187 -
Dockerfile:
188 -
189 -
```
190 -
FROM alpine:3.7
191 -
192 -
RUN apk add --update \
193 -
      git && \
194 -
    rm -rf /var/cache/apk/*
195 -
196 -
ENV HUGO_VERSION 0.42.2
197 -
ENV HUGO_RESOURCE hugo_${HUGO_VERSION}_Linux-64bit
198 -
199 -
ADD https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/${HUGO_RESOURCE}.tar.gz /tmp/
200 -
201 -
RUN mkdir /tmp/hugo && \
202 -
    tar -xvzf /tmp/${HUGO_RESOURCE}.tar.gz -C /tmp/hugo/ && \
203 -
    mv /tmp/hugo/hugo /usr/bin/hugo && \
204 -
    rm -rf /tmp/hugo*
205 -
```
206 -
207 -
.gitlab-ci.yml
208 -
```
209 -
image: docker:latest
210 -
211 -
services:
212 -
  - docker:dind
213 -
214 -
stages:
215 -
- build
216 -
217 -
variables:
218 -
  DOCKER_IMAGE_TAG: registry.gitlab.com/ruedigerp/ci-build-hugo
219 -
220 -
before_script:
221 -
  # - echo $CI_BUILD_TOKEN | docker login --username gitlab-ci-token --password-stdin registry.gitlab.com
222 -
  - echo "AAA-BBBBBBBBBBBBB" | docker login --username gitlab-ci-token --password-stdin registry.gitlab.com
223 -
224 -
build:
225 -
  stage: build
226 -
  script:
227 -
    - echo "AAA-BBBBBBBBBBBBB" | docker login --username gitlab-ci-token --password-stdin registry.gitlab.com
228 -
    - docker build --pull -t $DOCKER_IMAGE_TAG .
229 -
    - docker push $DOCKER_IMAGE_TAG
230 -
```
231 -
232 -
233 -
### Sync Deploy Docker Image
234 -
235 -
Um die Seiten zu deployen ...
236 -
237 -
Docker image: registry.gitlab.com/ruedigerp/ci-deploy-rsync-ssh
238 -
```
239 -
# folgt noch
240 -
```
241 -
242 -
.gitlab-ci.yml
243 -
244 -
```
245 -
# folgt noch
246 -
```
gelöscht content/2019-08-02-quagga-bgp-prefix-list.md
+0 −39
@@ -1,39 +0,0 @@
1 -
---
2 -
title: 'Quagga BGP prefix-list'
3 -
date: 2019-08-03 01:03:26
4 -
update: 2019-08-03 01:03:26
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/05/network.webp"
7 -
tags:
8 -
    - Netzwerk
9 -
    - IP
10 -
    - BGP
11 -
    - Routing
12 -
    - Internet
13 -
preview: "*Notiz an mich, um nich noch einmal suchen zu müssen*  Um im BGP manche Netze nicht zu erlauben:"
14 -
categories: 
15 -
    - Internet
16 -
toc: false
17 -
hide: false
18 -
type: post
19 -
---
20 -
21 -
*Notiz an mich, um nich noch einmal suchen zu müssen* :point_up:
22 -
23 -
Um im BGP manche Netze nicht zu erlauben:
24 -
25 -
<!--more-->
26 -
```
27 -
router bgp 65001
28 -
 bgp router-id 10.10.10.1
29 -
 network 10.101.0.0/16
30 -
 neighbor 10.11.0.1 remote-as 65002
31 -
 neighbor 10.11.0.1 description 65002
32 -
 neighbor 10.11.0.1 prefix-list icvpn4 in
33 -
 neighbor 10.11.0.1 prefix-list icvpn4 out
34 -
!
35 -
ip prefix-list icvpn4 description *** ICVPN prefix-list for internal and public IP address space ***
36 -
ip prefix-list icvpn4 seq 20 deny 10.101.0.0/16 le 24
37 -
```
38 -
39 -
Damit ist 10.101.0.0/16 und /24er aus dem Block nicht mehr erlaubt.
gelöscht content/2019-08-03-wireguard-vpn.md
+0 −72
@@ -1,72 +0,0 @@
1 -
---
2 -
title: "Wireguard VPN"
3 -
date: 2019-08-03 14:53:26
4 -
update: 2019-08-03 14:53:26
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/03/network.webp"
7 -
tags:
8 -
    - Netzwerk
9 -
    - IP
10 -
    - IPSec
11 -
    - VPN
12 -
    - Tunnel
13 -
    - Routing
14 -
    - Internet
15 -
preview: "Seit Jahren benutze ich OpenVPN, das wird auch so bleiben. Gerade für mobile Geräte ist aber auch Racoon für IPSec im Einsatz. IPSec aus einem Grund: Authentifizieren mit Zertifikaten."
16 -
categories: 
17 -
    - Internet
18 -
toc: false
19 -
hide: false
20 -
type: post
21 -
---
22 -
23 -
### WireGuard VPN
24 -
25 -
Seit Jahren benutze ich OpenVPN, das wird auch so bleiben. Gerade für mobile Geräte ist aber auch Racoon für IPSec im Einsatz. IPSec aus einem Grund: Authentifizieren mit Zertifikaten.
26 -
27 -
Denn OnDemand Verbindungen zu bestimmten Zielen im internen Netz bekommt man auf dem iPhone nur per Profilen hin wenn man Zertifikate benutzt.
28 -
29 -
Also habe ich meine eigene CA mit der ich die Benutzer mit den entsprechenden Zertifikaten verwalten kann. Funktioniert auch sehr gut, ist aber auch etwas aufwändiger.
30 -
<!--more-->
31 -
Da ich privat und auch mit Arbeitskollegen Server, Rechner und VPN Verbindungen betreibe um Daten auszutauschen ist der Aufwand mit IPSec immer etwas mehr. Daher wird da meistens OpenVPN genommen.
32 -
33 -
Hat aber wieder das Problem das OnDemand und manche Client Konfiguration komplizierter ist.
34 -
35 -
### WireGuard - VPN in einfach
36 -
37 -
Seit längerem schwirrt im Netz WireGuard herum. Ich hatte mir das auch schon vor ein paar Monaten angeguckt. Damals zum testen auf einem RaspberryPI und auch als Docker Container. Die Tests waren nicht so erfolgreich.
38 -
39 -
Da sich ein Kollege jetzt auch mit WireGuard beschäftigt hat kam das Thema auch bei mir wieder auf. Und siehe da! Es hat sich einiges getan und die Entwicklung hat große Schritte gemacht.
40 -
41 -
Der Server läuft und die Konfiguration ist simple. Und das trifft auch auf die für die Clients zu.
42 -
43 -
Auf beiden Seiten wird ein Schlüsselpaar generiert. Jetzt werden einige sagen: aber das kann man in der Familie gar nicht benutzen. Das kapiert doch keiner.
44 -
45 -
Doch kann man. Ich hatte vorher auch die Zertifikate, ob OpenVPN oder IPSEC, generiert. Das Schlüsselpaar wird auch einfach von mir generiert und damit die Konfiguration erstellt.
46 -
47 -
### Konfiguration in 3 Minuten
48 -
49 -
Die Konfiguration besteht immer aus 2 Teilen. Einmal das Interface und dem Peer, dem Client.
50 -
Beim Server sind es halt mehrere Peers.
51 -
52 -
Für den Anfang erst einmal nur Server und einen Client.
53 -
Dann hat man jeweils 3-5 Zeilen und das war es.
54 -
55 -
Jetzt hat man eine simple Datei mit ca 10 Zeilen und kann sie an den Benutzer verteilen.
56 -
57 -
Jetzt kann man die Datei client.conf schicken. Oder man schickt die Datei einfach einmal durch qrencode und erhält einen QRCode.
58 -
59 -
### Client installiert und QRCode scannen
60 -
61 -
Der Benutzer installiert sich jetzt einfach nur noch die WireGuard App. Nach dem öffnen Tunnel hinzufügen und einmal auf QRCode scannen tippen.
62 -
63 -
Den QRCode einscannen und schon ist alles fertig. Der Client kann sich sofort verbinden und bei Bedarf auch einstellen das in bestimmten Wifi Netzen und/oder mobil immer das VPN aufgebaut werden soll.
64 -
65 -
### Schritt für schritt Konfiguration
66 -
67 -
Eine Anleitung zu WireGuard wird es die Tage noch geben. Dann wird es auch Config Beispiele geben.
68 -
69 -
Auch wie das mit dem Routing in das Netz zuhause oder zu anderen geht.
70 -
Wir benutzen in unserem kleinem Mesh Netz für jeden Teilnehmer eigene Netze und Routen diese mit Hilfe von BGP.
71 -
72 -
Viele Sachen davon waren immer kompliziert. Mit WireGuard ist vieles aber einfacher geworden und es kann jeder jetzt Schell und einfach sichere Verbindungen aufbauen.
gelöscht content/2019-08-04-shortcodes-hugo-cms.md
+0 −140
@@ -1,140 +0,0 @@
1 -
---
2 -
title: "Eigene Shortcodes Hugo CMS"
3 -
date: 2019-08-04 01:00:00
4 -
update: 2019-08-04 01:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/04/programming.webp"
7 -
tags:
8 -
    - Webpage
9 -
    - CMS
10 -
    - Hugo
11 -
    - Generator
12 -
    - Pipeline
13 -
    - Deploymend
14 -
    - Automatisierung
15 -
preview: "Um Bilder in Seiten oder einem Blogartikel schnell einfügen zu können habe ich mit im Hugo CMS einen eigenen Shortcut erstellt."
16 -
categories: 
17 -
    - Technik
18 -
toc: false
19 -
hide: false
20 -
type: post
21 -
---
22 -
23 -
### Shortcode erstellen
24 -
25 -
Um Bilder in Seiten oder einem Blogartikel schnell einfügen zu können habe ich mit im Hugo CMS einen eigenen Shortcut erstellt.
26 -
27 -
Ich habe immer das originale Bild und ein kleiner gerechnetes Bild. Diese werden
28 -
im Ordner `/static/img/posts/` gespeichert.
29 -
<!--more-->
30 -
Datei im Ordner: `/layouts/shortcodes/postimage.html`
31 -
32 -
```
33 -
<div>
34 -
<a href="{{ $.Site.BaseURL}}/img/posts/{{ index .Params 2 }}"><img src="{{ $.Site.BaseURL}}/img/posts/{{ index .Params 1 }}" width="800"></a>
35 -
<p>{{ index .Params 0 }}</p>
36 -
</div>
37 -
```
38 -
39 -
In Seiten/Artikeln kann ich so jetzt einfach mitfolgendem Code einfach Bilder einbinden:
40 -
41 -
```
42 -
{{ < postimage "title" "image-original.webp" "Image-thumbnail.webp" >}}
43 -
```
44 -
45 -
Die Bilder liegen aktuell noch alle in `/static/img/posts/`. Das werde ich aber noch ändern und auch den Shortcode anpassen. Die Originale bleiben in `/static/img/posts/` aber die Thumbnails werden aber in `/static/img/posts/thumbs` landen. Denn ich möchte die Bilder auch noch automatisch generieren lassen ohne großen Aufwand.
46 -
47 -
Aktuell wird jedes Bild einzeln verkleinert.
48 -
```
49 -
nconvert -resize 800 -o DB-Wifi-1-800.png DB-Wifi-1.png
50 -
```
51 -
52 -
Das will ich gerne in folgendes ändern:
53 -
```
54 -
for FILE in $(find ${IMAGEDIR} -type f -maxdepth 1)
55 -
do
56 -
  nconvert -resize 800 -o ${IMAGEDIR}/thumbs/${FILE} ${FILE}
57 -
done
58 -
```
59 -
60 -
Für das Image Rezise habe ich jetzt ein Docker Image erstellt.
61 -
62 -
Dockerfile
63 -
64 -
```
65 -
FROM alpine:edge
66 -
MAINTAINER "Rüdiger Küpper <ruediger@kuepper.nrw>"
67 -
RUN apk update && apk add imagemagick bash
68 -
COPY entrypoint.sh /entrypoint.sh
69 -
ENTRYPOINT ["/entrypoint.sh"]
70 -
```
71 -
72 -
Entrypint.sh
73 -
74 -
```
75 -
#!/bin/bash
76 -
cd /posts
77 -
for FILE in $(find . ! -name "*.svg" -type f -maxdepth 1); do convert -resize 800 ${FILE} thumbs/${FILE}; done
78 -
```
79 -
80 -
Im Ordner `/static/img/imagesresize.sh`:
81 -
82 -
```
83 -
#!/bin/bash
84 -
docker run -it -v $(pwd)/posts:/posts imageresize
85 -
```
86 -
87 -
Ein `./imagereszie.sh` im Ordner `/static/img/` generiert jetzt alle Bilder als Thumbnails in fester Breite neu und legt sie im Ordner `thumbs` ab.
88 -
89 -
Den Shortcode habe ich jetzt noch wie folgt angepasst:
90 -
91 -
```
92 -
<div>
93 -
<a href="{{ $.Site.BaseURL}}/img/posts/{{ index .Params 1 }}"><img src="{{ $.Site.BaseURL}}/img/posts/thumbs/{{ index .Params 1 }}" width="800"></a>
94 -
<p>{{ index .Params 0 }}</p>
95 -
</div>
96 -
```
97 -
98 -
### Shortcode für Soundcloud
99 -
100 -
Um meine oder von anderen Soundcloud Tracks einzubinden habe ich mir auch einen Shortcode geschrieben.
101 -
102 -
Datei im Ordner: `/layouts/shortcodes/soundcloud.html`
103 -
```
104 -
<p>{{ index .Params 1 }}</p>
105 -
<p>
106 -
<iframe width="736" height="400" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?visual=true&#038;url=https%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F{{ index .Params 0 }}&#038;show_artwork=true&#038;maxwidth=736&#038;maxheight=1000"></iframe>
107 -
</p>
108 -
```
109 -
110 -
Eingebunden wird das ganze dann in Artikel oder Seiten mit:
111 -
112 -
```
113 -
{{ < soundcloud 235962771 "Rock Solo Guitar - New Version" >}}
114 -
```
115 -
116 -
<!-- 
117 -
Das Ergebnis sieht dann so aus:
118 -
119 -
{{< soundcloud 235962771 "Rock Solo Guitar - New Version" >}}
120 -
-->
121 -
122 -
123 -
### Shortcode für Soundcloud Alben
124 -
```
125 -
<p>{{ index .Params 1 }}</p>
126 -
<p>
127 -
<iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/playlists/{{ index .Params 0 }}&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
128 -
</p>
129 -
```
130 -
131 -
Eingebunden wird das ganze dann in Artikel oder Seiten mit:
132 -
```
133 -
{{ < soundcloudalbum 298199575 "clockopera - Veen Album 2017" >}}
134 -
```
135 -
136 -
<!-- 
137 -
Das Ergebnis sieht so aus:
138 -
139 -
{{< soundcloudalbum 298199575 "clockopera - Veen Album 2017" >}}
140 -
-->
gelöscht content/2019-08-05-recent-posts-widget.md
+0 −82
@@ -1,82 +0,0 @@
1 -
---
2 -
title: "Recent Posts Widget"
3 -
date: 2019-08-05 22:00:00
4 -
update: 2019-08-05 22:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/05/programming.webp"
7 -
tags:
8 -
    - Hugo
9 -
    - CMS
10 -
    - Sidebar
11 -
    - Widgets
12 -
preview: "In meinen Blogs hatte ich immer ein Widgets für die letzte Posts. Das habe ich gerade auch für das Hugo CMS erstellt."
13 -
categories: 
14 -
    - Technik
15 -
toc: false
16 -
hide: false
17 -
type: post
18 -
---
19 -
20 -
### Recent Posts Widget für die Sidebar
21 -
22 -
In meinen Blogs hatte ich immer ein Widgets für die letzte Posts. Das habe ich gerade auch für das Hugo CMS erstellt.
23 -
24 -
Im Theme unter Layouts -> Partials -> Widgets habe ich eine Datei `lastposts.html` erstellt:
25 -
<!--more-->
26 -
27 -
```
28 -
    <div class="panel-body">
29 -
      <ul class="nav nav-pills nav-stacked">
30 -
      {{ $count := .Site.Params.widgets.recent_posts }}
31 -
      {{ range first $count .Pages }}
32 -
        <li><a href="{{ .Permalink }}">{{ .Name }}</a></li>
33 -
      {{ end }}
34 -
      </ul>
35 -
    </div>
36 -
  </div>
37 -
```
38 -
39 -
40 -
Die Zeilen 1, 9-12 und 16 sind markiert. Das sind Zeilen die das Widget steuern bzw. die Anzahl an konfigurierten letzten Posts ausgeben.
41 -
42 -
* Zeile 1 überprüft ob das Widget aktiv ist.
43 -
* Zeile 9 setzt die Variable $count auf die konfiguriere Anzahl der posts
44 -
* Zeile 10 bis 12 durchläuft die letzte $count Posts und zeigt sie an.
45 -
46 -
Das funktioniert auf der Startseite gut, aber in den Artikeln bleibt die Liste leer.
47 -
48 -
Also wurde jetzt noch folgender Code ersetzt:
49 -
```
50 -
{{ $count := .Site.Params.widgets.recent_posts }}
51 -
{{ range first $count .Pages }}
52 -
  <li><a href="{{ .Permalink }}">{{ .Name }}</a></li>
53 -
{{ end }}
54 -
```
55 -
56 -
Durch:
57 -
```
58 -
{{ $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections }}
59 -
{{ range first $count $pages }}
60 -
<li><a href="{{ .Permalink }}">{{ .Name }}</a></li>
61 -
{{ end }}
62 -
```
63 -
64 -
Jetzt wird das Widget auf allen Seiten befüllt.
65 -
66 -
### Konfiguration des Widget
67 -
68 -
Das Widget kann in der `config.toml` konfiguriert werden.
69 -
70 -
```
71 -
...
72 -
# Enable and disable widgets for the right sidebar
73 -
[params.widgets]
74 -
    categories = true
75 -
    tags = true
76 -
    search = true
77 -
    recent_posts = 10
78 -
...
79 -
```
80 -
81 -
Das Widget kann mit `false` deaktiviert werden.
82 -
Die Anzahl kann frei gewählt werden.
gelöscht content/2019-08-07-Apple-Mac-Address-spoofing-cool-and-uncool.md
+0 −142
@@ -1,142 +0,0 @@
1 -
---
2 -
title: "Apple Mac Address Spoofing cool und uncool"
3 -
date: 2019-08-07 23:35:47
4 -
update: 2019-08-07 23:35:47
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/07/vpn.webp"
7 -
tags:
8 -
    - Apple
9 -
    - AppleTV
10 -
    - TimeCapsule
11 -
    - Network
12 -
    - VLAN
13 -
    - ARP
14 -
    - TCP
15 -
    - IP
16 -
    - Spoofing
17 -
preview: "Kriege ich gerade aus der 1. Etage hier im Haus eine iMessage: Hast du eine Ahnung warum das Internet so langsam ist? Streaming über Lan stoppt nach einer halben Sekunde."
18 -
categories: 
19 -
    - Technik
20 -
toc: false
21 -
hide: false
22 -
type: post
23 -
---
24 -
25 -
# Alarm aus der 1. Etage
26 -
27 -
Kriege ich gerade aus der 1. Etage hier im Haus eine iMessage:
28 -
29 -
> Hast du eine Ahnung warum das Internet so langsam ist? Streaming über Lan stoppt nach einer halben Sekunde.
30 -
31 -
Kurz gegen gechecked und Youtube auf dem iPhone hat keine Probleme. Also selbst mal den AppleTV anschmeissen und da überprüfen. ARD Mediathek ok, Youtube OK.
32 -
FireTV mit Netflix und Co getesten. Selbst FireTV und DreamTV den Stream Haus intern vom Octagon kann ohne Probleme HD abrufen. Kein ruckeln, keine Abbrüche.
33 -
<!--more-->
34 -
# Kurzes debugging
35 -
Kurzer Blick auf dem RaspberryPI der DHCP gemacht und da viele DHCP Requests von dem AppleTV gesehen der als Problemgerät gemeldet wurde. Mutt auf dem RaspberryPI aufgemacht und nach ArpWatch Mails geschaut. Treffer, sehr viele Mails mit "flip flop" Meldungen passend zum Gerät.
36 -
37 -
```
38 -
60114 N + Aug 07 Arpwatch pi01.9 (  10) flip flop (appletv-01-2.intern.pretzlaff.co) eth0
39 -
60115 N + Aug 07 Arpwatch pi01.9 (  10) flip flop (appletv-01-2.intern.pretzlaff.co) eth0
40 -
60116   + Aug 07 Arpwatch pi01.9 (  10) flip flop (appletv-01-2.intern.pretzlaff.co) eth0
41 -
```
42 -
43 -
Dann pingen wir mal das Gerät über die IP an:
44 -
45 -
```
46 -
ping 192.168.178.108
47 -
PING 192.168.178.108 (192.168.178.108) 56(84) bytes of data.
48 -
From 192.168.176.106: icmp_seq=1 Redirect Host(New nexthop: 192.168.178.108)
49 -
From 192.168.176.106: icmp_seq=2 Redirect Host(New nexthop: 192.168.178.108)
50 -
```
51 -
52 -
# Erste Analyse
53 -
54 -
Sieht komisch aus und mir fällt auch prompt etwas ein was die Ursache sein kann. Mac-Address Spoofing der Apple TimeCapsule Geräten, wenn sie andere Apple Geräte offline gehen sehen oder meinen die Geräte sind offline.
55 -
56 -
Eurer AppleTV ist ausgeschaltet und trotzdem zeigt ein iPhone, iPad oder Mac das Gerät trotzdem sofort an wenn Ihr auf AirPlay geht? Genau das ist gemeint.
57 -
58 -
Apple Geräte wie die TimeCapsule oder AppleTV gucken welche anderen Geräte noch im Netzwerk sind und geht eines der Geräte offline, zum Beispiel in den Standby, melden sie sich im Netzwerk ab und ein anderes Gerät wie die TimeCapsule nimmt sich auf sein Netzwerkinterface die Mac-Adresse des Gerätes welches in Standby gegangen ist.
59 -
60 -
Dadurch sieht das Gerät immer noch als online im Netzwerk aus. Das gleiche wird auch so beim Mac / Macbook gemacht.
61 -
62 -
Fragen jetzt andere Geräte im Netzwerk eines der Geräte im Standby an antwortet die TimeCapsule auch brav und sendet im Hintergrund ein Datenpaket an das Standby Gerät, welches dadurch aufgeweckt wird.
63 -
64 -
Praktisch wenn man Back to my Mac, VPN oder einfach lokal mal auf einen Rechner zugreifen will. Oder wenn man AirPlay machen möchte. Die Geräte wachen wie von selbst auf.
65 -
66 -
# Kann aber auch mal doof sein
67 -
68 -
Zurück zum Problem. Checken wir mal den Arp Cache:
69 -
70 -
```
71 -
arp -a| grep 78:ca:39:ff:ee:3c
72 -
...
73 -
appletv-01-2.intern.pretzlaff.co (192.168.178.108) auf 78:ca:39:ff:ee:3c [ether] auf eth0
74 -
appletv-0-1.intern.pretzlaff.co (192.168.177.3) auf 78:ca:39:ff:ee:3c [ether] auf eth0
75 -
tc02.intern.pretzlaff.co (192.168.176.106) auf 78:ca:39:ff:ee:3c [ether] auf eth0
76 -
...
77 -
```
78 -
Das ganze noch mal mit -n um schneller und übersichtlicher die Ergebnisse zu sehen. Denn im Netzwerk sind 92 Geräte zu dem Zeitpunkt aktiv gewesen und ohne -n dauert das schon etwas länger.
79 -
80 -
```
81 -
arp -a -n | grep 78:ca:39:ff:ee:3c
82 -
? (192.168.176.106) auf 78:ca:39:ff:ee:3c [ether] auf eth0
83 -
? (192.168.178.108) auf 78:ca:39:ff:ee:3c [ether] auf eth0
84 -
? (192.168.177.3) auf 78:ca:39:ff:ee:3c [ether] auf eth0
85 -
```
86 -
87 -
Zm Vergleich die Mac Adressen die eigentlich hinter IP `192.168.178.108` und `192.168.177.3` stecken:
88 -
89 -
```
90 -
arp -a -n | grep 192.168.178.108
91 -
? (192.168.178.108) auf 34:c0:59:31:c7:92 [ether] auf eth0
92 -
arp -a | grep 192.168.178.108
93 -
appletv-01-2.intern.pretzlaff.co (192.168.178.108) auf 34:c0:59:31:c7:92 [ether] auf eth0
94 -
95 -
arp -a -n | grep 192.168.177.3
96 -
? (192.168.177.3) auf 34:c0:59:31:fe:46 [ether] auf eth0
97 -
arp -a | grep 192.168.177.3
98 -
appletv-0-1.intern.pretzlaff.co (192.168.177.3) auf 34:c0:59:31:fe:46 [ether] auf eth0
99 -
```
100 -
101 -
Man sieht hier das die IPs bei anderen Geräten benutzt werden. Aber eben genau die Geräte haben aber jetzt die Mac Adresse `78:ca:39:ff:ee:3c`.
102 -
103 -
# Ursache ist eigentlich eine Super Funktion
104 -
105 -
Aber hier macht sie gerade ein Problem. Apple Geräte wie die TimeCapsule bekommen mit wenn sich andere Apple Geräte im Netz befinden. Geht jetzt der betroffene AppleTV in den Standby nimmt sich die TimeCapsule die Mac Adresse vom AppleTV und simuliert die Funktionen des AppleTV. Für andere Clients wirkt es als wäre der AppleTV online. AirPlay zeigt den AppleTV als verfügbar an und man kann diesen auswählen.
106 -
107 -
Verbindet sich ein Client jetzt mit dem AppleTV wird er per WakeOnLan Magic Paket aufgeweckt und die TimeCapsule entfernt die Mac Addresse wieder von seinem Netzwerk Interface. Der AppleTV übernimmt sie wieder und bekommt seine IP.
108 -
109 -
> The sleep proxy service responds to address resolution protocol requests on behalf of the low-power-mode device
110 -
111 -
> When a sleep proxy sees an IPv4 ARP or IPv6 ND Request for one of the sleeping device's addresses, it answers on behalf of the sleeping device, without waking it up, giving its own MAC address as the current (temporary) owner of that address.
112 -
113 -
Wir haben hier mehrere TimeCapsule und 4 aktive AppleTV. Der 5te ist aktuell nicht in Benutzung. Das Verhalten war aber jetzt auch nur von der TimeCapsule bekannt. Die beiden AppleTV die hier aber auch die Mac Adresse übernommen hatten waren AppleTV der neuesten Generation.
114 -
115 -
Es scheint also so zu sein das jetzt auch der AppleTV als Bonjour Sleep Proxy eingesetzt wird. Das würde auch die sporadischen komischen Netzwerkprobleme erklären die immer mal wieder im Haus aufkommen.
116 -
117 -
TimeCapsule und AppleTV kümmern sich also drum das iTunes Sharing, File Sharing, Druckerfreigaben auch dann erreichbar sind, bzw. die entsprechenden Geräte auch im Standby angesprochen werden können.
118 -
119 -
Und ja, da Apple sich immer mehr aus dem Routermarkt verabschiedet ist die Funktion in den AppleTV bzw. TVOS gewandert.
120 -
121 -
> Mit der Funktion „Ruhezustand bei Bedarf beenden“ (auf Ihrem Mac) und mit Bonjour Sleep Proxy (durch ein AirPort-Gerät oder Apple TV bereitgestellt) können Sie Energie sparen und Kosten senken, während gleichzeitig der Zugriff auf alle freigegebenen Dienste sichergestellt bleibt. Zudem können Sie über Zugang zu meinem Mac auch aus der Ferne über das Internet auf die freigegebenen Dienste zugreifen. Die Funktion „Ruhezustand bei Bedarf beenden“ wird zusammen mit Bonjour Sleep Proxy auf Ihrer AirPort-Basisstation, Time Capsule oder Apple TV (wenn sich keine AirPort-Basisstation oder Time Capsule im Netzwerk befindet) ausgeführt. Hinweis: Apple TV agiert auch im Ruhemodus als Bonjour Sleep Proxy.
122 -
123 -
# Apple hat wohl nicht an die Masse an Geräte gedacht
124 -
125 -
Wie erwähnt haben wir mehrere AppleTV, TimeCapsule und eine grössere Menge MacOS und iOS Geräten im Hause. Da kommt bei 3 Haushalten schon was zusammen.
126 -
Jede Wohnung bzw. Etage hat hier einen eigenen Switch und AccessPoint. Per Vlans getrennt. Bis auf das Zeug was Media angeht. Die AppleTV und TimeCapsule Geräte sind in einem Netz zusammen.
127 -
128 -
Jetzt geht der AppleTV von meinem Bruder offline und die TimeCapsules meinen jetzt beide sie müssten im Netz behaupten sie seien der AppleTV. Die anderen AppleTV behaupten das gleiche. Der AppleTV wird dann wieder aufgeweckt und dann fängt die ARP schlacht im Netzwerk an.
129 -
130 -
Eines der Geräte hat das Datenpacket für den AppleTV bekommen, sagt dem Apple TV bescheid und lässt die Mac Adresse wieder frei, was dann aber für eines der anderen TimeCapsules oder AppleTV als "Da geht ein Device offline ich mach mal Bonjour Sleep Proxy", fragt beim DHCP nach IP und schreit das dann auch so ins Netz damit alle bescheid wissen. Der eigentliche AppleTV ist irritiert und meldet sich im Netz "Ey bin doch online, ich brauche eine IP."
131 -
132 -
Jetzt fängt das gleiche von vorne an. Mac Adresse wird vom AppleTV aktiviert und ins Netz geblasen und von einem anderen Device freigegeben und das nächste meint da geht was offline und macht einen auf Bonjour Sleep Proxy. usw. usw.
133 -
134 -
# Ok, im Urlaub auch Media-Netze mit Vlans trennen
135 -
136 -
Wir haben hier zuhause 4 Etagen. EG und 1. OG sind jeweils 1 Wohnung und wir hier oben haben 2. und 3. Etage. Zwischen den einzelnen Wohungen sind immer 2 Verbindungen, die als LAG geschaltet sind. Also 1 <-> 2 <-> 3 und noch mal 1 <-> 3 Etagen. Im schlimmsten Fall könnte man also 4 Gigabit Bandbreite benutzen. Alles mit Cisco Switchen. Sollte das mal nicht mehr ausreichen gehen wir einfach über Glasfaser und könnten auf 10 Gigabit oder mit LAG auf 20 Gigabit.
137 -
138 -
Die AccessPoints haben mehrere SSID konfiguriert, die aber auf allen Etagen. So das man hier von einer Wohnung in die nächste gehen kann, Verbindungen bestehen bleiben und man überall sein WiFi Netz hat. Zusätzlich noch Media WiFi und Gäste WiFi.
139 -
140 -
Alles schön getrennt mit VLANs. Bis auf das Media-Netz. Da wird dann ab nächster Woche dran geschraubt und auch da alles schön getrennt. Dann kommen auch die beiden Ubiquiti Edge Router X zum Einsatz.
141 -
142 -
Ich werde auch mal im Detail den Aufbau des Netzes hier beschreiben. Das steht schon länger auf er ToDo und wird auch mal Zeit.
gelöscht content/2019-08-09-Netzwerk-Umbaulabor.md
+0 −52
@@ -1,52 +0,0 @@
1 -
---
2 -
title: "Netzwerk Umbaulabor"
3 -
date: 2019-08-09 07:32:59
4 -
update: 2019-08-09 07:32:59
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/09/network.webp"
7 -
tags:
8 -
    - Internet
9 -
    - Netzwerk
10 -
    - Router
11 -
    - VLAN
12 -
    - IP
13 -
preview: "Oder auch erst einmal nicht. Ich wusste vom letzten Test die IP vom Ubiquiti EdgeRouterX nicht mehr. Dann halt mal wieder IPv6 zur Hilfe nehmen"
14 -
categories: 
15 -
    - Internet
16 -
toc: false
17 -
hide: false
18 -
type: post
19 -
---
20 -
21 -
# Testlabor für den Netzwerkumbau
22 -
23 -
In den nächsten 3 Wochen ist Urlaub angesagt. Das heisst jetzt für die Family: Es wird umfangreiche Änderungen am Netzwerk geben.
24 -
25 -
Das ist schon länger geplant, aber die Zeit ist immer so eine Sache. Das Netzwerk hatte ich ja schon angesprochen. 4 Etagen, 3 Wohnungen, 5 Switche, 3 WiFi AccessPoints, jede Menge Smarthome, smarte Geräte und Zeug drum her rum.
26 -
<!--more-->
27 -
# Ubiquiti Edge Router X als Testlabor
28 -
29 -
Ich habe mit einem der beiden Router schon ein paar Sachen gemacht. Jetzt wird auch der wieder zum testen genommen. Ein zweiter liegt auch schon etwas länger bereit zum Einsatz daneben.
30 -
31 -
Die beiden werden jetzt dafür genommen sie als Gateways zum Internet und für die Interne Netztrennung einzusetzen.
32 -
33 -
Im ersten Schritt kommen beide erst einmal an den Switch ins vorhandene Netz. Auf der anderen Seite kommen dann die ersten Geräte zum testen. Getrennt vom Rest und damit wird dann alles so vorbereitet wie es nachher sein soll.
34 -
35 -
Funktioniert das wird ein zweites VLAN erstellt und so das nächste Etagen Netz getestet. Kommt das ins Netz und kann man bei Bedarf einzelne Geräte mit anderen im anderen Netz verbinden wird noch das 3. Netz genau so vorbereitet.
36 -
37 -
# Edge Router vom Labor hinten nach ganz vorne stellen.
38 -
39 -
Wenn die Punkte oben alle rund laufen werden die beiden bzw. einer davon vom Testlabor nach vorne hinter die Fritzbox gepackt. Ok, das passiert nicht per Kabel, es wird eher an den Switchports anders konfiguriert.
40 -
41 -
Ziel ist das alles vorzubereiten und dann an einem Tag einfach per Schalter umzustellen. Es soll keiner im Haus davon etwas bemerken. Die IPs werden sich ändern, aber das im Hintergrund.
42 -
43 -
Die Geräte per Kabel bekommen an allen Switchen kurz ein Port Down und Up. Die sollten das alle mitbekommen und das Interface neu konfigurieren. Sie sind dann in einem anderen VLAN und bekommen die neuen IPs.
44 -
45 -
Geräte per WiFi werden ganze einfach neu bespasst. Alle AccessPoints werden einfach kurz resettet, Clients werden neu verbunden und danach auch mit anderer Netzwerkkonfiguration wieder online kommen.
46 -
47 -
# So der Plan
48 -
49 -
Wir werden sehen wir schnell das alles klappt und wann alles fertig ist.
50 -
Erst mal im kleinen testen und dann weiter machen.
51 -
52 -
Ich werde dann mal die nächsten Tage und Wochen berichten.
gelöscht content/2019-08-09-Netzwerkumbau-VLANs-und-Firewall.md
+0 −144
@@ -1,144 +0,0 @@
1 -
---
2 -
title: "Netzwerkumbau VLANs und Firewall"
3 -
date: 2019-08-09 22:52:27
4 -
update: 2019-08-09 22:52:27
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/09/network.webp"
7 -
tags:
8 -
    - Netzwerk
9 -
    - Internet
10 -
    - TCP
11 -
    - IP
12 -
    - VLAN
13 -
    - Switch
14 -
    - Router
15 -
    - Routing
16 -
    - Security
17 -
preview: "Oder auch erst einmal nicht. Ich wusste vom letzten Test die IP vom Ubiquiti EdgeRouterX nicht mehr. Dann halt mal wieder IPv6 zur Hilfe nehmen"
18 -
categories: 
19 -
    - Internet
20 -
toc: false
21 -
hide: false
22 -
type: post
23 -
---
24 -
25 -
# Dann wollen wir mal
26 -
27 -
Oder auch erst einmal nicht. Ich wusste vom letzten Test die IP vom Ubiquiti EdgeRouterX nicht mehr.
28 -
Dann halt mal wieder IPv6 zur Hilfe nehmen :smirk:
29 -
30 -
Ich habe ja eine Liste alle bekannten Adressen in dem Segment, also einfach `ping6` auf das interface `en0` und `ff02::1` und wir sollten die IPv6 Adresse von dem Teil haben.
31 -
<!--more-->
32 -
```
33 -
pi01:~# ping6 -I en0 ff02::1
34 -
16 bytes from fe80::7a8a:20ff:fe07:7a94%en0, icmp_seq=17 hlim=64 time=6.148 ms
35 -
16 bytes from fe80::7a8a:20ff:fe07:7a94%en0, icmp_seq=18 hlim=64 time=11.023 ms
36 -
16 bytes from fe80::7a8a:20ff:fe07:7a94%en0, icmp_seq=19 hlim=64 time=3.578 ms
37 -
```
38 -
Bingo, wir haben die IPv6 Adresse und so auch die Mac Adresse von dem Teil. Jetzt noch die ARP Table checken und wir sollten die IP haben.
39 -
40 -
```
41 -
pi01:~# arp -a -n | grep "78:8a:20:07:7a:94"
42 -
pi01:~# arp -a -n | grep "78:8a"
43 -
? (192.168.179.204) auf 78:8a:20:07:7a:95 [ether] auf eth0
44 -
```
45 -
46 -
Okay die Mac-Adresse passte dann nicht so ganz, aber da IPv6 von einem anderen Interface kommt, als nachher die IP-Adresse, einfach mit weniger String der Mac Adresse noch mal ARP fragen und zack da ist sie.
47 -
48 -
Also Netzwerkkabel von dem Teil raus und den Ping starten, um zu checken ob es wirklich der Ubiquiti EdgeRouterX ist.
49 -
50 -
```
51 -
pi01:~# ping 192.168.179.204
52 -
PING 192.168.179.204 (192.168.179.204) 56(84) bytes of data.
53 -
From 192.168.176.2 icmp_seq=1 Destination Host Unreachable
54 -
From 192.168.176.2 icmp_seq=2 Destination Host Unreachable
55 -
...
56 -
64 bytes from 192.168.179.204: icmp_req=19 ttl=64 time=1992 ms
57 -
64 bytes from 192.168.179.204: icmp_req=20 ttl=64 time=991 ms
58 -
64 bytes from 192.168.179.204: icmp_req=21 ttl=64 time=0.858 ms
59 -
```
60 -
Alles klar, der Abend war gerettet und nach dem einloggen erst mal checken was ich da vor ein paar Monaten verbrochen habe.
61 -
Mit der Konfig noch mal etwas ausprobiert und dann noch mal von vorne.
62 -
63 -
# Dann wird jetzt konfiguriert
64 -
65 -
Mit der vorhandenen Konfiguration weiter gemacht und auf den Interfaces
66 -
`eth1 (VLAN2)`, `eth2 (3)`, `eth3 (4)` und `eth4 (5)` die VLANs konfiguriert.
67 -
IP-Adressen jeweils aus einem Netz drauf gelegt und in jedem VLAN einen DHCP Server spendiert.
68 -
69 -
VLAN 2 auf dem Cisco Switch auf `gi8` und `gi10` getagged. Auf `gi10` hängt ein Accesspoint der das VLAN braucht, da er eine eigene SSID zum testen für die neuen Netze hat.
70 -
71 -
Das iPhone ins neue WiFi geworfen. Es gekommt eine IP wie gewünscht. Nur war trotzdem alles irgendwie hakelig.
72 -
Routing, Firewall usw. alles gechecked und ausprobiert. So will man das nicht haben.
73 -
Da ich mir eh gerade, durch ein blöden Konfigurationsfehler, die IP weg gezogen hatte und ich resetten musste, konnte ich auch gleich noch mal was anders konfigurieren.
74 -
75 -
Anstatt auf dem EdgeRouterX auf den Interfaces, jetzt auf dem EdgeRouterX Switch die VLANs eingerichtet. Um es kurz zu machen das wollte so gar nicht. Trotz der ganzen Anleitungen im Netz und genauen Beschreibungen das andere es so einsetzen. Es wollte einfach nicht.
76 -
77 -
Also noch einmal von vorne wie am Anfang schon. Nur dieses mal nach einem Reset des Routers. Ich hatte eh schon das Gefühl das ich da mal was drauf gemacht hatte was jetzt störte.
78 -
79 -
VLANs und VLAN-Interfaces anlegen, IPs setzen, Routing usw. und jetzt klappt es. An eth0 ist der Uplink zum Switch, hinter dem dann auch irgendwo das DSL Modem hängt. Switche, DSL und noch 1-2 andere Sachen werden in dem alten Netz bleiben. Das wird jetzt das Management Netz. Alle anderen VLANs bekommen jetzt eigene IP-Bereiche, inklusive DHCP Server.
80 -
81 -
Zwischen den Netzen Inter-VLAN-Routing und Firewall macht alles dicht bis auf das was durch soll. Gerade der Punkt war wichtig, da wir bei uns den einzigen Drucker im Haus haben den alle benutzen. Der kann jetzt auch weiter freigegegen werden. Genau wie unsere Synology. In die andere Richtung müssen wir auch mal auf andere Geräte in den anderen Wohnungen zugreifen. Daher müssen einzelne Geräte freigeschaltet werden können.
82 -
83 -
# So sieht die Konfiguration bis jetzt aus
84 -
85 -
Auf dem Ubiquiti sind die Interfaces jetzt eingerichtet.
86 -
87 -
{{< postimage "Ubiquiti Interfaces" "2019-08-10-Netzwerkumbau-VLANs-und-Firewall-1.webp" "2019-08-10-Netzwerkumbau-VLANs-und-Firewall-1.webp" >}}
88 -
89 -
![Ubiquiti Interfaces](/images/posts/2019-08-10-Netzwerkumbau-VLANs-und-Firewall-1.webp)
90 -
91 -
92 -
Auf dem AccessPoint ist eine Test-SSID im Vlan '2' und auf dem Port am Switch hat der AccessPoint auch das VLAN getagged bekommen.
93 -
94 -
Der Sitch an dem das ganze Zeug häng ist ein Cisco SG300-10 10-Port Gigabit Managed Switch. Der hat jetzt erst einmal 4 neue VLANs bekommen.
95 -
96 -
Auf dem Switch sieht die Config jetzt also für die VLANs so aus:
97 -
98 -
```
99 -
sw-02-1#show vlan tag 2
100 -
Created by: D-Default, S-Static, G-GVRP, R-Radius Assigned VLAN, V-Voice VLAN
101 -
102 -
Vlan       Name           Tagged Ports      UnTagged Ports      Created by
103 -
---- ----------------- ------------------ ------------------ ----------------
104 -
 2       VLAN2.OG           gi8,gi10             gi2                S
105 -
106 -
sw-02-1#show vlan tag 3
107 -
Created by: D-Default, S-Static, G-GVRP, R-Radius Assigned VLAN, V-Voice VLAN
108 -
109 -
Vlan       Name           Tagged Ports      UnTagged Ports      Created by
110 -
---- ----------------- ------------------ ------------------ ----------------
111 -
 3       VLAN1.OG           gi4,gi10                                S
112 -
113 -
sw-02-1#show vlan tag 4
114 -
Created by: D-Default, S-Static, G-GVRP, R-Radius Assigned VLAN, V-Voice VLAN
115 -
116 -
Vlan       Name           Tagged Ports      UnTagged Ports      Created by
117 -
---- ----------------- ------------------ ------------------ ----------------
118 -
 4        VLANEG                                                    S
119 -
120 -
sw-02-1#show vlan tag 5
121 -
Created by: D-Default, S-Static, G-GVRP, R-Radius Assigned VLAN, V-Voice VLAN
122 -
123 -
Vlan       Name           Tagged Ports      UnTagged Ports      Created by
124 -
---- ----------------- ------------------ ------------------ ----------------
125 -
 5        Server                                                    S
126 -
```
127 -
128 -
Hauptsächlich ist `VLAN 2` jetzt konfiguriert. Ist zwar auch noch nicht komplett fertig, aber dafür muss ich mir nachher erst einmal genau angucken welcher Port wo verkabelt ist und wie sich die beiden 16 Port Switche verhalten. Die beiden sind keine Cisco Switche sondern TP-Link Managed Switche. Ich weiß nicht wieso managed, weil naja die verrichten ihren Dienst, aber so viel können die auch nicht und das Webinterface ist einfach nur mies. Hätte ich das vorher gewusst wären das auch Cisco Switche geworden.
129 -
130 -
Sollten die mich nachher ärgern fliegen die raus und werden heute noch gegen Cisco Switche ersetzt. Dann heisst es dann wenigstens auch dabei: "On, Plug , Config und fertig."
131 -
132 -
Die TP-Link-Switche könnten noch ein Problem werden. Ich müsste eigentlich Tagged zu denen rübber und die VLANs dann UnTagged auf die Ports geben. Das war letzten schon nicht so erfolgreich.
133 -
134 -
# Die anderen Etagen sind dann auch noch dran
135 -
136 -
Das wird sehr schnell gehen. VLANs an den Uplink mit anlegen und dann alle Ports die dort für die die Etage sind mit dem VLAN Tag versehen. Auf dem AccessPoint das VLAN setzen und einfach nur alle Geräte kurz vor die Tür setzen damit sie wieder neu reinkommen. Danach sind sie in einer frisch renovierten Wohnung ... ähm ... Netzwerkumgebung.
137 -
138 -
Dann das gleiche noch auf der letzten Etage und dann ist das Thema durch.
139 -
140 -
# Das war ein Urlaubsprojekt für die nächsten 3 Wochen
141 -
142 -
Tja, erster Abend und eigentlich schon fertig. Der Rest ist jetzt nur noch stumpfes Port konfigurieren.
143 -
144 -
Aber es gibt ja noch genug für die 3 Wochen. Zum Beispiel da wir 2 DSL Anschlüsse haben auch jetzt wieder das Wechseln nach Last oder bei Ausfällen auf den anderen DSL Anschuss. Zutun gibt es immer etwas :laughing:.
gelöscht content/2019-08-10-WiFi-QRCode-mit-qrencode-erstellen.md
+0 −68
@@ -1,68 +0,0 @@
1 -
---
2 -
title: "WiFi QRCode mit qrencode erstellen"
3 -
date: 2019-08-10 20:18:49
4 -
update: 2019-08-10 20:18:49
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/10/wifi.webp"
7 -
tags:
8 -
    - QRCode
9 -
    - qrencode
10 -
    - brew
11 -
    - apt
12 -
    - WLAN
13 -
    - WiFi
14 -
preview: "Um ohne langes tippen in das WiFi Netz zu kommen erstelle ich immer QRCodes. Ich erstelle sie mit qrencode."
15 -
categories: 
16 -
    - Technik
17 -
toc: false
18 -
hide: false
19 -
type: post
20 -
---
21 -
22 -
# QRCode für WiFi Zugänge erstellen
23 -
24 -
Um ohne langes tippen in das WiFi Netz zu kommen erstelle ich immer QRCodes.
25 -
Ich erstelle sie mit qrencode.
26 -
27 -
```
28 -
# Debian
29 -
apt install -y qrencode
30 -
# MacOS
31 -
brew install qrencode
32 -
```
33 -
<!--more-->
34 -
Anschliessend kann man sehr einfach einen WiFi QRCode erstellen:
35 -
36 -
```
37 -
qrencode -o wifi-zugang.png "WIFI:S:UnserWlan;T:WPA2;P:strengeheim12345;;" --dpi=300 -s 100
38 -
```
39 -
40 -
![Der QRCode für das WiFi, generiert mit qrencode](/images/posts/wifi-zugang.png)
41 -
42 -
So kann für neue WiFi Netze schnell der Zugang weitergegeben werden. Wir benutzen das zuhause regelmässig für die WiFi-Gastzugänge, da auch da regelmässig die Passwörter geändert werden.
43 -
44 -
# Kann auch Adressdaten in einen QRCode packen
45 -
46 -
Addresse.txt
47 -
```
48 -
BEGIN:VCARD
49 -
VERSION:3.0
50 -
N:Nachname, Vorname
51 -
ORG:nachname.de
52 -
TITLE:Webmaster und Author
53 -
EMAIL;TYPE=PREF,INTERNET: info@nachname.de
54 -
END:VCARD
55 -
```
56 -
57 -
```
58 -
qrencode -o vcard-low.png < adresse.txt
59 -
```
60 -
61 -
![VCard QRCode](/images/posts/vcard-low.png)
62 -
63 -
```
64 -
qrencode -l H -o vcard.png < adresse.txt
65 -
```
66 -
67 -
68 -
![VCard mit mehr Fehlerkorrektur](/images/posts/vcard.png)
gelöscht content/2019-08-12-vlans-und-firewall.md
+0 −74
@@ -1,74 +0,0 @@
1 -
---
2 -
title: "VLANS und Firewall"
3 -
date: 2019-08-12 17:35:27
4 -
update: 2019-08-12 17:35:27
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/12/vpn.webp"
7 -
tags:
8 -
    - Netzwerk
9 -
    - IP
10 -
    - VPN
11 -
    - VLAN
12 -
    - IPSec
13 -
    - OpenVPN
14 -
preview: "Wenn man das komplette Netzwerk endlich mal umkrämpelt und in den Zustand bringt den man schon lange haben wollte sind manche Fails beim Einrichten auch etwas gutes um zu sehen das alles funktioniert."
15 -
categories: 
16 -
    - Technik
17 -
toc: false
18 -
hide: false
19 -
type: post
20 -
---
21 -
22 -
Wenn man das komplette Netzwerk endlich mal umkrämpelt und in den Zustand bringt den man schon lange haben wollte sind manche Fails beim Einrichten auch etwas gutes um zu sehen das alles funktioniert.
23 -
24 -
Damit auch eine Kommunikation zwischen den Netzen funktioniert muss zwischen den VLANS geroutet werden. Damit dann aber nicht alles mit jedem telefonieren kann braucht es dann auch eine(n) ~~Firewall~~ Paketfilter.
25 -
26 -
<!--more-->
27 -
Gestern sind hier alle Smarthome Geräte in ein neues VLAN umgezogen. Beim einrichten wollte direkt zu Beginn der Tradfri Gateway nicht mit dem neuen Netz funktionieren.
28 -
29 -
WiFi A soll VLAN 10 sein. WiFi B soll Vlan 20 sein. Wenn man aber die VLANs vertauscht und dem AP die WiFi SSID mit dem falschem VLAN konfiguriert klappt das auch nicht nicht so wie man es will.
30 -
31 -
Als die 1. Etage umgezogen ist wurden auf dem Cisco Switch dort alle Ports mit dem VLAN versorgt und den UpLink das VLAN getagged. Wollte auch erst einmal nicht.
32 -
Man sollte auch auf dem anderen Switch auf dem UpLink Port zur 1. Etage das VLAN mit auf den Port schmeissen. Und zack, die ersten Geräte tauchen auch schon auf.
33 -
34 -
Oh ein Firmware Update verfügbar für den Switch da unten, also das auch noch direkt mit drauf auf den Switch. Dann muss der ja eh einen Restart machen und das könnte für die Geräte die noch nichts mitbekommen haben reichen um die Netzwerkports in den Geräte dazu zu veranlassen sich einmal auf down zu setzen und wenn die Switch Ports wieder hoch kommen das Netzwerk wieder up.
35 -
36 -
3 Etagen umgezogen und sauber getrennt. Fehlt nur noch eine. Die darf aber vielleicht noch 1-2 Tage warten.
37 -
38 -
In der Zwischenzeit wird die Firewall noch etwas feinjustiert. Wir haben 5 Amazon Echo/EchoDot, von denen 4 ohne Probleme funktioniert haben. Nur der Echo in der Küche. Der ist einer der ersten Generation und irgend etwas können die neuen, was das alte Schätzcken nicht kann. Denn der Echo konnte heute morgen Streamen, Radio Essen und EinsLive liefen ohne Probleme.
39 -
40 -
Linda wollte aber vorhin bei der Hausarbeit in der Küche Hörspiele hören. iPhone auf und mit dem Echo verbinden und es passierte nichts. Erst dachte ich, ok das iPhone ist ja noch im alten Netz, ziehste sie eben um. QRCode gescanned fertig.
41 -
30 Sekunden später steht sie wieder da: `Geht immer noch nicht.`
42 -
43 -
Alle anderen Echo Devices ohne Probleme. Amazon Music App auf, Hörspiel an und Echo auswählen klappt. Nur der in der Küche nicht.
44 -
45 -
Der Echo wurde gerade etwas länger bespasst:
46 -
47 -
* Es wurde alles mögliche gemacht.
48 -
* Er wurde ins alte Media WiFi zurück gepackt.
49 -
* Das iPhone hinterher.
50 -
* Echo zwischen den WiFi Netzen hin und her.
51 -
* iPhone per Bluetooth mit dem Echo gekoppelt.
52 -
* iPhone wieder getrennt.
53 -
* Alle Geräte gelöscht.
54 -
* Echo komplett zurückgesetzt.
55 -
* Echo lange vom Strom.
56 -
57 -
Es wurde wirklich alles ausprobiert. Das komische war es gab bei einigen der Aktionen oben aus der Liste Situationen bei denen es z.B. bei mir kurz klappte und wenn wir Lindas iPhone verbunden haben ging wieder nichts. Zwischendurch klappte auch mal kurz wieder an ihrem iPhone. Dann wieder nicht.
58 -
59 -
Die ganze Situation war sehr strange, da alles was man Alexa gefragt hat, wie Wetter, Verkehr usw. klappt. Also nur alles wo Alexa Text aus dem Netz abfragt und als Sprache aus gibt.
60 -
61 -
"Alexa, spiele Musik.". Kurze Zeit später sagt Alexa auch dabei sie kann die Musik nicht abspielen. Also Online ist sie, aber kann nicht alles machen.
62 -
63 -
Noch mal alles gechecked, AccessPoint, Switche, Ports, VLANs, IPs, Gateway, aber alles hat gepasst. Und mit anderen Echos klappt es ja auch. Also noch mal Firewall, tcpdump und Log auf dem EdgeRouter checken. Die Default Policy hatte Log an und hat das Logfile bei der Masse an Daten schon dicht gemacht. Da war erst einmal nichts mehr zu sehen, da die Platte voll war. Wenn vorher eine Rule etwas blockt konnte man das in dem Moment nicht sehen. Ein `echo "" > /var/log/messages` und noch mal getestet.
64 -
65 -
`[2OG-50-A]IN=eth0 OUT=eth1.2 MAC=78:8a:20:07:7a:94:38:10:d5:76:31:46:08:00 SRC=192.168.176.2 DST=10.0.2.115 LEN=540 TOS=0x00 PREC=0x00 TTL=62 ID=23432 PROTO=UDP SPT=53 DPT=53080 LEN=520`
66 -
67 -
Ok, DNS kommt nicht durch. Das wird dann mal freigeschaltet. Weiter Logfile geguckt und noch weiter Ports und Protokolle freigegeben. Ist zwar aufwändig bis alles läuft, aber ich will das so haben. Das die anderen Echos das Problem nicht hatten werde ich mir die Tage noch genauer angucken.
68 -
69 -
Alles wird geblockt, alles freigegeben was man braucht und der Rest der dann noch fehlt fällt auf wenn es nicht klappt.
70 -
71 -
Es gibt Leute die meinen alles offen und dann nur das verbieten was man nicht haben will. Bei vielen Sachen weiß man aber nicht welche Protokolle und Ports es benutzt. Das kann man nicht sicher machen, weil man nicht alles kennt was irgendwann mal durchs Netz schwirrt.
72 -
73 -
Die vertauschten VLANS am AccessPoint und die fehlenden Firewallfreischaltungen haben gezeigt: `Alles richtig gemacht und genau so sollte es werden`.
74 -
Das fühlt sich so einfach einfach richtig an.
gelöscht content/2019-08-13-Octagon-SF4008-Receiver.md
+0 −188
@@ -1,188 +0,0 @@
1 -
---
2 -
title: "Octagon SF4008 Receiver"
3 -
date: 2019-08-13 15:16:10
4 -
update: 2019-08-13 15:16:10
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/13/multimedia.webp"
7 -
tags:
8 -
    - Octagon
9 -
    - Satelit
10 -
    - Kabel
11 -
    - DVB-T
12 -
    - Receiver
13 -
    - DVB-S2
14 -
    - DVB-C
15 -
    - TV 
16 -
preview: "Server immer wieder von extern nicht mehr erreichbar"
17 -
categories: 
18 -
    - Technik
19 -
toc: false
20 -
hide: false
21 -
type: post
22 -
---
23 -
24 -
# Unser Octagon Receiver
25 -
26 -
![Octagon SF4008 Receiver](/images/posts/sf4008.webp)
27 -
28 -
29 -
Wir haben seit über einem Jahr einen Ocatgon SF4008 Receiver an der Sat-Anlage.
30 -
Da ich immer wieder Aussagen oder Fragen höre wie:
31 -
32 -
* "Ach, das kann der Receiver?"
33 -
* "Wie, das machst Du auch damit?"
34 -
* uva.
35 -
36 -
werde ich mal versuchen zusammen zufassen wieso der Octagon Receiver ausgewählt wurde.
37 -
38 -
<!--more-->
39 -
40 -
Auswahlkriterien waren:
41 -
42 -
* Preis
43 -
* Sat und/oder Kabel und/oder DVB-T
44 -
* Aufnahmemöglichkeit auf Festplatte
45 -
* Alternativ oder parallel Aufnahme auf einem Netzwerklaufwerk
46 -
* Individuell anpassbar (installierte Funktionen/Oberfläche)
47 -
* Den HD+-Dreck brauchen wir nicht (wäre aber möglich)  
48 -
* Auch noch Updates wenn das Gerät älter ist
49 -
50 -
Die Liste wurde im Kopf noch viel länger was die gewünschten Funktionen waren.
51 -
Um das schon mal vorweg zu nehmen. Diese Liste im Kopf konnte der Ocatgon eigentlich komplett erfüllen.
52 -
53 -
# Preis und Zukunft
54 -
55 -
Der Octagon SF4008, andere Modelle oder auch von anderen Herstellern, die in diese Richtung gehen, sind auf dem ersten Blick für viele teuer. Aber ganz wichtig ist dabei zu beachten das es eben kein MediaMarkt 49,- € Receiver ist, sondern schon einiges mehr kann, besser gessagt zu einem Gerät gemacht werden kann was alles mögliche machen kann.
56 -
57 -
Wir setzen ihn aktuell nur für Sat TV ein. Sollten die Kabel-TV Anbieter endlich mal ihren Schrott besser machen könnten wir aber auch schnell um Kabel erweitern. Das wäre nur eine weitere Karte in den freien Slot stecken, Kabel rein und fertig.
58 -
59 -
Die aktuelle Karte im Slot 1 kann Dual Sat (DVB-S2), heisst zwei Kabel von der SChüssel bzw. der Weiche können einfach in das Gerät gesteckt werden und Bild-in-Bild oder Aufnahme und parallel gucken sind kein Problem.
60 -
61 -
Würden wir uns mal für DVB-T entscheiden könnten wir aber auch eine Karte für DVB-T reinstecken.
62 -
63 -
Vorteil: Egal was die nächsten Jahre passiert: Wir müssen kein neues Gerät kaufen und auch nicht viel neu einrichten, nur weil sich der Anschluß / die Quelle des TV Programms ändert.
64 -
65 -
# Unser Octagon ist immer noch ohne Festplatte
66 -
67 -
Es liegen zwar noch genug Festplatten herum die aus anderen Geräten noch übrig waren. Trotzdem hat der Octagon immer noch keine Festplatte eingebaut.
68 -
Der Octagon ist hier im Netzwerk per Kabel angeschlossen und hat auch Zugriff auf mehrere Freigaben auf einem Synology NAS.
69 -
70 -
Der Ocatagon kann z.B. auf ein Homeverzeichnis von einem User zugreifen, auf das ich auch von meinem Rechner schnell Zugriff habe und kann Daten für den Ocatgon dort ablegen oder Aufnahmen abrufen.
71 -
72 -
Aufnahmen kann man so auch auf den Rechner laden und sie unterwegs gucken. Oder wir kopieren Fotos und Videos auf das NAS, um sie anderen auf dem großen TV zu zeigen.
73 -
74 -
Ja, das könnten wir auch vom iPhone, iPad oder Rechner auch direkt über den AppleTV machen. Oder dem FireTV. Aber wir möchten das auch mal von unterwegs aus machen können. Oder wir lassen über Streaming ein oder mehrere Videos auf mehreren Geräten gleichzeitig abspielen. Zig Leute zu besuch und alle hängen um ein kleines Gerät und veruchen zu gucken? Nö, hier kann jeder einfach auf seinem Gerät mitgucken.
75 -
76 -
Das ganze funktioniert auch mit dem TV-Programm. Sogar von unterwegs. Möchte man etwas nicht unbedingt am Fernseher gucken, sondern einen Bericht/Doku im Sommer auf dem Balkon oder unterwegs Live gucken. Auch kein Problem, einfach streamen.
77 -
Das geht auch parellel zum TV gucken. Brauchen wir auch nicht so oft, aber immer wenn wir mal was im TV gucken und jemand aus der Family kurz nach oben kommt, schellt und mal eben was durch den Dokumenten-Scanner schicken will, weil er es per Mail versenden möchte wird es gerne benutzt. iPhone oder iPad in die Hand, Streaming des aktuellen Senders auf das iPad und so nichts verpassen. Die anderen können ja auch ganz normal am TV weitergucken.
78 -
79 -
# Anpassen wie es einem gefällt
80 -
81 -
Beim anpassen von Funktionen, Oberfläche oder gar Senderlisten ist alles mögliche machbar. Alleine schon das Senderlisten anpassen war wichtig. Wer schon mal Unitymedia / KabelBW hatte und da alle paar Monate eine neue Senderliste untergejubelt bekommen hat, der wird wissen wie es dazu kommt das man für den Anbieter nur noch hass empfinden kann. Stundenlanges hin- und herschieben von Sendern mit einer sehr schlechten Bedieneroberfläche.
82 -
83 -
Beim Octagon kann man das über eine viel bessere Oberfläche viel schneller erledigen.
84 -
Oder man lädt sich die Aktuelleliste per Sat oder Kabel, je nach Anschluss vom Anbieter. Dann lädt man eine Datei vom Ocatgon herunter. Diese Datei öffnet man in einem Texteditor. Schiebt alles so zurecht wie man die Sender haben möchte und kopiert die Datei wieder auf den Ocatgon. Die Datei wird eingelesen und schon ist die Senderliste wie gewünscht.
85 -
86 -
Wer jetzt nicht unbedingt immer neue Sender unbedingt sofort haben muss, der kann sich ein paat Zeilen Script schreiben, welche die gewünscht Senderliste aus einer neuen Anbieterliste zusammenbaut und alle restlichen neuen Sender einfach ans Ende packt. Die kann man dann auch schnell über das Webinterface verschieben.
87 -
88 -
Eine andere Möglichkeit ist eine Liste von jemanden anderem zu benutzen. Das mache ich bei unserem Ocatgon so. Ich habe die Liste seit der Ersteinrichtung nicht mehr angepackt. Der hat eine Webadresse zu einer Liste bekommen und überprüft regelmässig ob sich etwas an den Sendern verändert hat.
89 -
Die neue Liste wird dann heruntergeladen und installiert.
90 -
91 -
Da kümmert sich jemand anderes drum und der macht es richtig gut. Wir haben noch nie mitbekommen das ein Sender weg ist weil auf einem Transponder sich eteas geändert hat. Da müsste ich mal nachgucken wer das ist, mich mal bedanken und ggf. mal mit einer Kleinigkeit erkenntlich zeigen. Der Typ macht das als Hobby und in einer Qualität, Top Arbeit.
92 -
93 -
Auch die Oberfläche ist anpassbar und erweiterbar bis ins kleinste Detail. Es gibt zig vorgefertigte Designs, die per Paketverwaltung einfach installiert werden. Aktivieren und gucken ob es gefällt. Man kann aber auch einfach noch ein paar andere installieren und zwischen den Oberflächen wechseln. Gerade am Anfang sehr nett um zusehen was man eigentlich wie haben will.
94 -
95 -
# Bildergalerie von der Oberfläche
96 -
97 -
<!-- {{< foldergallery src="images/galleries/2019/08/Octagon-SF4008-Receiver" >}} -->
98 -
99 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-24-23.webp)
100 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-24-34.webp)
101 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-24-53.webp)
102 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-01.webp)
103 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-38.webp)
104 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-50.webp)
105 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-57.webp)
106 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-26-55.webp)
107 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-29-31.webp)
108 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-29-44.webp)
109 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-31-23.webp)
110 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-31-50.webp)
111 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-32-01.webp)
112 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-32-09.webp)
113 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-32-35.webp)
114 -
![](/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-33-40.webp)
115 -
116 -
Für die Bilder habe ich einfach ein paar Sender, Menüs und Plugins aufgerufen und dann am Rechner einen einfachen Befehl ausgeführt.
117 -
118 -
```
119 -
curl -s -u Benutzer:Passwort "http://10.0.2.105/grab?format=png&r=1280&&filename=screen1.png" > screen-$(date "+%H-%M-%S").png
120 -
```
121 -
122 -
Das erstellt mir einfach einen Screenshot vom Bild was der Octagon in dem Moment auf dem TV anzeigt. Die Bilder werden mit dem Name `screen-<Stunde>-<Minute>-<Sekunde>.png` gespeichert. Dabei sind `r=1280` sind 720p und `r=1920` wären 1080p.
123 -
124 -
# PlugIns für alles
125 -
126 -
Es gibt zum Beispiel:
127 -
128 -
* Mediacenter Fotos/Videos von der Festplatte oder Netzwerklaufwerk abspielen
129 -
* Filebrowser
130 -
* IMDB für Infos zu Filmen/Serien
131 -
* Moviecutter (Videos/Aufnahmen schneiden)
132 -
* OpenWebIf (Webinterface um per Browser auf den Ocatgon zugreifen zu können)
133 -
* Youtube
134 -
* ZDF-Mediathek
135 -
136 -
Die Liste ist sehr lang. Komplett verfügbar sind über 4000 Pakete. Davon sind natürlich einige Linux System Tools und Librarys. Aktuell haben ich insgesamt 534 installiert. WakeOnLan, Fritzbox, Speedtest uvm.
137 -
138 -
Fritzbox ist dafür installiert um Anrufe auf dem Festnetz mit einer kleinen Infobox kurz auf dem TV anzuzeigen. Kein störendes klingeln mehr wenn man eigentlich nur TV gucken will.
139 -
140 -
# Wir steuern auch per Sprache
141 -
142 -
Da wir auch das Webinterface installiert haben können wir per Api jeden Befehl der Fernbedienung auch von einem Rechner aus ausführen. Durch eine Einstellung wurde der Untertitel immer angezeigt. Welche Taste das ausschaltet haben wir immer vergessen. Irgend wann habe ich einfach die Videotext-Taste so belegt das der Untertitle an- bzw ausgeschaltet wurde. Das hat Linda dann aber auch immer wieder vergessen. Also habe ich die Api vom Webinterface dazu benutzt mit HTTP Requests zusammen zu bauen die das einfach über die API machen.
143 -
Die HTTP Aufrufe habe ich in HomeBridge geworfen und jetzt kann man einfach den Untertitle einfach per Sprache ausschalten:
144 -
145 -
> Alexa, schalte Untertitel aus.
146 -
147 -
Das kann der Octagon von sich aus so nicht. Dazu ist HomeBridge und Amazon Alexa oder AppleTV mit Siri nötig. Beim schrieben denke ich gerade:
148 -
149 -
> Ich will das nicht so zu 100% sagen, weil irgendwo im Netz hat jemand das bestimmt auch schon mit dem Octagon genau so gemacht.`
150 -
151 -
Da hier ein HomeBridge und FHEM Server für unser SmartHome vorhanden ist macht der das einfach für uns so möglich.
152 -
153 -
# Der Octagon macht vieles einfach entspannter
154 -
155 -
* Sat, Kabel, DVB-T auswechselbar oder kombinierbar.
156 -
* Viele Möglichkeiten zum Erweitern von Funktionen
157 -
* Er wird noch sehr lange Updates bekommen.
158 -
159 -
# Was der Octagon hier nie machen wird
160 -
161 -
Wir werden den Octagon niemals mit einer HD+ Karte betreiben. ARD/ZDF sind eh alle HD und die privaten sind es nicht wert da Geld für mehr Pixeln einzuwerfen.
162 -
Ich sage da immer:
163 -
164 -
> Hätte man bei der Einführung von Farbfernsehen damals Geld verlangt wäre die Entwicklung stehen geblieben und wir hätten heute noch Schwarz/Weiß`
165 -
166 -
Ausserdem kann ein Sender sehr viel einschränken wenn er möchte. Er kann jeder Zeit sagen das Aufnahmen nicht mehr oder für bestimmte Sendungen/Filme nicht mehr erkaubt ist. Oder Aufnahmen sind erlaubt, aber man darf nicht mehr vorspulen. Das sind einfach zu viele unberechenbare Einschränkungen, die einfach nur unverschämt sind.
167 -
168 -
# Updates der Firmware und Oberfläche
169 -
170 -
Bei den üblichen SAT-/Kabel-/DVB-T-Receivern hat man immer das Problem das sie nach ein paar Jahren kein Update mehr bekommen. Ausserdem ist das Update bei den meisten Geräten immer fast unmöglich gewesen. Die Boxen haben zwar USB, serielle Schnittstelle, aber wer hat heute noch die passenden Geräte um damit ein binary des Updates auf das Gerät zu schieben?
171 -
Viele der Gerate haben zwar noch funktioniert, wurden aber in die Tonne geschmissen weil Änderungen in der Infrastruktur nicht auf den Geräten angekommem sind. Da sind Anbieter und Hersteller eigentlich in der Pflicht.
172 -
173 -
Umweltschutz interessiert da wohl keinen. Und so wurden jahrelang Millionen von Geräten sinnlos in den Müll geworfen.
174 -
175 -
Der Octagon hat Netzwerk per Kabel. Könnte aber auch per USB WiFi Adapter per WLAN ins heimische Netzwerk gebracht werden. Andere Modelle haben sogar WLAN direkt dabei.
176 -
177 -
# Octagon mit WLAN, da geht noch mehr ;-)
178 -
179 -
Wer zuhause bescheidenes WLAN hat, da der Anschluss mal wieder im Flur oder gar in einer anderen Etage ist. Einfach mal dran denken: Auf dem Octagon läuft ein Linux.
180 -
181 -
Wenn der Octagon mit WiFi per Kabel ins Netzwerk gebracht werden kann:
182 -
183 -
* Octagon per Kabel ins Netzwerk  
184 -
* WiFi vom Octagon als AccessPoint konfigurieren
185 -
* Weiterleitung zwischen WLAN und Kabel aktivieren
186 -
* Andere Geräte können sich per Wifi jetzt auch mit dem Ocatgon verbinden und kommen dann über den ins Netz.
187 -
188 -
So viel zu den Möglichkeiten die so ein Gerät mitbringt.
gelöscht content/2019-08-18-networkserver-of-death.md
+0 −152
@@ -1,152 +0,0 @@
1 -
---
2 -
title: "Networkserver of Death"
3 -
date: 2019-08-18 22:30:00
4 -
update: 2019-08-18 22:30:00
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/18/serverofdeath.webp"
7 -
tags:
8 -
    - Storage
9 -
    - NAS
10 -
    - Router
11 -
    - UPnP
12 -
    - AVM
13 -
    - Fritzbox
14 -
preview: "Server immer wieder von extern nicht mehr erreichbar"
15 -
categories: 
16 -
    - Technik
17 -
toc: false
18 -
hide: false
19 -
type: post
20 -
---
21 -
22 -
# Server immer wieder von extern nicht mehr erreichbar
23 -
24 -
Für das Projekt [Essenz - Rock Dein Block](https://www.beone-projects.com/projekte/essenz/ "Rock Dein Block Projekseite") haben wir hier auf einem Synology NAS mehrere Dienste laufen damit sich die Coaches und Teilnehmer austauschen können.
25 -
26 -
Es gab immer mal wieder Probleme mit dem Zugriffen auf das NAS. Und das Monitoring (Icinga) hat auch immer wieder alamiert. Nach dem umfangreichem Netzwerkumbau in den letzten Tagen hatte ich gestern Abend teilweise die Änderungen am Netz als Ursache nicht mehr ausschliessen können.
27 -
<!--more-->
28 -
Vorteil der Änderungen war aber ,durch die strickte Trennung mit VLANs und den Routern zwischen den Netzen, kann man jetzt gezielt nach Fehlern suchen. Es ist nicht mehr alles eine große Suppe IP Traffic von über 90 Geräten.
29 -
30 -
Das ganze könnte aber auch die Ursache des ganzen Übels sein. Daher habe ich heute die komplette Netzwerkkonfiguration noch mal auf links gedreht.
31 -
32 -
Auch weil, immer wenn das Problem aufgetaucht ist, der Traffik zwischen den Netzen und Switchen auf einmal massiv angestiegen ist. So stark das ich das eigentiche Problem da noch gar nicht auf dem Schirm hatte. Dazu war der Traffic auf den Ports viel zu hoch, als das man auf UPnP kommen könnte.
33 -
34 -
Der Traffik blieb selbst wenn dann das Portforwarding komplett ausgestiegen ist und sogar aus den Routern auf einmal verschwunden ist. Manuell gesetzt, Problem taucht auf, Portforwarding nicht mehr in der Konfiguration.
35 -
36 -
Und selbst dann blieb der Traffic intern weiter sehr hoch. Da geht man von einem Problem in der Netzwerkkonfiguration oder an den Geräten im Netz aus.
37 -
38 -
# Das NAS ist im Netzwerk noch mal umgezogen
39 -
40 -
Um einige Sachen ausschliessen zu können ist das NAS noch mal umgezogen. Also es blieb da stehen wo es ist, aber es wurden an den Switchen ein paar Ports umkonfiguriert, so das es so gesehen wieder direkt hinter den Routern angeordnet war. Das Problem war ... immer noch vorhanden.
41 -
42 -
Um das Problem an einem der Switche auszuschliessen wurde ein frischer Ubiquiti EdgeRouterX SPF aus dem Karton genommen und das NAS da angeschlossen. Da zum Switch, an dem das NAS eigentlich hängt, 4 Leitungen als LAG aus der anderen Etage kommen um 4 GigaBit/s hochschieben zu können, einfach eine davon gezogen und auch an den EdgeRouterX geklemmt. Die andere Seite unten vom Switch auch gezogen und direkt auf den Router zum Internet geklemmt.
43 -
44 -
> Internetrouter -> EdgeRouterX -> NAS
45 -
46 -
Portforwarding konfiguriert und getestet. Online war das NAS wieder auch wieder ohne Probleme. So bald wieder Requests rein kommen ist das Portforwarding weg und auf dem EdgeRouterX sieht man massig Traffik. Also alles andere im Netzwerk kann jetzt schon einmal ausgeschlossen werden.
47 -
48 -
Aber woher kommt es und was ist die Ursache?
49 -
50 -
# DNS gändert und Ruhe
51 -
52 -
Nach langem Suchen nach der Ursache und nicht wirklich der Ursache näher kommend noch mal überlegt was nicht ausgeschlossen wurde. Das war zu dem Zeitpunkt noch der Zugriff von außen auf das NAS. Die Domain dafür wird bestimmt schon bei einigen <s>BadBoys</s> SkriptKiddies rumgeistern. Also Attacken kann man nicht ausschliessen.
53 -
54 -
Also DNS Record löschen und auf `127.0.0.1` setzen.
55 -
56 -
```
57 -
dnsmngt -d -z domain.de -s subdomain
58 -
dnsmngt -a -z domain.de -s subdomain -i 127.0.0.1
59 -
```
60 -
61 -
Danach war auch erst einmal alles ruhig und es gab auch keine Probleme mehr im Netzwerk.
62 -
63 -
Das ganze wieder zurück und den DNS Record auf den alten Wert setzen. Kurze Zeit später war das Problem wieder da. Portforwarding zeigt den Server dahinter wieder als Offline an. Netzwerktraffik ging wieder hoch. Es besteht weiter.
64 -
65 -
Jetzt eben eine neue Subdomain anlegen und damit testen.
66 -
67 -
```
68 -
dnsmngt -a -z domain.de -s testsubdomain -i 111.222.333.444
69 -
```
70 -
71 -
Portforwarding wieder konfiguriert. Aufgerufen und es ist alles damit online. ein wenig getestet und auch jetzt wieder alles weg. Traffik ... ihr wisst schon.
72 -
 Bber die neue Subdomain kann keiner kennen. Dazu ist sie noch zu frisch.
73 -
74 -
Es muss also noch etwas anderes sein. Um zu prüfen ob die Fritzbox vielleicht mal wieder eine kaputte Konfiguration hat musste sie ausgeschlossen werden. Weil die Box Resetten, komplett auf Werkseinstellung und neu einrichten wäre nicht so der Aufwand. Aber wieso wenn es nicht nötig ist.
75 -
76 -
# Weg über den 2. Anschluss testen
77 -
78 -
Wir haben ja zwei Anschlüsse und daher auch zwei Fritzboxen. Auf der anderen Fritzbox das Portforwarding eingerichtet. Andere Fritzbox, anderer Anschluss. Wenn es da auch so ist, dann ist es nicht die Fritzbox.
79 -
80 -
Damit das ganze überhaupt funktioniert musste das NAS einfach nur als Standard Gateway die andere Fritzbox IP bekommen.
81 -
82 -
Parallel wurden ein paar Geräte in anderen Etage dazu angehalten den anderen Anschluss zu benutzen. So wurden alle anderen Geräte nicht gestört und über die Leitung ging nur noch das NAS online.
83 -
84 -
Default Routen werden hier auf den Routern eh immer beide gesetzt. Aber so das immer das andere Gateway als Fallback dient wenn ein Anschluss gestört ist.
85 -
So kann man auch mal eine Fritzbox vom Netz nehmen, ohne das groß jemand etwas merkt.
86 -
87 -
NAS online, alles ok. Doch auch da dann wieder Probleme. Da sogar so heftig, das die Fritzbox sogar komplett jedesmal das DSL verloren hat. Das ganze konnte ich 5 mal reproduzieren.
88 -
89 -
# UPnP noch mal gechecked
90 -
91 -
In den Fritzboxen noch einmal überprüft ob das UPnP aus ist. Bei dem Gerät war es auch nicht an. Das wurde jetzt schon zig mal überprüft, aber trotzdem noch mal gucken kann ja nicht schaden.
92 -
93 -
Auf dem NAS sollte es auch nicht an sein, das wird nicht benutzt und soll auch nicht aktiv sein. Aber ein Blick in die Config zeigt: da ist etwas konfiguriert ist. Also noch mal checken ob das auch aktiv ist.
94 -
95 -
Und siehe da, der Mist ist da aktiv.
96 -
97 -
Der ganze Aufriss, auf den Cisco Switchen alles möglich checken und tracen, auf den anderen Switche, auf dem EdgeRoutern, auf den AccessPoints, auf allen möglichen Geräten, weil das komplette Netzwerk auf einmal Traffic machte, der weder von innen nach draussen, noch von aussen nach drinnen so massiv kommen konnte. Tcpdump, traceroutes, mtr usw. um das Problem zu finden. Und dann ist es dieses fucking UPnP.
98 -
99 -
Portforwarding aktiviert, NAS wieder online. Also Tcpdump noch mal gezielt an einigen Punkten im Netzwerk auf UPnP Zeug angesetzt.
100 -
101 -
```
102 -
tcpdump -i eth0 udp and port 1900 and dst 239.255.255.250 -s0 -w UPnP.pcap
103 -
```
104 -
105 -
Das Netzwerk war die ganze Zeit ruhig. Bis man die App am Smartphone aus dem mobilen Netz aufruft und Daten vom NAS abruft und kopiert. Einfach auf das iPhone kopieren oder selbst auf dem NAS an einen anderen Ort kopieren.
106 -
107 -
In dem Moment brach jedesmal die Multicast Hölle aus. Das NAS hat jedesmal die Router zugebommt mit Multicast Paketen bis die eine das Portforwarding eingestellt hatte. Oder bei der anderen ja sogar so weit das DSL komplett ausgestiegen ist. Der Router musste jedesmal DSL neu synchronisieren.
108 -
109 -
# WTF
110 -
111 -
UPnP für internen Kram wie Media Server, Media Printer, Netzlaufwerke usw. ist ja toll und schön. Das benutzen wir hier mit einigen Geräten auch. Der Octagon z.B. stellt Streaming, Mediaplayer für Fotos und Videos damit bereit.
112 -
113 -
Aber an den Router soll so ein Mist bitte nicht. Das wurde 2013 schon sehr gut gezeigt. Als man ca. 50 Millionen Geräte im Netz gefunden hatte, die darüber von aussen übernommen werden konnten.
114 -
115 -
Das, also UPnP, ist wieder so ein tolles Beispiel für: `Dem Benutzer alles abnehmen, weil es so für ihn einfacher ist.`
116 -
117 -
Ja einfach, aber macht es nur schlimmer. Die Leute stellen sich Geräte zuhause hin die dann mal eben so das komplette Leben (Daten auf den Geräten) frei ins Internet stellen. Weil irgend ein Gerät meint dem Router über UPnP zu sagen: `Mach mal Port auf und schick alle rein zu mir, ich habe die Daten.`
118 -
119 -
> Ja, kannste schon so machen, ist dann halt kacke!
120 -
121 -
Wieso versucht man den Leuten immer alles abzunehmen? Wer ein Geräte hinter seinem "sicheren" Internetanschluss freigeben möchte, der soll das gefälligst selbst einrichten. Und ja dazu gehört auch: `Beschäftige Dich mit dem Scheiss`. Man sollte zumindest ein wenig verstehen was man da macht. Vor allem was man da mit seinen Daten im schlimmsten Fall machen. Oder man macht sich wenigstens kurz Gedanken darüber ob man das auch wirklich so will und nicht besser noch andere Sicherheitsmassnahmen dazu schaltet.
122 -
123 -
# Aber auch die Hersteller könnten mal ...
124 -
125 -
1. Wieso ballert da eine Synology einfach so massiv Multicast ins Netzwerk und zwar so das man an alles mögliche denkt. Nur nicht an UPnP.
126 -
127 -
Leute, wir haben hier zwischen den Wohnungen jeweils 2x1 GB im LAG. Und wir hier in unserer Wohnung nach oben ins Büro 4x1 GB im LAG. Und der UPnP-Traffik war zwischen dem ganzen Streaming und Backups die in der Zeit liefen zu sehen. Also es war nicht der UPnP-Traffik selbst zusehen. Danach wurde ja noch nicht geziehlt geguckt. Der Traffik war halt so viel das er in den Graphen und Statistiken nur auffallen konnte.
128 -
129 -
Und wenn etwas, wie in dem Fall UPnP, nicht funktioniert, wo war da eine Mail oder eine Meldung in der Oberfläche? Jeder Mist wird einem zig mal benachrichtigt, aber das nicht? Aber dafür das Netz mal komplett zu müllen. Ausserdem kann man einen Service auch sagen er soll ruhig sein wenn etwas nicht klappt und nicht einfach noch lauter ins Netz brüllen lassen.
130 -
Meinem Sohn sage ich auch:
131 -
132 -
> Es bringt nichts wenn Du lauter wirst, dadurch höre ich Dir nicht besser zu wenn ich Dir nicht gerade zuhören kann. Warte kurz und sei bitte kurz leise.
133 -
134 -
Und ja, wenn er dann nicht hört bekommt auch mein Sohn ein `FIN-RST` von mir und darf sich erst einmal abkühlen gehen.
135 -
136 -
2. AVM macht ja eigentlich immer einen guten Job. Aber UPnP deaktiveren haben sie ja jetzt so gut versteckt und ist auch nicht mehr so gut zu erkennen ob es aktiviert ist oder nicht. Das könnte bitte besser sein.
137 -
138 -
Und leider kann man auch nie gut erkennen, was, wann, wie schief läuft oder gelaufen ist. Man kann auch nicht so gut auf den Dingern gucken was in so einer Situation gerade passiert. Da wären ein wenig mehr Infos schon nicht schlecht.
139 -
140 -
Ausserdem wäre eine Funktion in der Fritzbox nicht schlecht, die einfach mal sagt: `Device XY, du kommst hier gerade mit ein paar tausend UPnP Zeug rein, das ist hier nicht, geh sterben` und dann strickt wegblockt. Fertig. Dazu dann noch in der Oberfläche eine Meldung, das da gerade ein Device scheisse baut.
141 -
142 -
# UPnP wird jetzt weggeblockt
143 -
144 -
Nachdem jetzt alles wieder zurück gebaut wurde. Also eher zurück-zurück ;-). Wird jetzt die Firewall zwischen den VLANS und zu den Routern noch um ein UPnP DROP erweitert.
145 -
146 -
Das ein Gerät meint es darf sich hier alles erlauben soll ja nicht noch einmal vorkommen. Ausserdem will ich sehen wenn so etwas noch einmal passiert und dann auch benachrichtigt werden.
147 -
148 -
UPnP vom Synology aus sollte eigentlich ausgeschaltet gewesen sein. Ich kann mir auch nicht vorstellen das irgend ein Paket, was installiert wurde, das selbstständig gemacht hat. Das ist eigentlich nicht Synology-Style
149 -
150 -
Das jemand beim Einrichten eines Services gedacht hat man muss das in den Einstellungen auch noch unter "Routerkonfigurieren" aktivieren, will ich nicht ausschliessen.
151 -
152 -
Ist schon heftig, wenn so etwas solche Auswirkungen hat. Und wird so auch nicht mehr passieren. Dafür wird es schöne Rules in den Firewall geben.
gelöscht content/2019-08-18-wifi-hotspot-und-hugo-grid-theme.md
+0 −46
@@ -1,46 +0,0 @@
1 -
---
2 -
title: "WiFi Hotspot und Hugo Grid Theme"
3 -
date: 2019-08-28 22:30:00
4 -
update: 2019-08-28 22:30:00
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/19/wifi.webp"
7 -
tags:
8 -
    - Router
9 -
    - Hotspot
10 -
    - Chillispot
11 -
    - Hugo
12 -
    - CMS
13 -
    - Theme
14 -
    - Grid
15 -
    - Responsive
16 -
preview: "Auf dem EdgeRouterX [^1] habe ich zum testen die Tage auch einmal [Chillispot Captive Portal](http://www.chillispot.org) installiert."
17 -
categories: 
18 -
    - Internet
19 -
toc: false
20 -
hide: false
21 -
type: post
22 -
---
23 -
24 -
# EdgeRouterX und Chillispot Captive Portal
25 -
26 -
Auf dem EdgeRouterX [^1] habe ich zum testen die Tage auch einmal [Chillispot Captive Portal](http://www.chillispot.org) installiert.
27 -
28 -
Auf dem WiFi AccessPoint eine neue SSID mit neuem VLAN angelegt, SwitchPort getagged und auf dem EdgeRouterX das VLAN angelegt mit den passenden Config für Chillispot.
29 -
<!--more-->
30 -
Für die Authentifizierung habe ich [Hotspotsystem.com](https://www.hotspotsystem.com) genommen. Die Einrichtung und das aktivieren ist recht simple. Und wenn man neben dem Gast WiFi noch ein Pay-WiFi anbieten möchte kann man das damit sehr gut umsetzen.
31 -
32 -
# Hugo CMS Grid Theme
33 -
34 -
Zwischen dem ganzen Netzwerkkram [^2], [^3], [^4], [^5] die letzten Tage habe ich mich mal an ein eigenes Theme für dieses Blog gemacht. Das ist nicht so mein Ding. Nicht so wie Netzwerk und Serverkram.
35 -
36 -
Aber so ein HTML5 Grid werde ich ja wohl hinbekommen. Hauptsächlich sollte es immer auf mobilen Geräten immer passen. Keine Bilder die zu groß sind und Dinge, wie Sidebar sollen einfach wo anders hin verschwinden wo sie erst einmal nicht stören. Oder manche Sachen in der mobilen Ansicht einfach komplett verschwinden.
37 -
38 -
Was auf mobile passt, das passt auch auf dem Desktop. Also Mobile-First.
39 -
40 -
An ein paar Ecken muss ich noch ran. Aber für einen Tag HTML- und CSS-Session schon mal nicht schlecht. Jetzt noch mal in Ruhe etwas aufräumen und dann weiter verbessern und verschönern.
41 -
42 -
[^1]: EdgeRouterX [Ubiquiti](https://www.ui.com/edgemax/edgerouter-x-sfp/)
43 -
[^2]: [Netzwerk Umbaulobar](https://blog.kuepper.nrw/2019/08/09/netzwerk-umbaulabor/)
44 -
[^3]: [Netzwerkumbau VLANs und Firewall](https://blog.kuepper.nrw/2019/08/09/netzwerkumbau-vlans-und-firewall/)
45 -
[^4]: [VLANs und Firewall](https://blog.kuepper.nrw/2019/08/12/vlans-und-firewall/)
46 -
[^5]: [Networkserver of Death](https://blog.kuepper.nrw/2019/08/18/networkserver-of-death/)
gelöscht content/2019-08-20-blog-theme-noch-einmal-angepasst.md
+0 −37
@@ -1,37 +0,0 @@
1 -
---
2 -
title: "Blog Theme noch einmal angepasst"
3 -
date: 2019-08-20 21:27:00
4 -
update: 2019-08-20 21:27:00
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/12/vpn.webp"
7 -
tags:
8 -
    - Hugo
9 -
    - CMS
10 -
    - Theme
11 -
preview: "Auch heute wurde noch etwas weiter am Theme geschraubt. Es waren noch ein paar Baustellen was die Darstellung von Bildern betrifft."
12 -
categories: 
13 -
    - Technik
14 -
toc: false
15 -
hide: false
16 -
type: post
17 -
---
18 -
19 -
20 -
Auch heute wurde noch etwas weiter am Theme geschraubt. Es waren noch ein paar
21 -
Baustellen was die Darstellung von Bildern betrifft.
22 -
Jetzt passt erst einmal alles wie gewünscht. Und gerade wurde auch ein großer Test mit
23 -
Apple iPhones (4s bis XR), iPads (Alle von 1er bis Pro), Samsumg Phones und Tables (Alles mögliche), LG, Nexus (6,9), HTC One, Sony, Kindle usw.
24 -
25 -
<!--more-->
26 -
27 -
Eigentlich alles was man so draussen erwarten kann. Passt alles und die nächste Zeit jetzt nur noch Kleinigkeiten verbessern.
28 -
29 -
Da wären z.B. die Codeblöcke. Die gefallen mir noch nicht so gut, da ich aktuell keinen Hintergrund setzen kann. Code der auf der Seite angezeigt wird passt von der Breite zwar jetzt, aber die Box im Hintergrund geht nur ca. 60-70 der verfügbaren Breite.
30 -
Sieht dann halt doof aus wenn der Code dann drüber hinaus geht.
31 -
32 -
Bilder waren heute mittag noch mal nervig. Alles hat gepasst und ein Ende war in Sicht. Bis ich dann auch wieder alle anderen  Browser mit getestet habe. Und der Firefox hat alles komplett ~~beschis~~ zerschossen angezeigt.
33 -
34 -
Die Bilder liegen jetzt in einem CDN und können da auch schnell deployed werden. Die fliegen auch noch aus dem Hugo Ordner raus. Die kommen ja erst später in die Seite.
35 -
Das Theme und der restliche Content sind im Git auch schon getrennt, so das alles einzeln angefasst werden kann und erst in der Gitlab Pipeline wird alles zusammen gesteckt und die Seite generiert.
36 -
37 -
Für die Bilder habe ich jetzt ein kleines Script was die Bilder verkleinert. Da wird noch was verbessert. Da jetzt das Theme  fertig ist kann ich auch mal geziehlt mit den Grössen gucken. Die Bilder dann damit auch in die passende Grösse automatisch anpassen und ins CDN deployen, fertig.
gelöscht content/2019-08-28-tmux-xpanes-ultimate-terminal-divider-powered-by-tmux.md
+0 −71
@@ -1,71 +0,0 @@
1 -
---
2 -
title: "tmux-xpanes - Ultimate terminal divider powered by tmux"
3 -
date: 2019-08-28 08:15:00
4 -
update: 2019-08-28 08:15:00
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/28/ping_pane_title.webp"
7 -
tags:
8 -
    - Terminal
9 -
    - tmux
10 -
    - tmux-xpanes
11 -
preview: "Bei diesem Terminal-Multiplexer kann man sehr gut und schnell per Shortcut aktivieren das Befehle in allen Fenstern ausgeführt werden. Nach dem Wechsel auf den Mac habe ich immer eine brauchbare Alternative gesucht."
12 -
categories: 
13 -
    - Internet
14 -
toc: false
15 -
hide: false
16 -
type: post
17 -
---
18 -
19 -
Als ich noch eine Linux Workstation hatte, habe ich eine lange Zeit [Terminator](https://gnometerminator.blogspot.com) benutzt.
20 -
Bei diesem Terminal-Multiplexer kann man sehr gut und schnell per Shortcut aktivieren das Befehle in allen Fenstern ausgeführt werden.
21 -
Nach dem Wechsel auf den Mac habe ich immer eine brauchbare Alternative gesucht.
22 -
Jetzt bin ich über [tmux-xpanes](https://github.com/greymd/tmux-xpanes) gestolpert.
23 -
24 -
<!--more-->
25 -
26 -
![xpanes Ultimate terminal divider powered by tmux](/images/posts/2019/08/28/movie_v4.gif)
27 -
28 -
29 -
<!-- /img/posts/2019/08/28/movie_v4.gif -->
30 -
31 -
Mit [csshx](http://macappstore.org/csshx/) bin ich nie richtig warm geworden.
32 -
33 -
Bei [iterm2](https://iterm2.com) den ich benutze geht das auch mit
34 -
`send input to all tabs` . Aber irgendwie war das auch immer nicht so super.
35 -
36 -
Mit [tmux](https://github.com/tmux/tmux) kann man das aktivieren mit `:setw synchronize-panes` und wieder ausschalten mit `:setw synchronize-panes off`
37 -
38 -
[tmux-xpanes](https://github.com/greymd/tmux-xpanes) macht es aber irgend wie schicker. Alleine schon der Aufruf ist schon mal
39 -
sehr cool.
40 -
41 -
```
42 -
xpanes --log=~/log --ssh user1@host1 user2@host2 user2@host3
43 -
docker ps -q | xpanes -s -c "docker exec -it {} sh"
44 -
```
45 -
46 -
Weitere Beispiele sind auf der Github Seite von [tmux-xpanes](https://github.com/greymd/tmux-xpanes) beschrieben.
47 -
48 -
# Installieren
49 -
50 -
Mac:
51 -
52 -
```
53 -
brew install tmux-xpanes
54 -
```
55 -
56 -
CentOS, RHEL:
57 -
58 -
```
59 -
yum install \
60 -
https://github.com/greymd/tmux-xpanes/releases/download/v4.1.1/tmux-xpanes_v4.1.1.rpm
61 -
```
62 -
63 -
Ubuntu/Debian:
64 -
65 -
```
66 -
sudo apt install software-properties-common
67 -
68 -
sudo add-apt-repository ppa:greymd/tmux-xpanes
69 -
sudo apt update
70 -
sudo apt install tmux-xpanes
71 -
```
gelöscht content/2019-08-29-caddyserver-als-nginx-alternative.md
+0 −60
@@ -1,60 +0,0 @@
1 -
---
2 -
title: "Caddyserver als nginx Alternative"
3 -
date: 2019-08-29 08:15:00
4 -
update: 2019-08-29 08:15:00
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/29/caddyserver.webp"
7 -
tags:
8 -
    - caddy
9 -
    - webserver
10 -
    - nginx
11 -
    - alternative
12 -
preview: "Gerade für Testseiten bietet sich der kleine Webserver an. Er kann lokal einfach gestartet werden und man kann seine Seiten testen."
13 -
categories: 
14 -
    - Internet
15 -
toc: false
16 -
hide: false
17 -
type: post
18 -
---
19 -
20 -
Ich benutze sehr gerne den Nginx Webserver und das wird auch so bleiben.
21 -
Aber für keine Projekte habe ich jetzt einen Webserver gefunden der einfach und schnell benutzt werden kann.
22 -
23 -
<!--more-->
24 -
25 -
Die rede ist vom [Caddyserver](https://caddyserver.com).
26 -
27 -
Das nette ist:
28 -
29 -
* Konfigfile mit 3 Zeilen und läuft
30 -
* Läuft auf allen Plattformen
31 -
* Macht auf wunsch auch Letsencrypt SSL Certs On-The-Fly
32 -
33 -
Gerade für Testseiten bietet sich der kleine Webserver an. Er kann lokal einfach gestartet werden und man kann seine Seiten testen.
34 -
35 -
Auf der [Downloadseite](https://caddyserver.com/download) kann der Caddyserver für alle Plattformen heruntergeladen werden.
36 -
Dabei kann man auch PlugIns für sehr viele DNS Anbieter hinzufügen, um DNS Einträge für das generieren der SSL Certs zu erstellen.
37 -
Die Liste enthält alle möglichen Anbieter wie Cloudflare, Route53 (AWS), Azure, DYN usw.
38 -
In der PlugIn Liste sind sehr viele Plugins z.B. Proxy, HTTP-Auth, Geo-IP, IP-Filter und viele andere mehr.
39 -
40 -
Für Docker gibt es ein fertiges [Image](https://hub.docker.com/r/abiosoft/caddy/).
41 -
42 -
Das configfile ist wie gesagt sehr simple:
43 -
44 -
```
45 -
test1.homepage.net
46 -
browse
47 -
tls off
48 -
```
49 -
50 -
Möchte man PHP-FPM benutzen reichen 2 weitere Zeilen:
51 -
52 -
```
53 -
fastcgi / 127.0.0.1:9000 php # php variant
54 -
on startup php-fpm7 # php variant only
55 -
```
56 -
57 -
Die zweite Zeile kümmert sich sogar gleich darum das php-fpm7 vor dem Start des Webserver mit gestartet wird.
58 -
Hier kann man beliebige so genannte `RUN COMMANDS` ausführen um Dienste oder Befehle auszuführen die vor dem Start benötigt werden.
59 -
60 -
Ich werde den Webserver in nächster Zeit noch weiter testen. Hauptsächlich erst einmal für Testumgebungen. Mal sehen wie er sich so macht.
gelöscht content/2019-09-03-Rasbian-ohne-Monitor-tastatur-installieren.md
+0 −258
@@ -1,258 +0,0 @@
1 -
---
2 -
title: "Rasbian ohne Monitor und Tastatur installieren"
3 -
date: 2019-09-03 18:37:42
4 -
update: 2019-09-03 18:37:42
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
  - RaspberryPi
9 -
  - Raspbian
10 -
  - Installation
11 -
  - WiFi
12 -
  - Headless
13 -
  - silentinstall
14 -
preview: "Einen neuen Raspbarry mit Rasbian ohne Monitor und Tastatur einrichten"
15 -
categories: 
16 -
  - Internet
17 -
toc: false
18 -
hide: false
19 -
type: post
20 -
---
21 -
22 -
23 -
Ich bestelle immer RaspberryPi Bundles wie das hier [UCreate Raspberry Pi 3 Model B+ Desktop Starter Kit (16 GB, schwarz)](https://www.amazon.de/gp/product/B07BNPZVR7/). Eigentlich immer mit einem vorinstallierten Rasbian. Dieses mal war aber kein Rasbian vorinstalliert sondern Noobs auf der SD-Card.
24 -
25 -
Nur stecke ich immer ein Netzwerkkabel an und Strom, warte kurz bis der RaspberryPi im Netz ist und logge mich dann per SSH dauf dem RaspberryPi ein. Das einzige was ich sonst immer mache ist im ROOT auf der SD-Card eine leere Datei `ssh` anlegen.
26 -
27 -
Um jetzt Headless zu installieren geht man wie folgt vor:
28 -
29 -
* In das Verzeichnis `/os` wechseln und alle Distributions Verzeichnisse löschen die man nicht benötigt. In diesem Fall bleibt dann nur das Verzeichnis `/os/Rasbian_Full` übrig.
30 -
* Im Root Verzeichnis die Datei `recovery.cmdline` öffnen und an das Ende `silentinstall` anhängen.
31 -
* Im Root Verzeichnis: `touch ssh`
32 -
33 -
Vorher:
34 -
```
35 -
runinstaller quiet vt.cur_default=1 coherent_pool=6M elevator=deadline
36 -
```
37 -
Nachher:
38 -
```
39 -
runinstaller quiet vt.cur_default=1 coherent_pool=6M elevator=deadline silentinstall
40 -
```
41 -
42 -
SD-Card einstecken und Strom anschliessen. Dann ist Kaffee holen angesagt. Die Installation dauert ein paar Minuten.
43 -
Wenn der RaspberryPi fertig ist sollte er wie gewohnt im Netz auftauchen und man kann sich drauf einloggen.
44 -
45 -
# Kleines WLAN Problem
46 -
47 -
Dieser RaspberryPi soll später mobil per WiFi über einen LTE Router ins Internet und per Kabel soll ein Kassendrucker angeschlossen werden. Da wpa_supplicant noch nicht konfiguriert war, aber schon gestartet ist hatte das noch kurz Probleme gemacht.
48 -
49 -
Die Datei `/etc/wpa_supplicant/wpa_supplicant.conf` wurde angepasst:
50 -
51 -
```
52 -
cat /etc/wpa_supplicant/wpa_supplicant.conf
53 -
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
54 -
ap_scan=1
55 -
update_config=1
56 -
network={
57 -
	ssid="Section3"
58 -
  psk="1234123412341234"
59 -
}
60 -
```
61 -
62 -
Kurzer Test mit laufendem `tail -f /var/log/message &` hat erst einmal überhaupt nicht funktioniert.
63 -
64 -
```
65 -
iw wlan0 info
66 -
Interface wlan0
67 -
	ifindex 3
68 -
	wdev 0x1
69 -
	addr b8:27:eb:87:71:dc
70 -
	type managed
71 -
	wiphy 0
72 -
	channel 11 (2462 MHz), width: 40 MHz, center1: 2452 MHz
73 -
	txpower 31.00 dBm
74 -
```
75 -
76 -
Läuft doch. Aber wieso klappt die Verbindung nicht? Ein Scan mit `iwlist wlan0 scan` hat auch geklappt, die gewohnt lange Liste der SSID hier wird ausgegeben.  
77 -
78 -
```
79 -
# > wpa_supplicant -i wlan0 -Dnl80211 -c /etc/wpa_supplicant/wpa_supplicant.conf
80 -
Successfully initialized wpa_supplicant
81 -
Failed to create interface p2p-dev-wlan0: -16 (Device or resource busy)
82 -
nl80211: Failed to create a P2P Device interface p2p-dev-wlan0
83 -
P2P: Failed to enable P2P Device interface
84 -
Sep  3 20:27:17 raspberrypi kernel: [ 2046.293855] brcmfmac: brcmf_cfg80211_add_iface:
85 -
iface validation failed: err=-16
86 -
Sep  3 20:27:17 raspberrypi kernel: [ 2046.293855] brcmfmac: brcmf_cfg80211_add_iface:
87 -
iface validation failed: err=-16
88 -
wlan0: Trying to associate with 90:de:d0:d0:f1:98 (SSID='Section3' freq=2462 MHz)
89 -
wlan0: Associated with 90:de:d0:d0:f1:98
90 -
wlan0: CTRL-EVENT-DISCONNECTED bssid=90:de:d0:d0:f1:98 reason=0 locally_generated=1
91 -
wlan0: WPA: 4-Way Handshake failed - pre-shared key may be incorrect
92 -
wlan0: CTRL-EVENT-SSID-TEMP-DISABLED id=0 ssid="Section3" auth_failures=1 duration=10
93 -
reason=WRONG_KEY
94 -
wlan0: CTRL-EVENT-REGDOM-CHANGE init=CORE type=WORLD
95 -
wlan0: CTRL-EVENT-REGDOM-CHANGE init=USER type=COUNTRY alpha2=US
96 -
wlan0: CTRL-EVENT-SSID-REENABLED id=0 ssid="Section3"
97 -
wlan0: Trying to associate with 90:de:d0:d0:f1:98 (SSID='Section3' freq=2462 MHz)
98 -
Sep  3 20:27:31 raspberrypi kernel: [ 2060.046763] brcmfmac: brcmf_cfg80211_escan:
99 -
Connecting: status (3)
100 -
Sep  3 20:27:31 raspberrypi kernel: [ 2060.046777] brcmfmac: brcmf_cfg80211_scan:
101 -
scan error (-11)
102 -
Sep  3 20:27:31 raspberrypi kernel: [ 2060.046763] brcmfmac: brcmf_cfg80211_escan:
103 -
Connecting: status (3)
104 -
Sep  3 20:27:31 raspberrypi kernel: [ 2060.046777] brcmfmac: brcmf_cfg80211_scan:
105 -
scan error (-11)
106 -
```
107 -
108 -
Alles noch mal überprüft. Die SSID stimmt, PSK stimmt, PSK auch noch mal verschlüsselt hinterlegt. Keine Verbindung mit dem WiFi möglich.
109 -
110 -
Dann mal checken ob vielleicht noch etwas läuft:
111 -
112 -
```
113 -
#> ps fauxww | grep wpa
114 -
root       468  0.0  0.3  10156  2864 ?        Ss   19:53   0:02 wpa_supplicant -B
115 -
-c/etc/wpa_supplicant/wpa_supplicant.conf -iwlan0 -Dnl80211,wext
116 -
root      2454  0.0  0.0   4372   572 pts/0    S+   20:38   0:00                  
117 -
        \_ grep wpa
118 -
```
119 -
120 -
Ah, ok. Da ist noch ein alter wpa_supplicant gestartet, der den Treiber falsch hatte.
121 -
Der wird dann einfach mal gekillt.
122 -
```
123 -
# > kill -9 468
124 -
```
125 -
126 -
Check ob er wirklich beendet ist:
127 -
```
128 -
# > ps fauxww | grep wpa
129 -
root      2456  0.0  0.0   4372   564 pts/0    S+   20:38   0:00                   
130 -
       \_ grep wpa
131 -
```
132 -
133 -
Alles klar und jetzt wpa_supplicant noch mal starten. Und siehe da, jetzt klappt es.
134 -
135 -
```
136 -
# > wpa_supplicant -i wlan0 -Dnl80211 -c /etc/wpa_supplicant/wpa_supplicant.conf
137 -
Successfully initialized wpa_supplicant
138 -
wlan0: Trying to associate with 90:de:d0:d0:f1:98 (SSID='Section3' freq=2462 MHz)
139 -
wlan0: Associated with 90:de:d0:d0:f1:98
140 -
wlan0: WPA: Key negotiation completed with 90:de:d0:d0:f1:98 [PTK=CCMP GTK=TKIP]
141 -
wlan0: CTRL-EVENT-CONNECTED - Connection to 90:de:d0:d0:f1:98 completed [id=0 id_str=]
142 -
Sep  3 20:38:28 raspberrypi kernel: [ 2717.234843] IPv6: ADDRCONF(NETDEV_CHANGE):
143 -
wlan0: link becomes ready
144 -
Sep  3 20:38:28 raspberrypi dhcpcd[414]: wlan0: carrier acquired
145 -
Sep  3 20:38:28 raspberrypi dhcpcd[414]: wlan0: IAID eb:87:71:dc
146 -
Sep  3 20:38:28 raspberrypi dhcpcd[414]: wlan0: adding address fe80::997b:1be8:e6e0:f5c8
147 -
Sep  3 20:38:28 raspberrypi dhcpcd[414]: wlan0: soliciting a DHCP lease
148 -
Sep  3 20:38:29 raspberrypi dhcpcd[414]: wlan0: soliciting an IPv6 router
149 -
Sep  3 20:38:29 raspberrypi dhcpcd[414]: wlan0: offered 10.0.2.125 from 10.0.2.1
150 -
Sep  3 20:38:29 raspberrypi dhcpcd[414]: wlan0: probing address 10.0.2.125/24
151 -
Sep  3 20:38:30 raspberrypi avahi-daemon[318]: Joining mDNS multicast group on interface
152 -
wlan0.IPv6 with address fe80::997b:1be8:e6e0:f5c8.
153 -
Sep  3 20:38:30 raspberrypi avahi-daemon[318]: New relevant interface wlan0.IPv6 for mDNS.
154 -
Sep  3 20:38:30 raspberrypi avahi-daemon[318]: Registering new address record for
155 -
fe80::997b:1be8:e6e0:f5c8 on wlan0.*.
156 -
Sep  3 20:38:34 raspberrypi dhcpcd[414]: wlan0: leased 10.0.2.125 for 3600 seconds
157 -
Sep  3 20:38:34 raspberrypi avahi-daemon[318]: Joining mDNS multicast group on interface
158 -
wlan0.IPv4 with address 10.0.2.125.
159 -
Sep  3 20:38:34 raspberrypi avahi-daemon[318]: New relevant interface wlan0.IPv4 for mDNS.
160 -
Sep  3 20:38:34 raspberrypi dhcpcd[414]: wlan0: adding route to 10.0.2.0/24
161 -
Sep  3 20:38:34 raspberrypi avahi-daemon[318]: Registering new address record for
162 -
10.0.2.125 on wlan0.IPv4.
163 -
Sep  3 20:38:34 raspberrypi dhcpcd[414]: wlan0: adding default route via 10.0.2.1
164 -
```
165 -
166 -
Damit das ganze auch noch nach dem Start funktioniert auch noch systemd konfiguriert.
167 -
168 -
`vim /lib/systemd/system/wpa_supplicant@wlan0.service`
169 -
170 -
```
171 -
[Unit]
172 -
Description=WPA-Supplicant-Daemon (wlan0)
173 -
Requires=sys-subsystem-net-devices-wlan0.device
174 -
BindsTo=sys-subsystem-net-devices-wlan0.device
175 -
After=sys-subsystem-net-devices-wlan0.device
176 -
Before=network.target
177 -
Wants=network.target
178 -
179 -
[Service]
180 -
Type=simple
181 -
RemainAfterExit=yes
182 -
ExecStart=/sbin/wpa_supplicant -qq -c/etc/wpa_supplicant/wpa_supplicant.conf -Dnl80211
183 -
-iwlan0
184 -
Restart=on-failure
185 -
186 -
[Install]
187 -
Alias=multi-user.target.wants/wpa_supplicant@wlan0.service
188 -
```
189 -
190 -
Und anschliessend aktivieren:
191 -
192 -
```
193 -
# > systemctl daemon-reload
194 -
# > systemctl enable wpa_supplicant@wlan0.service
195 -
# > systemctl start wpa_supplicant@wlan0.service
196 -
# > reboot
197 -
```
198 -
199 -
Das Netzwerkkabel entfernt und der RaspberryPi kam wieder über WiFi online.
200 -
Per SSH eingeloggt und den Rest gemacht. User pi deaktiviert, neuen User angelegt und weitere Software installiert.
201 -
Das was man halt so üblicherweise macht um den PI Safe und fertig zu bekommen.
202 -
203 -
Um das WiFi Password nicht im Klartext in der Konfiguration zu haben:
204 -
205 -
```
206 -
# > wpa_passphrase "WLAN-NAME" "123412341234" | grep -v "#"
207 -
network={
208 -
	ssid="WLAN-NAME"
209 -
	psk=c6e5b342b0bc6fe1aff18ee420ee5adbed3e8bfa1a7d5da9a7c7585fe0446fc0
210 -
}
211 -
# also:
212 -
# > wpa_passphrase "WLAN-NAME" "123412341234" | grep -v "#" >> \
213 -
/etc/wpa_supplicant/wpa_supplicant.conf
214 -
```
215 -
216 -
Wer WiFi schon bei der Headless Installation konfigurieren möchte lege die Datei
217 -
`wpa_supplicant.conf` einfach in das `/boot` Verzeichnis der SD-Card vor dem ersten Start.
218 -
219 -
```
220 -
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
221 -
ap_scan=1
222 -
update_config=1
223 -
country=DE
224 -
network={
225 -
	ssid="WLAN-NAME"
226 -
  psk=c6e5b342b0bc6fe1aff18ee420ee5adbed3e8bfa1a7d5da9a7c7585fe0446fc0
227 -
}
228 -
```
229 -
230 -
Dann ist WiFi auch nach der Installation sofort fertig konfiguriert.
231 -
232 -
# Power Management ausschalten
233 -
234 -
Da der RaspberryPi das WiFi Interface nicht abschalten soll muss noch das Power-Management
235 -
ausgeschaltet werden.
236 -
237 -
```
238 -
# > iwconfig wlan0 | grep Power
239 -
          Bit Rate=135 Mb/s   Tx-Power=31 dBm
240 -
          Power Management:on
241 -
```
242 -
243 -
Dazu in der Datei `/etc/rc.local` einfach vor dem `exit 0;` folgendes hinzufügen:
244 -
245 -
```
246 -
iwconfig wlan0 power off
247 -
```
248 -
249 -
Nach dem Reboot sollte auch das Power-Management ausgeschaltet sein:
250 -
251 -
```
252 -
> # iwconfig wlan0 | grep Power
253 -
          Bit Rate=135 Mb/s   Tx-Power=31 dBm
254 -
          Power Management:off
255 -
```
256 -
257 -
258 -
gelöscht content/2021-10-21-safari-nervige-cookiebanner-automatisch-schliessen.md
+0 −41
@@ -1,41 +0,0 @@
1 -
---
2 -
title: "Safari: Nervige Cookiebanner automatisch schliessen"
3 -
date: 2021-10-21 08:00:00
4 -
lastmod: 2021-10-21 08:00:00
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
  - iOS
9 -
  - MacOS
10 -
  - Safari
11 -
  - Erweiterung
12 -
  - Consent
13 -
  - Cookiebanner
14 -
  - Cookie
15 -
preview: "Beim surfen werden wir ja den ganzen Tag von nervigen DSGVO-Banner, Cookiebanner, Consentbanner belästigt und klicken sie weg."
16 -
categories: 
17 -
  - Internet
18 -
toc: false
19 -
hide: false
20 -
type: post
21 -
draft: false
22 -
---
23 -
24 -
25 -
Beim surfen werden wir ja den ganzen Tag von nervigen DSGVO-Banner, Cookiebanner,
26 -
Consentbanner belästigt und klicken sie weg.
27 -
Oft werden Voreinstellungen gesetzt, die mehr erlauben als wir möchten. Zusätzlich
28 -
werden diese Banner optisch so gestaltet, damit wir ja "Alles akzeptieren", oft grün, anklicken.
29 -
Der Button "Nur notwendige" ist oft grau.
30 -
31 -
Mit der Safari Erweiterung "Super Agent for Safari" [Mac App Store)](https://apps.apple.com/de/app/super-agent-for-safari/id1568262835) (Universal App für MacOS und iOS) kann man einfach diese nervigen Banner automatisch schliessen lassen.
32 -
33 -
In den Cookie Settings von Super Agent kann man einstellen welche Cookies akzeptiert bzw. nicht akzeptiert werden dürfen.
34 -
Im Dashboard wird angezeigt wie viele Seiten man schon besucht hat, wie viele Klicks gespart wurden und wieviel Zeit dadurch gewonnen wurde.
35 -
36 -
### Gallerie
37 -
38 -
![Super Agent Dashboard](/images/galleries/2021/10/safari-nervige-cookiebanner-automatisch-schliessen/01-super-agent-dashboard.webp)
39 -
40 -
![Super Agent Cookie Settings](/images/galleries/2021/10/safari-nervige-cookiebanner-automatisch-schliessen/02-super-agent-cookie-settings.webp)
41 -
gelöscht content/2022-06-27-DayTrek-167-udm-pro-ipv6.md
+0 −69
@@ -1,69 +0,0 @@
1 -
---
2 -
title: "DrayTek 167 UDM Pro IPv6"
3 -
date: 2022-06-27 12:00:00
4 -
lastmod: 2022-06-27 12:00:00
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
  - Ubiquiti
9 -
  - Unfiy
10 -
  - UDM
11 -
  - DreamMachine
12 -
  - DrayTek
13 -
  - Vigor
14 -
  - 167
15 -
  - IPv6
16 -
preview: "Der etwas längere Weg zu IPv6 am Draytek Vigor 167 und der Ubiquiti DreamMachine Pro."
17 -
categories: 
18 -
  - Internet
19 -
toc: false
20 -
hide: false
21 -
draft: false
22 -
type: post
23 -
---
24 -
25 -
26 -
Der etwas längere Weg zu IPv6 am Draytek Vigor 167 und der Ubiquiti DreamMachine Pro.
27 -
28 -
![Ubiquiti DreamMachine Pro](/images/posts/unifiy-pro.webp)
29 -
30 -
31 -
[Der Chris](https://twitter.com/lelei) hatte mich letztes Jahr auf die neue Firmware hingewiesen, in der
32 -
IPv6 funktionieren soll. Bei ihm hatte es auch an seinem Anschluss auch sofort geklappt.
33 -
34 -
Hier funktionierte es aber überhaupt nicht. Selbst alles mögliche aus Foren hatte keinen Erfolg.
35 -
IPv6 Prefix setzen, WAN/Lan IPv6 Firewall regeln und vieles mehr. Selbst VLAN7 in der DreamMachine ausschalten und von dem Vigor übernehmen lassen, oder anders herum. Nichts hat funktioniert.
36 -
37 -
Immer wieder nach neuem Update der UDM Firmware habe ich dann getestet und probiert. Bis dann in einem Forum in einem Beitrag auf ein Firmware Update für das DrayTek Vigor 176 Modem gibt, welche das Problem beheben sollte.
38 -
39 -
Und siehe da, mit der neuen Firmware Version ist jetzt auch eine IPv6 Adresse verfügbar. Aber man sieht sie nicht im Webinterface der DreamMachine. Aber die Seite [ipv6-test.com](https://ipv6-test.com) zeigt IPv4 und IPv6 an.
40 -
41 -
IPv6-Test.com zeigt aber erst einmal einen Score mit 18 von 20 an. Weil ICMP blockiert wird.
42 -
Das kann behoben werden indem man Firewall Rules dafür anlegt.
43 -
44 -
    Type: Internet v6 Local
45 -
    IPv6 Protocol: ICMPv6
46 -
    IPv6 ICMP Type Name: Any
47 -
    Action: Accept
48 -
49 -
    Type: Internet v6 Local
50 -
    IPv6 Protocol: IPv6-ICMP
51 -
    Match all protocols except for this: enable
52 -
53 -
Zusätzlich kann man jetzt auch die IPv6 Prefixe bei den internen Netzen hinzufügen.
54 -
55 -
    IPv6 Interface Type: Prefix Delegation
56 -
    Router Advertisement (RA): Enable
57 -
    RA Priority: high
58 -
    DHCPv6 Range start: ::2
59 -
    DHCPv6 Range stop: ::7d1
60 -
    DHCPv6/RDNSS DNS Control: auto
61 -
62 -
Diese Einstellungen einfach bei allen internen Netzen hinzufügen und jedes Netz bekommt seinen eigenen IPv6 Prefix.
63 -
64 -
Damit haben alle Clients IPv6 Adressen bekommen. Der nächste Schritt war dann auch für IPv4 DHCP über die DreamMachine zu machen. Das wurde bis jetzt immer von einem der beiden Ubiquiti EgdeRouterX SPF erledigt.
65 -
Netzbereiche eingetragen aktiviert und die DHCP Services im EgdeRouterX deaktiviert. Und dann auch gleich die interfaces deaktiviert.
66 -
67 -
Jetzt macht die DreamMachine DHCP, IPv6 und alles was sie auch schon vorher gemacht hatte.
68 -
69 -
DreamMachine, ein Träumchen. ;-)
gelöscht content/2022-07-02-Smarthome-ioBroker-Zigbee.md
+0 −129
@@ -1,129 +0,0 @@
1 -
---
2 -
title: "Smarthome ioBroker Zigbee"
3 -
date: 2022-07-02 10:45:00
4 -
lastmod: 2022-07-02 10:45:00
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
  - ZigBee
9 -
  - Gateway
10 -
  - RaspbeeII
11 -
  - Raspberry
12 -
  - Phoscon
13 -
  - ioBroker
14 -
preview: "Das Smarthome wurde eine zeitlang mit FHEM, HA-Bridge bzw. HomeBridge betrieben. Es lief auch recht lange sehr gut. Irgend wann wollte aber HA-Bridge nicht mehr funktionieren. Alle versuche, selbst komplette Neuinstallation konnte HA-Bridge nicht mehr zum laufen bewegen. HA-Bridge ist dann erst einmal rausgeflogen und die meisten Sachen wurde einige Zeit direkt über den Echo direkt angebunden."
15 -
categories: 
16 -
  - Internet
17 -
toc: false
18 -
hide: false
19 -
type: post
20 -
draft: false
21 -
---
22 -
23 -
## Smarthome
24 -
25 -
Das Smarthome wurde eine zeitlang mit FHEM, HA-Bridge bzw. HomeBridge betrieben. Es lief auch recht lange sehr gut. Irgend wann wollte aber HA-Bridge nicht mehr funktionieren. Alle versuche, selbst komplette Neuinstallation konnte HA-Bridge nicht mehr zum laufen bewegen. HA-Bridge ist dann erst einmal rausgeflogen und die meisten Sachen wurde einige Zeit direkt über den Echo direkt angebunden.
26 -
27 -
![ioBroker HABPanel Keller](/images/posts/ioBroker-keller.webp)
28 -
29 -
Funktioniert auch gut, aber man muss alles mögliche, was vorher über HA-Bridge oder FHEM gemacht wurde über Routinen erstellen.
30 -
Kann man machen, ist dann aber oft sehr sperrig.
31 -
32 -
Viele der vorher gemachten Dinge können aber überhaupt nicht abgebildet werden. Vor allem nicht so schnell und einfach wie vorher. In der Alexa App mal eine kleine Routine anlegen ok. Aber z.B. bestimmte Zustände von Lichtern, Steckdosen, Multimedia Geräten zum Beispiel in Abhängkeit von 1-n an-/abwesenden Personen, ist sehr aufwändig bis gar nicht möglich.
33 -
34 -
## HomeAssistant kennengelernt
35 -
36 -
Vor ein paar Monaten habe ich dann bei einem Bekannten ein HomeAssistant (HA) migriert und konnte da mal ein wenig reingucken. Das hat mich natürlich wieder getriggert. Also habe ich mir HA einmal etwas angeguckt. Da ich aber hier keinen großen Server hinstellen möchte für ein "bisschen" SmartHome und HA offiziell nicht mit Docker supported wird, hatte sich das leider erledigt.
37 -
38 -
Also noch einmal nach HA-Bridge und anderen Alternativen geschaut. Dabei dann auch mal einen genaueren Blick auf ioBroker geworfen. Die Installation war schon mal sehr simple und schnell erledigt.
39 -
40 -
![ioBroker HABPanel Wohnzimmer](/images/posts/ioBroker-wohnzimmer.webp)
41 -
42 -
## ioBroker installieren
43 -
44 -
Das Raspbian auf eine SD-Karte schmeißen und anschliessend ioBroker installieren:
45 -
46 -
    curl -sL https://iobroker.net/install.sh | bash -
47 -
48 -
Dieser Befehl startet die gesamte ioBroker-Installation.
49 -
Am Ende der Installation wird dir die URL angezeigt, wie der ioBroker zu erreichen ist.
50 -
51 -
Aufrufen von ioBroker über die Web-Oberfläche
52 -
53 -
Gehe an deinen PC/Mac und öffne die Adresse, die am Ende des Setups zu sehen war. Folge den Anweisungen im ioBroker (Lizenzbestimmungen, Grundeinstellungen)
54 -
55 -
Passwortänderung des Benutzers “pi”
56 -
57 -
Das war es dann schon.
58 -
59 -
Im ioBroker kann man sich dann erst einmal umschauen und sich einen Überlick verschaffen was ioBroker überhaupt alles kann. Und das ist eine Menge. Auch hier wie immer erst einmal alles möglich getestet und ausprobiert.
60 -
61 -
## ioBroker Adapter
62 -
63 -
Bei ioBroker nennen sich zusätzliche Tools und Anbindungen an z.B. Alexa, VW-Coonect usw. Adapter.
64 -
65 -
Für mich natürlich interessant Alexa, VW-Connect, Adapter für die Visualisierung und viele andere mehr.
66 -
67 -
### Smarthome: Alexa2 Adapter.
68 -
69 -
Der Alexa2 Adapter sorgt nicht nur dafür um Smarte Geräte im ioBroker hinzuzufügen und sie dann auf den Echo Devices zu finden. Man bekommt auch sehr viel Information über alle möglichen Alexa Geräte und über Geräte die noch über eine Alexa, bzw. den eingebauten Hub verbunden sind.
70 -
71 -
Man kann auch Sprachausgaben an Echo Geräte schicken. Und nicht nur Ankündigungen die erst durch "Alexa, habe ich neue Benachrichtigungen" ausgegeben werden. Sie können auch direkt ausgegegeben werden.
72 -
Anwendung dafür wäre z.B. eine smarte Türklingel, die ab 20 Uhr keine Töne mehr von sich gibt, sondern nur noch im Wohnzimmer eine Sprachausgabe macht. Oder per Sprache und/oder Textausgabe auf einem FireTV.
73 -
74 -
### VW-Connect
75 -
76 -
In der Fülle an Adapter ist mir dann der VW-Connect Adapter aufgefallen. Den habe ich direkt mal installiert und getestet. Da ich einen Skoda mit Skoda Connect und war sehr überrascht was man mit diesem Adapter alles machen kann. Von KM-Stand (Gesamt, letzte Fahrt), Verbrauch, bis zum Status aller Fenster/Türen (offen, geschlossen, verriegelt). Und vieles andere mehr.
77 -
78 -
In Verbindung mit Datenpunkten und eGraph können so auch schöne Graphen zu allen möglichen Daten erstellt werden.
79 -
Dazu aber mal in einem anderen Beitrag mehr Info.
80 -
81 -
### Weitere Adapter
82 -
83 -
Alle hier aktuell installierten Adapter einmal in einer Liste. Wie schon oben bei egraph geschrieben, werde ich in anderen Beiträgen bestimmt noch mal genauer auf einzelne Adapter eingehen.
84 -
85 -
Die Liste erhält man mit: `iobroker list adapters`
86 -
87 -
   * admin
88 -
   * alexa2
89 -
   * backitup
90 -
   * cloud
91 -
   * daswetter
92 -
   * deconz
93 -
   * devices
94 -
   * discovery
95 -
   * dwd
96 -
   * echarts
97 -
   * firetv
98 -
   * habpanel
99 -
   * history
100 -
   * hue
101 -
   * hue-extended
102 -
   * icons-open-icon-library-png:
103 -
   * iot
104 -
   * javascript
105 -
   * net-tools
106 -
   * openweathermap
107 -
   * pi-hole
108 -
   * ping
109 -
   * smartthings
110 -
   * socketio
111 -
   * synology
112 -
   * tado
113 -
   * time-switch
114 -
   * unifi
115 -
   * vis
116 -
   * vis-weather
117 -
   * vw-connect
118 -
   * web
119 -
   * ws
120 -
   * yahka
121 -
122 -
### Wichtigsten Adapter
123 -
124 -
Die für mich erst einmal wichtigsten Adapter sind Alexa2, deConz ZigBee, HABpanel, Philips Hue-Bridge und Extended, Javascript, Pi-Hole, Samsung Smartthings, Tado, Unifiy Network.
125 -
Damit konnten dann alle Smarthome Geräte eingebunden, gesteuert und mit den JavaScript Adapter umfangreich programmiert werden.
126 -
127 -
Die Adapter DeConz und habpanel sind für das im [letzten Artikel](/posts/2022-06-29-zigbee-gateway-raspbee-ii/) erwähnte ZigBee Gateway und für die Viualisierung der einzelnen Räume auf dem jeweiligen Tablet an der Wand. Zu den Tablets in den Räumen mit der jeweiligen Ansicht der Geräte und einer View für Multimedia werde ich auch noch einen Artikel schreiben.
128 -
129 -
![ioBroker HABPanel Küche](/images/posts/ioBroker-kueche.webp)
gelöscht content/2022-07-04-Fremde-Geräte-im-Wifi.md
+0 −88
@@ -1,88 +0,0 @@
1 -
---
2 -
title: "Fremde Geräte im Wifi"
3 -
date: 2022-07-04 10:00:00
4 -
lastmod: 2022-07-04 10:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2019/08/03/network.webp"
7 -
tags:
8 -
  - Router
9 -
  - Wifi
10 -
  - WLAN
11 -
preview: "Fremde Geräte im WLAN? Chip.de, Telekom.de, pcwelt.de und ihre Tipps beim Thema WLAN. Es ist zum Haare raufen. Bei manchen Artikeln fast man sich nur noch an den Kopf und will eine Aspirin einwerfen."
12 -
categories: 
13 -
  - Internet
14 -
toc: false
15 -
hide: false
16 -
type: post 
17 -
draft: false
18 -
---
19 -
20 -
Fremde Geräte im WLAN?
21 -
22 -
Chip.de, Telekom.de, pcwelt.de und ihre Tipps beim Thema WLAN. Es ist zum Haare raufen. Bei manchen Artikeln fast man sich nur noch an den Kopf und will eine Aspirin einwerfen.
23 -
24 -
Ja, nutzt jemand das WiFi unberechtigt kann es zu einer langsamen Internetverbindung führen. Oder im schlimmsten Fall zu rechtlichen Problemen kommen. Dann, wenn jemand illegales Zeug mit dem Internetanschluss macht.
25 -
26 -
Aber was bitte werden in den Artikeln für Tipps gegeben? Es fängt damit an, daß man vielleicht vermutet jemand ist im WiFi und dann wird anhand vom Router erklärt wie man so einen Benutzer dort findet. Es stimmt das sehr viele wahrscheinlich eine Fritzbox haben. Also wird es anhand der Weboberfläche der Fritzbox erklärt. Nur was machen bitte alle Kunden der Telekom, die einen Speedport Router haben. Oder Netgear, TP-Link usw.?
27 -
28 -
Also, hat man den Verdacht, es befindet sich ein unbefugter Benutzer in WiFi, dann ist die Lösung sehr kurz und Knapp: Änder Dein WiFi-Passwort. Punkt.
29 -
30 -
Damit wäre jeder Artikel in 2-3 Sätzen schon erledigt. Aber das wichtigste fehlt in allen dieser Artikel. Keiner geht drauf ein was man sonst noch machen könnte. Es wird eigentlich in allen immer nur geraten den MAC-Adressen Filter zu aktivieren.
31 -
32 -
Damit, mit den Mac-Filter, dann auch viel Spaß. Denn z.B. iOS/iPadOS (Apple)  und auch einige Andoid Geräte haben die Möglichkeit die MAC-Adressen zu verschleiern. Bei Apple heißt es in den WLAN Einstellungen „Private WLAN-Adresse“. Das ist eigentlich als Standard immer aktiv.
33 -
34 -
Was heißt das genau?
35 -
36 -
Jedes Gerät hat bei Bluetooth und Netzwerkschnittstellen (Kabel oder WiFi) immer eine weltweit eindeutige MAC-Adresse, über die es identifizierbar ist. Im Heimnetzwerk und in Firmen bekommt jedes Gerät meistens seine IP beim Verbinden von einem DHCP-Server zugewiesen. Dazu sendet das Gerät die Anfrage für eine IP ins Netzwerk. In dieser Anfrage ist die Mac-Adresse enthalten. Die IP-Adressen werden aus einem Pool genommen und entsprechend eine freie an das Gerät vergeben. Verlässt man das Netzwerk oder schaltet das Gerät aus, geht dann nach kurzer Zeit wieder in Netzwerk, bekommt man meistens die gleiche IP zugewiesen.
37 -
Oft kann man sich trotz DHCP in den meisten Routern auch immer die gleiche IP Adresse geben lassen, indem man dem Gerät im Router die IP fest zuweisen kann.
38 -
39 -
Dabei wird immer die MAC-Adresse herangezogen. Wir erinnern uns an die Anfrage mit der Mac-Adresse weiter oben.
40 -
41 -
Jetzt aktivieren wir aber an einem iPhone „Private WLAN-Adresse“ und erhalten damit jedes mal sogar eine andere MAC-Adresse. Entsprechend ist das Gerät auch noch für den Router und dem darauf laufenden DHCP-Server ein neues Gerät. Also bekommen wir jedesmal eine andere IP-Adresse im Netzwerk.
42 -
43 -
Und jetzt schlägt dann der „Pro-Tipp“ großer IT Bereiche mancher Portale zu.
44 -
Die Empfehlung den MAC-Adressenfilter zu aktivieren.
45 -
Da sitzt jetzt der nicht Internet-Pro an seinem iPhone und macht sich Sorgen um sein WiFi. Irgend etwas stimmt damit nicht. Kommt jetzt auf einen der Artikel und in ihm kommt etwas Angst auf beim lesen. „Es könnte jemand Dein Netzwerk benutzen“. MAC-Adressenfilter aktivieren, super wird gemacht. Verstanden wozu und was er damit macht, keine Ahnung. Wird schon richtig sein. Es funktioniert auch prima, da der Filter aktiviert werden kann und sein iPhone, so wie das Gerät der Holden auch schön in der Liste eingetragen sind.
46 -
47 -
Bis er dann sein Gerät einige Zeit nicht mehr an hatte. Es lag aus auf dem Tisch. iPhone entsperren und surf…..
48 -
Es bleibt offline, keine App kann sich verbinden, keine Internetseite funktioniert mehr. Die Frau kann aber noch alles machen, sie war die ganze Zeit am Telefon.
49 -
Würde man jetzt mit dem noch funktionierenden Gerät auf dem Router noch mal den MAC-Adressenfilter überprüfen, würde man sehen:
50 -
   * Sein Gerät ist offline
51 -
   * Ein neues Gerät versucht zu verbinden, wird aber geblockt. 
52 -
   * Das „neue“ Gerät ist aber sein Gerät.
53 -
54 -
Da „Private WLAN-Adresse“ aktiv ist, hat er jedesmal eine neue MAC-Adresse. Daher ist es für den Router und seinen Mac-Adressenfilter auch jedesmal ein neues Gerät.
55 -
56 -
Im Normalfall geht der unbedarfte Benutzer nicht hin und deaktiviert den Filter jetzt oder fügt das „neue“ Gerät im Filter hinzu. Am besten deaktiviert er „Private WLAN-Adresse“ im iPhone.
57 -
58 -
Nein, es klappt bei Ihr und nicht mehr bei ihm. Also scheint wohl irgend etwas am WLAN zu sein. Also: „ich starte mal den Router neu, vielleicht geht es ja dann wieder.“
59 -
60 -
Der Supergau tritt ein. Ab jetzt, also der Fall wie er heutzutage oft üblich ist, wenn es nur noch Smartphone und/oder Tablets im Haushalt gibt, kommt kein Gerät mehr in das WiFi rein.
61 -
Alle haben die Einstellung für die „Private WLAN-Adresse“ aktiviert. Der MAC-Adressenfilter ist aktiv und sagt jetzt zu jedem Gerät: „ich kenn Dich nicht, du kommst hier nicht rein.
62 -
63 -
Und jetzt wird es für die beiden spaßig. Die kommen in Ihr WiFi nicht mehr rein. Sie können jetzt auch nicht mehr den Filter deaktivieren. Sie müssen das mit einem Laptop machen der mit einem Kabel an den Router angeschlossen wird.
64 -
Und selbst wenn sie den haben wird das für die meisten ein schwieriges Unterfangen. Denn oft wissen sie nicht mal die IP von ihrem Router.
65 -
66 -
Und alles nur weil man Probleme mit dem WiFi hatte. Auf ein paar Seiten nach der Lösung geguckt hat und dabei dann die Panik wegen fremden Nutzern aufkam. Dann der Tipp mit dem Mac-Adressenfilter, der heutzutage nicht nur unwillkommene Benutzer aussperrt, sondern direkt alle. Auch die, die rein dürfen, besser gesagt bis dahin durften.
67 -
68 -
Sollte ein WiFi langsam sein oder es öfters zu Abbrüchen kommen, ist es in den aller meisten Fällen kein fremder Benutzer. Das wird in sehr, wirklich sehr wenigen Fällen die Ursache sein.
69 -
In den meisten Fällen sind es bescheidene WiFi Router, die von der Hardware und Software nicht die tollsten Geräte sind.
70 -
Auch immer störend,
71 -
gerade in Städten, sind viele andere WiFi-Netzwerke, die sich die Frequenzen teilen und sich so gegenseitig stören.
72 -
Oder andere Geräte in der eigenen Wohnung und sehr oft der falsche Standort. Oft reicht es den Router nur etwas anders zu positionieren. Die meisten haben gefühlt ihre Router auf Hüfthöhe auf der Komode oder im schlimmsten Fall dahinter. Sieht ja nicht toll aus die Box. Einfach mal nach oben an die Wand hängen. Wirkt oft Wunder.
73 -
74 -
Aber was wäre wenn man sich jetzt einmal wirklich nicht sicher ist, ob nicht doch jemand einfach das WiFi mit benutzt? Wie oben beschrieben hilft da einfach am besten das WiFi Passwort zu ändern. Wer
75 -
möchte kann sich ja gerne die verbundene Geräte einmal auf dem Router angucken. Vielleicht hat ja doch jemand das WiFi Passwort erraten oder woher sich immer.
76 -
Aber wenn man sich unsicher ist, wie bei allen anderen Sachen auch: Passwort ändern.
77 -
78 -
Alles andere ist unnötig und kann zu mehr Problemen führen.
79 -
80 -
Wer das Passwort ändert und nicht auf anderen Geräten mühsam eingeben möchte:
81 -
   * iPhone und iPad können WiFi Passwörter teilen. Ein anderes Gerät will verbinden und ein anderen, welches schon damit verbunden ist kriegt eine Meldung und kann es dann einfach per antippen teilen.
82 -
   * Falls andere Geräte sich verbinden sollen kann man auch einfach einen QR-Code für WiFi-Name und WiFi-Passwort erstellen.
83 -
84 -
Bei der Wahl des WiFi-Passworts nicht sparsam sein. Es sollte schon sehr sicher sein. Man gibt es ja auch nicht jeden Tag ein. Es wird ja auch gespeichert.
85 -
Also ruhig auch mal nach Monaten oder 1-2 Jahren auch mal wieder ändern.
86 -
Gerade wenn man einen Router zum ersten Mal eingerichtet hat, ändern.
87 -
Oft sind die WiFi-Passwörter recht einfach. Teilweise haben manche Hersteller einfach die MAC-Adresse des Routers genommen. Oder die MAC-Adresse mit eigenen Tools in eine WiFi-Passwort umgewandelt. Was aber unsicher war und so von fremden schnell selbst berechnet werden konnte.
88 -
Also immer ruhig das WiFi-Passwort selbst einmal ändern.
gelöscht content/2022-08-12-motorrad-alpen-3218km-7-laender.md
+0 −141
@@ -1,141 +0,0 @@
1 -
---
2 -
title: "Motorradtour Alpen 3218km 7 Länder"
3 -
date: 2022-08-12 08:00:00
4 -
update: 2022-08-12 08:00:00
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
    - Motorrad
9 -
    - Tour
10 -
    - Alpen
11 -
    - Deutschland
12 -
    - Schweiz
13 -
    - Frankreich
14 -
    - Italien
15 -
    - Luxemburg
16 -
    - Belgien
17 -
    - Niederlande
18 -
preview: "Was für eine Tour. Das Wetter war perfekt, bis auf 2 Tage. An einem Tag hat es geregnet und an dem anderen war es sehr warm. Die 39-40 Grad waren schon sehr anstrengend, aber dank dem Stadler Textilkombi noch erträglich. Einfach mehr Pausen und trinken."
19 -
categories: 
20 -
    - Motorrad
21 -
toc: false
22 -
hide: true
23 -
draft: true
24 -
---
25 -
26 -
Was für eine Tour. Das Wetter war perfekt, bis auf 2 Tage. An einem Tag hat es geregnet und an dem anderen war es sehr warm. Die 39-40 Grad waren schon sehr anstrengend, aber dank dem Stadler Textilkombi noch erträglich. Einfach mehr Pausen und trinken.
27 -
28 -
Die Tour Zusammengefasst und ein paar Eckpunkte:
29 -
30 -
   * 16 Tage
31 -
   * 3.218 Kilometer
32 -
   * 7 Länder
33 -
   * 45 Steps
34 -
   * 201 Photos
35 -
   * 15 Hotels
36 -
37 -
Erst einmal grob die Strecke. Ziel ist sind die Alpen gewesen. Der erste Step ging also Richtung Karlsruhe, wo dann auch gleich der erste Halt gemacht wurde. Da konnte ich dann auch einen alten Arbeitskollegen von 1&1 treffen. Wo möglich sollte man solche Treffen auch gleich mit einbinden.
38 -
Von Karlsruhe ging es dann auch weiter Richtung Tuttlingen und zwar ins Bährental. Auch dort war ein kurzer Besuch und die nächste Hotelübernachtung geplant. Bährental deswegen, da eine Bekannte dort ein Restaurant hat. Vegane Küche, sehr lecker und hatte von anderen Bekannten vorher immer sehr viel Schwärmerei vom Essen gehört.
39 -
Von Tuttlingen ging es dann weiter zum nächsten Stop kurz vor der Grenze zur Schweiz und Frankreich. Auch hier waren kurze Stops für Besuche eingeplant.
40 -
41 -
Bis zum vorletzte Tag war es das mit den Besuchen dann auch erst einmal. Es ging weiter über Frankreich und kurze Stecken Schweiz weiter in den Süden. Kurze Strecken Schweiz, weil auf der Route eine Straße mit vielen Kurven alle paar 100 Meter ein Schild gestanden hat. Entweder stand dort Frankreich oder Schweiz drauf.
42 -
Das erste Stück in Frankreich war erst einmal nicht so prickelnd. Es waren ca. 13 Kilometer neue Strasse. Jetzt fragt sich vielleicht der ein oder andere wieso das nicht super war. Es lag noch Rollsplit und das nicht gerade wenig. Dort dann 13 Kilometer fahren war nicht gerade Spass und eher sehr anstrengend.
43 -
44 -
Aber danach ging es viel entspannter weiter. Mit jedem Kilometer wurde die Landschaft immer bergiger und immer öfters bin ich näher den Strecken gekommen die Kurven und Serpentinen brachten.
45 -
Über Pontarlier, dann Genf und Bonneville nach Magland waren dann die nächsten Steps. Pontarlier und Magland sind dann auch Steps gewesen mit Übernachtungen. Da das Wetter bis dahin super gewesen ist, war es auch bis dahin sehr schon die Strecken zufahren.
46 -
47 -
Magland war der Step mit Übernachtung vor den ersten großen Pässen in den Alpen. Am nächten Tag war aber Regen angesagt. Wieso die Pässe bei Regen fahren? Von den Motorradsachen die ich anhatte kein Problem. Aber bei Nässe fährt man halt nicht so wie man es eigentlich möchte. Auch kenne ich die Gegend dort nicht und konnte gar nicht einschätzen was Regen dort oben heisst. Man kennt es ja aus dem Bergischen Land hier hin und wieder wie die Strassen nach einem Regentag öfters mal aussehen. Nach oder gar in jeder Kurve könnte Schotter und Dreck liegen. Das macht keinen Spaß und man will im Urlaub auf so einer Tour auch nichts riskieren.
48 -
49 -
Der Step in Magland wurde daher auch der einzige mit 2 Übernachtungen. Auch weil ich nicht 1300 km fahre, für die Alpen und Pässe, um dann bei Regen und verdreckten Strassen durch die Kurven zu schleichen. Nö dann besser mal einen Tag im trockenen und auch gleich mal mehr planen wo es weiter hin geht.
50 -
51 -
Der Halt in Magland war auch wegen der Unterkunft sehr schön. Ein super Hotel, mit einem noch besseren Restaurant. Aber die Übernachtung war nicht im Hotel, sondern in einer kleinen schnuckeligen Holzhütte.
52 -
Da könnte man dann den Regentag auch sehr gut aushalten. Es hatte dann auch geregnet, aber wie gehofft nur vormittags ein wenig. Unterm Dach für der Hütte im Regen gesessen und auf den Berg gegenüber geguckt. Was dann auch dafür gesorgt hat mal auf dem iPhone zu gucken was auf dem Berg so alles ist und wie man dort hinkommen könnte. Wenn ich schon von unten den Berg sehe, dann kann man vielleicht auch eine Stelle finden an der man die Hütte sieht.
53 -
54 -
Geplant, getan. Nachdem es aufgehört hat zu regnen, Motorradsachen angezogen und dort einmal hochgefahren. Die Stelle von der man die Hütte dann auch sehen konnte wurde auch gefunden. Wieder runter und auf der anderen Seite, dem Berg hinter der Hütte, hoch. Dort war auch ein kleiner Pass und die Auffahrt bzw. danach auch die Abfahrt, wurde mit einigen Serpentinen belohnt.
55 -
56 -
Die zweite Nacht in der Hütte übernachtet und am nächsten Tag wieder super Wetter. Also konnten die ersten beiden größeren Pässe angegangen werden. Es ging von Magland über Vallorcine und Champex nach Martigny, wobei zwischen Vallorcine und Martigny der erste Pass ist. Bei der Planung mit Calimoto war die Strecke schon sehr gut. Ich hatte dann aber gesehen das es ab zirka der Mitte rechts von der Strecke weitere Serpentinen gibt. Die wurden dann gleich mit eingeplant. Da die Strecke sehr gut ausgebaut ist war sie aach gut zu fahren. Aber der Abstecher über die weiteren Serpentinen war eine gute Entscheidung. Alles fuhr die gut ausgebaute Strasse nach oben. Autos waren in den Kurven oft sehr langsam. Nach dem Abbiegen von der Hauptstrecke war die Strasse leer und Kurven konnten einfach geschmeidig gefahren werden, ohne das man wegen PKWs vorher noch abbremsen muss.
57 -
58 -
Da ich die Übernachtungen immer wieder erwähne, aber noch nicht viel auf das Thema eingegangen bin: Das werde ich noch ausgiebiger machen. Die ganzen Highlight müssen erwähnt werden. Aber auch die 1-2 Unterkünfte die aus verschiedenen Gründen nicht so toll waren. Dort was es ok, aber es gab bei diesen zwei Unterkünften halt Punkte die nicht so gut angekommen sind.
59 -
Auch das Thema Calimoto, der Motorrad Navigations App, werde ich noch mal aufgreifen. In den Touren letztes Jahr und der Tour vor dieser Alpentour sind immer wieder Sachen aufgefallen die einfach nur unverständlich sind. Das verstehe ich bei einer App für so einen Preis einfach nicht.
60 -
61 -
Aber weiter zu Tour. Es ging direkt von Martigny weiter zum nächsten Pass. Und zwar dem zum grossen Sankt Bernhard. 2473 Meter hoch und dort war es dann auch gleich etwas frischer. Der erste Halt dort, für Fotos, war dann auch wieder einer in der Schweiz (Bourg-Saint-Pierre). Und 2 Minuten Später dann wieder auf der italienischen Seite (Saint-Rhémy-En-Bosses).
62 -
63 -
Die Aussicht war einfach schön. Muss man mal gesehen haben. Mit Blick auf den Mont Blanc. Da kann man sich auch mal einen Kaffee dort gönnen und den Ausblick geniessen, bevor es dann weiter geht Richtung Aosta. Oben war es frisch und windig, aber es war trotzdem sehr gutes Wetter. Kurz danach, nach einigen schönen Serpentinen, ein paar Kilometern und ein paar Höhenmeter weiter unten war es dann wieder viel wärmer.
64 -
Der Blick auf die Uhr zeigte das es gar nicht so spät ist. An manchen Tagen schafft man die geplanten Kilometer nicht und an manchen Tagen kommt man viel weiter als geplant. Macht ja nichts, es ist kein Hotel vorher gebucht, sondern wird immer erst an dem Tag selbst gesucht und gebucht. Also Zeit ist noch, also kann man noch den 3. Pass mitnehmen. Ziel war der kleine Sankt Bernhard.
65 -
66 -
Also das gleiche Spiel noch mal mit dem 3. Pass des Tages. Eine Seite Italien und andere Seite ist dann Frankreich. Der Stop mit Übernachtung war eigentlich für Italien geplant, wurde nichts draus, daher wieder in Frankreich. Ist aber auch nicht schlimm, dafür mehr und viele weiteren Kurven gefahren. Höhe übrigens 2188km.
67 -
68 -
Nach dem 3. Pass über den kleinen Sankt Bernhard in Séez angekommen wieder in kleines Hotel erwischt. Das war auch eines der Highlights. Nicht wegen dem Hotel, sondern auch hier wieder wegen dem Restaurant und den Menschen die es betreiben und dort arbeiten. Es war einfach gemütlich und man hat gemerkt das wieder Inhaber ihr Ding machen, dabei Spaß haben und einfach super nett sind.
69 -
70 -
Von Séez aus ging es dann über Bonneval-sur-Arc zum höchsten befahrbaren Pass der Alpen. Col de L´Iseran, mit einer Höhe von 2770 Meter. Das es der höchste befahrbare Pass ist, hatte ich aber erst später gelesen als ich später im Hotel in Lanslevillard noch mal im Internet nachgeguckt hatte. Das Hotel in Lanslevillard war auch wieder sehr gut. Restaurant war super, aber auch hier wieder ein paar Sachen die es noch besser gemacht hatten.
71 -
Es wurde direkt bemerkt das man mit dem Motorradtour unterwegs ist. Sofort wurde erklärt das man einfach bis zur nächsten Strassenecke fahren soll, dort dann 2 mal links, hinter das Hotel fahren kann und das Motorrad dort in der Garage parken soll. Aber auch der Service im Restaurant. Perfekt eingespieltes Team und der Laden war super organisiert. Aber dabei sind sie sehr freundlich miteinander umgegangen. War schön anzusehen das ein organisierter Service nichts mit Stress und ruppigen Umgangston zutun haben muss.
72 -
73 -
Ach so, wenn man von Séez nach Lanslevillard fährt, dann kommt keine 5 km nach Séez noch eine Möglichkeit anzuhalten. Dort ist auch ein See, der einfach wünderschön ist. Die Farbe des Wassers, einfach ein perfekter Anblick. Kurz danach geht es kleine Strasse nach oben mit reichlich Serpentinen und oben angekommen kann man den gleichen Anblick auch noch einmal aus einer anderen Perspektive geniessen. Wer da nicht anhalten und nicht angucken möchte, mit dem Stimmt etwas nicht. Man muss ja nicht andauernd Pause machen, aber wenn man schon mal so eine Tour macht sollten Stops für Fotos oder einfach nur mal angucken drin sein.
74 -
75 -
Weiter ging es am nächsten Tag von Lanslevillard, über Fourneaux nach Montgellafrey, also Col de la Madeleine. Höhe hier glatte 2000 Meter. Der Stop dort war so naja. Die Bedienung war nach dem hinsetzen schnell am Tisch und die Getränke kamen auch prompt. Nur war dann noch die Überlegung etwas zu essen oder ein Eis bzw. Sorbet zu bestellen. Aber es kam dann keiner, auch nicht wenn man es deutlich zeigte. Das ging aber auch anderen so. Manche Blicke und wenn deutsche etwas sagten könnte man verstehen das sie das auch etwas strange gefunden haben. Die Bedienungen haben eher weg oder auf den Boden geguckt, als auf die Gäste zu achten. War jetzt nur ein Pausen Step, aber wenn man das als Mittagessen Stop geplant hätte, wäre das sehr enttäuschend gewesen.
76 -
77 -
78 -
Die Gesamte Strecke war an diesem Tag 280 Kilometer bis nach Saint-Pierre-En-Faucigny. An den Amaturen war auf Step 1 gestellt um die Gesamtkilometer zu sehen. Irgendwann habe ich dann mal auf Step 2 umgestellt, der die Kilometer seit dem letzen Tankstop anzeigt. Ok, 230 Kilometer, es wird Zeit zu tanken. Das war knapp, da es kurz vor Reserve war und Tankstellen auf den Pääsen eher weniger zu finden sind. Kurzer Stop in Saint-Nicolas-La-Chapelle, tanken und wichtig bei dem Wetter, trinken.
79 -
Das letzte Stück nach Saint-Pierre-En-Faucigny war eine sehr schöne Strecke. Gerade wenn man aus den Alpen kommt stellt man fest das Strecken die kurvig sind im Vergleich zu den Alpen eher "langweilig" sind. Aber das letzte Stück war mit vielen schönen Kurven und teilweise so regelmässig das es sich wie Slalom fahren.
80 -
81 -
Das Hotel in Saint-Pierre-En-Faucigny war schön, sehr gut ausgestattet. Aber es war das erste Hotel, welches nicht so gebucht wurde wie die anderen davor und war eher sehr unpersönlich. Rezeption war erst einmal keiner zu finden. Man fragte nach Frühstück aber nicht ob man nachher noch ins Restaurant möchte. Dafür kam dann nach einer 1/2 Stunde der Anruf auf dem Zimmer. Es ist kein Platz mehr im Restarant, man sie ausgebucht. Empfehlung war ein Restaurant keine 100 Meter vom Hotel. Auf Google und anderen Seiten nachgeguckt, es war ein Steakhaus. Ok, das passte und wäre ok gewesen. Nur gab es im Internet verschiedene Informationen. Manchmal war es offen, auf anderen Seiten stand "Montags geschlossen". Wie bei einigen anderen Restaurants in der Nähe, die waren fast alle montags geschlossen. Das war auch bei dem Steakhaus wirklich so. Es hatte zu und alles andere ist weiter weg. Gerade mit Motorrad nicht gerade schön. Wieder anziehen und dann noch mal los, in Motorradsachen essen gehen, nicht gerade das was man will. Eigentlich will man ins Hotel, duschen und umziehen, dann einfach runter und gemütlich den Tag ausklingen lassen.
82 -
Also zurück ins Hotel und dort bescheid geben und nach einer guten Alternative fragen. Man kennt sich nicht aus und will dann auch nicht in einer billigen Pommesbude landen oder noch lange etwas suchen was offen hat. Die Reaktion war dann aber nicht so wie erwartet. Ich glaube in den anderen Hotels vorher wäre das so nicht passiert.
83 -
Die Laune ging etwas in den Keller und ich dachte mir dann: "Nö, das habt Ihr jetzt verbockt. Andere Reaktion, dann hätte ich jetzt auch eine gute Alternative akzeptiert." Das wurde dann wohl auch an der Reaktion bemerkt und man telefonierte mit dem Manager. Der gab grünes Licht und auf einmal war es möglich doch noch einen Tisch im Restaurant zu gekommen. Aber das war noch alles. Man musste dann noch an dem Restaurantmanager vorbei. Und der reagierte recht unfreundlich und sehr überheblich. Da ist man kurz davor wieder zur Rezeption zu gehen, um denen mitzuteilen das man die Kreditkarte jetzt für sie sperren wird und das Hotel sofort wieder verlässt.
84 -
Das ganze war leider etwas enttäuschend.
85 -
Aber wieso sich den Urlaub durch so etwas vermiesen lassen. Es gab dann am nächsten Tag noch einmal ein Hotel, welches auch noch mal gefailed hat. Es fing mit der Adresse an. In der Booking.com Mail war eine Adresse zu der navigiert wurde. Dort war das Hotel gar nicht. Auch Adressen die im Internet gefunden wurden passten nicht so recht. Da kam kurz die Frage auf ob das ganze ein Fake war und jetzt etwas Geld futsch ist. Aber das konnte sich dann doch noch klären und das Hotel wurde gefunden. Rezeption sollte bis 19 Uhr offen sein, aber war schon früher zu. Rufnummer nicht erreichbar usw. Aber dann kam doch noch jemand und es konnte eingechecked werden.
86 -
Urlaub deswegen vermiesen lassen? Nö, es waren nur die beiden, bei denen es etwas komisch und unfreundlich gewesen ist.
87 -
Die restlichen Hotels waren ja alle vollkommen ok.
88 -
89 -
Auf dem Weg wurde noch Halt in Desingy gemacht. Und zwar an Route du Chateau de Chatel. Da es sehr warm war unter Bäumen und etwas länge. Auch um zu gucken wo der nächste Supermarkt auf der Strecke liegt um dort dann Wassernachschub zu bekommen. Daher wurde es nach Divonne-les-Bains ins Hotel etwas später, aber noch pünktlich genug.
90 -
91 -
In Divonne-les-Bains wurde auch schnell geguckt was es dort an Restaurants gibt. In der City selbst gibt es eine Ecke an der es eigentlich alles gibt. Da wurde dann der Inder gewählt. Und der war echt der Hammer. Freundlich, das Essen super und vorallem ein Dip war der Burner. Einfach geniales Zeug. Als das Essen kam auch gleich erwähnt das der Dip einfach sehr sehr lecker ist. Prompt wurde noch ein Schälchen davon hingestellt. Das Lob war zwar nicht deswegen gemacht worden, aber das dann noch eins kam, da will man sich jetzt nicht beschweren.
92 -
93 -
Next Step: Schweiz, aber nur zum durchfahren. Aber ein kurzer Halt musste sein. Auch wegen dem Wetter, da es immer wärmer wurde. Dafür das die Rückfahrt schon wegen angesagtem Regenwetter eingeleitet war, hatte sich das Wetter noch sehr gut gewendet. Und es wurde noch richtig heiß. Der Halt in der Schweiß war eher spontan gewählt, da einfach ein Pause sein musste. Auch um etwas zu trinken.
94 -
Grandson liegt direkt an einem See und wo Wasser ist, ist es immer etwas kühler. Also wurde dort ein Camping angesteuert, auch um ggf. mal die Füße im Wasser baumeln zu lassen. Der Campingplatz hatte am Eingang auch einen Kiosk, Cafe und Restaurant. Dort konnte dann direkt etwas kühles getrunken werden und anschliessend ein Eis gegessen werden. Danach ging es dann mal kurz über den Campingplatz zum See. Da hat man dann auch mal gesehen wie schön der ist und vor allem was das für ein Wasser ist. Die Farbe und am Rand sehr klares Wasser. Wäre bestimmt auch mal ein super Ziel für einen längeren Aufenthalt, vielleicht auch mit segeln.
95 -
96 -
In Frankreich angekommen konnte auch dann direkt die nächste Tankstelle angefahren werden. Zur Not wäre das auch in der Schweiz möglich gewesen. Aber der Preisunterschied war schon nicht ohne. Hätte beim Motorradtank jetzt nicht unbedingt die Reisekasse gesprengt, aber wenn der Plan vor der Schweiz und nach der Schweiz zu tanken aufgeht, dann war der Plan gut.
97 -
98 -
Bis dahin hat mal schon gemerkt das es immer wärmer wird. Und es sollte noch wärmer werden. Auf dem Weg nach BaWü war es noch gut auszuhalten. In Efringen-Kirchen noch einmal einen Besuch abgestattet. Und die Nacht in Schallbach verbracht. Im gleichen Hotel wie schon bei der 2. Übernachtung. Das kennt man, das war gut, also einfach noch einmal dort übernachten.
99 -
100 -
Es ging, gerade weil das Wetter nicht ab Donnerstag mit dem angesagten Regen kam, sondern schön Sonne und Hitze, weiter zurück nach Frankreich. Der Plan Donnerstag wieder zurück zu sein wurde also wieder geändert. Die Rückfahrt am Donnerstag wäre eigentlich direkt nach Hause gewesen. Gerade weil es dann vielleicht nur das letzte Stück im Regen fahren gewesen wäre.
101 -
102 -
Dann änderte sich das Wetter und es ging weiter nach Steige und zum Ziel un Urmatt. Das war nicht das eigentliche Ziel, aber die 40 Grad entschuldigen das sehr gut. Das Hotel in Urmatt war auch wieder ein sehr liebevoll geführtes Hotel. Das Essen war prima. Auch hier würde ich eine klare Empfehlung geben.
103 -
104 -
Die 40 Grad waren auch für mich der Test von Textil. Ich war froh nicht im Lederkombi unterwegs zu sein. Anfang des Jahres wurde ein neuer Textilkombi nötig. Da viel die Wahl auf den Stadler. Und der hatte sich schon die ersten Tage bezahlt gemacht. Lüftungen hinten auf und vorne je nach Bedarf zu oder auf. Dadruch war immer die perfekt Lüftung garantiert. Auf Landstrassen und durch die Berge war es so immer perfekt. In Dörfern oder Städten, in denen es kurz etwas langsamer voran ging reichte ein kurzes öffnen des Reißverschlusses. Aus dem Dorf oder der Stadt raus einfach wieder zu machen und weiter gehts.
105 -
106 -
Der nächste Step war dann Saarlouis, um dort noch einen kleinen Besuch abzustatten. Auf dem Marktplatz etwas gegessen und getrunken, dabei dann später auch noch die weiterte Route geplant. Bis dahin gab es noch kein Ziel. das wurde dann einfach später gesucht, nachdem man nach den ganzen Unterhaltungen wußte wie spät es ist.
107 -
Geplant war zu dem Zeitpunkt weiter Richtung Norden und Richtung Heimat.
108 -
Bei der Suche nach einem Hotel viel dann Luxemburg auf der Karte ins Auge. Könnte man ja auch noch mitnehmen. Dabei viel dann die Wahl auf ein Hotel in Habscht, was direkt an der Grenze zu Belgien liegt. Aber auch hieß: Einmal komplett durch Luxemburg durch.
109 -
Kein Problem, Luxemburg ist ja auch nicht so groß. Und wenn Belgien direkt nebenan ist, ist die Route für den nächsten Tag ja auch schon irgendwie klar. Es geht dann einfach auch noch durch Belgien weiter.
110 -
Und Belgien war wirklich nicht sehr weit. Aus dem Hotel raus, links gehen und 50 Meter weiter war die Grenze nach Belgien.
111 -
112 -
Am nächsten Morgen ging es dann also durch Belgien und zwischendurch immer mal wieder Luxemburg. Das erste Stück war sehr zäh, da es überwiegend außerorts über ziemlich langweilige lange Geraden ging. Bis auf alle paar Kilometer mal Kreisverkehr oder Abbiegen war da nicht sehr viel. Da kam schon mal kurz der Gedanke, wenn das so weitergeht, dann wird doch schnell umgeplant und lieber durch die Eifel zurück gefahren.
113 -
Aber das hatte sich dann doch noch geändert. Denn Belgien und Luxemburg haben auch andere Ecken. Klar nicht die Aplen, aber es gibt auch etwas Berge und kurvenreiche Strecken. Es wurde also auch noch dort wieder schöner zu fahren. Auch von der Landschaft und der Umgebung ist es sehr interessant zu sehen wie sich Belgien immer wieder verändert. Man hat die verschiedenen Einflüsse immer sehr gut erkennen können. Immer wieder veränderten sich die Dörfer. Manchmal kommt es einem vor wieder in Frankreich zu sein. Die nächste Ecke erinnert einen an Deutschland. Dann sieht es schon irgendwie wie in den Niederlanden aus. Und so geht es die ganze Zeit abwechselnd und nicht nur weil mal gerade der Grenze zu einem Land näher gekommen ist.
114 -
115 -
Eigentlich war dann auch schon geplant über Belgien direkt nach Deutschland zurück. Aber was soll's, wenn man eh schon in der Ecke ist, wieso dann nicht auch noch die Niederlande mitnehmen?
116 -
In Belgien und Luxemburg noch ein paar kurze Stops in Wincrange, Verviers und weiteren kleineren Dörfern oder weil die Landschaft so schön war eingelegt. Oft nur zum Fotos machen und nur selten für richtige Pausen. Die wurde dann erst wieder in den Niederlanden gemacht.
117 -
118 -
In den Niederlanden als erstes kurz getankt. Das war vor kurz vor dem eigentlichem Ziel in Kerkrade, dem Kasteel Erenstein. Für die Fotos bin ich einfach mal Frech in den Hof gefahren. Das Schild hatte ich natürlich erst beim rausfahren gesehen. Danach bin ich auch ums Kasteel Erenstein gefahren, habe an der Seite eine Pause gemacht. Natürlich auch noch ein paar Fotos.
119 -
Auf der anderen Seite ist ein Parkplatz und auf dem Stand direkt gegenüber ein Foodanhänger. Was gibt es denn da? Also rüber und mal gucken. Es gab Eis in verschiedenen Variationen. Normales Eis, Softeis und noch ein paar andere Sachen. Die Wahl viel auf ein Sundea Caramel. Leute ich sage euch: Empfehlung, das muss sein.
120 -
121 -
Der Tankstop vorher war auch aus dem Grund geplant um das letzte Stück nach Hause durch zu fahren.
122 -
Auch weil die geplante Strecke schon knapp 350 km gewesen ist. Waren dann auch 350 km und 7:31 Stunden.
123 -
Und das letzte Stück sollte auch wie die komplette Tour nicht über die Autobahn gehen.
124 -
125 -
Um 18:50 Uhr war dann diese Tour vorbei. Viele Kurven und Serpentinen, viele Pässe, Berge, Städte und Dörfer gesehen. Schöne Seen und Landschaften. Insgesamt waren es dann also 3218 km, 7 Länder, 15 Hotels in 16 Tagen.
126 -
Unterwegs war ich mit der Suzuki GSXR 750. Würde ich so etwas noch einmal mit der GSXR machen? Ja klar.
127 -
Aber ich würde so eine Tour gerne auch noch mal mit der BMW GS machen.
128 -
129 -
Motorradtouren sind einfach schön. Auch wenn sie so geplant sind wie diese. Das Ziel war einfach nur:
130 -
131 -
   * Alpen
132 -
   * Schweiz, Frankreich, Italien.
133 -
   * Ob alle Länder von den dreien oder nur 1 oder 2: unklar.
134 -
   * Woher geht die Route: Unklar
135 -
   * Hotels: Unklar, wird spontan gebucht.
136 -
137 -
Man kann von Tag zu Tag entscheiden wohin es geht. Entweder weil man irgendwo etwas gelesen oder gesehen (z.B. in der Karten.app) hat. Oder das Wetter ist auf der eigentlichen Route schlecht. Einfach anders planen und den Regen umfahren. Musste dieses mal, bis auf den einen Tag, nicht gemacht werden.
138 -
139 -
140 -
141 -
{{< foldergallery src="images/galleries/2022/08/motorrad-alpen-3218km-7-laender" >}}
gelöscht content/2022-08-23-unifi-udm-pro-ipsec-dynamic-wan-ip.md
+0 −87
@@ -1,87 +0,0 @@
1 -
---
2 -
title: "Unifi UDM PRO IPSec dynamische WAN-IP"
3 -
date: 2022-09-23 15:00:00
4 -
update: 2022-09-23 15:00:00
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
  - ubiquiti
9 -
  - unifi
10 -
  - udmpro
11 -
  - VPN
12 -
  - Site2Site
13 -
  - WAN
14 -
  - IP
15 -
preview: "IPSec Site2Site Tunnel mit der Unifi Dream Machine Pro ist sehr einfach eingerichtet.
16 -
Bei einer statischen WAN-IP hat man auch keine Probleme damit. Wer aber eine UDM Pro mit einer dynamischen IP-Adresse benutzt wird schnell merken wenn der Tunnel nicht läuft, wenn durch einen Reconnect am Anschluss eine neue IP gesetzt ist."
17 -
categories: 
18 -
  - Technik
19 -
showToc: false
20 -
hide: false
21 -
type: post
22 -
draft: false
23 -
---
24 -
25 -
IPSec Site2Site Tunnel mit der Unifi Dream Machine Pro ist sehr einfach eingerichtet.
26 -
Bei einer statischen WAN-IP hat man auch keine Probleme damit. Wer aber eine UDM Pro mit einer dynamischen IP-Adresse benutzt wird schnell merken wenn der Tunnel nicht läuft, wenn durch einen Reconnect am Anschluss eine neue IP gesetzt ist.
27 -
28 -
Die UDM ändert leider nicht die Config automatisch ab. Aber auch auf der Gegenseite muss die Config angepasst werden.
29 -
30 -
Das ganze erledige ich jetzt mit Ansible. Ändert sich die IP wird die aktuelle IP per Ninja Template in die neue Config gegossen und auf den Remote-IP-Server kopiert.
31 -
Für die UDM kommt auch ein Script zum Einsatz. Es wird per Ansible kopiert und anschliessend auch ausgeführt.
32 -
33 -
Der Ansible Task für den Remote IPSec-Server holt sich erst einmal die aktuelle IP.
34 -
Damit wird dann das Template gefüllt, also an der Stelle für die LeftID (rightid=...) und auf den Remote Server kopiert.
35 -
36 -
```
37 -
---
38 -
39 -
- name: Get JSON from the Interwebs
40 -
  uri: url="https://ip.tytik.cloud/json" return_content=yes method="GET" body_format="json"
41 -
  register: json_response
42 -
  delegate_to: localhost
43 -
44 -
- name: set ip var
45 -
  set_fact: ip="{{ (json_response.content|from_json)['data'] }}"
46 -
47 -
48 -
- name: ipsec.conf
49 -
  template:
50 -
    src: ipsec.conf.j2
51 -
    dest: /etc/ipsec.conf
52 -
    owner: root
53 -
    group: root
54 -
    mode: 0640
55 -
```
56 -
57 -
Bei der UDM Pro wird ein Shell Script kopiert, welches auch die aktuelle IP Adresse per Curl abruft und dann per sed die alte IP gegen die neue ersetzt. Anschliessend wird IPSec neugestartet und der Tunnel aufgebaut.
58 -
59 -
```
60 -
---
61 -
62 -
- name: Copy file with owner and permissions
63 -
  copy:
64 -
    src: ip_wan_ip.sh
65 -
    dest: /root/ip_wan_ip.sh
66 -
    owner: root
67 -
    group: root
68 -
    mode: '0544'
69 -
70 -
- name: Change Remote ip
71 -
  command: /root/ip_wan_ip.sh
72 -
```
73 -
74 -
Da die IP bei `rightid` gesetzt ist und bei `right` der Subdomain und dieser auf die dynamische IP Zeigt, wird die Subdomain auch direkt noch aktualisert. Dazu habe ich ein Update Script, mit dem im BIND DNS Server der A-Record für diese Subdomain aktualisiert wird.
75 -
76 -
```
77 -
- name: Change Domain Record
78 -
  command: /root/nsupdate.sh -z domain.tld -t A -h ipsec -v {{ ip }}
79 -
  delegate_to: localhost
80 -
```
81 -
82 -
Damit kann regelmässig überprüft werden ob sich die IP geändert hat und es werden auf allen Seiten die nötigen Änderungen gemacht um den Tunnel wieder aufzubauen.
83 -
84 -
Das umständliche DNS Update und das herumgeklicke in der UDM Pro Weboberfläche fällt weg. Ausserdem kann das dann auch automatisiert gemacht werden und man muss sich auch nicht mehr drum kümmern.
85 -
86 -
Die Scripte und Ansible Roles sind fertig. Da noch ein paar Sachen auf das Setup hier angepasst sind und an mehreren Stellen etwas angepasst werden müsste, ist der Code noch nicht im Git.
87 -
Das werde ich noch nachholen und ein Update hier hinterlassen. So das es von jedem genutzt werden kann und nur an einer oder zwei Stellen dann die IPs, Hostnames, User usw. eingetragen werden müssen.
gelöscht content/2022-09-24-dovecot-sieve-delimiters-rules.md
+0 −114
@@ -1,114 +0,0 @@
1 -
---
2 -
title: "Dovecot Sieve Delimiters Rules"
3 -
date: 2022-09-24 10:00:00
4 -
lastmod: 2022-09-24 10:00:00
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
  - Dovecot
9 -
  - Sieve
10 -
  - Delimiters
11 -
  - Rules
12 -
preview: Ich benutze seit einigen Jahren für manche Mailaccounts Delimiter im Local-Part der Adressen. So kann ich für bestimmte Seite immer, ohne erst einen Account oder eine Weiterleitung einrichten zu müssen, extra E-Mailadressen benutzen.
13 -
categories: 
14 -
  - Technik
15 -
type: post
16 -
toc: false
17 -
hide: false
18 -
draft: false
19 -
---
20 -
21 -
22 -
### Was sind Delimiter Mailadressen?
23 -
24 -
Ich benutze seit einigen Jahren für manche Mailaccounts Delimiter im Local-Part der Adressen. So kann ich für bestimmte Seite immer, ohne erst einen Account oder eine Weiterleitung einrichten zu müssen, extra E-Mailadressen benutzen.
25 -
26 -
Die E-Mailadressen sind immer nach folgendem Schema aufgebaut.
27 -
28 -
    username+order1.order2@domain.de
29 -
30 -
ordner1 ist dabei dann z.B. shops, social usw.
31 -
ordner2 ist z.B. bei shops dann amazon, ebay usw.
32 -
33 -
So könnte es dann folgende E-Mailadressen für die einzelnen Seiten geben:
34 -
35 -
   * username+shops.amazon@domain.de
36 -
   * username+shops.ebay@domain.de
37 -
   * username+social.facebook@domain.de
38 -
   * username+social.instagram@domain.de
39 -
   * username+social.twitter@domain.de
40 -
41 -
So hat jeder Shop und jedes soziale Netzwerk und viele weitere Portale und Services immer eine eigene E-Mailadresse.
42 -
43 -
### Automatische Sortierung
44 -
45 -
Die Mail können anschliessend per Filterregeln natürlich passend einsortiert werden. Wer seine Domains und Mailadressen auf einem Server mit Sieve als Filter, kann diese Mailadressen auch automatisch in die Ordner ablegen lassen.
46 -
47 -
Dafür gibt es einen Ordner im Postfach `Autosort` in dem dann alle Mails in die entsprechenden Ordnern speichert.
48 -
49 -
```
50 -
.Autosort.shops.amazon
51 -
.Autosort.shops.ebay
52 -
.Autosort.social.facebook
53 -
.Autosort.social.instagram
54 -
.Autosort.social.twitter
55 -
```
56 -
57 -
Im Mailclient wird dann unter dem Ordner Autosort die Ordner shops und social angelegt und dort drin dann Amazon und Ebay, bzw. Facebook, Instagram und Twitter angelegt, in denen dann die Mails jeweils einsortiert werden.
58 -
59 -
{{< postimage "Autosort Folders Mailpostfach" "folsers.png" "folders.png" >}}
60 -
61 -
![Autosort Folders Mailpostfach](/images/posts/folders.webp)
62 -
63 -
64 -
### Sieve Filterregeln
65 -
66 -
Damit das ganze funktioniert muss natürlich auch ein passender Filter im Sieve hinterlegt werden.
67 -
68 -
```
69 -
require ["reject","fileinto","imap4flags","body","vacation","copy","variables","regex","envelope"];
70 -
71 -
# rule:[autodelemiter]
72 -
if header :regex "Delivered-To" "username\\+([^.]*)\\.?([^.]*)\\.?([^.]*)\\.?([^.]*)\\.?([^.]*)@.*$" {
73 -
  if string :is "${1}" "" {} else { set :lower "part1" "${1}"; }
74 -
  if string :is "${2}" "" {} else { set :lower "part2" "${2}"; }
75 -
  if string :is "${3}" "" {} else { set :lower "part3" "${3}"; }
76 -
  if string :is "${4}" "" {} else { set :lower "part4" "${4}"; }
77 -
  if string :is "${5}" "" {} else { set :lower "part5" "${5}"; }
78 -
  if string :is "${6}" "" {} else { set :lower "part6" "${6}"; }
79 -
80 -
  set "targetfolder" "";
81 -
  if string :is "${part1}" "" {} else { set "targetfolder" "${part1}"; }
82 -
  if string :is "${2}" "" {} else { set "targetfolder" "${targetfolder}/${part2}"; }
83 -
  if string :is "${3}" "" {} else { set "targetfolder" "${targetfolder}/${part3}"; }
84 -
  if string :is "${4}" "" {} else { set "targetfolder" "${targetfolder}/${part4}"; }
85 -
  if string :is "${5}" "" {} else { set "targetfolder" "${targetfolder}/${part5}"; }
86 -
  if string :is "${6}" "" {} else { set "targetfolder" "${targetfolder}/${part6}"; }
87 -
88 -
  fileinto "Autosort/${targetfolder}";
89 -
}
90 -
```
91 -
92 -
Damit können die Mailadressen einfach angegeben werden und sie werden automatisch sortiert. Das ganze ist hier für bis zu 6 Ordnern ausgelegt. Damit wäre also folgende Mailadresse möglich `username+ordner1.ordner2.order3.order4.order5.order6@domain.tld` möglich.
93 -
94 -
Die Ordner dazu hätten dann folgende Struktur im Postfach:
95 -
```
96 -
Autosort
97 -
+-ordner1
98 -
  +-ordner2
99 -
    +-order3
100 -
      +-order4
101 -
        +-order5
102 -
          +-order6
103 -
```
104 -
105 -
Ich selbst habe bis jetzt glaube ich maximal 4 Ordner benutzt. Aber so ist halt noch Luft nach oben. ;-)
106 -
107 -
Das ist der Grund wieso ich 2789 Ordner in meinen Mailpostfächern habe. Und 97% habe ich nicht einmal selbst angelegt. Das passiert alles automatisch und die die Mails landen auch noch automatisch in diesen Ordnern.
108 -
109 -
So sind auch nur die wichtigsten E-Mail in der Inbox.
110 -
111 -
### Wieso Delimiter Adresse noch sinnvoll sind
112 -
113 -
Es kam in den letzten Jahren mehrfach zu Datenschutzvorfällen bei einigen Anbietern und Portalen. Werden solche E-Mailadresse durch einen Hack einer Seite abgezogen und eine Spamwelle kommt, schaltet man diese einzelne Delimiter Mailadresse einfach mit einer Filterregel ab. Also einfach löschen.
114 -
In ein paar Fällen war den Betreibern auch nicht bewusst das Daten von dem Portal abgezogen wurden. Durch die Erklärung und teils sogar recht kryptischen Mailadressen von mir war ihnen schnell klar das diese Spam/Pishing E-Mails nicht durch Zufall bei mir angekommen sind. Es wurde dann überprüft und durch den Hinweis konnten manche Vorfälle dann auch bestätigt und andere Benutzer direkt gewarnt werden.
gelöscht content/2022-09-25-nginx-googlefonts-filtern.md
+0 −59
@@ -1,59 +0,0 @@
1 -
---
2 -
title: "Nginx Google Fonts Filtern"
3 -
date: 2022-09-25 10:00:00
4 -
lastmod: 2022-09-25 10:00:00
5 -
author: ruediger
6 -
cover: "/images/cat/technik.webp"
7 -
tags:
8 -
  - Nginx
9 -
  - GoogleFonts
10 -
  - Internet
11 -
preview: Wir ersetzen einfach die Domain für die Google Fonts 
12 -
categories: 
13 -
  - Technik
14 -
type: post
15 -
ShowToc: false
16 -
hide: false
17 -
draft: false
18 -
---
19 -
20 -
21 -
### Abmahnwelle wegen Google Fonts?
22 -
23 -
Seit ein paar Tagen finden einige wieder Briefe im Briefkasten wegen einer Abmahnwelle zu Google Fonts. Dieses mal lässt sich sogar ein Anwalt vor den Karren spannen und er versendet aktuell wohl tausende Abmahnungen.
24 -
25 -
Laut Post einer Kanzlei sind dort alleine am Freitag vorletzter Woche 300 dieser Schreiben eingetroffen die man bearbeitet.
26 -
27 -
Wer noch Google Fonts direkt von den Google Server einbunden hat, sollte diese lokal speichern und direkt selbst ausliefern.
28 -
29 -
### Was machen wenn Theme Updates Fonts wieder einbinden?
30 -
31 -
Es gibt z.B. Wordpress Themes bei denen man die Fonts zwar anpassen kann, aber nach einem Update des Themes wird wieder Google Fonts von den Servern bei Google geladen.
32 -
33 -
Anderes Problem sind Personen die nicht wissen was sie machen müssen.
34 -
Wer, egal wieso, die Nutzung von Google Fonts von Google Servern unterbinden möchte und selbst einen Nginx Webserver einsetzt, der kann das sehr leicht für alle Seiten vom Nginx ereldigen lassen.
35 -
36 -
In der Config vom Nginx einfach folgende Zeile mit eintragen.
37 -
38 -
39 -
Wir ersetzen einfach die Domain für die Google Fonts gegen:
40 -
`https://fonts.googleapis.com`.
41 -
42 -
43 -
```
44 -
sub_filter 'https://fonts.googleapis.com' 'https://disable-google-fonts';
45 -
```
46 -
47 -
Die Zeile könnte man jetzt auch gut dafür nutzen um alle Seiten zu finden die noch Google Fonts einbinden.
48 -
49 -
```
50 -
sub_filter 'https://fonts.googleapis.com' '/googlefonts/';
51 -
```
52 -
53 -
Damit wird der Font nicht auf dem Sevrer gefunden der die Seite ausliefert. Dafür kann man dann aber einfach in den Logfiles alles Seiten nach `/googlefonts/` suchen und hat dann schnell alle Seiten und Stellen wo man noch anpassen müsste.
54 -
55 -
```
56 -
grep '/googlefonts/' /path/to/logfiles/*.log
57 -
```
58 -
59 -
Sollten Einträge vorhanden sein weiß man schnell wo noch Google Fonts eingebunden sind.
gelöscht content/2023-09-09-Hetzner-Cloud-server-k3s-gatus-monitoring.md
+0 −228
@@ -1,228 +0,0 @@
1 -
---
2 -
title: Hetzner-Cloud-server-k3s-gatus-monitoring
3 -
date: 2023-09-09 11:26:47
4 -
author: ruediger
5 -
tags:
6 -
  - Hetzner
7 -
  - k3s
8 -
  - monitoring
9 -
categories: 
10 -
  - Internet
11 -
draft: true
12 -
top: false
13 -
type: post
14 -
hide: true
15 -
toc: false
16 -
---
17 -
18 -
19 -
```
20 -
#!/bin/bash
21 -
22 -
# INSTALL K3S
23 -
curl -sfL https://get.k3s.io | sh
24 -
echo 'export KUBECONFIG=/etc/rancher/k3s/k3s.yaml' >> ~/.bashrc
25 -
source ~/.bashrc
26 -
27 -
# INSTALL HELM
28 -
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
29 -
chmod 700 get_helm.sh
30 -
./get_helm.sh
31 -
32 -
# INSTALL K9S
33 -
# ARM 
34 -
curl -L -O https://github.com/derailed/k9s/releases/download/v0.27.4/k9s_Linux_arm64.tar.gz
35 -
tar -xzf k9s_Linux_arm64.tar.gz
36 -
# AMD
37 -
# curl -L -O https://github.com/derailed/k9s/releases/download/v0.27.4/k9s_Linux_amd64.tar.gz
38 -
# tar -xzf k9s_Linux_amd64.tar.gz
39 -
mv k9s /usr/local/bin/.
40 -
41 -
cat /etc/rancher/k3s/k3s.yaml
42 -
43 -
```
44 -
45 -
```
46 -
cat << 'EOF' | kubectl apply -f -
47 -
apiVersion: cert-manager.io/v1
48 -
kind: ClusterIssuer
49 -
metadata:
50 -
  name: letsencrypt-prod
51 -
spec:
52 -
  acme:
53 -
    email: ruediger@kuepper.nrw
54 -
    server: https://acme-v02.api.letsencrypt.org/directory
55 -
    privateKeySecretRef:
56 -
      name: letsencrypt-prod
57 -
    solvers:
58 -
    - http01:
59 -
        ingress:
60 -
          class: traefik
61 -
EOF          
62 -
```
63 -
64 -
```
65 -
hcloud server create --image ubuntu-22.04 --type cx11 --name Ubuntu22-server --location fsn1 --ssh-key ruediger@kuepper.nrw
66 -
```
67 -
68 -
69 -
```
70 -
export INSTALL_K3S_VERSION=v1.21.3+k3s1
71 -
export INSTALL_K3S_EXEC="server --disable traefik --disable servicelb --disable metrics-server --disable-cloud-controller \
72 -
       --kube-proxy-arg proxy-mode=ipvs --cluster-cidr=10.42.0.0/16,fd42::/48 --service-cidr=10.43.0.0/16,fd43::/112 \
73 -
       --disable-network-policy --flannel-backend=none --node-ip=162.55.33.231,2a01:4f8:c013:882::1"
74 -
75 -
wget https://get.k3s.io -O k3s.sh
76 -
less k3s.sh
77 -
bash k3s.sh
78 -
```
79 -
80 -
```
81 -
wget https://docs.projectcalico.org/manifests/calico.yaml
82 -
```
83 -
84 -
```
85 -
"ipam": {
86 -
    "type": "calico-ipam",
87 -
    "assign_ipv4": "true",
88 -
    "assign_ipv6": "true"
89 -
},
90 -
```
91 -
92 -
```
93 -
kubectl apply -f calico.yaml
94 -
```
95 -
96 -
97 -
```
98 -
wget https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/namespace.yaml -O metallb-namespace.yaml
99 -
wget https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/metallb.yaml -O metallb-0.10.2-manifest.yaml
100 -
kubectl apply -f metallb-namespace.yaml -f metallb-0.10.2-manifest.yaml
101 -
```
102 -
103 -
```
104 -
apiVersion: v1
105 -
kind: ConfigMap
106 -
metadata:
107 -
  namespace: metallb-system
108 -
  name: config
109 -
data:
110 -
  config: |
111 -
    address-pools:
112 -
    - name: default
113 -
      protocol: layer2
114 -
      addresses:
115 -
      - 162.55.33.231/32
116 -
      - 2a01:4f8:c013:882::1/128
117 -
```
118 -
119 -
```
120 -
kubectl apply -f metallb-config.yaml
121 -
```
122 -
123 -
```
124 -
cat << 'EOF' | kubectl apply -f -
125 -
apiVersion: metallb.io/v1beta1
126 -
kind: IPAddressPool
127 -
metadata:
128 -
  name: default-pool
129 -
  namespace: metallb-system
130 -
spec:
131 -
  addresses:
132 -
  - 162.55.33.231/32
133 -
  - 2a01:4f8:c013:882::/64
134 -
---
135 -
apiVersion: metallb.io/v1beta1
136 -
kind: L2Advertisement
137 -
metadata:
138 -
  name: default
139 -
  namespace: metallb-system
140 -
spec:
141 -
  ipAddressPools:
142 -
  - default-pool
143 -
EOF
144 -
```
145 -
146 -
147 -
```
148 -
helm install cilium cilium/cilium \
149 -
--namespace kube-system \
150 -
--set ipv4.enabled=true \
151 -
--set ipv6.enabled=true \
152 -
--set ipam.mode=cluster-pool \
153 -
--set ipam.operator.clusterPoolIPv4PodCIDRList="10.96.0.0/16" \
154 -
--set ipam.operator.clusterPoolIPv6PodCIDRList="2a01:4f8:c013:882::/96" \
155 -
--set ipam.operator.clusterPoolIPv4MaskSize=24 \
156 -
--set ipam.operator.clusterPoolIPv6MaskSize=112 \
157 -
--set bpf.masquerade=true \
158 -
--set enableIPv6Masquerade=false
159 -
```
160 -
161 -
<!-- 
162 -
```
163 -
# First add metallb repository to your helm
164 -
helm repo add metallb https://metallb.github.io/metallb
165 -
# Check if it was found
166 -
helm search repo metallb
167 -
# Install metallb
168 -
helm upgrade --install metallb metallb/metallb --create-namespace \
169 -
--namespace metallb-system --wait
170 -
```
171 -
172 -
```
173 -
cat << 'EOF' | kubectl apply -f -
174 -
apiVersion: metallb.io/v1beta1
175 -
kind: IPAddressPool
176 -
metadata:
177 -
  name: default-pool
178 -
  namespace: metallb-system
179 -
spec:
180 -
  addresses:
181 -
  - 188.34.183.120-188.34.183.120
182 -
---
183 -
apiVersion: metallb.io/v1beta1
184 -
kind: L2Advertisement
185 -
metadata:
186 -
  name: default
187 -
  namespace: metallb-system
188 -
spec:
189 -
  ipAddressPools:
190 -
  - default-pool
191 -
EOF
192 -
```
193 -
194 -
```kubectl get pods -n metallb-system ```
195 -
196 -
```
197 -
root@control01:~/metallb# kubectl get pods -n metallb-system
198 -
NAME                         READY   STATUS    RESTARTS   AGE
199 -
controller-57fd9c5bb-rdl7v   1/1     Running   0          5m42s
200 -
speaker-h7chj                1/1     Running   0          5m42s
201 -
speaker-pg7kp                1/1     Running   0          5m42s
202 -
speaker-78pdz                1/1     Running   0          5m42s
203 -
speaker-ghpxz                1/1     Running   0          5m42s
204 -
speaker-8cf7k                1/1     Running   0          5m42s
205 -
speaker-2t6jp                1/1     Running   0          5m42s
206 -
speaker-cjcpn                1/1     Running   0          5m41s
207 -
speaker-mv7v4                1/1     Running   0          5m42s
208 -
```
209 -
210 -
```
211 -
kubectl get svc -n kube-system
212 -
NAME                   TYPE              CLUSTER-IP    EXTERNAL-IP       PORT(S)                                 AGE
213 -
kube-dns           ClusterIP        10.43.0.10           <none>           53/UDP,53/TCP,9153/TCP       3h45m
214 -
metrics-server   ClusterIP         10.43.254.144     <none>           443/TCP                                  3h45m
215 -
traefik                LoadBalancer 10.43.159.145      192.168.0.200        80:31771/TCP,443:30673/TCP 3h44m
216 -
217 -
```
218 -
219 -
```
220 -
kubectl get events -n kube-system --field-selector involvedObject.name=traefik
221 -
LAST SEEN TYPE REASON OBJECT MESSAGE
222 -
61s Normal IPAllocated service/traefik Assigned IP ["192.168.0.200"]
223 -
60s Normal nodeAssigned service/traefik announcing from node "cube02" with protocol "layer2"
224 -
```
225 -
226 -
 -->
227 -
228 -
gelöscht content/2023-09-11-Bedrock-Minecraft-on-kubernetes.md
+0 −161
@@ -1,161 +0,0 @@
1 -
---
2 -
title: Deploy Minecraft Server on Kubernetes Cluster
3 -
date: 2023-09-11 19:15:00
4 -
update: 2023-09-11 19:15:00
5 -
cover: "/images/cat/technik.webp"
6 -
author: ruediger
7 -
draft: false
8 -
top: false
9 -
tags:
10 -
  - Kubernetes
11 -
  - Minecraft
12 -
  - Bedrock
13 -
categories: 
14 -
    - Internet
15 -
preview: "Deploy Minecraft Server on Kubernetes Cluster"
16 -
type: post
17 -
hide: false
18 -
toc: false
19 -
---
20 -
21 -
# Create Kubernetes YAML for 
22 -
23 -
* Namespace
24 -
* Configmap
25 -
* PersistentVolumeClaim
26 -
* Loadbalancer Service
27 -
* StatefulSet
28 -
29 -
```
30 -
cat > minecraft.yaml <<EOF
31 -
---
32 -
apiVersion: v1
33 -
kind: Namespace
34 -
metadata:
35 -
  name: blog-kuepper
36 -
---
37 -
apiVersion: v1
38 -
kind: ConfigMap
39 -
metadata:
40 -
  name: minecraft-bedrock
41 -
  namespace: minecraft
42 -
  labels:
43 -
    role: service-config
44 -
    app: bds
45 -
data:
46 -
  # Find more options at https://github.com/itzg/docker-minecraft-bedrock-server#server-properties
47 -
  # Remove # from in front of line if changing from default values.
48 -
  EULA: "TRUE" # Must accept EULA to use this minecraft server
49 -
  GAMEMODE: "creative" # Options: survival, creative, adventure
50 -
  #DIFFICULTY: "easy" # Options: peaceful, easy, normal, hard
51 -
  #DEFAULT_PLAYER_PERMISSION_LEVEL: "member" # Options: visitor, member, operator
52 -
  LEVEL_NAME: "my_minecraft_world"
53 -
  #LEVEL_SEED: "33480944"
54 -
  #SERVER_NAME: "my_minecraft_server"
55 -
  #SERVER_PORT: "19132"
56 -
  #LEVEL_TYPE: "DEFAULT" # Options: FLAT, LEGACY, DEFAULT
57 -
  #ALLOW_CHEATS: "false" # Options: true, false
58 -
  #MAX_PLAYERS: "10"
59 -
  #PLAYER_IDLE_TIMEOUT: "30"
60 -
  #TEXTUREPACK_REQUIRED: "false" # Options: true, false
61 -
  #
62 -
  ## Changing these will have a security impact
63 -
  #ONLINE_MODE: "true" # Options: true, false (removes Xbox Live account requirements)
64 -
  #WHITE_LIST: "false" # If enabled, need to provide a whitelist.json by your own means. 
65 -
  #
66 -
  ## Changing these will have a performance impact
67 -
  #VIEW_DISTANCE: "10"
68 -
  #TICK_DISTANCE: "4"
69 -
  #MAX_THREADS: "8"
70 -
---
71 -
kind: PersistentVolumeClaim
72 -
apiVersion: v1
73 -
metadata:
74 -
  name: bds
75 -
  namespace: minecraft
76 -
spec:
77 -
  accessModes:
78 -
    - ReadWriteOnce
79 -
  resources:
80 -
    requests:
81 -
      storage: 1Gi
82 -
---
83 -
apiVersion: apps/v1
84 -
kind: StatefulSet
85 -
metadata:
86 -
  labels:
87 -
    app: bds
88 -
  name: bds
89 -
  namespace: minecraft
90 -
spec:
91 -
  # never more than 1 since BDS is not horizontally scalable
92 -
  replicas: 1
93 -
  serviceName: bds
94 -
  selector:
95 -
    matchLabels:
96 -
      app: bds
97 -
  template:
98 -
    metadata:
99 -
      labels:
100 -
        app: bds
101 -
    spec:
102 -
      containers:
103 -
        - name: main
104 -
          image: itzg/minecraft-bedrock-server
105 -
          imagePullPolicy: Always
106 -
          envFrom:
107 -
            - configMapRef:
108 -
                name: minecraft-bedrock
109 -
          volumeMounts:
110 -
            - mountPath: /data
111 -
              name: data
112 -
          ports:
113 -
            - containerPort: 19132
114 -
              protocol: UDP
115 -
          readinessProbe: &probe
116 -
            exec:
117 -
              command:
118 -
                - mc-monitor
119 -
                - status-bedrock
120 -
                - --host
121 -
                # force health check against IPv4 port
122 -
                - 127.0.0.1
123 -
            initialDelaySeconds: 30
124 -
          livenessProbe: *probe
125 -
          tty: true
126 -
          stdin: true
127 -
  volumeClaimTemplates:
128 -
    - metadata:
129 -
        name: data
130 -
      spec:
131 -
        accessModes:
132 -
          - ReadWriteOnce
133 -
        resources:
134 -
          requests:
135 -
            storage: 1Gi
136 -
---
137 -
apiVersion: v1
138 -
kind: Service
139 -
metadata:
140 -
  name: bds
141 -
  namespace: minecraft
142 -
spec:
143 -
  selector:
144 -
    app: bds
145 -
  ports:
146 -
    - port: 19132
147 -
      protocol: UDP
148 -
  # ipFamily: IPv4
149 -
  # Use LoadBalancer if running on a provider that supports that
150 -
  type: LoadBalancer
151 -
  # or use NodePort on a non-managed system;
152 -
  # however, you'll need to lookup port assigned to the service
153 -
  # type: NodePort
154 -
EOF
155 -
```
156 -
# Deploy to Kubernetes Cluster:
157 -
158 -
```
159 -
kubectl apply -f minecraft.yaml
160 -
```
161 -
gelöscht content/2023-09-11-Kubernetes-no-default-StorageClass.md
+0 −57
@@ -1,57 +0,0 @@
1 -
---
2 -
title: Kubernetes, no default StorageClass
3 -
date: 2023-09-11 12:15:00
4 -
update: 2023-09-11 12:15:00
5 -
cover: "/images/cat/technik.webp"
6 -
author: ruediger
7 -
draft: false
8 -
top: false
9 -
tags:
10 -
  - Kubernetes
11 -
  - StorageClass
12 -
categories: 
13 -
    - Internet
14 -
preview: "Kubernetes, no default StorageClass"
15 -
type: post
16 -
hide: false
17 -
toc: false
18 -
---
19 -
20 -
Beim Anlegen eines PVC, ohne Angabe einer StorageClass, wird das PV nicht angelegt, wenn im Cluster keine StorageClass als `default` ausgewählt ist. Das PVC steht anschliesend dauerhaft auf `pending`.
21 -
22 -
Mit `kubectl` die Liste der verfügbaren StorageClass abrufen und aus der Liste die gewünschte Storageclass heraus suchen. 
23 -
24 -
> When creating a PVC without specifying a StorageClass, the PV is not created if no StorageClass is selected as default in the cluster. The PVC then remains in a pending state indefinitely.
25 -
26 -
> Retrieve the list of available StorageClass using kubectl and search for the desired StorageClass from the list.
27 -
28 -
```
29 -
kubectl get storageclass
30 -
NAME                 PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
31 -
csi-disk             everest-csi-provisioner         Delete          Immediate              true                   66d
32 -
csi-disk-topology    everest-csi-provisioner         Delete          WaitForFirstConsumer   true                   66d
33 -
...
34 -
```
35 -
36 -
Mit dem Namen der StorageClass ein Kubectl Path ausführen und dabei dann `is-default-class` auf `true` setzen.
37 -
38 -
> Execute a kubectl path with the name of the StorageClass and set is-default-class to true.
39 -
40 -
```
41 -
kubectl patch storageclass csi-disk -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
42 -
storageclass.storage.k8s.io/csi-disk patched
43 -
```
44 -
45 -
46 -
Die StorageClass wird anschliessend als Default StorageClass angezeigt. 
47 -
48 -
> The StorageClass will then be displayed as the default StorageClass.
49 -
50 -
51 -
```
52 -
kubectl get storageclass
53 -
NAME                 PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
54 -
csi-disk (default)   everest-csi-provisioner         Delete          Immediate              true                   66d
55 -
csi-disk-topology    everest-csi-provisioner         Delete          WaitForFirstConsumer   true                   66d
56 -
...
57 -
```
\ No newline at end of file
gelöscht content/2023-09-13-crypt-decrypt-files-with-openssl.md
+0 −66
@@ -1,66 +0,0 @@
1 -
---
2 -
title: Crypt/Decrypt files with openssl
3 -
date: 2023-09-13 13:12:00
4 -
author: ruediger
5 -
cover: "/images/cat/technik.webp"
6 -
tags: [Crpto, Openssl, Keys, Files, Encrypt, Decrypt]
7 -
categories: 
8 -
    - Internet
9 -
preview: "If you want to encrypt a file that should also be decrypted by several people, openssl is a very good choice. Anyone who wants to decrypt the file later must first create a key pair." 
10 -
draft: true
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
Wenn man eine Datei verschlüsseln möchte, die auch von mehreren Personen wieder entschlüsselt werden soll, 
18 -
bietet sich openssl sehr gut an. Jeder der die Datei später wieder entschlüsseln können soll, muss sich erst einmal ein Schlüsselpaar anlegen: 
19 -
20 -
> If you want to encrypt a file that should also be decrypted by several people, openssl is a very good choice. Anyone who wants to decrypt the file later must first create a key pair.
21 -
22 -
23 -
```
24 -
openssl req -x509 -newkey rsa:4096 -days 3650 -subj "/C=DE/ST=*/L=*/O=*/OU=*/CN=User1/" -keyout user1.key -out user1.pub
25 -
...+.......+.....+.+......+.....+...+.+..+.......+...+..+.......+...+......+............+.....+...+............+....+...+...........+......+.............+.....+.+............+..+.+.........+++++++++++++++++++++++++++++++++++++++++++++*...+......+.............+..+...+.+......+.....+...+.+...............+...............+..............+...+...+.......+.....+...+.+......+.................+.+.........+..+++++++++++++++++++++++++++++++++++++++++++++*..+..........+..+..........+.....+....+.....+...+.+..............+.....................+.+.....+.+.........+........+...+...+..........+............+...+.........+..+......+..........+........+.+...+.....+.............+...+.........+.....+...+...+......+.........+....+...+.................+++++
26 -
.........+...+.......+...+.....+...+.+...+..+...............+.+.....+++++++++++++++++++++++++++++++++++++++++++++*..+.....+.+............+.....+...+.+...+...+.........+.....+....+...........+.+..+......+..........+++++++++++++++++++++++++++++++++++++++++++++*.........+......+.+..+...+....+...+...+...+..+..........+..+...............+.......+...+............+.....+....+....................+.+.....+.........+......+......+.........+.+........................+...+...........+....+............+..............+....+.....................+..+...............+.......+..+........................+................+......+.....+.......+...........+......+.+........+............+....+..............+....+.....+.+...............+...........+...+...+.........+.+.........+.....+....+.........+......+..+....+...+...............+...+...+............+..+.+.....+..........+++++
27 -
Enter PEM pass phrase:
28 -
Verifying - Enter PEM pass phrase:
29 -
-----
30 -
openssl req -x509 -newkey rsa:4096 -days 3650 -subj "/C=DE/ST=*/L=*/O=*/OU=*/CN=User2/" -keyout user2.key -out user2.pub
31 -
...
32 -
```
33 -
34 -
Die beiden Secret User Keys bleiben bei den jeweiligen Usern, so das nur er diesen Schlüssel hat. Den Public Key kann man auch miteinander teilen, so das jeder Dateien für den anderen oder alle anderen Personen verschlüsseln kann. 
35 -
36 -
Möchte man jetzt eine Datei für beide User verschlüsseln übergibt man einfach die entsprechenden Public Key an openssl. 
37 -
38 -
> The two secret user keys remain with their respective users, so that only he has this key. The public key can be shared with each other, so that anyone can encrypt files for the other or all other people.
39 -
40 -
> If you now want to encrypt a file for both users, simply hand over the corresponding public key to openssl.
41 -
42 -
```
43 -
openssl smime -encrypt -aes256 -in test.pdf -out test.pdf.enc -binary -outform DER user1.pub user2.pub
44 -
ls -la *.pdf*
45 -
-rw-r--r--@ 1 rk  staff  240654 13 Sep 13:21 test.pdf
46 -
-rw-r--r--  1 rk  staff    6689 13 Sep 13:22 test.pdf.enc
47 -
```
48 -
49 -
Damit ist die Datei Verschlüsselt und beide User haben die Möglichkeit die Datei zu entschlüsseln. 
50 -
51 -
> With that, the file is encrypted, and both users have the ability to decrypt the file.
52 -
53 -
```
54 -
openssl smime -decrypt -in test.pdf.enc -inform DEM -inkey user1.key -out decrypt-test.pdf
55 -
ls -la *pdf*
56 -
-rw-r--r--@ 1 rk  staff  1355211 13 Sep 13:48 decrypt-test.pdf
57 -
-rw-r--r--@ 1 rk  staff  1355211 13 Sep 13:44 test.pdf
58 -
-rw-r--r--  1 rk  staff  1355942 13 Sep 13:45 test.pdf.enc
59 -
md5 test.pdf decrypt-test.pdf
60 -
MD5 (test.pdf) = 42f83d23f5d23cd474574c5bc2f93b8e
61 -
MD5 (decrypt-test.pdf) = 42f83d23f5d23cd474574c5bc2f93b8e
62 -
```
63 -
64 -
Möchet man mehrere Datein verschlüsseln nimmt man einfach `tar` und komprimiert alle Dateien. Anschliessend verschlüsselt man das komplette Tarball. 
65 -
66 -
> If you want to encrypt multiple files, simply use tar to compress all files. Afterwards, encrypt the entire tarball.
\ No newline at end of file
gelöscht content/2023-09-19-inkproject-blog-github-workflow-en.md
+0 −96
@@ -1,96 +0,0 @@
1 -
---
2 -
title: InkProject Blog Github Workflow
3 -
date: 2023-09-19 21:00:00
4 -
author: ruediger
5 -
cover: "/images/cat/technik.webp"
6 -
tags: [InkProjekt, Blog, GitHub, Action, Workflow, Trigger]
7 -
categories: 
8 -
    - Internet
9 -
preview: "Dieses Blog wird nicht mehr durch Hugo generiert. Der Hugo Static Content Generator war jetzt lange im Einsatz, doch seit ein paar Wochen habe ich mir alternativen angeguckt. Dabei bin ich mehrere durchgegangen und bin schließlich bei InkProjekt geblieben. " 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: true
14 -
toc: false
15 -
---
16 -
17 -
[German Version](/posts/2023-09-19-inkproject-blog-github-workflow.html)
18 -
19 -
## Bey Bey Hugo, welcome Ink
20 -
21 -
This blog is no longer generated by Hugo. The Hugo Static Content Generator has been in use for a long time, but over the past few weeks, I've been exploring alternatives. I went through several and eventually settled on InkProjekt.
22 -
23 -
After the initial tests, more and more posts were gradually migrated. During this process, the first steps towards Docker and Kubernetes were also taken for both Ink and this blog. I've been working with Docker and Kubernetes for a few years now.. 
24 -
25 -
## Write, publish, build, and deploy
26 -
27 -
The sequence is clear, as always. A new post is written, or as now with Ink, copied. After that, `ink publish` is executed. All files from the `public` directory are copied to `html`, allowing a Dockerfile for Nginx to populate the html directory with the new content. Docker Push into the Docker Registry, followed by a `kubectl set image`.... The new version was online.
28 -
29 -
These were initially manual steps. Just a few shell scripts. 
30 -
31 -
## GitHub Actions
32 -
33 -
After everything ran smoothly, it was time to automate the entire process. Create a post or page, git add, commit, push, and GitHub Action would handle the page assembly, building Docker images for all platforms, and managing the HelmChart.
34 -
35 -
Initially, everything was in one Git repo, so first off, the Helm Chart was moved into its own.
36 -
After a push, the workflow took care of the following steps:
37 -
38 -
    1. Repo checkout
39 -
    2. Increment Semantic Release version
40 -
    3. Save version in GitHub Environment
41 -
    4. Create page with ink publish
42 -
    5. Package pages into Docker images for all platforms
43 -
    6. Combine Docker images into a MultiPlatform image
44 -
    7. Push Docker image to the registry
45 -
    8. Checkout Helm Chart repo
46 -
    9. Create Helm Chart with the semantic version
47 -
    10. Push Helm Chart to the Helm Chart Museum
48 -
    11. Deploy Helm Chart to the Kubernetes cluster.
49 -
50 -
## Since everything ran perfectly, it was time to split things up.
51 -
52 -
As everything, except for the Helm Chart, was in one repository, it made parts of it hard to reuse for other websites or blogs. Thus, the first step was to place the content into its own GitHub repo.
53 -
54 -
With InkProject, not only the Markdown files containing the content are found in the Source, but also the images. These were promptly separated out and copied into their own repo, ensuring that only the Markdown files for the blog content remained in a single repo.
55 -
56 -
As for themes, they were given their own Helm repository. The same was done for the foundational components of InkProject. The binary files — yes, files, because I included direct arm, amd, etc., in case the GitHub Runners operate on different platforms — along with the configuration, were also separated.
57 -
58 -
## The GitHub Workflow was then adjusted.
59 -
60 -
The workflow now starts in the `ink-blog` repo. It sequentially pulls the following repositories:
61 -
62 -
    * ink-content
63 -
    * ink-images
64 -
    * ink-theme
65 -
    * ink-html
66 -
67 -
These are placed in the `source`, `source/images`, `theme`, and `html` directories, respectively, thus maintaining the directory structure required by InkProject.
68 -
69 -
In the next step, the blog is created using `ink publish`, after which the files are copied to the `html` directory. The html directory is its own GitHub repo, so we switch to it and execute git add, commit, and push. This way, I have the new content stored in its own repo.
70 -
71 -
The rest is discarded from the workflow, and in the next step, Docker images for multiple platforms are created. For this, the `ink-html` repo is needed and thus is checked out in the steps.
72 -
73 -
All Docker images are then merged into a MultiPlatform image and uploaded to the Docker Registry.
74 -
75 -
During all these steps, Semantic Release is used, which means both Docker images and Helm Chart are automatically tagged with the correct version.
76 -
77 -
Finally, the Helm Chart is checked out, created with the semantic version, and the image is set via the `values.yaml`. The Helm Chart is pushed to the Chart Museum, and then installed in the Kubernetes cluster.
78 -
79 -
## Workflow, the 3rd version.
80 -
81 -
The workflow is good, and one could leave it as it is. However, since I manage the content in its own repository, I would always have to first create or modify the content and then push it. Then I'd have to do the same with the `ink-blog` repo to trigger the pipeline.
82 -
83 -
No, there's a different way to do it.
84 -
85 -
## Content with its own Action
86 -
87 -
The Action in the Content Repo doesn't do much. It doesn't even assemble anything. It simply triggers the other pipeline in the `ink-blog` repo, which then handles everything else.
88 -
89 -
Content triggers `ink-blog`; `ink-blog` checks out `ink-content` and other repos, compiles everything, creates images and a Helm Chart, and deploys everything in Kubernetes.
90 -
91 -
It's as simple as that.
92 -
93 -
The advantage is: I can even create and modify content from my phone. I can also expand this for other blogs and websites. Only the content for individual sites is then stored; the build with other data always comes from the same repos. It's not set up yet, but the foundation for it is already in place. 
94 -
95 -
96 -
gelöscht content/2023-09-19-inkproject-blog-github-workflow.md
+0 −99
@@ -1,99 +0,0 @@
1 -
---
2 -
title: InkProject Blog Github Workflow
3 -
date: 2023-09-19 21:00:00
4 -
author: ruediger
5 -
cover: "/images/cat/technik.webp"
6 -
tags: [InkProjekt, Blog, GitHub, Action, Workflow, Trigger]
7 -
categories: 
8 -
    - Internet
9 -
preview: "Dieses Blog wird nicht mehr durch Hugo generiert. Der Hugo Static Content Generator war jetzt lange im Einsatz, doch seit ein paar Wochen habe ich mir alternativen angeguckt. Dabei bin ich mehrere durchgegangen und bin schließlich bei InkProjekt geblieben. " 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
[English Version](/posts/2023-09-19-inkproject-blog-github-workflow-en.html)
18 -
19 -
## Bey Bey Hugo, welcome Ink
20 -
21 -
Dieses Blog wird nicht mehr durch Hugo generiert. Der Hugo Static Content Generator war jetzt lange im Einsatz,
22 -
doch seit ein paar Wochen habe ich mir alternativen angeguckt. Dabei bin ich mehrere durchgegangen und bin schließlich bei InkProjekt geblieben. 
23 -
24 -
Nach den ersten Tests wurden dann auch nach und nach immer mehr Posts umgezogen. Dabei wurden dann auch gleich die ersten Schritte in Richtung Docker und Kubernetes gemacht. Also für Ink und dieses Blog. Docker und Kubernetes mache ich ja jetzt schom ein paar Jahre. 
25 -
26 -
## Schreiben, publish, build und deploy
27 -
28 -
Die Reihenfolge ist klar, wie immer halt. Ein neuer Post wird geschrieben, oder wie jetzt in Ink kopiert, anschliessend `ìnk publish` ausgeführt. Alle Files aus dem `public` nach `html` kopiert, so das ein Dockerfile für Nginx das html Verzeichnis mit dem neuen Content bespielen kann. Docker Push in die Docker Registry, gefolgt von einem `kubectl set image...`. Die neue Version war online. 
29 -
30 -
Das waren erst einmal noch manuelle Schritt. Ein paar Shell Scripte. 
31 -
32 -
## GitHub Actions
33 -
34 -
Nachdem das alles wunderbar lief war es an der Zeit alles automatisiert zu erledigen. Post oder Page anlegen, git add,commit,push und GitHub Action sollten sich um das zusammen bauen der Page, das Builden von Docker Images für alle Plattformen und den HelmChart kümmern. 
35 -
36 -
Das war alles erst einmal in einem Git Repo, da kam das als ersten der Helm Chart wieder raus in ein eigens. 
37 -
Der Workflow kümmerte sich nach dem Push dann um folgende Schritt: 
38 -
39 -
    1 repo Checkout
40 -
    2 Semantic Release Version hoch zählen
41 -
    3 Version in GitHub Env speichern
42 -
    4 Page im ink publish erstellen
43 -
    5 Seiten in Docker Images für alle Plattformen packen
44 -
    6 Docker Image zu einem MultiPlatform Image zusammenfügen
45 -
    7 Docker Image in die Registrie pushen
46 -
    8 Helm Chart Repo auschecken
47 -
    9 Mit der Semantiv Version Helm Chart erstellen
48 -
    10 Helm Chart ins Helm Chart Museum pushen
49 -
    11 Helm Chart in den Kubernetes Cluster deployen
50 -
51 -
## Da alles perfekt lieft, alles auseinander reißen
52 -
53 -
Da alles, bis auf der Helm Chart, in einem Repository gewesen ist konnte man Teile davon schlecht für andere Seiten oder Blogs wiederverwenden. Also wurde als erstes der Content in ein eigenes GitHub Repo gesteckt. 
54 -
55 -
Beim InkProject befindet sich in Source nicht nur die Markdown Files mit dem Content, auch die Images sind dort drin. Die wurden da auch direkt raus und auch in ein eigenes Repo kopiert. so das man wirklich nur Markdown Dateien für den Blog Content in einem Repo hat. 
56 -
57 -
Themes, die haben noch ein Helm Repository bekommen. Genau so wie die grundsätzlichen Teile von InkProject. Die Binary Files, ja Files, da ich direkt arm, amd usw dazu gepackt habe, falls die GitHub RUnner mal auf anderen Plattformen laufen, genau so wie die Config. 
58 -
59 -
## Der GitHub Workflow konnte dann angepasst werden. 
60 -
61 -
Der Workflow wird jetzt im Repo `ink-blog` gestartet. Dieser zieht sich nach einander die Repositories: 
62 -
    
63 -
    * ink-content
64 -
    * ink-images
65 -
    * ink-theme
66 -
    * ink-html
67 -
68 -
Die werden in den Ordnern `source`, `source/images`, `theme` und `html` abgelegt und somit ist die Ordner-Struktur von InkProject wie sie ein muss. 
69 -
70 -
Im nächsten Schritt wird der Blog erstellt: `ink publish` und dann die Dateien nach `html` kopiert. 
71 -
das Verzeichnis `html` ist ein GitHub Repo, da wird dann rein gewechselt und ein git add,commit,push gemacht. Damit habe ich dann schon einmal den neuen Content in einem eigenen Repo. 
72 -
73 -
Der Rest wird dann schon mal wieder im Workflow weggeschmissen und im nächsten Schritt werden jetzt die Docker Images für mehere Plattformen erstellt. Dazu wird dann das Repo `ink-html` benötigt und daher in den Steps ausgecheckt. 
74 -
75 -
Alle Docker Images werden wieder zu einem MultiPlatform Image zusammengefügt und in die Docker Registry geladen. 
76 -
77 -
Bei den ganzen Schritten natürlich wieder Semantoc Release, also Docker Images und Helm Chart automatisch mit der richtigen Version versehen. 
78 -
79 -
Der Helm Chart wird zum Schluß noch ausgecheckt und mit der Semantic Version erstellt, das Image über die `values.yaml` gesetzt. HelmChart ins Chart Museum und der Helm Chart in den Kubernetes Cluster installieren. 
80 -
81 -
## Workflow die 3. 
82 -
83 -
Der Workflow ist gut und man könnte ihn so lassen. Da ich aber den Content in einem eigenen Repo pflege, müsste man je immmer den Content erstellen oder ändern, dann pushen. Dann das gleiche beim `ink-blog` Repo auch noch machen, damit die Pipeline getriggert wird. 
84 -
85 -
Nö, das geht auch anders. 
86 -
87 -
## Content mit eigener Action 
88 -
89 -
Die Action in dem Content Repo macht nicht viel. Sie baut nicht mal irgend etwas zusammen. 
90 -
Sie triggert einfach nur die andere Pipeline im Reop `ink-blog`, welches dann alles weitere macht. 
91 -
92 -
Content triggert ink-blog, ink-blog checked `ink-content` und weitere Repos aus, baut alles zusammen, erstellt Images und Helm Chart und deployed alles in Kubernetes. 
93 -
94 -
So einfach ist das. 
95 -
96 -
Der Vorteil ist: Ich kann Content auch mal eben vom Handy aus erstellen und anpassen. Ich kann das ganze auch noch erweitern für andere Blogs und Homepages. Dann wird nur noch der Content für die einzelnen Seiten hinterlegt, der Build mit anderen Daten kommt immer aus den gleichen Repos. Das ist noch nicht eingerichtet, aber die Grundlage dafür ist schon mal angelegt. 
97 -
98 -
99 -
gelöscht content/2023-09-21-github-actions-das-triggern-von-anderen-actions-en.md
+0 −90
@@ -1,90 +0,0 @@
1 -
---
2 -
title: 'GitHub Actions: Triggering Other Actions'
3 -
date: 2023-09-21 20:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/github-actions-banner.webp"
6 -
tags: [GitHub, Action, Workflow, Trigger]
7 -
categories: 
8 -
    - Internet
9 -
preview: "GitHub Actions is a CI/CD service (Continuous Integration/Continuous Deployment) provided by GitHub, allowing developers to create and share automation workflows directly within their GitHub repositories. A common requirement is triggering one Action from another. In this article, we will explore how to effectively chain GitHub Actions to create more complex automation processes." 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: true
14 -
toc: false
15 -
---
16 -
17 -
[English Version](/posts/2023-09-21-github-actions-das-triggern-von-anderen-actions-en.html)
18 -
19 -
![Github Actions](/images/posts/github-actions-banner.webp)
20 -
21 -
## Introduction
22 -
23 -
GitHub Actions is a CI/CD service (Continuous Integration/Continuous Deployment) provided by GitHub, allowing developers to create and share automation workflows directly within their GitHub repositories. A common requirement is triggering one Action from another. In this article, we will explore how to effectively chain GitHub Actions to create more complex automation processes.
24 -
25 -
## Basics of GitHub Actions
26 -
27 -
GitHub Actions are based on workflows, defined in YAML files within the .github/workflows directory of a repository. A workflow consists of one or more jobs, and each job contains steps, which are commands or Actions.
28 -
29 -
## Triggering Other Actions
30 -
31 -
To trigger a GitHub Action from another Action, several approaches are available:
32 -
33 -
1. Repository Dispatch Event:
34 -
   * One can trigger a Repository Dispatch Event from an Action to start a workflow in the same or a different repository.
35 -
   * This requires a Personal Access Token to authenticate the event.
36 -
2. Workflow Dispatch Event:
37 -
   * The Workflow Dispatch Event allows for manually triggering a workflow.
38 -
   * It can also be triggered by an API call, making it startable from another Action.
39 -
3. Scheduled Workflows:
40 -
   * Workflows can be configured to run at specific times.
41 -
   * This can be used to trigger subsequent workflows.
42 -
43 -
44 -
45 -
## Example: Repository Dispatch Event
46 -
47 -
Here is a simple example of using a Repository Dispatch Event to trigger a workflow:
48 -
49 -
50 -
```
51 -
# .github/workflows/triggering-workflow.yml
52 -
name: Triggering Workflow
53 -
on: [push]
54 -
jobs:
55 -
  trigger:
56 -
    runs-on: ubuntu-latest
57 -
    steps:
58 -
      - name: Trigger Another Workflow
59 -
        run: |
60 -
          curl -XPOST -u "USERNAME:${{ secrets.PAT }}" \
61 -
            -H "Accept: application/vnd.github.everest-preview+json" \
62 -
            -H "Content-Type: application/json" \
63 -
            https://api.github.com/repos/OWNER/REPO/dispatches \
64 -
            --data '{"event_type": "triggered"}'
65 -
66 -
67 -
```
68 -
69 -
```
70 -
# .github/workflows/triggered-workflow.yml
71 -
name: Triggered Workflow
72 -
on:
73 -
  repository_dispatch:
74 -
    types: [triggered]
75 -
jobs:
76 -
  build:
77 -
    runs-on: ubuntu-latest
78 -
    steps:
79 -
      - name: Checkout Code
80 -
        uses: actions/checkout@v2
81 -
      # Additional steps...
82 -
83 -
84 -
```
85 -
86 -
In this example, a push event starts the triggering-workflow.yml workflow, which then triggers the triggered-workflow.yml through a Repository Dispatch Event.
87 -
88 -
## Conclusion
89 -
90 -
Triggering GitHub Actions from other Actions enables the creation of complex and flexible automation workflows. By using methods like the Repository Dispatch Event or the Workflow Dispatch Event, developers can efficiently design and optimize their CI/CD processes.
\ No newline at end of file
gelöscht content/2023-09-21-github-actions-das-triggern-von-anderen-actions.md
+0 −85
@@ -1,85 +0,0 @@
1 -
---
2 -
title: 'GitHub Actions: Das Triggern von Anderen Actions'
3 -
date: 2023-09-21 20:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/github-actions-banner.webp"
6 -
tags: [GitHub, Action, Workflow, Trigger]
7 -
categories: 
8 -
    - Internet
9 -
preview: "GitHub Actions ist ein CI/CD-Service (Continuous Integration/Continuous Deployment) von GitHub, der es Entwicklern ermöglicht, Automatisierungsworkflows direkt in ihren GitHub-Repositories zu erstellen und zu teilen. Eine häufige Anforderung ist das Triggern einer Action aus einer anderen Action heraus. In diesem Artikel werden wir untersuchen, wie man GitHub Actions effektiv verkettet und so komplexere Automatisierungsprozesse erstellt." 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
[English Version](/posts/2023-09-21-github-actions-das-triggern-von-anderen-actions-en.html)
18 -
19 -
![Github Actions](/images/posts/github-actions-banner.webp)
20 -
21 -
## Einleitung
22 -
23 -
GitHub Actions ist ein CI/CD-Service (Continuous Integration/Continuous Deployment) von GitHub, der es Entwicklern ermöglicht, Automatisierungsworkflows direkt in ihren GitHub-Repositories zu erstellen und zu teilen. Eine häufige Anforderung ist das Triggern einer Action aus einer anderen Action heraus. In diesem Artikel werden wir untersuchen, wie man GitHub Actions effektiv verkettet und so komplexere Automatisierungsprozesse erstellt.
24 -
25 -
## Grundlagen von GitHub Actions
26 -
27 -
GitHub Actions basieren auf Workflows, die in YAML-Dateien innerhalb des .github/workflows-Verzeichnisses eines Repositories definiert sind. Ein Workflow besteht aus einem oder mehreren Jobs, und jeder Job besteht aus Schritten, die Befehle oder Actions sind.
28 -
29 -
## Triggern von Anderen Actions
30 -
31 -
Um eine GitHub Action aus einer anderen Action heraus zu triggern, gibt es verschiedene Ansätze:
32 -
33 -
Man kann ein Repository Dispatch Event von einer Action auslösen, um einen Workflow in demselben oder einem anderen Repository zu starten.
34 -
Dies erfordert ein Personal Access Token, um das Event zu authentifizieren.
35 -
36 -
  1. Workflow Dispatch Event:
37 -
    * Mit dem Workflow Dispatch Event kann man manuell einen Workflow starten.
38 -
    * Es kann auch durch einen API-Aufruf ausgelöst werden, was es von einer anderen Action aus startbar macht.
39 -
  2. Scheduled Workflows:
40 -
    * Workflows können so konfiguriert werden, dass sie zu bestimmten Zeiten ausgeführt werden.
41 -
    * Dies kann genutzt werden, um nachfolgende Workflows zu triggern.
42 -
43 -
## Beispiel: Repository Dispatch Event
44 -
45 -
Hier ist ein einfaches Beispiel, wie man ein Repository Dispatch Event verwendet, um einen Workflow zu triggern:
46 -
47 -
```
48 -
# .github/workflows/triggering-workflow.yml
49 -
name: Triggering Workflow
50 -
on: [push]
51 -
jobs:
52 -
  trigger:
53 -
    runs-on: ubuntu-latest
54 -
    steps:
55 -
      - name: Trigger Another Workflow
56 -
        run: |
57 -
          curl -XPOST -u "USERNAME:${{ secrets.PAT }}" \
58 -
            -H "Accept: application/vnd.github.everest-preview+json" \
59 -
            -H "Content-Type: application/json" \
60 -
            https://api.github.com/repos/OWNER/REPO/dispatches \
61 -
            --data '{"event_type": "triggered"}'
62 -
63 -
```
64 -
65 -
```
66 -
# .github/workflows/triggered-workflow.yml
67 -
name: Triggered Workflow
68 -
on:
69 -
  repository_dispatch:
70 -
    types: [triggered]
71 -
jobs:
72 -
  build:
73 -
    runs-on: ubuntu-latest
74 -
    steps:
75 -
      - name: Checkout Code
76 -
        uses: actions/checkout@v2
77 -
      # Weitere Schritte...
78 -
79 -
```
80 -
81 -
In diesem Beispiel wird durch einen push Event der triggering-workflow.yml Workflow gestartet, der dann das triggered-workflow.yml durch ein Repository Dispatch Event auslöst.
82 -
83 -
### Fazit
84 -
85 -
Das Triggern von GitHub Actions aus anderen Actions heraus ermöglicht die Erstellung von komplexen und flexiblen Automatisierungsworkflows. Durch die Verwendung von Methoden wie dem Repository Dispatch Event oder dem Workflow Dispatch Event können Entwickler ihre CI/CD-Prozesse effizient gestalten und optimieren.
\ No newline at end of file
gelöscht content/2023-09-21-github-workflow-trigger-in-other-repository-en.md
+0 −185
@@ -1,185 +0,0 @@
1 -
---
2 -
title: Github workflow trigger in other repository
3 -
date: 2023-09-21 21:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/github-actions-banner.webp"
6 -
tags: [GitHub, Action, Workflow, Trigger]
7 -
categories: 
8 -
    - Internet
9 -
preview: "In the first repository, a workflow named trigger_on_push.yaml is created, which triggers a workflow named trigger_prod.yaml in another repo. This second repo could even reside in another GitHub account. All you need is a valid token." 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: true
14 -
toc: false
15 -
---
16 -
17 -
[German Version](/posts/2023-09-21-github-workflow-trigger-in-other-repository.html)
18 -
19 -
![Github Actions](/images/posts/github-actions-banner.webp)
20 -
21 -
## Triggering a GitHub Action in another repository
22 -
23 -
In the first repository, a workflow named trigger_on_push.yaml is created, which triggers a workflow named trigger_prod.yaml in another repo. This second repo could even reside in another GitHub account. All you need is a valid token.
24 -
25 -
But why via an intermediate action? The answer is simple. The 2nd repository doesn't receive any pushes unless something changes within that repository. Since all changes are made in the 1st repository, and the second only contains the software for generating the page and the Docker images, nothing there changes. Thus, Semantic Release can't increment a version.
26 -
27 -
Hence, the trigger action in the 2nd repo. It modifies a file within the repo and pushes it to itself. After that, it triggers the actual build action main.yaml. This means a change is present, and Semantic Release finds commits that can be included in this release. 
28 -
29 -
First repository workflow `trigger_on_push.yaml`: 
30 -
31 -
```
32 -
name: Build Develop
33 -
on:
34 -
    push:
35 -
        branches:
36 -
            - develop
37 -
jobs:
38 -
    trigger-workflow:
39 -
        runs-on: ubuntu-latest
40 -
        steps:
41 -
            - name: Trigger build Repo
42 -
              uses: convictional/trigger-workflow-and-wait@v1.6.1
43 -
              with:
44 -
                owner: ruedigerp
45 -
                repo: ink-blog
46 -
                github_token: ${{ secrets.GH_TOKEN }}
47 -
                workflow_file_name: trigger_prod.yaml 
48 -
                ref: develop 
49 -
                wait_interval: 10 
50 -
                propagate_failure: true 
51 -
                trigger_workflow: true
52 -
                wait_workflow: true
53 -
```
54 -
55 -
In the Second Repo `trigger_prod.yaml`
56 -
57 -
```
58 -
name: Trigger Build Prod
59 -
on:
60 -
  workflow_dispatch:
61 -
    inputs:
62 -
        workflow_02:
63 -
            description: 'ًWorkflow 2 which will be triggered'
64 -
            required: true
65 -
            default: 'trigger-workflow'
66 -
        workflow2_github_account:
67 -
            description: 'GitHub Account Owner'
68 -
            required: true
69 -
            default: 'youraccount'
70 -
        workflow2_repo_github:
71 -
            description: 'repo-name'
72 -
            required: true
73 -
            ref: main
74 -
            default: 'repo1'
75 -
jobs:
76 -
  trigger-build: 
77 -
    runs-on: ubuntu-latest
78 -
    steps:
79 -
      - name: Checkout repository
80 -
        uses: actions/checkout@v2
81 -
        with:
82 -
          fetch-depth: 0
83 -
      - name: add Trigger page
84 -
        run: |
85 -
          ls -la 
86 -
          echo "build $(date)" > buildit.txt
87 -
          ls -la
88 -
          git remote -v
89 -
          export GH_TOKEN="${{ secrets.DOCKHUB_TOKEN }}"
90 -
          git config --global user.email "your@main.com"
91 -
          git config --global user.name "Your Name"
92 -
          git add .
93 -
          git commit -m "fix: new build $(date)"
94 -
          git push
95 -
  trigger-workflow:
96 -
    runs-on: ubuntu-latest
97 -
    steps:
98 -
        - name: Trigger build Repo
99 -
          uses: convictional/trigger-workflow-and-wait@v1.6.1
100 -
          with:
101 -
            owner: ruedigerp
102 -
            repo: repo2
103 -
            github_token: ${{ secrets.DOCKERHUB_TOKEN }}
104 -
            workflow_file_name: main.yaml 
105 -
            ref: main 
106 -
            wait_interval: 10 
107 -
            propagate_failure: true 
108 -
            trigger_workflow: true
109 -
            wait_workflow: true   
110 -
```
111 -
112 -
The significantly shortened main.yaml in the second repository.
113 -
```
114 -
name: Build Prod
115 -
on:
116 -
  push:
117 -
    branches:
118 -
      - 'main'
119 -
  workflow_dispatch:
120 -
    inputs:
121 -
        workflow_02:
122 -
            description: 'ًWorkflow 2 which will be triggered'
123 -
            required: true
124 -
            default: 'trigger-workflow'
125 -
        workflow2_github_account:
126 -
            description: 'GitHub Account Owner'
127 -
            required: true
128 -
            default: 'youraccount'
129 -
        workflow2_repo_github:
130 -
            description: 'repo-name'
131 -
            required: true
132 -
            default: 'repo2'
133 -
env:
134 -
  IMAGE_NAME: ghcr.io/youraccount/imagename
135 -
  DOCKERFILE: Dockerfile
136 -
jobs:
137 -
  prepare:
138 -
    runs-on: ubuntu-latest
139 -
    steps:
140 -
      - name: Checkout repository
141 -
        uses: actions/checkout@v2
142 -
        with:
143 -
          fetch-depth: 0
144 -
      - name: Create Sematic Release Version
145 -
        env:
146 -
          GITHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
147 -
        run: |
148 -
          export HOME=/tmp
149 -
          git config --global user.email "your@main.com"
150 -
          git config --global user.name "youraccount"
151 -
          git config --global credential.helper cache
152 -
          npx semantic-release
153 -
  build-amd64:
154 -
    needs: [ prepare ]
155 -
    runs-on: ubuntu-latest
156 -
    steps:
157 -
      - name: Check out code
158 -
        uses: actions/checkout@v2
159 -
        with:
160 -
          fetch-depth: 0
161 -
      
162 -
      - name: Login to GitHub Container Registry
163 -
        uses: docker/login-action@v2
164 -
        with:
165 -
          registry: "ghcr.io"
166 -
          username: ${{ secrets.GH_USERNAME }}
167 -
          password: ${{ secrets.GH_TOKEN }}
168 -
      - name: Build and push AMD64 image
169 -
        run: |
170 -
          # ...
171 -
          # build stuff 
172 -
          # ...
173 -
          docker build -f ${{ env.DOCKERFILE }} --build-arg GOOS=linux --build-arg GOARCH=amd64 --build-arg NEXT_VERSION="$VERSION" --build-arg BUILD_TIMESTAMP="$BUILD_TIMESTAMP" --build-arg GIT_BRANCH="$GIT_BRANCH" --build-arg COMMIT_HASH="$COMMIT_HASH" -t ${{ env.IMAGE_NAME }}:$VERSION-amd64 -t ${{ env.IMAGE_NAME }}:latest-amd64 .
174 -
          docker push ${{ env.IMAGE_NAME }}:$VERSION-amd64          
175 -
          # ... 
176 -
  merge-images: 
177 -
     # ... 
178 -
  other-cool-stuff: 
179 -
     # ... 
180 -
```
181 -
182 -
183 -
184 -
185 -
gelöscht content/2023-09-21-github-workflow-trigger-in-other-repository.md
+0 −202
@@ -1,202 +0,0 @@
1 -
---
2 -
title: Github workflow trigger in other repository
3 -
date: 2023-09-21 21:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/github-actions-banner.webp"
6 -
tags: [GitHub, Action, Workflow, Trigger]
7 -
categories: 
8 -
    - Internet
9 -
preview: "Im ersten Repository wird ein Workflow `trigger_on_push.yaml` erstellt, der in einem anderen Repo einen Worklow `trigger_prod.yaml` triggert. Dieser kann sogar in einem anderen GitHub Account liegen. Man benötigt nur einen gültigen Token. " 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
[English Version](/posts/2023-09-21-github-workflow-trigger-in-other-repository-en.html)
18 -
19 -
![Github Actions](/images/posts/github-actions-banner.webp)
20 -
21 -
## Eine Github Action in einem anderem Repository triggern
22 -
23 -
Im ersten Repository wird ein Workflow `trigger_on_push.yaml` erstellt, der in einem anderen Repo einen Worklow `trigger_prod.yaml` triggert. Dieser kann sogar in einem anderen GitHub Account liegen. Man benötigt nur einen gültigen Token. 
24 -
25 -
Aber wieso über eine dazwischen geschaltete Action? Ganz einfach, das 2. Repository bekommt keine Pushes, ausser es würde sich etwas in diesem Repository ändern. Da aber die Änderungen nur im 1. Repository gemacht werden und das zweite nur die Software für das Generieren der Page und der Docker Images enthält, wird sich da nichts ändern. Also kann Semantic Release auch keine Version hochzählen. 
26 -
27 -
Daher die Trigger Action im 2. Repo. Die ändert nur eine Datei im Repo und pushed es in sich selbst. Danach Triggert sie die eigentliche Build Action `main.yaml`. Damit ist eine Änderung vorhanden und Semantic Release findet Commits, die dann in dieses Release mit rein kommen. 
28 -
29 -
Repo 1 Workflow `trigger_on_push.yaml`: 
30 -
31 -
```
32 -
name: Build Develop
33 -
34 -
on:
35 -
    push:
36 -
        branches:
37 -
            - develop
38 -
39 -
jobs:
40 -
    trigger-workflow:
41 -
        runs-on: ubuntu-latest
42 -
        steps:
43 -
            - name: Trigger build Repo
44 -
              uses: convictional/trigger-workflow-and-wait@v1.6.1
45 -
              with:
46 -
                owner: ruedigerp
47 -
                repo: ink-blog
48 -
                github_token: ${{ secrets.GH_TOKEN }}
49 -
                workflow_file_name: trigger_prod.yaml 
50 -
                ref: develop 
51 -
                wait_interval: 10 
52 -
                propagate_failure: true 
53 -
                trigger_workflow: true
54 -
                wait_workflow: true
55 -
```
56 -
57 -
Im 2. Repo `trigger_prod.yaml`
58 -
59 -
```
60 -
name: Trigger Build Prod
61 -
62 -
on:
63 -
  workflow_dispatch:
64 -
    inputs:
65 -
        workflow_02:
66 -
            description: 'ًWorkflow 2 which will be triggered'
67 -
            required: true
68 -
            default: 'trigger-workflow'
69 -
70 -
        workflow2_github_account:
71 -
            description: 'GitHub Account Owner'
72 -
            required: true
73 -
            default: 'youraccount'
74 -
75 -
        workflow2_repo_github:
76 -
            description: 'repo-name'
77 -
            required: true
78 -
            ref: main
79 -
            default: 'repo1'
80 -
81 -
82 -
jobs:
83 -
  trigger-build: 
84 -
    runs-on: ubuntu-latest
85 -
    steps:
86 -
      - name: Checkout repository
87 -
        uses: actions/checkout@v2
88 -
        with:
89 -
          fetch-depth: 0
90 -
      - name: add Trigger page
91 -
        run: |
92 -
          ls -la 
93 -
          echo "build $(date)" > buildit.txt
94 -
          ls -la
95 -
          git remote -v
96 -
          export GH_TOKEN="${{ secrets.DOCKHUB_TOKEN }}"
97 -
          git config --global user.email "your@main.com"
98 -
          git config --global user.name "Your Name"
99 -
          git add .
100 -
          git commit -m "fix: new build $(date)"
101 -
          git push
102 -
103 -
  trigger-workflow:
104 -
    runs-on: ubuntu-latest
105 -
    steps:
106 -
        - name: Trigger build Repo
107 -
          uses: convictional/trigger-workflow-and-wait@v1.6.1
108 -
          with:
109 -
            owner: ruedigerp
110 -
            repo: repo2
111 -
            github_token: ${{ secrets.DOCKERHUB_TOKEN }}
112 -
            workflow_file_name: main.yaml 
113 -
            ref: main 
114 -
            wait_interval: 10 
115 -
            propagate_failure: true 
116 -
            trigger_workflow: true
117 -
            wait_workflow: true   
118 -
```
119 -
120 -
Die `main.yaml` in Repo2: 
121 -
122 -
```
123 -
name: Build Prod
124 -
125 -
on:
126 -
  push:
127 -
    branches:
128 -
      - 'main'
129 -
  workflow_dispatch:
130 -
    inputs:
131 -
        workflow_02:
132 -
            description: 'ًWorkflow 2 which will be triggered'
133 -
            required: true
134 -
            default: 'trigger-workflow'
135 -
136 -
        workflow2_github_account:
137 -
            description: 'GitHub Account Owner'
138 -
            required: true
139 -
            default: 'youraccount'
140 -
141 -
        workflow2_repo_github:
142 -
            description: 'repo-name'
143 -
            required: true
144 -
            default: 'repo2'
145 -
146 -
env:
147 -
  IMAGE_NAME: ghcr.io/youraccount/imagename
148 -
  DOCKERFILE: Dockerfile
149 -
150 -
jobs:
151 -
  prepare:
152 -
    runs-on: ubuntu-latest
153 -
    steps:
154 -
      - name: Checkout repository
155 -
        uses: actions/checkout@v2
156 -
        with:
157 -
          fetch-depth: 0
158 -
159 -
      - name: Create Sematic Release Version
160 -
        env:
161 -
          GITHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
162 -
        run: |
163 -
          export HOME=/tmp
164 -
          git config --global user.email "your@main.com"
165 -
          git config --global user.name "youraccount"
166 -
          git config --global credential.helper cache
167 -
          npx semantic-release
168 -
169 -
  build-amd64:
170 -
    needs: [ prepare ]
171 -
    runs-on: ubuntu-latest
172 -
    steps:
173 -
      - name: Check out code
174 -
        uses: actions/checkout@v2
175 -
        with:
176 -
          fetch-depth: 0
177 -
      
178 -
      - name: Login to GitHub Container Registry
179 -
        uses: docker/login-action@v2
180 -
        with:
181 -
          registry: "ghcr.io"
182 -
          username: ${{ secrets.GH_USERNAME }}
183 -
          password: ${{ secrets.GH_TOKEN }}
184 -
185 -
      - name: Build and push AMD64 image
186 -
        run: |
187 -
          # ...
188 -
          # build stuff 
189 -
          # ...
190 -
          docker build -f ${{ env.DOCKERFILE }} --build-arg GOOS=linux --build-arg GOARCH=amd64 --build-arg NEXT_VERSION="$VERSION" --build-arg BUILD_TIMESTAMP="$BUILD_TIMESTAMP" --build-arg GIT_BRANCH="$GIT_BRANCH" --build-arg COMMIT_HASH="$COMMIT_HASH" -t ${{ env.IMAGE_NAME }}:$VERSION-amd64 -t ${{ env.IMAGE_NAME }}:latest-amd64 .
191 -
          docker push ${{ env.IMAGE_NAME }}:$VERSION-amd64          
192 -
          # ... 
193 -
194 -
  merge-images: 
195 -
     # ... 
196 -
  other-cool-stuff: 
197 -
     # ... 
198 -
```
199 -
200 -
201 -
202 -
gelöscht content/2023-09-21-kubernetes-network-policies-en.md
+0 −77
@@ -1,77 +0,0 @@
1 -
---
2 -
title: 'Kubernetes Network Policies'
3 -
date: 2023-09-21 22:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2023/09/kubernetes-netpol.webp"
6 -
tags: [Kubernetes, NetworkPolicy]
7 -
categories: 
8 -
    - Internet
9 -
preview: "In the world of container orchestration, Kubernetes plays a leading role in managing and automating containerized applications. One of the key components in Kubernetes is the NetworkPolicy, an essential tool for controlling communication between Pods. In this article, we will explore the basics of NetworkPolicies and how they can be used to secure Kubernetes clusters." 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: true
14 -
toc: false
15 -
---
16 -
17 -
[German Version](/posts/2023-09-21-kubernetes-network-policies.html)
18 -
19 -
![Github Actions](/images/posts/2023/09/kubernetes-netpol.webp)
20 -
21 -
22 -
## Introduction
23 -
24 -
In the world of container orchestration, Kubernetes plays a leading role in managing and automating containerized applications. One of the key components in Kubernetes is the NetworkPolicy, an essential tool for controlling communication between Pods. In this article, we will explore the basics of NetworkPolicies and how they can be used to secure Kubernetes clusters.
25 -
26 -
## Basics of NetworkPolicies
27 -
28 -
NetworkPolicies are specific objects in Kubernetes that define how groups of Pods may communicate with each other and with other network endpoints. They use labels to identify Pods and define rules that govern the traffic between these Pods.
29 -
30 -
## Types of NetworkPolicies
31 -
32 -
  1. Ingress Rules:
33 -
    * These rules control incoming traffic to Pods.
34 -
    * They can specify which sources (IP addresses or Pods) are allowed to access a Pod.
35 -
  2. Egress Rules:
36 -
    * These rules control outgoing traffic from Pods.
37 -
    * They can define which destinations (IP addresses or Pods) a Pod is allowed to communicate with.
38 -
39 -
### Creating a NetworkPolicy
40 -
41 -
To create a NetworkPolicy, you define a YAML file with the desired rules and apply it to the Kubernetes cluster. Here is a simple example of an Ingress NetworkPolicy:
42 -
43 -
```
44 -
apiVersion: networking.k8s.io/v1
45 -
kind: NetworkPolicy
46 -
metadata:
47 -
  name: example-networkpolicy
48 -
  namespace: default
49 -
spec:
50 -
  podSelector:
51 -
    matchLabels:
52 -
      app: myapp
53 -
  policyTypes:
54 -
  - Ingress
55 -
  ingress:
56 -
  - from:
57 -
    - ipBlock:
58 -
        cidr: 172.17.0.0/16
59 -
```
60 -
61 -
62 -
This policy allows incoming traffic to Pods with the label app: myapp only from the IP range 172.17.0.0/16.
63 -
64 -
## Best Practices
65 -
66 -
  1. Principle of Least Privilege:
67 -
    * Grant only the minimal necessary permissions.
68 -
    * By default, deny all connections and only allow specific ones.
69 -
  2. Explicit Egress Rules:
70 -
    * Define clear Egress rules to control outgoing traffic.
71 -
  3. Use of Labels:
72 -
    * Use labels to identify Pods, making the management of NetworkPolicies more straightforward.
73 -
74 -
75 -
## Conclusion
76 -
77 -
NetworkPolicies are an indispensable tool for securing Kubernetes clusters. They enable fine-grained control over the communication between Pods and help enforce the principle of least privilege. Through the effective use of NetworkPolicies, organizations can operate their applications in Kubernetes securely and reliably.
\ No newline at end of file
gelöscht content/2023-09-21-kubernetes-network-policies.md
+0 −76
@@ -1,76 +0,0 @@
1 -
---
2 -
title: 'Kubernetes Network Policies'
3 -
date: 2023-09-21 22:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2023/09/kubernetes-netpol.webp"
6 -
tags: [Kubernetes, NetworkPolicy]
7 -
categories: 
8 -
    - Internet
9 -
preview: "In der Welt der Container-Orchestrierung spielt Kubernetes eine führende Rolle bei der Verwaltung und Automatisierung von containerisierten Anwendungen. Eine der Schlüsselkomponenten in Kubernetes ist die NetworkPolicy, ein wichtiges Werkzeug zur Kontrolle der Kommunikation zwischen Pods. In diesem Artikel werden wir uns mit den Grundlagen von NetworkPolicies befassen und wie sie zur Sicherung von Kubernetes-Clustern eingesetzt werden können." 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
[Englisch Version](/posts/2023-09-21-kubernetes-network-policies-en.html)
18 -
19 -
![Github Actions](/images/posts/2023/09/kubernetes-netpol.webp)
20 -
21 -
22 -
## Einleitung
23 -
24 -
In der Welt der Container-Orchestrierung spielt Kubernetes eine führende Rolle bei der Verwaltung und Automatisierung von containerisierten Anwendungen. Eine der Schlüsselkomponenten in Kubernetes ist die NetworkPolicy, ein wichtiges Werkzeug zur Kontrolle der Kommunikation zwischen Pods. In diesem Artikel werden wir uns mit den Grundlagen von NetworkPolicies befassen und wie sie zur Sicherung von Kubernetes-Clustern eingesetzt werden können.
25 -
26 -
## Grundlagen von NetworkPolicies
27 -
28 -
NetworkPolicies sind spezifische Objekte in Kubernetes, die festlegen, wie Gruppen von Pods miteinander und mit anderen Netzwerkendpunkten kommunizieren dürfen. Sie verwenden Labels, um Pods zu identifizieren und Regeln zu definieren, die den Datenverkehr zwischen diesen Pods steuern.
29 -
30 -
## Arten von NetworkPolicies
31 -
32 -
  1. Eingehende (Ingress) Regeln:
33 -
    * Diese Regeln steuern den eingehenden Datenverkehr zu Pods.
34 -
    * Sie können spezifizieren, welche Quellen (IP-Adressen oder Pods) erlaubt sind, auf einen Pod zuzugreifen.
35 -
  2. Ausgehende (Egress) Regeln:
36 -
    * Diese Regeln steuern den ausgehenden Datenverkehr von Pods.
37 -
    * Sie können festlegen, zu welchen Zielen (IP-Adressen oder Pods) ein Pod kommunizieren darf.
38 -
39 -
## Erstellung einer NetworkPolicy
40 -
41 -
Um eine NetworkPolicy zu erstellen, definiert man eine YAML-Datei mit den gewünschten Regeln und wendet sie auf den Kubernetes-Cluster an. Hier ist ein einfaches Beispiel für eine Ingress NetworkPolicy:
42 -
43 -
```
44 -
apiVersion: networking.k8s.io/v1
45 -
kind: NetworkPolicy
46 -
metadata:
47 -
  name: example-networkpolicy
48 -
  namespace: default
49 -
spec:
50 -
  podSelector:
51 -
    matchLabels:
52 -
      app: myapp
53 -
  policyTypes:
54 -
  - Ingress
55 -
  ingress:
56 -
  - from:
57 -
    - ipBlock:
58 -
        cidr: 172.17.0.0/16
59 -
60 -
```
61 -
62 -
Diese Policy erlaubt den eingehenden Datenverkehr zu Pods mit dem Label app: myapp nur aus dem IP-Bereich 172.17.0.0/16.
63 -
64 -
## Best Practices
65 -
66 -
  1. Gewähren Sie nur die minimal notwendigen Berechtigungen.
67 -
    * Verweigern Sie standardmäßig alle Verbindungen und erlauben Sie nur spezifische.
68 -
  2. Explizite Egress-Regeln:
69 -
    * Definieren Sie klare Egress-Regeln, um den ausgehenden Datenverkehr zu kontrollieren.
70 -
  3. Verwendung von Labels:
71 -
    * Verwenden Sie Labels zur Identifizierung von Pods, um die Verwaltung von NetworkPolicies zu erleichtern.
72 -
73 -
## Fazit
74 -
75 -
NetworkPolicies sind ein unverzichtbares Werkzeug zur Sicherung von Kubernetes-Clustern. Sie ermöglichen feingranulare Kontrolle über die Kommunikation zwischen Pods und helfen, das Prinzip der geringsten Privilegien durchzusetzen. Durch den effektiven Einsatz von NetworkPolicies können Organisationen ihre Anwendungen in Kubernetes sicher und zuverlässig betreiben.
76 -
gelöscht content/2024-01-04-Warp-Editor-en.md
+0 −49
@@ -1,49 +0,0 @@
1 -
---
2 -
title: 'Warp Editor'
3 -
date: 2024-01-04 19:20:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/01/warp-editor.webp"
6 -
tags: [Internet, Develop, Terminal]
7 -
categories: 
8 -
    - Internet
9 -
    - Develop
10 -
    - Terminal
11 -
preview: "Warp Terminal. The replacement for iTerm with many features. Session management, command palette, workflows, and much more. It is now being extensively tested, and more will be reported about it later." 
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: true
16 -
toc: false
17 -
---
18 -
19 -
[German Version](/posts/2024-01-04-warp-editor.html)
20 -
21 -
22 -
![Warp Editor](/images/posts/2024/01/warp-editor.webp)
23 -
24 -
25 -
Before the holidays, I came across a chic terminal replacement. Wave is very chic and offers many features. Unfortunately, it had one downside. It doesn't support ZSH, so we were all a bit disappointed in the company.
26 -
27 -
But today, my colleague Jan came up with a new alternative, which he enthusiastically reported about in the Develop Channel on Slack, including a link. So, of course, we had to check it out right away. Yep, it looked very chic too. So, we tested it immediately. It's about the [Warp Terminal](https://www.warp.dev), which supports ZSH and also has good features. 
28 -
29 -
   * Write with an IDE-style editor
30 -
   * Easily navigate through outputs
31 -
   * Save commands to reuse later
32 -
   * Ask Warp AI for explanations or debugging
33 -
   * Customize keybindings and launch configurations
34 -
   * Choose from preloaded themes or create your own
35 -
36 -
Installation via binary download or through Homebrew:
37 -
38 -
    brew install --cask warp
39 -
40 -
After opening it, a login or registration screen appears. Those who wish can complete the onboarding survey.
41 -
42 -
In addition to appearance settings, it features a very large command palette, AI support, and session management. Sessions can be saved and restored.
43 -
Settings can also be saved. This allows for custom setups for different use cases. In the Dev environment, everything is green, and when working in Prod, everything turns red, so you know when to be cautious.
44 -
45 -
Warp is very powerful, and today was just a first look and initial settings were made.
46 -
47 -
There will definitely be a follow-up post about it, including some tips and more information about individual features.
48 -
49 -
gelöscht content/2024-01-04-Warp-Editor.md
+0 −47
@@ -1,47 +0,0 @@
1 -
---
2 -
title: 'Warp Terminal'
3 -
date: 2024-01-04 19:20:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/01/warp-editor.webp"
6 -
tags: [Internet, Develop, Terminal]
7 -
categories: 
8 -
    - Internet
9 -
    - Develop
10 -
    - Terminal
11 -
preview: "Warp Terminal. Der Ersatz für iTerm mit sehr vielen Funktionen. Session Management, Command Palette, Workflows und vielem mehr. Wird jetzt ausgiebig getestet und dann noch mehr drüber berichtet." 
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
[Englisch Version](/posts/2024-01-04-warp-editor-en.html)
20 -
21 -
22 -
![Warp Editor](/images/posts/2024/01/warp-editor.webp)
23 -
24 -
Vor den Feiertagen, bin ich auf einen schicken Terminal-Ersatz gestossen. Wave ist sehr schick und bietet viele Funktionen. Leider hatte er einen Nachteil. ZSH kann er nicht, daher waren wir in der Firma alle etwas entäuscht. 
25 -
26 -
Aber heute kam mein Kollege Jan mit einer neuen Alternative um die Ecke, von dem er begeistert im Develop Channel in Slack berichtete. Inklusive eines Links, also mussten wir natürlich direkt nachsehen. Yep, das sah auch sehr schick aus. Also direkt mal getestet. Es geht um den [Warp Terminal](https://www.warp.dev), der zsh unterstützt und zudem über gute Features verfügt. 
27 -
28 -
   * Schreiben mit einem IDE-Stil-Editor
29 -
   * Einfaches Navigieren durch Ausgaben
30 -
   * Befehle speichern, um sie später wiederzuverwenden
31 -
   * Warp-KI um Erklärungen oder Debugging bitten
32 -
   * Tastenkombinationen und Startkonfigurationen anpassen
33 -
   * Aus vorgeladenen Themen auswählen oder eigene erstellen
34 -
35 -
Installation per Binary Download oder per Homebrew: 
36 -
37 -
    brew install --cask warp
38 -
39 -
Danach wird nach dem Öffnen ein Login bzw. die Registrierung angezeigt. Wer möchte kann die Onboarding Survey machen. 
40 -
41 -
Neben Einstellungen zum Aussehen hat er eine sehr große Command Palette, AI Support und Session Management. Sessions können gespeichert werden und wieder hergestellt werden. 
42 -
Auch die Settings können gespeichert werden. So kann man sich auch für verschiedene Anwendungsfälle das Setup extra zusammen stellen. In der Dev-Umgebung ist alles grün und wenn man in Prod arbeitet, ist alles rot, sodass man weiß, wann man vorsichtig sein sollte. 
43 -
44 -
Warp ist sehr mächtig und heute wurde erst einmal reingeguckt und erste Einstellungen gemacht. 
45 -
46 -
Es wird bestimmt ein Follow-Up-Post dazu kommen, dann auch mit ein paar Tipps und mehr Infos zu einzelnen Funktionen. 
47 -
gelöscht content/2024-01-11-static-blog-automation copy.md
+0 −54
@@ -1,54 +0,0 @@
1 -
---
2 -
title: 'Static InkProject Blog Automation API'
3 -
date: 2024-01-11 16:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/01/static-blog.webp"
6 -
tags: [Blog, InkProjekt, API]
7 -
categories: 
8 -
    - Internet
9 -
preview: "" 
10 -
draft: true
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
<!-- [Englisch Version](/posts/2023-09-21-kubernetes-network-policies-en.html)
18 -
-->
19 -
20 -
![Static Weblog](/images/posts/2024/01/static-blog.webp)
21 -
22 -
Mein Blog ist jetzt seit ein past Jahren ein Static Html Blog. Benutzt hstte ich Jekyll, Octopress und etwas lönger Hugo. 
23 -
Seit ein paar Monaten benutze ich dafür InkProject. Mach der Migration der Blogposts, den ersten manuellen durchläufen und manuellem 'docker build' für dem nginx mit dem generierten HTML, ist das ganze dann auch recht schnell auf github gelandet. Mit ein paar Github Actions Zeilen wurde das Blog so scgon mal nach Änderungen und einem Push automatisch zusammen gebaut. 
24 -
25 -
Im nächsten Schritt wurde alles aufgeteilt. Das ink Binary und die Config selbst, der Content, die Images und das Theme sind in eigene Git Repository getrennt wurden. Gleichzeitig wurde der git Branch develop erstellt, so das es auch eine Testversion gibt. 
26 -
27 -
Im Content Repository wurde ein Workflow hinzugefügt, der bei commits automatisch das ink-Blog repository triggert und dort den Workflow aufruft um das Blog zu generieren.
28 -
29 -
Dabei wird eine neue Version mit semantic-Release getagged. Die Repository content, images und theme werden ausgechecked. Das Blog wird generiert und das fertig geberierte statische HTML wird in ein repository 'html' gepushed. 
30 -
31 -
Um dann alles zu deployen wird ein docker image erstellt und das vorher generierte HTML aus dem Repository ausgechecked und hinzugefügt. Das Docker Image in die Docker Registry gepushed und kann dann deployed werden. 
32 -
33 -
Für das Blog gibt es einen Helm Chart. Da alles automatisiert ist wird auch dieser im GitHub Actions Worklow mit erstellt. 
34 -
Also auch hier den Code auschecken, Helm package mit '--Version' und der vorher erstellten semantic-Release Version aufgerufen. Der fertige Helm Chart ins Chartmuseum gepushed und schon kann der nächste Step ein 'helm upgrade ...' ausführen. 
35 -
36 -
Die neue Blog Version ist online. Läuft auch sehr zuverlässig und stabil. Doch vom Push bis zur aktuellen Version im Browser dauert dann doch schon so 3-4 Minuten. 
37 -
38 -
Da musste noch etwas gehen. Und es ging noch etwas. Denn die Idee war dann ein Docker Image zu haben, welches durchgehend im Kubernetes löuft. Es hat alle nötigen Binary und alle Repository, die bei Bedarf aktualisiert werden. Das Blog wird generiert und auf jeweils für Prod und DEV eingehangene Mounts geschrieben. Diese werden dann für Kubernetes Deployments als ReadOnly Volumes genutzt. In den Deployments können dann so auch schnell weitere Pods skaliert werden. 
39 -
40 -
Jetzt möchte ich aber nicht jedesmal in den Pod im Kubernetes manuell ein Update anstoßen, vorallem mobil manchmal recht aufwändig am iPhone. Daher musste etwas her was das erledigt. 
41 -
42 -
Das Docker Image für das generieren hat einen kleinen API Service bekommen. Damit kann ich verschiedene URLs aufrufen, die dann verschiedene Sachen für das Blog in Prod oder DEV erledigen. 
43 -
Ok, die API macht das nicht selbst, die macht keine Logik oder für andere Commands aus. Sie schreibt Jobs als Textfiles in ein Verzeichnis und löscht sie dann auch gleich wieder. Mehr macht sie nicht. 
44 -
45 -
Denn ein 2. Service im ink Builder Docker Image ist auch wieder ein kleines, in go geschrienes Programm, was nur eine Aufgabe hat. Es überwacht ein Verzeichnis und so bald eine Datei für einen Job angelegt wurde, wird dieser Job ausgeführt. 
46 -
Das kann der Build vom Prod Blog oder für Dev sein. Aktualisieren der Images, das Theme oder andere Aufgaben. 
47 -
48 -
Ein Commit wie dieser Blog Post ins Git ist dann eine Aktualisierte Blog Version innerhalb von 20-30 Sekunden. 
49 -
50 -
Da ich eine andere Seite demnächst auch auf inkProject umstellen möchte, werde ich die API noch erweitern und kann dann alle Seiten damit erstellen lassen. 
51 -
52 -
53 -
54 -
gelöscht content/2024-01-12-sudo-ohne-passwort-in-gaming-tutorials-warum-das-ein-no-go-ist.md
+0 −43
@@ -1,43 +0,0 @@
1 -
---
2 -
title: 'Sudo ohne Passwort in Gaming Tutorials: Warum das ein No-Go ist'
3 -
date: 2024-01-12 18:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/01/gaming-howto-sudo.webp"
6 -
tags: [Linux, Security, Gaming, sudo]
7 -
categories: 
8 -
    - Linux
9 -
preview: "Hey Gamer-Community! Habt ihr schon mal Tutorials für eure Linux-Gaming-Setups gecheckt und gesehen, wie oft da einfach sudo Befehle ohne Passwortabfrage genutzt werden? Es sieht super easy aus, aber was, wenn ich euch sage, dass das eigentlich mega unsicher ist? Lasst uns darüber reden, warum das ein echtes Sicherheits-No-Go ist." 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
<!-- [Englisch Version](/posts/2023-09-21-kubernetes-network-policies-en.html)
18 -
-->
19 -
20 -
![Static Weblog](/images/posts/2024/01/gaming-howto-sudo.webp)
21 -
22 -
Hey Gamer-Community! Habt ihr schon mal Tutorials für eure Linux-Gaming-Setups gecheckt und gesehen, wie oft da einfach sudo Befehle ohne Passwortabfrage genutzt werden? Es sieht super easy aus, aber was, wenn ich euch sage, dass das eigentlich mega unsicher ist? Lasst uns darüber reden, warum das ein echtes Sicherheits-No-Go ist.
23 -
24 -
# Sudo-Easy-Mode: Bequem aber gefährlich
25 -
26 -
Sudo in Linux ist wie ein Master-Key für euren Computer. Wenn ihr sudo vor einen Befehl setzt, sagt ihr im Grunde: "Hey, führe das als Superuser aus!" Aber wenn ihr das ohne Passwort macht (die 'NOPASSWD'-Option), dann ist das, als würdet ihr eure Haustür offen lassen. Jeder, der vorbeikommt, könnte reinspazieren!
27 -
28 -
# Das Sicherheitsproblem: Easy Access für Bad Guys
29 -
30 -
Stellt euch vor, ihr ladet euch was für euer Game runter, und ein Hacker hat sich darin versteckt. Mit sudo ohne Passwort könnte der alles auf eurem System machen – wie in einem Game mit Cheat-Codes, nur dass ihr die Verlierer seid.
31 -
32 -
# Real-Talk: Beispiele aus dem echten Leben
33 -
34 -
Es gab schon Fälle, wo solche Sicherheitslücken zu echten Desastern geführt haben – von geklauten Infos bis hin zu komplett übernommenen Systemen. Nicht cool!
35 -
36 -
# Wie man’s besser macht: Sicherheit first!
37 -
38 -
Also, Leute, lasst uns smart sein. Benutzt sudo mit Passwort. Ja, es dauert ein paar Sekunden länger, aber euer System bleibt sicher. Ändert auch regelmäßig eure Passwörter und bleibt wachsam, wenn ihr Tutorials folgt.
39 -
40 -
41 -
# Fazit
42 -
43 -
Gaming auf Linux ist super, aber Sicherheit ist wie bei jedem guten Game: Man muss die Regeln kennen und sich dran halten. sudo ohne Passwort? Lasst das lieber sein. Sicher sein im Internet ist wie ein unsichtbarer Rüstungsboost – ihr seht es nicht direkt, aber es rettet euch vor den fiesen Überraschungen. Bleibt sicher, zockt cool! 🎮🔐✨
gelöscht content/2024-01-14-AdBlock-mit-Pi-Hole-ist-selbstverteidigung.md
+0 −105
@@ -1,105 +0,0 @@
1 -
---
2 -
title: 'AdBlock mit Pi-Hole ist Selbstverteidigung'
3 -
date: 2024-01-14 14:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/01/adblocker-pihole-protection.webp"
6 -
tags: [RaspberryPi, Pi-Hole]
7 -
categories: 
8 -
    - Internet
9 -
preview: "Pi-hole ist eine Netzwerk-basierte Anwendung zur Werbe- und Tracking-Blockierung. Es funktioniert, indem es als DNS-Server in Ihrem Netzwerk agiert und unerwünschte Inhalte, insbesondere Werbung und Tracker, filtert, bevor sie auf Ihre Geräte geladen werden. Hier sind die grundlegenden Schritte, um Pi-hole einzusetzen" 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
<!-- [Englisch Version](/posts/2023-09-21-kubernetes-network-policies-en.html)
18 -
-->
19 -
20 -
![Pi-Hole](/images/posts/2024/01/adblocker-pihole-protection.webp)
21 -
22 -
23 -
Pi-hole ist eine Netzwerk-basierte Anwendung zur Werbe- und Tracking-Blockierung. Es funktioniert, indem es als DNS-Server in Ihrem Netzwerk agiert und unerwünschte Inhalte, insbesondere Werbung und Tracker, filtert, bevor sie auf Ihre Geräte geladen werden. Hier sind die grundlegenden Schritte, um Pi-hole einzusetzen:
24 -
25 -
1. **Hardware-Voraussetzungen**: Pi-hole kann auf Hardware wie einem Raspberry Pi, einem anderen Einplatinencomputer oder sogar auf einem alten Computer installiert werden. 
26 -
27 -
2. **Betriebssystem**: Du musst ein kompatibles Betriebssystem auf Deiner Hardware installieren, oft ist dies eine Linux-Distribution.
28 -
29 -
3. **Installation von Pi-hole**: Die Installation erfolgt normalerweise über eine einfache Befehlszeile. Pi-hole bietet auf ihrer Website eine offizielle Installationsanleitung.
30 -
31 -
4. **Konfiguration Ihres Netzwerks**: Nach der Installation müssen Sie Ihren Router so konfigurieren, dass er Pi-hole als primären DNS-Server verwendet. Dadurch wird der gesamte Datenverkehr Ihres Netzwerks durch Pi-hole geleitet.
32 -
33 -
5. **Verwaltung und Wartung**: Pi-hole bietet ein Web-Dashboard, über das Sie die Einstellungen verwalten, Statistiken einsehen und die Blockierlisten anpassen können.
34 -
35 -
6. **Regelmäßige Updates**: Es ist wichtig, Pi-hole regelmäßig zu aktualisieren, um sicherzustellen, dass es effektiv bleibt und Sicherheitsrisiken minimiert werden.
36 -
37 -
Pi-hole ist besonders beliebt für seine Effizienz bei der Reduzierung von Werbung auf allen Geräten im Netzwerk, seine relativ einfache Einrichtung und geringe Hardwareanforderungen. Es bietet auch einen erhöhten Datenschutz, da es hilft, Online-Tracking zu reduzieren.
38 -
39 -
# Pi-Hole installieren
40 -
41 -
Die Installation von Pi-hole auf einem Raspberry Pi ist ein relativ einfacher Prozess. Hier sind die grundlegenden Schritte:
42 -
43 -
1. **Raspberry Pi vorbereiten**: 
44 -
   - Besorgen Dir einen Raspberry Pi und stellen sicher, dass Du eine SD-Karte, ein Netzteil und eine Netzwerkverbindung (entweder über Ethernet oder WLAN) hast.
45 -
   - Installiere ein Betriebssystem auf Deinem Raspberry Pi, üblicherweise wird Raspbian verwendet, das auf Debian basiert.
46 -
47 -
2. **Betriebssystem einrichten**:
48 -
   - Schreibe das Betriebssystem-Image auf die SD-Karte. Dazu kannst Du Software wie BalenaEtcher verwenden.
49 -
   - Lege die SD-Karte in den Raspberry Pi ein und starte ihn.
50 -
   - Führe die grundlegende Konfiguration durch, wie das Einrichten einer Netzwerkverbindung und das Ändern des Standardpassworts.
51 -
52 -
3. **Pi-hole installieren**:
53 -
   - Öffne einen Terminal auf dem Raspberry Pi.
54 -
   - Führe den folgenden Befehl aus: `curl -sSL https://install.pi-hole.net | bash`
55 -
   - Dieses Kommando lädt das Installationsskript von Pi-hole herunter und führt es aus.
56 -
57 -
4. **Pi-hole Konfiguration**:
58 -
   - Während der Installation wirst Du durch verschiedene Konfigurationsoptionen geführt, einschließlich der Auswahl eines DNS-Servers, der Einstellung von IPv4 oder IPv6 und der Festlegung von Filterlisten.
59 -
   - Nach Abschluss der Konfiguration zeigt das Installationsprogramm die IP-Adresse des Pi-hole-Servers sowie das Passwort für das Web-Administrationsinterface an.
60 -
61 -
5. **Router-Konfiguration**:
62 -
   - Um Pi-hole für Dein gesamtes Netzwerk zu verwenden, muss der Raspberry Pi als primären DNS-Server in Deinem Router eingerichtet werden.
63 -
   - Melde Dich sich bei Deinem Router an und suche die DNS-Einstellungen. Hier trägst Du die IP-Adresse des Raspberry Pi ein.
64 -
65 -
6. **Überprüfen und verwalten**:
66 -
   - Nachdem Du Pi-hole als DNS-Server eingestellt hast, kannst Du auf das Pi-hole-Administrations-Dashboard zugreifen, indem Du die IP-Adresse des Raspberry Pi in einem Webbrowser eingibst und Dich anmeldest.
67 -
   - Überprüfe, ob die Werbeblockierung funktioniert und passe bei Bedarf die Einstellungen im Dashboard an.
68 -
69 -
Vergewissere dich, dass regelmäßige Updates für sowohl das Betriebssystem als auch Pi-hole durchgeführt werden, um Sicherheit und Funktionalität zu gewährleisten.
70 -
71 -
# Sperrelisten hizufügen und verwalten
72 -
73 -
Um weitere Listen in Pi-hole hinzuzufügen, kkannst Du das Web-Administrationsinterface nutzen. Hier sind die Schritte, um zusätzliche Blocklisten hinzuzufügen:
74 -
75 -
1. **Pi-hole Webinterface öffnen**: 
76 -
   - Gebe die IP-Adresse Deines Raspberry Pi in einem Webbrowser ein, um auf das Pi-hole Dashboard zuzugreifen.
77 -
   - Melde Dich an, falls erforderlich.
78 -
79 -
2. **Zum Blocklisten-Management navigieren**:
80 -
   - Im Dashboard findest Du einen Abschnitt oder eine Registerkarte namens "Group Management" oder "Gruppenverwaltung".
81 -
   - Klicke darauf und wähle dann „Adlists“ oder „Blocklisten“.
82 -
83 -
3. **Neue Listen hinzufügen**:
84 -
   - Hier kannst Du die URLs der zusätzlichen Blocklisten eingeben. Blocklisten sind in der Regel als URL zu einer Liste im Internet verfügbar, die von verschiedenen Quellen gepflegt werden.
85 -
   - Gebe die URL der gewünschten Liste ein und klicke auf „Add“ oder „Hinzufügen“.
86 -
87 -
4. **Änderungen anwenden**:
88 -
   - Nachdem Du neue Listen hinzugefügt hast, ist es wichtig, die Gravity-Datenbank zu aktualisieren, damit die Änderungen wirksam werden. 
89 -
   - Dies können Du tun, indem Du im Hauptdashboard auf „Tools“ und dann auf „Update Gravity“ klickst.
90 -
91 -
5. **Überprüfen und Testen**:
92 -
   - Überprüfe nach dem Aktualisieren der Gravity-Datenbank, ob die neuen Listen korrekt hinzugefügt wurden und funktionieren.
93 -
   - Du kkannst dies testen, indem Du auf Websites zugreifst, die normalerweise Werbung anzeigen, und überprüfen, ob diese Werbung nun blockiert wird.
94 -
95 -
6. **Regelmäßige Wartung**:
96 -
   - Beachte, dass einige Listen möglicherweise regelmäßig aktualisiert werden müssen, um effektiv zu bleiben. 
97 -
   - Pi-hole führt standardmäßig regelmäßige Updates durch, aber Du kannst dies auch manuell im Webinterface unter „Tools“ > „Update Gravity“ durchführen.
98 -
99 -
Denke, dass das Hinzufügen vieler Listen die Leistung Deines Pi-hole beeinträchtigen kann, besonders wenn Dein Raspberry Pi über begrenzte Ressourcen verfügt. Es ist auch möglich, dass zu viele Listen zu falsch-positiven Ergebnissen führen, bei denen legitime Websites fälschlicherweise blockiert werden. Es ist daher wichtig, ein Gleichgewicht zu finden und Listen auszuwählen, die Deinen spezifischen Anforderungen und Präferenzen entsprechen.
100 -
101 -
# Listen mit denen gute Erfahrungen gemacht wurden
102 -
103 -
Ende 2022 habe ich von [Frank Plaschke](https://about.me/Frank.Plaschke) eine Seite geschickt bekommen. 
104 -
Auf [Firebog.net](https://firebog.net) sind eine Menge Sperrlisten für Pi-Hole gelistet, die Pi-Hole bei ihm sehr effizient gemacht haben. Ich selbst habe sie bei mir auch eingetragen und Pi-Hole wurde sehr viel besser. 
105 -
gelöscht content/2024-01-16-eine-simple-homepage-wuerde-schon-mal-reichen.md
+0 −46
@@ -1,46 +0,0 @@
1 -
---
2 -
title: 'Eine simple Homepage würde schon mal reichen'
3 -
date: 2024-01-16 18:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/01/young-seo-casper.webp"
6 -
tags: [Firma, Business, Homepage, SEO]
7 -
categories: 
8 -
    - Internet
9 -
preview: "Such dir aus, was zu dir passt. Lass dich nicht beeinflussen oder abzocken von irgendeinem jungen Business-Typen, mit schicken Instagram-Profil und auf Threads von ihrem sechsstelligen Marketing-Business prahlen." 
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
![Young Seo & Marketing Casper](/images/posts/2024/01/young-seo-casper.webp)
18 -
19 -
20 -
Wenn dir jemand sagt, wie wichtig eine eigene Homepage ist, hat er eigentlich ganz recht. Aber was brauchst du wirklich, um im Internet präsent zu sein? Nicht viel. Es muss nicht unbedingt HTML und CSS im Texteditor sein, es sei denn, das ist dein Beruf oder Hobby und du kennst dich damit bestens aus. Selbst dann wirst du wahrscheinlich zu einem CMS wie WordPress, Drupal oder Typo3 greifen. Oder du entscheidest dich für einen der vielen Anbieter, die dir einen kompletten Website-Baukasten zur Verfügung stellen.
21 -
22 -
Egal für was du dich entscheidest, prüfe mal die Exportmöglichkeiten in den Einstellungen oder Plugins. Denn es ist unwahrscheinlich, dass du beim ersten Mal das perfekte CMS oder den perfekten Baukasten erwischst. Manchmal passt es, weil es einfach genug für deine Bedürfnisse ist. Aber oft kommt der Punkt, an dem du wächst und mehr brauchst, wie zum Beispiel einen Shop oder Medienbereitstellung. Dann willst du vielleicht doch zu einem anderen System wechseln.
23 -
24 -
Such dir aus, was zu dir passt. Lass dich nicht beeinflussen oder abzocken von irgendeinem jungen Business-Typen, mit schicken Instagram-Profil und auf Threads von ihrem sechsstelligen Marketing-Business prahlen. Natürlich kannst du dir Infos und Tipps holen, aber wenn du nur eine einfache Homepage willst, dann mach das auf deine Weise. Du kannst jemanden für das Design dazunehmen, aber letztendlich ist es deine Entscheidung. Wichtig ist: Du willst ein Design, und womit du es umsetzt, ist egal. Ein Webdesigner, der nur für WordPress arbeitet, ist kein richtiger Webdesigner. Ein guter Designer liefert dir etwas, das du in das System deiner Wahl einfügen kannst. Wenn du Drupal willst und jemand versucht, dir WordPress aufzuschwatzen, sag nein und such dir lieber jemand anderen – und umgekehrt.
25 -
26 -
SEO ist wichtig, aber man muss es nicht übertreiben. Es frisst Zeit und kostet Geld. Du hast dich für ein System entschieden und hast das Webdesign gestalten lassen. Der Webdesigner, der ja ein Profi sein sollte, kennt sich mit SEO aus und hat die grundlegenden Sachen wie Absätze, Titel, Keywords und Überschriften im Design integriert. Wenn der SEO-Typ dir was anderes erzählt, stimmt entweder mit dem Webdesigner oder dem SEO-Typen was nicht.
27 -
28 -
Spar dir zuerst das SEO und teures Webdesign. Meistens bringt es dir anfangs nichts. Du willst ein Business aufbauen und brauchst erstmal Kunden. Konzentriere dich darauf, ob du es alleine schaffst und ob die Kunden überhaupt wollen, was du anbietest.
29 -
30 -
Du hast keine Zeit, dich mit Webdesign, CMS, Templates, Plugins und Hosting zu beschäftigen. Du willst dein Ding
31 -
32 -
machen und das für deine Kunden. Und dann sind da noch Bankgeschäfte, Rechnungen und das Finanzamt.
33 -
34 -
Die wichtigsten Dinge brauchst du: Ja, auch deine Homepage. Aber da machst du erstmal das, was dir passt und womit du klar kommst. Sichere dir deinen Namen als Domain und leg los.
35 -
36 -
Denn was du wirklich brauchst, ist erstmal eine Homepage, die zeigt, was du machst und wer du bist. Wichtig sind auch die Kontaktdaten.
37 -
38 -
Der Rest kommt später, wenn du Zeit und Geld dafür hast. Dann kannst du Leute suchen, die den Job für dich erledigen. Weil du dann die Ruhe dafür hast und dich nicht von Möchtegern-Experten abzocken lässt, die am Anfang deine Zeitknappheit ausnutzen.
39 -
40 -
Eine Domain, eine kleine Webseite mit kurzen Infos und Kontaktdaten reichen aus. Kunden suchen oft lokal und kennen vielleicht sogar deinen Namen, dann landen sie eh auf deiner Seite, wo sie alle aktuellen Informationen finden. 
41 -
42 -
Der einzige Nachteil ohne eigene Homepage ist, dass du dich vielleicht in irgendwelchen Portalen selbst eintragen musst oder von anderen eingetragen wirst. Andere Seiten greifen diese Daten ab und zeigen sie in ihrem Verzeichnis an. Kunden landen dort über Google. Ändert sich deine Telefonnummer, E-Mail-Adresse oder Anschrift, wird sie dort oft nie geändert. Auf Deiner Homepage schon. Da gucken die Leute drauf, also nutze sie genau dafür. 
43 -
44 -
Also, erstelle deine eigene Homepage. Das gewählte System ist zunächst zweitrangig. Plane nur dein weiteres Wachstum mit ein und vermeide unnötigen Schnickschnack.
45 -
46 -
Starte mit deiner Homepage wie mit deinem Business: Klein! Und wachse langsam mit deinem Business und deiner Webseite.
\ No newline at end of file
gelöscht content/2024-02-08-neues-selbst-gebautes-blog-cms copy.md
+0 −60
@@ -1,60 +0,0 @@
1 -
---
2 -
title: 'Neues, selbst gebautes Blog- und CMS'
3 -
date: 2024-02-08 18:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/02/cms.webp"
6 -
tags: [Homepage, CMS, Blog]
7 -
categories: 
8 -
    - Internet
9 -
preview: "Mit meinem neuen System können einzelne Bereiche oder Seiten auf separaten Instanzen betrieben werden, die nur bei Bedarf skaliert werden. Dies reduziert die Belastung für den Rest der Homepage, und selbst bei starker Last bleibt alles andere erreichbar."
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: true
14 -
toc: false
15 -
---
16 -
17 -
![Blog and CMS](/images/posts/2024/02/cms.webp)
18 -
19 -
20 -
Jekyll, Octopress, Hugo, InkProject ... Die Liste der CMS- und Static-Page-Generatoren neben Typo3, Joomla und WordPress, um nur einige zu nennen, ist bereits lang. Noch länger war der Plan, das eigene Projekt fertigzustellen. Es war sogar vorteilhaft, dass es länger dauerte als geplant, da mehrere Anläufe nötig waren. Die Erfahrungen mit den Static-Page-Generatoren waren jedoch sehr wertvoll, denn alle haben ihre Stärken und Schwächen.
21 -
22 -
Mit InkProject begann die Trennung von Software, Inhalten, Theme und der fertigen Seite. Dies führte zum aktuellen Ansatz, der noch weiter verfeinert wurde.
23 -
24 -
Auch der fertige Inhalt kann getrennt werden. Bei allen CMS oder Static-Page-Generatoren wird das gesamte System üblicherweise auf einem Server abgelegt, wobei eine horizontale Skalierung möglich ist. Dies betrifft dann jedoch alle Seiten. Wenn ein Bereich, wie der Blog, ein Ressort/Themenbereich oder eine einzelne Seite, stark belastet wird, musste bisher das gesamte System skaliert werden.
25 -
26 -
27 -
    cms_cli page --all
28 -
    cms_cli server --build --name default 
29 -
    cms_cli server --rollout --name default
30 -
 
31 -
    cms_cli page -s -f 2024-01-04-Warp-Editor
32 -
    cms_cli server --build --name technik
33 -
    cms_cli server --rollout --name technik
34 -
35 -
36 -
Mit meinem neuen System können einzelne Bereiche oder Seiten auf separaten Instanzen betrieben werden, die nur bei Bedarf skaliert werden. Dies reduziert die Belastung für den Rest der Homepage, und selbst bei starker Last bleibt alles andere erreichbar.
37 -
38 -
Inhaltlich wird alles im HTML-Ordner abgelegt, ähnlich wie bei anderen Systemen. Es besteht jedoch die Möglichkeit, Inhalte an zusätzlichen Orten zu speichern. Standardmäßig wird das Docker-Image unter dem Namen „default“ erstellt, neben zwei weiteren Images für CSS und Fonts, die unabhängig voneinander sind.
39 -
40 -
Wenn eine Seite oder ein Blog mehrere Bereiche hat, wie Allgemeines, Technik, Developer, Smart Home usw., könnte der Bereich Smart Home ausgelagert werden. Dies geschieht über die Konfiguration für den Inhalt.
41 -
42 -
Anschließend wird das entsprechende Docker-Image gebaut und ausgerollt.
43 -
44 -
Alle Schritte, vom Generieren aller Seiten, über das Erstellen der Docker-Images bis hin zum Rollout aller Container, können über die CLI erfolgen. Beiträge und Seiten können auch einzeln generiert werden, ohne dass sie auf der Webseite verlinkt werden. Sie werden erst durch das Generieren aller Seiten oder weiterer Seiten, wie Übersichtsseiten, zugänglich.
45 -
46 -
Durch diese Trennung können für einzelne Bereiche unterschiedliche Themes verwendet werden, was eine optische Unterscheidung ermöglicht. Bei verschiedenen Verantwortlichen für unterschiedliche Bereiche ermöglicht die Trennung ein paralleles Arbeiten und Veröffentlichen. Publishing und Deployment erfolgen nur für die jeweiligen Bereiche.
47 -
48 -
Das System unterstützt auch fortgeschrittene Szenarien, wie die Nutzung eines Gateways oder CDNs, und kann die Pfade für die Bereiche auf unterschiedliche Instanzen lenken, die sogar in einem Multi-Cloud-Setup bei AWS, Azure, GCP, OTC usw. laufen.
49 -
50 -
Der einzige fehlende Teil ist ein Kommentarsystem. Ein eigenes Kommentarsystem zu schreiben, wäre technisch machbar, aber die Integration in statische Seiten und die Bekämpfung von Spam erfordern zusätzlichen Aufwand.
51 -
52 -
Discus hatte ich schon mal früher im Einsatz. Ähnliche Systeme gibt es auch von anderen Anbietern. OpenSource und/oder Selfhosted Lösungen gibt es auch. Davon hatte ich mir über die Jahre auch immer mal wieder ein paar angeguckt. Leider waren alle nicht immer zufriedenstellend. Einige waren sehr aufwändig beim Einrichten und Betrieb. Manche hatten im Betrieb Probleme gemacht. Sei es nur wenn es nur um das Thema Updates ging. Es war einfach zu nervig andauernd eingreifen zu müssen. 
53 -
54 -
Klar man könnte jetzt Discus oder ein anderes System nehmen. Problem gelöst, um den Betrieb kümmert sich jemand anderes. Aber die Daten liegen bei jemanden anderen und nicht bei einem selbst. 
55 -
56 -
Also habe ich nach einiger Zeit mal wieder Tante Google befragt und ein wenig umgeguckt. Dabei bin ich auf Commento gestoßen und es sah auf dem ersten Blick schon sehr gut aus. Commento kann über die Seite von Commento benutzt werden, oder auch selfhosted auf dem eigenen Server installiert werden. 
57 -
58 -
Ich habe Commento für ARM64 kompiliert und in ein ARM64 Docker-Image integriert, inklusive PostgreSQL, Konfiguration und PersistentVolume im Kubernetes. Ein Helm-Chart und alles für das ARM-Image werde ich noch veröffentlichen, ebenso wie Commento, damit es direkt angeboten werden kann.
59 -
60 -
Wer den Footer dieses Blogs betrachtet, wird noch eine Weile das „Powered by InkProject“ sehen. Zuerst wird eine andere Seite auf mein System umgezogen, da dies dringender benötigt wird. Aber auch hier wird es nach und nach voran gehen, denn ich kann ja jetzt einzelne Bereiche nach und nach umziehen. 
\ No newline at end of file
gelöscht content/2024-09-18-statische-webseiten-in-kubernetes.md
+0 −121
@@ -1,121 +0,0 @@
1 -
---
2 -
title: 'Statische Webseiten in Kubernetes'
3 -
date: 2024-09-18 18:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/02/cms.webp"
6 -
tags: [Homepage, CMS, Blog, Kubernetes]
7 -
categories: 
8 -
    - Internet
9 -
preview: "Statische Webseiten in Kubernetes."
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
![Blog and CMS](/images/posts/2024/02/cms.webp)
18 -
19 -
Ich habe mehrere Seiten und benutze dafür Hugo, InkProject und ein eigenes in Go geschriebenes CMS. 
20 -
Der Content wird in allen drei mit Markdown Files erstellt. Mit den drei Systemen wird dann die jeweilige Seite statisch generiert. 
21 -
22 -
## Github/Gitlab Pipelines? 
23 -
24 -
Benutze ich Github oder Gitlab Pipelines für das generieren? Nein.
25 -
26 -
Der Content, die CMS Config, Themes usw. liegen alle in Github. Aber Github Actions oder Pipelines benutze ich bei den Seiten nicht mehr. Das habe ich über Jahre so gemacht, aber der Aufwand ist mir einfach zu groß. Und das veröffentlichen, also das generieren der Seiten, erstellen der Images und Deployment der Images in Kubernetes dauert einfach zu lange. 
27 -
28 -
### Aufwand und Zeit.
29 -
30 -
Damit meine ich das Hugo, InkProject und mein eigens CMS bei aktualisieren neu zu kompilieren, Docker Images zu bauen und so bei Updates der Systeme mit der neuen Version die Seiten erstellen zu können. 
31 -
32 -
Auch das generieren der Seiten und das anschliessende erstellen der Images dauert einfach sehr lange. Da jeder Step ein Docker Image hoch fährt, seine Aufgabe erledigt und anschliessende die fertigen Daten weiter verarbeitet. Images, da ich nur noch Multi-Arch Images baue, in die Registry pushen und mit dem fertigen Image den Helm Chart mit der neuen Image Version erstellt und deployed.
33 -
34 -
Das dauerte ja nach Seite 3-5 Minuten. Was bei kleinen Änderungen wie Typos einfach nervig war. 
35 -
36 -
## Wie ich jetzt Seiten aktualisiere
37 -
38 -
Jede Seite ist lokal auf dem Rechner und ich füge neue Markdown Files für neuen Content dazu. Ich kann bei allen drei Systemen einfach `<CMSNAME> build` oder `<CMSNAME serve` benutzen. So kann ich einfach aus dem Ordner `public` die Setie aufrufen oder mit dem `serve` die Seite über `http://localhost:8000` aufrufen. So kann man schnell die fertige Seiten oder Posts angucken. 
39 -
40 -
In jedem Ordner ist ein Script `build.sh`, welches dann die Seite generiert und die Docker Images erstellt und dann ein Multi-Arch Manifest generiert. 
41 -
Dabei wird die Version für die Image-Tags immer hochgezählt.
42 -
43 -
Das Image kann so auch direkt im Cluster aktualisiert werden, wird aber nur bei Tests oder schnellen Änderungen genutzt. 
44 -
45 -
Das Rollout wird aber über den Helm-Chart gemacht. 
46 -
47 -
```
48 -
#!/bin/bash
49 -
50 -
CMS="ink"
51 -
# CMS="hugo"
52 -
# CMS="kube-cms"
53 -
REGISTRY="ghcr.io"
54 -
USERNAME="youruser"
55 -
IMAGE="myblog"
56 -
57 -
${CMS} build
58 -
59 -
perl -pe 's/(version: )(v\d\.)(\d\.)(\d+)/$1 . $2.$3.($4 + 1)/ge' docker.yaml > docker.yaml.tmp; 
60 -
mv docker.yaml.tmp docker.yaml
61 -
VERSION=$(perl -pe 's/(version: )(v\d\.)(\d\.)(\d+)/$2.$3.($4)/ge' docker.yaml)
62 -
63 -
64 -
docker buildx build --no-cache -t ${REGISTRY}/${USERNAME}/${IMAGE}:${VERSION}-arm64 .
65 -
docker buildx build --no-cache --platform linux/arm64 -t ${REGISTRY}/${USERNAME}/${IMAGE}:${VERSION}-arm64-linux .
66 -
docker buildx build --no-cache --platform linux/amd64 -t ${REGISTRY}/${USERNAME}/${IMAGE}:${VERSION}-amd64 .
67 -
68 -
docker push ${REGISTRY}/${USERNAME}/${IMAGE}:${VERSION}-arm64
69 -
docker push ${REGISTRY}/${USERNAME}/${IMAGE}:${VERSION}-arm64-linux
70 -
docker push ${REGISTRY}/${USERNAME}/${IMAGE}:${VERSION}-amd64
71 -
72 -
docker manifest create ${REGISTRY}/${USERNAME}/${IMAGE}:$VERSION \
73 -
    --amend ${REGISTRY}/${USERNAME}/${IMAGE}:$VERSION-amd64 \
74 -
    --amend ${REGISTRY}/${USERNAME}/${IMAGE}:$VERSION-arm64-linux \
75 -
    --amend ${REGISTRY}/${USERNAME}/${IMAGE}:$VERSION-arm64
76 -
docker manifest push ${REGISTRY}/${USERNAME}/${IMAGE}:$VERSION
77 -
docker manifest create ${REGISTRY}/${USERNAME}/${IMAGE}:latest \
78 -
    --amend ${REGISTRY}/${USERNAME}/${IMAGE}:$VERSION-amd64 \
79 -
    --amend ${REGISTRY}/${USERNAME}/${IMAGE}:$VERSION-arm64-linux \
80 -
    --amend ${REGISTRY}/${USERNAME}/${IMAGE}:$VERSION-arm64
81 -
docker manifest push ${REGISTRY}/${USERNAME}/${IMAGE}:latest
82 -
```
83 -
84 -
## Helm-Chart
85 -
86 -
Der Helm-Chart kümmert sich um das Deployment in den bzw. die Kubernetes Cluster. Das Deployment, Service, Ingress, TLS-Cert, Traefik Middlewares und vielem mehr. Änderungen an den Workloads können so schnell gemacht werden und Rollback ist schnell möglich. 
87 -
88 -
Auch hier wird, wie beim Docker Image, die Version immer hoch gezählt. Der aktuelle Image-Tag wird aus dem Verzeichnis des CMS ausgelesen und als Value beim Installaieren bzw. beim Upgrade des Helm-Charts im Cluster übergeben. 
89 -
90 -
Damit ich beim Rollout des Helm-Charts nicht zusätzlich immer erst in das CMS Verzeichnis wechseln muss, um ein neues Image bei Änderungen zu generieren, kann ich einfach beim Aufrufe vom Script `package.sh` einfach ein `docker` mit anhängen. 
91 -
92 -
So bin ich flexible und kann auch nur Änderungen am Helm-Chart ausrollen, ohne immer wieder neue Docker Images zu erstellen. 
93 -
94 -
```
95 -
#!/bin/bash
96 -
97 -
HOMEPAGEURL="blog.example.net"
98 -
HELMREPO="charts.mydomain.de"
99 -
CHARTNAME="myblog"
100 -
CHARTUSER="bob"
101 -
CHARTPASSWORD="mysecret"
102 -
103 -
if [ "$1" = "docker" ];
104 -
then
105 -
    cd ../../services/${HOMEPAGEURL}/
106 -
    ./build.sh
107 -
    cd -
108 -
fi
109 -
110 -
111 -
perl -pe 's/(version: )(v\d\.)(\d\.)(\d+)/$1 . $2.$3.($4 + 1)/ge' helm/Chart.yaml > helm/Chart.yaml.tmp;
112 -
mv helm/Chart.yaml.tmp helm/Chart.yaml
113 -
114 -
TAG=$(grep -a -m1 'version: ' ../../services/${HOMEPAGEURL}/docker.yaml | cut -d " " -f2)
115 -
116 -
helm package helm
117 -
helm cm-push -u ${CHARTUSER} -p ${CHARTPASSWORD} $(ls -tr -1 *.tgz | tail -n 1) ${HELMREPO}
118 -
119 -
helm repo update
120 -
helm upgrade ${CHARTNAME} ${HELMREPO}/${CHARTNAME} --namespace ${CHARTNAME} --set tag=${TAG}
121 -
```
gelöscht content/2024-11-26-test.md
+0 −19
@@ -1,19 +0,0 @@
1 -
---
2 -
title: 'Test'
3 -
date: 2024-11-26 12:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/02/cms.webp"
6 -
tags: [Homepage, CMS, Blog, Kubernetes]
7 -
categories: 
8 -
    - Internet
9 -
preview: "Test Rollout."
10 -
draft: true
11 -
top: false
12 -
type: post
13 -
hide: true
14 -
toc: false
15 -
---
16 -
17 -
![Blog and CMS](/images/posts/2024/02/cms.webp)
18 -
19 -
Test rollout witch tc-package and tc-rollout 
gelöscht content/2024-12-15-nice-zsh-config.md
+0 −115
@@ -1,115 +0,0 @@
1 -
---
2 -
title: 'Nice Terminal und zsh Konfiguration'
3 -
date: 2024-12-15 16:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/12/zsh.webp"
6 -
tags: [MacOS, iTerm, zsh, nerdfonts]
7 -
categories: 
8 -
    - MacOS
9 -
preview: "Nice Terminal und zsh Konfiguration mit oh-my-zsh, Powerlevel10k, Plugins und weiteren Tools."
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
![iTerm zsh](/images/posts/2024/12/zsh.png)
18 -
19 -
## iTerm2 installieren und konfigurieren
20 -
21 -
Als erstes ersetzen wir den MacOS Terminal und installieren iterm2 
22 -
23 -
    brew install iterm2 
24 -
25 -
Für iTerm2 benutze ich das Gruvebox Colorscheme: 
26 -
27 -
    curl -so gruvebox.itermcolors https://raw.githubusercontent.com/mbadolato/iTerm2-Color-Schemes/master/schemes/GruvboxDark.itermcolors
28 -
29 -
Das Color-Scheme importiert man in den Settings von iTerm2 unter Profiles -> Colors -> Color Presets (unten rechts).
30 -
31 -
![Import colorscheme](/images/posts/2024/12/iterm-colors.png)
32 -
33 -
Anschliessend kann man dort dann "gruvebox" auswählen. 
34 -
35 -
Als nächstes brauchen wir noch Fonts. Die bekommt man auf Nerdfonts.com. Ich benutze den Font "Nerd Hack Fonts":
36 -
37 -
    curl -sLo Hack.zip https://github.com/ryanoasis/nerd-fonts/releases/download/v3.3.0/Hack.zip
38 -
39 -
Die Datei entpacken und den Font einfach mit Doppelklick öffnen. Unter MacOS ist damit die Font Installation schon erledigt. 
40 -
41 -
Den Font kann an dann in den Settings von iTerm2 direkt auswählen und aktivieren. Profiles -> Text -> Font.
42 -
43 -
44 -
## ZSH konfigurieren
45 -
46 -
Wer noch kein ZSH installiert hat kann ZSH mit `brew install zsh` installieren. 
47 -
48 -
oh-my-zsh managed die ZSH Konfiguration und bringt eine Menge an Plugins, Themes und noch mehr mit um ZSH so anpassen zu können wir man es benötigt. Egal Aussehen oder Funktionen. 
49 -
50 -
    sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
51 -
52 -
Das powerlevel10k Plugin installieren:
53 -
54 -
    git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
55 -
56 -
In der .zshrc kann man das Theme auf anschliessend auf Powerlevel10k setzen:
57 -
58 -
    ZSH_THEME="powerlevel10k/powerlevel10k"
59 -
60 -
Jetzt noch etwas die zsh Shell pimpen. Dazu werden jetzt noch zsh-syntax-highlighting und zsh-autosuggestions installiert.
61 -
62 -
    brew install zsh-autosuggestions
63 -
    brew install zsh-syntax-highlighting
64 -
65 -
Beide aktiveren, in dem man einfach folgende Zeilen in der .zshrc am Ende hinzufügt: 
66 -
67 -
    source $(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
68 -
    source $(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh
69 -
70 -
In der Datei `.zshrc` ist ziemlich am Anfang eine Variable `plugins`, bei dieser fügt man jetzt dir beiden Plugins hinzu.
71 -
72 -
Bei mir sieht die Zeile so aus:
73 -
74 -
    plugins=(command-not-found web-search git git-prompt systemadmin taskwarrior svn perl macos screen terminitor lol emoji-clock themes history zsh-syntax-highlighting zsh-autosuggestions)
75 -
76 -
Damit die File- und Ordnerliste so aussehen wir oben im Screenshot benutze ich colorls, welches mit Ruby gem installiert wird. 
77 -
78 -
    sudo gem install colorls
79 -
80 -
Ggf. muss vorher noch ein `gem install public_suffix -v 5.1.1` ausgeführt werden. Das wird aber auch in dem Fall beim install von colorls angezeigt. 
81 -
82 -
Damit ist dann auch `colorls` als Befehl nutzbar. Wenn man jetzt aber nicht immer colorls eingeben möchte, kann man sich einfach in der `.zshrc` einfach einen Alias dafür anlegen: 
83 -
84 -
    alias ls="colorls"
85 -
86 -
Jetzt kann man entweder einen neuen Termin öffnen oder man gibt einfach `source ~/.zshrc` ein um die Konfiguration einlesen zu lassen. 
87 -
88 -
## Noch mehr mit Powerlevel10k 
89 -
90 -
![zsh powerlevel10k](/images/posts/2024/12/p10k.png)
91 -
92 -
Hier sieht man meinen kompletten ZSH Prompt. Hier werden neben der Uhrzeit, Batterie, interne und externe IP, Akku jede Menge Sachen angezeigt. Wenn ich in einem Verzeichnis mit z.B. mit einer Kubeconfig bin und/oder einem Git Repository, wird man der Kuberentes Context, Git Branch usw. angezeigt. 
93 -
94 -
Die Konfig ist etwas größer, daher habe ich sie in einen [GitHub Gist](https://gist.github.com/ruedigerp/670abd2bfecba6c4cd481b7cf4352570) hinterlegt. 
95 -
96 -
Die Powerlevel10k Konfiguration habe ich in der Datei `~/.p10k.zsh` gespeichert. Und in der `.zshrc` wird dann anschliessend noch eingefügt: 
97 -
98 -
    # Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
99 -
    # Initialization code that may require console input (password prompts, [y/n]
100 -
    # confirmations, etc.) must go above this block; everything else may go below.
101 -
    if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
102 -
        source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
103 -
    fi
104 -
105 -
    source $(brew --prefix)/share/powerlevel10k/powerlevel9k.zsh-theme
106 -
107 -
    # To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
108 -
    [[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
109 -
110 -
    # typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet
111 -
    typeset -g POWERLEVEL9K_INSTANT_PROMPT=off
112 -
113 -
Jetzt noch mal einen neuen Terminal öffnen oder wieder ein `source ~/.zshrc`. 
114 -
115 -
gelöscht content/2024-12-15-tmux-configuration.md
+0 −138
@@ -1,138 +0,0 @@
1 -
---
2 -
title: 'Meine tmux konfiguration'
3 -
date: 2024-12-15 20:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/12/tmux.webp"
6 -
tags: [MacOS, iTerm, tmux]
7 -
categories: 
8 -
    - MacOS
9 -
preview: "Meine tmux konfiguration."
10 -
draft: false
11 -
top: false
12 -
type: post
13 -
hide: false
14 -
toc: false
15 -
---
16 -
17 -
![iTerm zsh](/images/posts/2024/12/tmux.webp)
18 -
19 -
## tmux installieren 
20 -
21 -
Installation von tmux mit homebrew 
22 -
23 -
    brew install tmux
24 -
25 -
## Konfiguration 
26 -
27 -
Damit Änderungen in der `tmux.conf` für alle Sessions, Windows und Panes neugeladen werden können wird als ersten `bind r ` konfiguriert:  
28 -
29 -
    unbind r
30 -
    bind r source-file ~/.tmux.conf
31 -
32 -
Der Standard Prefix ist default auf `control + b` und ich finde ihn auf `control +s` angenehmer. Was auch an meiner Zeit mit `screen` liegt. 
33 -
34 -
    set -g prefix C-s
35 -
36 -
Aktivieren der Mouse, damit auch die Panes mit der Maus angepasst werden können: 
37 -
38 -
    set -g mouse on
39 -
40 -
Um mit den Tasten `control + h,j,k,l` durch die Panes springen zu können: 
41 -
42 -
    setw -g mode-keys vi
43 -
    bind-key h select-pane -L
44 -
    bind-key j select-pane -D
45 -
    bind-key k select-pane -U
46 -
    bind-key l select-pane -R
47 -
48 -
Für die Plugins in tmux benutze ich den tmux plugin manager - tpm. 
49 -
50 -
    set -g @plugin 'tmux-plugins/tpm'
51 -
52 -
Für die Statusleiste hatte ich Dracula getestet, dann aber `tmux2k` gefunden. Das Plugin wird einfach mit folgender Zeile aktiviert. 
53 -
54 -
    set -g @plugin '2kabhishek/tmux2k'
55 -
56 -
Die Konfiguration für tmux2k: 
57 -
58 -
    set -g @tmux2k-theme 'onedark icons'
59 -
    set -g @tmux2k-icons-only true
60 -
    set -g @tmux2k-left-plugins "git cpu-usage ram-usage"
61 -
    set -g @tmux2k-right-plugins "battery cpu ram git time"
62 -
    set -g @tmux2k-network-name "en0"
63 -
    set -g @tmux2k-show-powerline true
64 -
    set -g @tmux2k-show-fahrenheit false
65 -
    set -g @tmux2k-military-time true
66 -
    set -g @tmux2k-border-contrast true
67 -
68 -
    # available colors: white, gray, dark_gray, light_purple, dark_purple, cyan, green, orange, red, pink, yellow
69 -
    # set -g @tmux2k-[plugin-name]-colors "[background] [foreground]"
70 -
    set -g @tmux2k-cpu-usage-colors "blue dark_gray"
71 -
72 -
    # it can accept `session`, `rocket`, `window`, or any character.
73 -
    set -g @tmux2k-show-left-icon ""
74 -
75 -
    # update powerline symbols
76 -
    set -g @tmux2k-show-left-sep ""
77 -
    set -g @tmux2k-show-right-sep ""
78 -
79 -
    # change refresh rate
80 -
    set -g @tmux2k-refresh-rate 5
81 -
82 -
Die Statusbar habe ich für Tmux gerne oben, da meine ZSH Statusbar immer unten ist wirkt das aufgräumter. 
83 -
Ausserdem sehe ich so auch oben immer die wichtigen Infos, wie welches Window aktiv ist, Git Branch usw. 
84 -
85 -
    set -g status-position top
86 -
87 -
Jetzt noch tpm aktivieren und schon kann man einen Reload der Konfiguration machen: 
88 -
89 -
    run '~/.tmux/plugins/tpm/tpm'
90 -
91 -
Wenn noch keine tmux Session vorhanden, einfach eine neue aufmachen. Ist schon eine vorhanden kann man jetzt mit `control + r` die Konfiguration laden und anschliessend noch tpm die Plugins installieren lassen mit `control + I`. 
92 -
93 -
Die Plugins werden installiert und die Statusleiste sollte jetzt aktiv und zu sehen sein. 
94 -
95 -
Die komplette Konfiguration: 
96 -
97 -
    unbind r
98 -
    bind r source-file ~/.tmux.conf
99 -
100 -
    set -g prefix C-s
101 -
    set -g mouse on
102 -
    setw -g mode-keys vi
103 -
    bind-key h select-pane -L
104 -
    bind-key j select-pane -D
105 -
    bind-key k select-pane -U
106 -
    bind-key l select-pane -R
107 -
108 -
    set -g @plugin 'tmux-plugins/tpm'
109 -
    set -g @plugin '2kabhishek/tmux2k'
110 -
    set -g @tmux2k-theme 'onedark icons'
111 -
    set -g @tmux2k-icons-only true
112 -
    set -g @tmux2k-left-plugins "git cpu-usage ram-usage"
113 -
    set -g @tmux2k-right-plugins "battery cpu ram git time"
114 -
    set -g @tmux2k-network-name "en0"
115 -
    set -g @tmux2k-show-powerline true
116 -
    set -g @tmux2k-show-fahrenheit false
117 -
    set -g @tmux2k-military-time true
118 -
    set -g @tmux2k-border-contrast true
119 -
120 -
    # available colors: white, gray, dark_gray, light_purple, dark_purple, cyan, green, orange, red, pink, yellow
121 -
    # set -g @tmux2k-[plugin-name]-colors "[background] [foreground]"
122 -
    set -g @tmux2k-cpu-usage-colors "blue dark_gray"
123 -
124 -
    # it can accept `session`, `rocket`, `window`, or any character.
125 -
    set -g @tmux2k-show-left-icon ""
126 -
127 -
    # update powerline symbols
128 -
    set -g @tmux2k-show-left-sep ""
129 -
    set -g @tmux2k-show-right-sep ""
130 -
131 -
    # change refresh rate
132 -
    set -g @tmux2k-refresh-rate 5
133 -
134 -
    set -g status-position top
135 -
136 -
    run '~/.tmux/plugins/tpm/tpm'
137 -
138 -
gelöscht content/2024-12-16-github-pull-request-from-terminal.md
+0 −40
@@ -1,40 +0,0 @@
1 -
---
2 -
title: 'Github Pull Requests mit gh cli Tool'
3 -
date: 2024-12-15 20:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/12/tmux.webp"
6 -
featureImage: "/images/posts/2024/12/tmux.webp"
7 -
tags: [MacOS, iTerm, tmux]
8 -
categories: 
9 -
    - MacOS
10 -
preview: "Meine tmux konfiguration."
11 -
draft: true
12 -
top: false
13 -
type: post
14 -
hide: true
15 -
toc: false
16 -
---
17 -
18 -
![iTerm zsh](/images/posts/2024/12/github.webp)
19 -
20 -
Die Änderungen sind gemacht, der Commit erstellt und gepushed. Jetzt fehlt nur noch der Pull Request um den neuen Code online zu bekommen. 
21 -
22 -
Browser öffnen, Github URL eingeben, Projekt und Repo wählen, Pull Requests anklicken. 
23 -
Neuen Pull Request erstellen, den Branch auswählen, Zielbranch auswählen und Titel + Body eintragen. 
24 -
25 -
Nervig? Yep. Das geht auch per Terminal in der Shell. 
26 -
27 -
## gh cli Tool installieren
28 -
29 -
    brew install gh 
30 -
31 -
    gh auth login
32 -
33 -
    git checkout -b feature-branch
34 -
    git add .
35 -
    git commit -m "Deine Nachricht für den Commit"
36 -
37 -
    git push origin feature-branch
38 -
39 -
    gh pr create --base main --title "Titel des PR" --body "Beschreibung des PR"
40 -
    
gelöscht content/2024-12-16-yazi-lazygit-neovim.md
+0 −158
@@ -1,158 +0,0 @@
1 -
---
2 -
title: 'yazi lazygit neovim'
3 -
date: 2024-12-15 20:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/12/tmux.webp"
6 -
featureImage: "/images/posts/2024/12/tmux.webp"
7 -
tags: 
8 -
  - MacOS
9 -
  - iTerm
10 -
  - tmux
11 -
categories: 
12 -
  - MacOS
13 -
preview: "Meine tmux konfiguration."
14 -
draft: true
15 -
top: false
16 -
type: post
17 -
hide: true
18 -
toc: false
19 -
---
20 -
21 -
![iTerm zsh](/images/posts/2024/12/tmux.webp)
22 -
23 -
## gh cli Tool installieren
24 -
25 -
    brew install gh 
26 -
27 -
    gh auth login
28 -
29 -
    git checkout -b feature-branch
30 -
    git add .
31 -
    git commit -m "Deine Nachricht für den Commit"
32 -
33 -
    git push origin feature-branch
34 -
35 -
    gh pr create --base main --title "Titel des PR" --body "Beschreibung des PR"
36 -
    
37 -
38 -
39 -
## tmux installieren 
40 -
41 -
Installation von tmux mit homebrew 
42 -
43 -
    brew install tmux
44 -
45 -
## Konfiguration 
46 -
47 -
Damit Änderungen in der `tmux.conf` für alle Sessions, Windows und Panes neugeladen werden können wird als ersten `bind r ` konfiguriert:  
48 -
49 -
    unbind r
50 -
    bind r source-file ~/.tmux.conf
51 -
52 -
Der Standard Prefix ist default auf `control + b` und ich finde ihn auf `control +s` angenehmer. Was auch an meiner Zeit mit `screen` liegt. 
53 -
54 -
    set -g prefix C-s
55 -
56 -
Aktivieren der Mouse, damit auch die Panes mit der Maus angepasst werden können: 
57 -
58 -
    set -g mouse on
59 -
60 -
Um mit den Tasten `control + h,j,k,l` durch die Panes springen zu können: 
61 -
62 -
    setw -g mode-keys vi
63 -
    bind-key h select-pane -L
64 -
    bind-key j select-pane -D
65 -
    bind-key k select-pane -U
66 -
    bind-key l select-pane -R
67 -
68 -
Für die Plugins in tmux benutze ich den tmux plugin manager - tpm. 
69 -
70 -
    set -g @plugin 'tmux-plugins/tpm'
71 -
72 -
Für die Statusleiste hatte ich Dracula getestet, dann aber `tmux2k` gefunden. Das Plugin wird einfach mit folgender Zeile aktiviert. 
73 -
74 -
    set -g @plugin '2kabhishek/tmux2k'
75 -
76 -
Die Konfiguration für tmux2k: 
77 -
78 -
    set -g @tmux2k-theme 'onedark icons'
79 -
    set -g @tmux2k-icons-only true
80 -
    set -g @tmux2k-left-plugins "git cpu-usage ram-usage"
81 -
    set -g @tmux2k-right-plugins "battery cpu ram git time"
82 -
    set -g @tmux2k-network-name "en0"
83 -
    set -g @tmux2k-show-powerline true
84 -
    set -g @tmux2k-show-fahrenheit false
85 -
    set -g @tmux2k-military-time true
86 -
    set -g @tmux2k-border-contrast true
87 -
88 -
    # available colors: white, gray, dark_gray, light_purple, dark_purple, cyan, green, orange, red, pink, yellow
89 -
    # set -g @tmux2k-[plugin-name]-colors "[background] [foreground]"
90 -
    set -g @tmux2k-cpu-usage-colors "blue dark_gray"
91 -
92 -
    # it can accept `session`, `rocket`, `window`, or any character.
93 -
    set -g @tmux2k-show-left-icon ""
94 -
95 -
    # update powerline symbols
96 -
    set -g @tmux2k-show-left-sep ""
97 -
    set -g @tmux2k-show-right-sep ""
98 -
99 -
    # change refresh rate
100 -
    set -g @tmux2k-refresh-rate 5
101 -
102 -
Die Statusbar habe ich für Tmux gerne oben, da meine ZSH Statusbar immer unten ist wirkt das aufgräumter. 
103 -
Ausserdem sehe ich so auch oben immer die wichtigen Infos, wie welches Window aktiv ist, Git Branch usw. 
104 -
105 -
    set -g status-position top
106 -
107 -
Jetzt noch tpm aktivieren und schon kann man einen Reload der Konfiguration machen: 
108 -
109 -
    run '~/.tmux/plugins/tpm/tpm'
110 -
111 -
Wenn noch keine tmux Session vorhanden, einfach eine neue aufmachen. Ist schon eine vorhanden kann man jetzt mit `control + r` die Konfiguration laden und anschliessend noch tpm die Plugins installieren lassen mit `control + I`. 
112 -
113 -
Die Plugins werden installiert und die Statusleiste sollte jetzt aktiv und zu sehen sein. 
114 -
115 -
Die komplette Konfiguration: 
116 -
117 -
    unbind r
118 -
    bind r source-file ~/.tmux.conf
119 -
120 -
    set -g prefix C-s
121 -
    set -g mouse on
122 -
    setw -g mode-keys vi
123 -
    bind-key h select-pane -L
124 -
    bind-key j select-pane -D
125 -
    bind-key k select-pane -U
126 -
    bind-key l select-pane -R
127 -
128 -
    set -g @plugin 'tmux-plugins/tpm'
129 -
    set -g @plugin '2kabhishek/tmux2k'
130 -
    set -g @tmux2k-theme 'onedark icons'
131 -
    set -g @tmux2k-icons-only true
132 -
    set -g @tmux2k-left-plugins "git cpu-usage ram-usage"
133 -
    set -g @tmux2k-right-plugins "battery cpu ram git time"
134 -
    set -g @tmux2k-network-name "en0"
135 -
    set -g @tmux2k-show-powerline true
136 -
    set -g @tmux2k-show-fahrenheit false
137 -
    set -g @tmux2k-military-time true
138 -
    set -g @tmux2k-border-contrast true
139 -
140 -
    # available colors: white, gray, dark_gray, light_purple, dark_purple, cyan, green, orange, red, pink, yellow
141 -
    # set -g @tmux2k-[plugin-name]-colors "[background] [foreground]"
142 -
    set -g @tmux2k-cpu-usage-colors "blue dark_gray"
143 -
144 -
    # it can accept `session`, `rocket`, `window`, or any character.
145 -
    set -g @tmux2k-show-left-icon ""
146 -
147 -
    # update powerline symbols
148 -
    set -g @tmux2k-show-left-sep ""
149 -
    set -g @tmux2k-show-right-sep ""
150 -
151 -
    # change refresh rate
152 -
    set -g @tmux2k-refresh-rate 5
153 -
154 -
    set -g status-position top
155 -
156 -
    run '~/.tmux/plugins/tpm/tpm'
157 -
158 -
gelöscht content/2024-12-17-neovim.md
+0 −287
@@ -1,287 +0,0 @@
1 -
---
2 -
title: 'neovim'
3 -
date: 2024-12-17 17:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/12/neovim.webp"
6 -
featureImage: "/images/posts/2024/12/neovim.webp"
7 -
tags: [MacOS, iTerm, neovim]
8 -
categories: 
9 -
    - MacOS
10 -
preview: "Seit langen höre und lese ich immer wieder von neovim und wie begeistert die Leute davon sind.
11 -
neovim ist eigentlich wie früher emacs, es ist ein eigenes Betriebssystem ;) Jetzt bin ich auch neovim User."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
git clone https://github.com/jimeh/tmuxifier.git ~/.tmuxifier
20 -
21 -
![iTerm zsh](/images/posts/2024/12/neovim.webp)
22 -
23 -
## neovim anstatt vim
24 -
25 -
Seit Langem höre und lese ich immer wieder von Neovim und wie begeistert die Leute davon sind. Neovim ist eigentlich wie früher Emacs – es ist ein eigenes Betriebssystem. ;)
26 -
27 -
In den letzten Monaten fiel dann wieder vermehrt der Name Neovim bei Kollegen und ITlern, mit denen man zusammenarbeitet. Die Konfigurationen, die ich so im Netz und von anderen gesehen habe, waren oft sehr groß. Damit war irgendwie alles möglich, aber die Konfiguration zu durchsteigen und zu verstehen, das ist oft fast unmöglich.
28 -
29 -
Durch Zufall bin ich im Netz dann über einen Post und kurz danach über ein Video von jemandem gestolpert, in dem er Neovim Schritt für Schritt einrichtet. Dabei hält er die Konfiguration, Tools und Co. sehr klein bzw. setzt nur wenige ein. Nur das Wichtigste wird verwendet und hauptsächlich so beschrieben, dass man erst einmal versteht, wie man Neovim und 1–2 Plugins einrichtet, um dann viele weitere Plugins installieren, verwalten und konfigurieren zu können.
30 -
31 -
## neovim installieren 
32 -
33 -
Installation von neovim mit homebrew 
34 -
35 -
    brew install nvim
36 -
37 -
## Konfiguration 
38 -
39 -
40 -
Alle Dateien meiner Config sind in einem [Github Repo](https://github.com/ruedigerp/neovim-config) veröffentlicht.
41 -
Wer direkt mit Neovim loslegen möchte, kann es einfach klonen und Neovim starten:
42 -
43 -
    git clone https://github.com/ruedigerp/neovim-config ~/.config/nvim
44 -
45 -
Wer sich alle Plugins genauer anschauen, konfigurieren und verstehen möchte, kann einfach ab hier Schritt für Schritt durchgehen und nach jedem Schritt/Plugin testen.
46 -
47 -
Die Konfiguration von Neovim liegt im Home-Verzeichnis in `.config/nvim`.
48 -
Als Erstes habe ich eine Datei `init.lua` erstellt und Lazy konfiguriert.
49 -
Normalerweise sind in der Datei noch andere Sachen, wie z. B. die Leader-Taste, die auf Space gesetzt ist.
50 -
Das konfiguriere ich später aber in einer anderen Datei.
51 -
52 -
Hier wird jetzt erst einmal nur Lazy konfiguriert, und anschließend legen wir noch im Verzeichnis lua weitere Dateien und Ordner an, in denen dann die anderen Sachen konfiguriert werden.
53 -
54 -
    local lazypath = vim. fn.stdpath("data") .. "/lazy/lazy.nvim"
55 -
    if not vim. loop.fs_stat(lazypath) then
56 -
        vim.fn.system({
57 -
        "git",
58 -
        "clone",
59 -
        "--filter=blob:none",
60 -
        "https://github.com/folke/lazy.nvim.git",
61 -
        "--branch=stable",     
62 -
        lazypath,
63 -
        })
64 -
    end
65 -
    vim.opt.rtp:prepend(lazypath)
66 -
67 -
    local opt = {}     
68 -
69 -
    require("vim-options")
70 -
    require("lazy").setup("plugins")
71 -
72 -
Als nächstes wird im Verzeichnis `.config/vim/lua/` die Datei `vim-options.lua` angelegt: 
73 -
74 -
    # Tab, Space und Co 
75 -
    vim.cmd("set expandtab")
76 -
    vim.cmd("set tabstop=2")
77 -
    vim.cmd("set softtabstop=2")
78 -
    vim.cmd("set shiftwidth=2")
79 -
    vim.g.mapleader = " "
80 -
81 -
    # Wechseln links, rechts, hoch und runter mit ctl + hjkl
82 -
    # Hier kommt nachher noch ein Plugin zum Einsatz
83 -
    vim.keymap.set( 'n', '<c-k>', ':wincmd k<CR>')
84 -
    vim.keymap.set( 'n', '<c-j>', ':wincmd j<CR>')
85 -
    vim.keymap.set( 'n', '<c-h>', ':wincmd h<CR>')
86 -
    vim.keymap.set( 'n', '<c-l>', ':wincd l<CR>')
87 -
88 -
    # Search und Zeilennummern 
89 -
    vim.keymap.set( 'n', '<leader>h', ':nohlsearch<CR>')
90 -
    vim.wo.number = true
91 -
92 -
## Plugins in neovim
93 -
94 -
### nvim-tmux-navigator 
95 -
96 -
Wie im Kommentar oben erwähnt, benutze ich ein paar Plugins – darunter auch eins, um aus Neovim mit den oben konfigurierten Keymaps nicht nur innerhalb von Neovim wechseln zu können, sondern auch in andere Fenster innerhalb einer Tmux-Session.
97 -
Aktuell könnte man zwar schon mit Tmux mehrere Fenster erstellen und mit der gleichen Konfiguration zwischen den Tmux-Fenstern hin- und herspringen. Ist jedoch in einem Fenster Neovim geöffnet, kommt man nicht mehr zurück in andere Tmux-Fenster.
98 -
99 -
Also fangen wir mal an, die Plugins zu konfigurieren, und nehmen uns direkt dieses Plugin vor.
100 -
101 -
Im `lua`-Ordner erstellen wir einen Ordner `plugins` und darin die Datei `nvim-tmux-navigator.lua`:
102 -
103 -
[christoomey/vim-tmux-navigator](https://github.com/christoomey/vim-tmux-navigator)
104 -
105 -
    return {
106 -
        "christoomey/vim-tmux-navigator",
107 -
        vim.keymap.set('n', 'C-h', ':TmuxNavigateLeft<CR>'),
108 -
        vim.keymap.set('n', 'C-j', ':TmuxNavigateDown<CR>'),
109 -
        vim.keymap.set('n', 'C-k', ':TmuxNavigateUp<CR>'),
110 -
        vim.keymap.set('n', 'C-l', ':TmuxNavigateRight<CR>'),
111 -
    }
112 -
113 -
Öffnet man jetzt Neovim (`nvim`), sollte als Erstes ein Fenster von `Lazy` zu sehen sein, und alle konfigurierten Plugins werden installiert. Es sollte also jetzt zu sehen sein, dass ein Repo geklont wird und `vim-tmux-navigator` installiert ist.
114 -
115 -
Ist Neovim nun in einer Tmux-Session mit mehreren Fenstern geöffnet, kann man mit Ctrl + h, j, k, l durch alle Fenster navigieren – egal, ob es ein Neovim- oder ein Tmux-Fenster ist.
116 -
117 -
### Weitere Puglins konfigurieren 
118 -
119 -
Bei allen Plugins kann nach dem Anlegen der Datei und dem Kopieren der Konfiguration Neovim gespeichert, geschlossen und neu geöffnet werden. Dann wird das jeweilige Plugin installiert.
120 -
121 -
Wer nicht alles Schritt für Schritt machen möchte, kann einfach alles anlegen und Neovim erst zum Schluss neu starten. Lazy kümmert sich dann darum, alle Plugins zu installieren. Falls jedoch etwas nicht funktioniert, wird es schwieriger, den Fehler zu beheben. Daher würde ich empfehlen, erst einmal alles einzeln zu machen und dabei zu testen. Dann erst das nächste Plugin einrichten.
122 -
123 -
Daher richten wir jetzt als Erstes die Sidebar für Dateien ein. Man kann dann einfach in das Verzeichnis `cd ~/.config/nvim` wechseln und dort `nvim` starten. Wenn `neo-tree` installiert ist, kann man mit `Ctrl + n` die Dateiliste anzeigen und schnell zwischen den Dateien wechseln. 
124 -
125 -
### Dateien in der Sidebar 
126 -
127 -
[Neo-tree](nvim-neo-tree/neo-tree.nvim) ist ein Neovim-Plugin, mit dem du das Dateisystem und andere baumartige Strukturen in jedem gewünschten Stil durchsuchen kannst, einschließlich Seitenleisten, schwebender Fenster, Netrw-Split-Style oder sogar alle gleichzeitig!
128 -
129 -
    return {
130 -
        "nvim-neo-tree/neo-tree.nvim",
131 -
        branch = "v3.x",
132 -
        dependencies = {
133 -
            "nvim-lua/plenary.nvim",
134 -
            "nvim-tree/nvim-web-devicons",
135 -
            "MunifTanjim/nui.nvim",
136 -
        },
137 -
        config = function()
138 -
            require("neo-tree").setup({
139 -
            filesystem = {
140 -
                filtered_items = {
141 -
                visible = true, -- Zeige standardmäßig alle ausgeblendeten Dateien
142 -
                hide_dotfiles = false, -- Zeige .dotfiles wie .gitignore
143 -
                hide_gitignored = false, -- Zeige Dateien, die in der .gitignore stehen
144 -
                hide_by_name = { -- Optional: spezifische Dateien oder Ordner ausblenden
145 -
                    -- "node_modules", "dist"
146 -
                },
147 -
                },
148 -
            },
149 -
            })
150 -
151 -
            -- Keymap für Neo-Tree
152 -
            vim.keymap.set('n', '<C-n>', ':Neotree filesystem reveal right<CR>', {} )
153 -
        end
154 -
    }
155 -
156 -
### Colorschema mit catppuccin
157 -
158 -
[catppuccin/nvim](https://github.com/catppuccin/nvim)
159 -
160 -
Funktionen
161 -
	•	Unterstützt sowohl Vim als auch Neovim (benötigt Neovim >= 0.8 oder Vim >= 9, kompiliert mit Lua >= 5.1)
162 -
	•	Hochgradig konfigurierbar mit 4 verschiedenen Varianten und der Möglichkeit, eigene zu erstellen!
163 -
	•	Benutzerkonfiguration kompilieren für schnellste Startzeit
164 -
	•	Integrationen mit LSP, Treesitter und zahlreichen Plugins
165 -
	•	Unterstützung für viele andere Anwendungen
166 -
167 -
    return {
168 -
        "catppuccin/nvim",
169 -
        -- lazy = false,
170 -
        name = "catppuccin",
171 -
        priority = 1000,
172 -
        config = function()
173 -
        -- require("catppuccin").setup()
174 -
        vim.cmd.colorscheme "catppuccin"
175 -
        end
176 -
    }
177 -
178 -
### Dashboard beim starten
179 -
180 -
[nvimdev/dashboard-nvim](https://github.com/nvimdev/dashboard-nvim) Fancy and Blazing Fast start screen plugin of neovim
181 -
182 -
    return {
183 -
        'nvimdev/dashboard-nvim',
184 -
        event = 'VimEnter',
185 -
        config = function()
186 -
            require('dashboard').setup {
187 -
            -- config
188 -
            }
189 -
        end,
190 -
        dependencies = { {'nvim-tree/nvim-web-devicons'}}
191 -
    }
192 -
193 -
### Neovim statusline 
194 -
195 -
A blazing fast and easy to configure Neovim statusline written in Lua.
196 -
[nvim-lualine/lualine.nvim](https://github.com/nvim-lualine/lualine.nvim)
197 -
198 -
    return {
199 -
        "nvim-lualine/lualine.nvim",
200 -
        config = function()
201 -
            require('lualine').setup({
202 -
            options = {
203 -
                theme = 'dracula'
204 -
            }
205 -
            })
206 -
        end
207 -
    }
208 -
209 -
### Fuzzy-Finder 
210 -
211 -
[telescope.nvim](https://github.com/nvim-telescope/telescope.nvim) ist ein hochgradig erweiterbarer Fuzzy-Finder für Listen. Es basiert auf den neuesten großartigen Funktionen des Neovim-Kerns. Telescope ist auf Modularität ausgerichtet und ermöglicht eine einfache Anpassung.
212 -
213 -
    return {
214 -
        {
215 -
            'nvim-telescope/telescope.nvim',
216 -
            tag = '0.1.8',
217 -
            dependencies = { 'nvim-lua/plenary.nvim' },
218 -
            config = function()
219 -
            local builtin = require("telescope.builtin")
220 -
            local telescope = require("telescope")
221 -
222 -
            -- Telescope setup
223 -
            telescope.setup({
224 -
                defaults = {
225 -
                hidden = true, -- Aktiviert die Anzeige von versteckten Dateien
226 -
                file_ignore_patterns = { "%.git/" },
227 -
                respect_gitignore = true,
228 -
                }
229 -
            })
230 -
231 -
            -- Keybindings
232 -
            vim.keymap.set('n', '<C-p>', function()
233 -
                builtin.find_files({ hidden = true }) -- Versteckte Dateien für `find_files` anzeigen
234 -
            end, {})
235 -
236 -
            -- vim.keymap.set('n', '<leader>fg', builtin.live_grep, {})
237 -
            vim.keymap.set('n', '<leader>fg', function()
238 -
                builtin.live_grep({ no_ignore = false }) -- Respektiere .gitignore
239 -
            end, {})
240 -
            end
241 -
        },
242 -
        {
243 -
            "nvim-telescope/telescope-ui-select.nvim",
244 -
            config = function()
245 -
            require("telescope").setup ({
246 -
                extensions = {
247 -
                ["ui-select"] = {
248 -
                    require("telescope.themes").get_dropdown {
249 -
                    }
250 -
                }
251 -
                }
252 -
            })
253 -
            require("telescope").load_extension("ui-select")
254 -
            end
255 -
        },
256 -
    }
257 -
258 -
### Treesitter 
259 -
260 -
Das Ziel von [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) ist es, sowohl eine einfache und benutzerfreundliche Schnittstelle für Tree-sitter in Neovim bereitzustellen als auch grundlegende Funktionen wie etwa Syntaxhervorhebung darauf basierend anzubieten.
261 -
262 -
    return {
263 -
        "nvim-treesitter/nvim-treesitter",
264 -
        build = ":TSUpdate",
265 -
        config = function()
266 -
            local config = require ("nvim-treesitter.configs")
267 -
            config. setup ({
268 -
            ensure_installed = {"lua", "javascript", "go", "dockerfile", "helm", "ssh_config", "terraform",
269 -
        "tmux", "toml", "yaml"},
270 -
            highlight = { enable = true },
271 -
            indent = { enable = true },
272 -
            })
273 -
        end
274 -
    }
275 -
276 -
### LSP und Vim-Tests
277 -
278 -
Ich habe noch zwei weitere Plugins. Und zwar `vim-test`, um Code-Tests auszuführen, die man direkt in Neovim starten kann. Dabei wird jedoch ein Buffer in Neovim geöffnet, und wenn man größere Ausgaben hat, sieht man diese zwar, aber man kann sie nicht in den Hintergrund schieben, den Code anschauen und dann wieder zur Ausgabe zurückwechseln. Die Ausgabe des Tests ist dann weg.
279 -
280 -
`vim-test` sorgt dafür, dass ein zweites Fenster in der Tmux-Session geöffnet wird, welches offen bleibt und zwischen dem Code- und dem Test-Fenster gewechselt werden kann. So können alle Fehler nach und nach behoben werden.
281 -
282 -
Das zweite Plugin ist für LSP: `nvim-lspconfig`. `nvim-lspconfig` ist ein „datenbasiertes“ Repository, das grundlegende, standardmäßige Neovim-LSP-Client-Konfigurationen für verschiedene `LSP-Server` bereitstellt.
283 -
So werden Fehler im Code direkt angezeigt, wie man es von Visual Studio und Co. kennt. Auch das Springen zu Definitionen, Anzeigen von Hilfen usw. ist damit möglich.
284 -
285 -
Die beiden Plugins werde ich später noch einmal ausführlicher beschreiben, da ich sie aktuell selbst noch teste und teilweise noch einrichte und konfiguriere. Für LSP müssen lokal passende LSP-Server für die entsprechenden Programmiersprachen installiert sein.
286 -
287 -
Das wird dann besser ein eigener Post.
gelöscht content/2024-12-18-tmux-sessions-mit-tmuxifier.md
+0 −126
@@ -1,126 +0,0 @@
1 -
---
2 -
title: 'tmux Sessions mit tmuxifier verwalten'
3 -
date: 2024-12-18 06:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/12/tmux.webp"
6 -
featureImage: "/images/posts/2024/12/tmux.webp"
7 -
tags: [MacOS, iTerm, tmux, tmuxifier]
8 -
categories: 
9 -
    - MacOS
10 -
preview: "Wer kennt es nicht, ein Kollege kommt an den Schreibtisch und beschreibt ein Problem auf einem Cluster.
11 -
Man öffnet ein Terminal und öffnet 4-5 Tabs, da man auf 2-3 Servern per SSH muss, 2-3 Shells für Config Verzeichnis und z.B. für Tests mit Curl."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![iTerm zsh](/images/posts/2024/12/tmux.webp)
20 -
21 -
## tmux Session mit Tmuxifier
22 -
23 -
Wer kennt es nicht: Ein Kollege kommt an den Schreibtisch und beschreibt ein Problem auf einem Cluster.
24 -
Man öffnet ein Terminal und 4–5 Tabs, da man auf 2–3 Servern per SSH zugreifen muss, sowie 2–3 Shells für das Config-Verzeichnis und z. B. für Tests mit Curl.
25 -
26 -
Allein die Logins, Verzeichniswechsel und das Öffnen der Konfigurationen zum Vergleichen dauert, bis man endlich loslegen kann.
27 -
28 -
Ich benutze im Terminal Tmux und dafür das Tool Tmuxifier, um diese Schritte zu automatisieren.
29 -
30 -
[Tmuxify](https://github.com/jimeh/tmuxifier) dein Tmux!
31 -
Erstelle, bearbeite, verwalte und lade komplexe Tmux-Konfigurationen für Sitzungen, Fenster und Panes mit Leichtigkeit.
32 -
33 -
Kurz gesagt, Tmuxifier ermöglicht es dir, „Layout“-Dateien einfach zu erstellen, zu bearbeiten und zu laden. Diese Dateien sind einfache Shell-Skripte, in denen du den Tmux-Befehl sowie von Tmuxifier bereitgestellte Hilfsbefehle verwendest, um Tmux-Sitzungen und Fenster zu verwalten.
34 -
35 -
36 -
### Fenster-Layouts
37 -
38 -
Fenster-Layouts erstellen ein neues Tmux-Fenster, wobei optional der Fenstertitel und das Root-Verzeichnis festgelegt werden können, in dem sich alle Shells standardmäßig befinden. Sie ermöglichen es dir, ein Fenster einfach in spezifisch dimensionierte Panes zu unterteilen und es nach deinen Wünschen anzupassen.
39 -
40 -
Du kannst ein Fenster-Layout direkt in deiner aktuellen Tmux-Sitzung laden oder es in ein Sitzungs-Layout integrieren, sodass das Fenster zusammen mit der Sitzung erstellt wird.
41 -
42 -
### Sitzungs-Layouts
43 -
44 -
Sitzungs-Layouts erstellen eine neue Tmux-Sitzung und legen dabei optional einen Sitzungstitel und ein Root-Verzeichnis fest, in dem sich alle Shells der Sitzung standardmäßig befinden. Fenster können der Sitzung entweder durch das Laden bestehender Fenster-Layouts hinzugefügt oder direkt innerhalb der Sitzungs-Layout-Datei definiert werden.
45 -
46 -
47 -
## Tmuxifier installieren 
48 -
49 -
Installation von Tmuxifier mit homebrew: 
50 -
51 -
    git clone https://github.com/jimeh/tmuxifier.git ~/.tmuxifier
52 -
53 -
## Konfiguration 
54 -
55 -
Als Erstes erstellt man eine neue Session, die man in Zukunft einfach mit load-session immer wieder aufrufen kann:
56 -
57 -
    tmuxifier create-session example 
58 -
59 -
Dadurch wird die Datei `.tmuxifier/layouts/example.session.sh` angelegt. Diese wird automatisch geöffnet und kann anschließend bearbeitet werden.
60 -
61 -
    session_root "~/Code/example-cluster/"
62 -
63 -
    if initialize_session "example"; then
64 -
65 -
        # Create a new window inline within session layout definition.
66 -
        new_window "cluster1"
67 -
        new_window "cluster1"
68 -
        new_window "deploy"
69 -
        new_window "services"
70 -
        new_window "shell
71 -
72 -
        # Select the default active window on session creation.
73 -
        select_window 0
74 -
        run_cmd "KUBECONFIG=/Users/rk/Code/example-cluster/cluster1-kubeconfig.yaml"
75 -
        run_cmd "cluster1"
76 -
        select_window 1
77 -
        run_cmd "KUBECONFIG=/Users/rk/Code/example-cluster/cluster2-kubeconfig.yaml"
78 -
        run_cmd "cluster1"
79 -
        select_window 2
80 -
        run_cmd "cd deployments; nvim "
81 -
        select_window 3
82 -
        run_cmd "cd services; nvim "
83 -
        select_window 4 
84 -
        run_cmd "cd deployments"
85 -
        select window 0
86 -
    fi
87 -
88 -
    # Finalize session creation and switch/attach to it.
89 -
    finalize_and_go_to_session
90 -
91 -
Muss ich auf die beiden Cluster und die entsprechenden Verzeichnisse zugreifen, um etwas zu debuggen, auszurollen usw., kann ich einfach eine neue Tmux-Session erstellen, die dann 4 Tmux-Fenster öffnet.
92 -
93 -
In den ersten beiden Fenstern sind die beiden Kubernetes-Cluster mit k9s geöffnet.
94 -
95 -
Im 3. und 4. Fenster befinden sich die Deployments (Helm-Charts) bzw. Services (Code und Docker-Skripte) und sind direkt in nvim geöffnet.
96 -
97 -
Das 5. Fenster ist eine Shell, die direkt im Verzeichnis deployments startet, um schnell Pakete erstellen oder Deployments durchführen zu können.
98 -
99 -
Die Session starte ich dann mit: 
100 -
101 -
    tmuxifier load-session example 
102 -
103 -
Nach 1–2 Sekunden ist in Tmux eine neue Session mit dem Namen Example geöffnet – mit 5 Fenstern, die genau so gestartet und geöffnet wurden, wie in der Tmuxifier-Konfiguration angegeben.
104 -
105 -
Falls dich jemand fragt, warum ich die kubeconfig.yaml-Dateien pro Cluster habe und nicht in der globalen Benutzer-Kubeconfig-Context-Datei: Ich benutze ein Tool (direnv) für Environment-Variablen (Env-Vars) in der Shell, das in Verzeichnissen die entsprechenden Env-Vars setzt, die dort benötigt werden. Das werde ich in einem anderen Post genauer beschreiben.
106 -
107 -
Öffnet man jetzt die Session- und Fensterliste, sieht man die Session mit allen Fenstern und kann diese auswählen.
108 -
Bei mir gibt es aktuell drei Sessions mit mehreren Fenstern. Die Session aus der Konfiguration ist die Session `example` mit ihren fünf Tmux-Fenstern.
109 -
110 -
    (1)   + dev-cluster: 2 windows
111 -
    (2)   - example: 4 windows
112 -
    (3)   ├─> 0: cluster1*
113 -
    (4)   ├─> 1: cluster1
114 -
    (5)   ├─> 2: deploy
115 -
    (6)   └─> 3: services
116 -
    (7)   └─> 3: shell
117 -
    (8) + prod-cluster: 3 windows
118 -
119 -
### Tmuxifier erleichtert wiederkehrende Sessions
120 -
121 -
Die Aufgaben und die damit einhergehenden, immer wieder gleichen Schritte, die man täglich ausführt, lassen sich mit Tmuxifier schnell und einfach automatisieren. Die Konfiguration ist recht simpel, und wenn man – wie ich – täglich auf mehreren Servern und Clustern arbeitet, kann man sich hierdurch einige Tasks erheblich erleichtern.
122 -
123 -
Ich habe eine Konfiguration für einen Test- und einen Produktions-Cluster erstellt, sodass ich schnell die wichtigsten Dinge geöffnet habe. Zusätzlich nutze ich das oben beschriebene Beispiel für meinen Blog und andere Tools auf meinen privaten Kubernetes-Clustern. Dadurch kann ich mein Blog und andere Projekte schnell aktualisieren.
124 -
125 -
Für Migrationen erstelle ich ebenfalls eine Tmuxifier-Konfiguration. In den Tagen vor der Migration bin ich häufig auf den entsprechenden Servern eingeloggt, um alles vorzubereiten – oft auch mit Migrationstests, die den eigentlichen Migrationstag simulieren. Die Tmux-Fenster und Sessions kann ich nach der Vorbereitung schließen und dann am Tag der Migration einfach die Session in Tmux neu erstellen lassen.
126 -
gelöscht content/2025-01-19-kubernetres-ingress-dns-pihole copy.md
+0 −182
@@ -1,182 +0,0 @@
1 -
---
2 -
title: 'Kubernetres Ingress DNS PiHole'
3 -
date: 2025-01-19 0:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2025/01/pihole-local-dns.webp"
6 -
featureImage: "/images/posts/2025/01/pihole-local-dns.webp"
7 -
tags: [Kubernetes, HomeLab, external-DNS, PiHole]
8 -
categories: 
9 -
    - Kubernetes
10 -
preview: "Home Lab mit PiHole lokalen DNS Records."
11 -
draft: false
12 -
top: false
13 -
type: post
14 -
hide: false
15 -
toc: false
16 -
---
17 -
18 -
![piHole local dns](/images/posts/2025/01/pihole-local-dns.webp)
19 -
20 -
## Lokales Lab auf dem Mac mit DNS Recordes
21 -
22 -
Ich habe auf dem Mac Mini mit Multipass mehrere Server, die mit Kubernetes mehrere Dienste bereitstellen. Damit diese auch per Domain angesprochen werden benutze ich die lokalen DNS Records im PiHole. 
23 -
24 -
Wenn ich einen Service per Ingress oder Service bereitstelle wird automatisch ein DNS Record angelegt. Dazu benutze ich External-DNS. Ich kann damit entweder im PiHole die DNS Records anlegen oder bei Cloudflare in einer Zone. 
25 -
External-DNS kann aber auch mit [sehr vielen](https://github.com/kubernetes-sigs/external-dns?tab=readme-ov-file#the-latest-release) anderen DNS-Providern genutzt werden. 
26 -
27 -
In diesem Post beschreibe ich das einrichten im PiHole. 
28 -
29 -
## Konfiguration 
30 -
31 -
Namespace anlegen:
32 -
33 -
    kubectl create ns external-dns
34 -
35 -
Secret anlegen:
36 -
37 -
    kubectl create secret generic pihole-password --from-literal EXTERNAL_DNS_PIHOLE_PASSWORD=YourSecret -n external-dns
38 -
39 -
40 -
YourSecret ist das Passwort für den Login in Deinem PiHole. 
41 -
42 -
pihole.yaml
43 -
44 -
    ---
45 -
    apiVersion: v1
46 -
    kind: ServiceAccount
47 -
    metadata:
48 -
    name: external-dns
49 -
    namespace: external-dns
50 -
    ---
51 -
    apiVersion: rbac.authorization.k8s.io/v1
52 -
    kind: ClusterRole
53 -
    metadata:
54 -
    name: external-dns
55 -
    namespace: external-dns
56 -
    rules:
57 -
    - apiGroups: [""]
58 -
    resources: ["services","endpoints","pods"]
59 -
    verbs: ["get","watch","list"]
60 -
    - apiGroups: ["extensions","networking.k8s.io"]
61 -
    resources: ["ingresses"]
62 -
    verbs: ["get","watch","list"]
63 -
    - apiGroups: [""]
64 -
    resources: ["nodes"]
65 -
    verbs: ["list","watch"]
66 -
    ---
67 -
    apiVersion: rbac.authorization.k8s.io/v1
68 -
    kind: ClusterRoleBinding
69 -
    metadata:
70 -
    name: external-dns-viewer
71 -
    namespace: external-dns
72 -
    roleRef:
73 -
    apiGroup: rbac.authorization.k8s.io
74 -
    kind: ClusterRole
75 -
    name: external-dns
76 -
    subjects:
77 -
    - kind: ServiceAccount
78 -
    name: external-dns
79 -
    namespace: external-dns 
80 -
    ---
81 -
    apiVersion: apps/v1
82 -
    kind: Deployment
83 -
    metadata:
84 -
    name: external-dns
85 -
    namespace: external-dns
86 -
    spec:
87 -
    strategy:
88 -
        type: Recreate
89 -
    selector:
90 -
        matchLabels:
91 -
        app: external-dns
92 -
    template:
93 -
        metadata:
94 -
        labels:
95 -
            app: external-dns
96 -
        spec:
97 -
        serviceAccountName: external-dns
98 -
        containers:
99 -
        - name: external-dns
100 -
            image: registry.k8s.io/external-dns/external-dns:v0.14.1
101 -
            # If authentication is disabled and/or you didn't create
102 -
            # a secret, you can remove this block.
103 -
            envFrom:
104 -
            - secretRef:
105 -
                # Change this if you gave the secret a different name
106 -
                name: pihole-password
107 -
            args:
108 -
            - --source=service
109 -
            - --source=ingress
110 -
            - --domain-filter=kuepper.lab
111 -
            # Pihole only supports A/CNAME records so there is no mechanism to track ownership.
112 -
            # You don't need to set this flag, but if you leave it unset, you will receive warning
113 -
            # logs when ExternalDNS attempts to create TXT records.
114 -
            - --registry=noop
115 -
            # IMPORTANT: If you have records that you manage manually in Pi-hole, set
116 -
            # the policy to upsert-only so they do not get deleted.
117 -
            - --policy=upsert-only
118 -
            - --provider=pihole
119 -
            # Change this to the actual address of your Pi-hole web server
120 -
            - --pihole-server=http://10.0.2.240
121 -
        securityContext:
122 -
            fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes token files
123 -
124 -
In dem `pihole.yaml` muss die IP für den piHole angepasst werden: 
125 -
126 -
    - --pihole-server=http://10.0.2.240
127 -
128 -
Zusätzlich sollte die Domain angepasst werden. 
129 -
130 -
Die IP 10.0.2.240 mit der IP Deines PiHole ersetzen, da Du sehr wahrscheinlich nicht `kuepper.lab` benutzen willst.
131 -
132 -
    - --domain-filter=yourdomain.tld 
133 -
134 -
Das yaml-File in Deinem Kubernetes installieren und schon werden die Records automatisch angelegt.
135 -
136 -
    kubectl apply -f pihole.yaml
137 -
138 -
139 -
## Ingress anlegen und Tests
140 -
141 -
ingress.yaml
142 -
143 -
    apiVersion: networking.k8s.io/v1
144 -
    kind: Ingress
145 -
    metadata:
146 -
    name: ink-blog
147 -
    namespace: ink
148 -
    spec:
149 -
    ingressClassName: traefik
150 -
    rules:
151 -
    - host: ink.kuepper.lab
152 -
        http:
153 -
        paths:
154 -
        - backend:
155 -
            service:
156 -
                name: ink-blog
157 -
                port:
158 -
                number: 80
159 -
            path: /
160 -
            pathType: Prefix
161 -
162 -
Den Ingress in Deinem Cluster anlegen:
163 -
164 -
    kubectl apply -f ingress.yaml 
165 -
166 -
Im Logfile vom external DNS sollte 1-2 Minuten nach dem apply folgende zeile im Log auftauchen:
167 -
168 -
    external-dns-786bc76c79-hbw84 time="2025-01-18T23:39:56Z" level=info msg="add ink.kuepper.lab IN A -> 192.168.64.6"
169 -
170 -
Die IP `192.168.64.6` ist die IP von meinem Cluster und der Domainname (fqdn) ink.kuepper.lab wird im PiHole eingetragen.
171 -
172 -
173 -
![piHole local dns](/images/posts/2025/01/pihole-local-dns.png)
174 -
175 -
Überprüfen wir das anschliessend, wird der hostname richtige aufgelöst:
176 -
177 -
    host ink.kuepper.lab
178 -
    ink.kuepper.lab has address 192.168.64.6
179 -
180 -
Dieses Setup ist für lokale Tests, kann aber auch für Services genutzt werden die extern erreichbar sind, so das die benötigten DNS Record automatisch bei Cloudflare oder anderen Providern eingerichtet werden. Dabei kann jeder Service auch Proxied bei Cloudflare eingerichtet werden. Also auch it SSL Zertifikaten. Im Free Account für Cloudflare können keine sub-sub Domains also xzy.foobar.yourdomain.tld mit einem Zertifikat ausgestattet werden. Diese kann man dann einfach ohne Cloudflare Proxy einrichten und dann lokal per Cert-Manager und Letsencrypt einfach mit Zertifikate ausstatten. 
181 -
182 -
Das beschreibe ich dann in einem weiterem Post. In diesem werde ich dann zeigen wie man das Zertifikat pro Domain oder einfach ein Wildcard Zertifikat erstellt. Je nachdem was man benötigt und wie Dein Setup ist. 
gelöscht content/2025-02-03-multipass-k3s-vm-mit-cloud-init.md
+0 −73
@@ -1,73 +0,0 @@
1 -
---
2 -
title: 'Multipass K3S VM mit Cloud-init'
3 -
date: 2025-02-03 21:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2024/12/tmux.webp"
6 -
featureImage: "/images/posts/2024/12/tmux.webp"
7 -
tags: [Kubernetes, k3s, HomeLab, multipass, Cloud-init]
8 -
categories: 
9 -
    - Kubernetes
10 -
preview: "Schnell eine k3s VM mit multipass erstellen "
11 -
draft: false
12 -
top: false
13 -
type: post
14 -
hide: false
15 -
toc: false
16 -
---
17 -
18 -
![k3s k9s](/images/posts/2024/12/tmux.webp)
19 -
20 -
# Multipass installieren
21 -
22 -
    ❯ brew install multipass
23 -
24 -
# Cloud-Init Yaml erstellen 
25 -
26 -
cloud-init.yaml
27 -
28 -
    packages:
29 -
    # - traceroute
30 -
    # - frr
31 -
32 -
    runcmd:
33 -
    - export HOME='/home/ubuntu'
34 -
    - export USER='ubuntu'
35 -
    - cd $HOME
36 -
    - curl -sfL https://get.k3s.io | sh -s - server --cluster-init --disable=servicelb --tls-san=192.168.64.251 --disable=traefik
37 -
    - echo "export KUBECONFIG=/etc/rancher/k3s/k3s.yaml" > /root/.bashrc
38 -
    - wget https://github.com/derailed/k9s/releases/download/v0.32.7/k9s_Linux_arm64.tar.gz; tar xzf k9s_Linux_arm64.tar.gz; mv k9s /usr/local/bin/;
39 -
    - curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3; chmod 700 get_helm.sh; ./get_helm.sh
40 -
41 -
# VM erstellen 
42 -
43 -
    ❯ multipass launch -c 1 -m 1G --disk 10G --network en0 --name controlplane-test --cloud-init cloud-init.yaml
44 -
45 -
    ❯ multipass list
46 -
    Name                    State             IPv4             Image
47 -
    cloud-init-test         Running           192.168.64.45    Ubuntu 24.04 LTS
48 -
                                            10.0.2.109
49 -
                                            10.42.0.0
50 -
                                            10.42.0.1
51 -
52 -
53 -
# In VM einloggen 
54 -
55 -
    ❯ multipass shell controlplane-test
56 -
    Welcome to Ubuntu 24.04.1 LTS (GNU/Linux 6.8.0-51-generic aarch64)
57 -
58 -
    Last login: Mon Feb  3 20:26:31 2025 from 192.168.64.1
59 -
    ubuntu@controlplane-test:~$ sudo su - 
60 -
    root@controlplane-test:~# kubectl get nodes
61 -
    NAME              STATUS   ROLES                       AGE   VERSION
62 -
    controlplane-test Ready    control-plane,etcd,master   7m    v1.31.5+k3s1
63 -
    root@controlplane-test:~# kubectl get pods -A
64 -
    NAMESPACE     NAME                                      READY   STATUS    RESTARTS        AGE
65 -
    kube-system   coredns-ccb96694c-knm8m                   1/1     Running   0               6m58s
66 -
    kube-system   local-path-provisioner-5cf85fd84d-h9rjg   1/1     Running   2 (6m49s ago)   6m58s
67 -
    kube-system   metrics-server-5985cbc9d7-cv25j           1/1     Running   2 (6m49s ago)   6m58s
68 -
    root@controlplane-test:~#
69 -
70 -
# VM löschen
71 -
72 -
    ❯ multipass delete controlplane-test
73 -
    ❯ multipass purge 
gelöscht content/2025-02-06-mino-bucket-sync.md
+0 −40
@@ -1,40 +0,0 @@
1 -
---
2 -
title: 'Minio Bucket sync'
3 -
date: 2025-02-06 12:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2025/02/minio.webp"
6 -
featureImage: "/images/posts/2025/02/minio.webp"
7 -
tags: [Minio, Bucket, Backup, Restore]
8 -
categories: 
9 -
    - Kubernetes
10 -
preview: "Minio S3-Bucket synchronisieren."
11 -
draft: true
12 -
top: false
13 -
type: post
14 -
hide: true
15 -
toc: false
16 -
---
17 -
18 -
![minio](/images/posts/2025/02/minio.webp)
19 -
20 -
21 -
    brew install s3cmd
22 -
    brew install rclone
23 -
    s3cmd --configure
24 -
    s3cmd get s3://terraform-state/state/terraform.tfstate
25 -
    rclone config
26 -
    rclone lsd tfstate:
27 -
    rclone ls tfstate:terraform-state
28 -
    rclone sync tfstate:terraform-state ./
29 -
30 -
    brew install s3cmd
31 -
    brew install rclone
32 -
    rclone config
33 -
    rclone lsd ftstate2:
34 -
    rclone mkdir ftstate2:terraform-state
35 -
    rclone copy  state ftstate2:terraform-state
36 -
    rclone lsd ftstate2:
37 -
38 -
    rclone sync tfstate:terraform-state ./
39 -
    rclone sync state ftstate2:terraform-state
40 -
gelöscht content/2025-03-17-kubernetes-homelab-haproxy.md
+0 −507
@@ -1,507 +0,0 @@
1 -
---
2 -
title: 'HomeLab mit mehreren Clustern hinter einer IP'
3 -
date: 2025-03-16 23:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2025/03/haproxy.webp"
6 -
featureImage: "/images/posts/2025/03/haproxy.webp"
7 -
tags: [HomeLab, Kubernetes, NFS, HAProxy]
8 -
categories: 
9 -
    - Kubernetes
10 -
preview: "HomeLab mit mehreren Clustern hinter einer IP."
11 -
draft: false
12 -
top: false
13 -
type: post
14 -
hide: false
15 -
toc: false
16 -
---
17 -
18 -
![HAProxy](/images/posts/2025/03/haproxy.webp)
19 -
20 -
# Homelab Übersicht 
21 -
22 -
Mein kleines Kubernetes Cluster Setup sieht aktuell wie folgt aus. 
23 -
24 -
25 -
<pre class="mermaid">
26 -
graph TB;
27 -
    Glasfaser-->UDM-Pro;
28 -
    UDM-Pro-->MacMini;
29 -
    MacMini-->Multipass-VM1;
30 -
    MacMini-->Multipass-VM2;
31 -
    MacMini-->Multipass-VM3;
32 -
    MacMini-->Multipass-VM4;
33 -
    MacMini-->Multipass-VM5;
34 -
    MacMini-->Multipass-VM6;
35 -
    MacMini-->Multipass-VM7;
36 -
    MacMini-->Multipass-VM8;
37 -
    MacMini-->Multipass-VM9;
38 -
    Multipass-VM7-->HaProxy
39 -
    HaProxy-->K8s-Controlplane1;
40 -
    HaProxy-->K8s-Controlplane2;
41 -
    HaProxy-->K8s-Controlplane3;
42 -
    HaProxy-->K8s-Worker1;
43 -
    HaProxy-->K8s-Worker2;
44 -
    HaProxy-->K8s-Worker3;
45 -
46 -
    subgraph Cluster01;
47 -
        subgraph Controlplanes;
48 -
            Multipass-VM1-->K8s-Controlplane1;
49 -
            Multipass-VM2-->K8s-Controlplane2;
50 -
            Multipass-VM3-->K8s-Controlplane3;
51 -
        end;
52 -
        subgraph Worker;
53 -
            Multipass-VM4-->K8s-Worker1;
54 -
            Multipass-VM5-->K8s-Worker2;
55 -
            Multipass-VM6-->K8s-Worker3;
56 -
        end;
57 -
    end;
58 -
59 -
    subgraph Cluster02;
60 -
        Multipass-VM8-->K8sdev-Controlplane1;
61 -
        Multipass-VM9-->K8sdev-Worker1;
62 -
    end;
63 -
64 -
    NFS-Server-->K8s-Controlplane1;
65 -
    NFS-Server-->K8s-Controlplane2;
66 -
    NFS-Server-->K8s-Controlplane3;
67 -
    NFS-Server-->K8s-Worker1;
68 -
    NFS-Server-->K8s-Worker2;
69 -
    NFS-Server-->K8s-Worker3;
70 -
71 -
    NFS-Server-->K8sdev-Controlplane1;
72 -
    NFS-Server-->K8sdev-Worker1;
73 -
</pre>
74 -
75 -
Alle VMs sind auf einem MacMini mit Multipass virtualisiert. Cluster01 hat 3 Controlplanes und 3 Worker. Der Cluster02 ist für DEV und Tests, hat aktuell nur ein Controlplane und einen Worker. Beide Cluster können aber bei Bedarf jederzeit vergrössert werden. Aktuell sind sogar noch 3 weitere Cluster aktiv, da aktuell viel getestet und ausprobiert wird. 
76 -
77 -
Auf der Multipass VM 07 ist ein HA-Proxy installiert, der sich um die Loadbalancing Frontends und Backends kümmert. 
78 -
Hier ist auch je Cluster eine VIP für die Kubernetes API. Über die kann die Kubernetes API über eine IP angesprochen werden und landet dann auf eines der Controlplanes. 
79 -
80 -
<pre class="mermaid">
81 -
graph TD;
82 -
    subgraph API-k8s;
83 -
        HaProxyAPI[HAProxy, VIP: 192.168.67.200, Port 6443]-->K8s-Controlplane1;
84 -
        HaProxyAPI[HAProxy, VIP: 192.168.67.200, Port 6443]-->K8s-Controlplane2;
85 -
        HaProxyAPI[HAProxy, VIP: 192.168.67.200, Port 6443]-->K8s-Controlplane3;
86 -
    end;
87 -
</pre>
88 -
89 -
Das gleiche gilt für die HTTP Zugriffe über Port 80, hier wird aber eine andere VIP genommen. Der Grund ist, das hier über Metallb andere oder auch weitere IPS für LoadbalancerIP oder einem weiteren IngressController im Kubernetes genutzt werden könnten. Aber auch für Migrationen des kompletten Clusters oder einzelner Services auf andere Cluster. 
90 -
91 -
<pre class="mermaid">
92 -
graph TD;
93 -
    subgraph Ingress-http;
94 -
        HaProxyhttp[HAProxy, VIP: 192.168.67.17, Port 80]-->K8s-Controlplane1-http;
95 -
        HaProxyhttp[HAProxy, VIP: 192.168.67.17, Port 80]-->K8s-Controlplane2-http;
96 -
        HaProxyhttp[HAProxy, VIP: 192.168.67.17, Port 80]-->K8s-Controlplane3-http;
97 -
        HaProxyhttp[HAProxy, VIP: 192.168.67.17, Port 80]-->K8s-Worker1-http;
98 -
        HaProxyhttp[HAProxy, VIP: 192.168.67.17, Port 80]-->K8s-Worker2-http;
99 -
        HaProxyhttp[HAProxy, VIP: 192.168.67.17, Port 80]-->K8s-Worker3-http;
100 -
    end;
101 -
</pre>
102 -
103 -
Auch für https sind im HA Proxy die Controlplanes und Worker des Clusters eingetragen. Die IP 192.168.67.17 ist die gleiche, da ich hier keine Trennung vornehme. Es währe aber möglich HTTPs Traffik nur auf bestimmte Nodes zu leiten oder gar schon vorne am HA-Proxy auf eine dedizierte IP. Da kommt es immer auf das Setup und den Service an den man bereitstellen möchte. Da Option besteht aber und man könnte auf stärkere Hardware TLS laufen lassen und auf den schwachen Nodes HTTP-Only. 
104 -
105 -
<pre class="mermaid">
106 -
graph TD;
107 -
    subgraph Ingress-https;
108 -
        HaProxyhttps[HAProxy, VIP: 192.168.67.17, Port 443]-->K8s-Controlplane1-https;
109 -
        HaProxyhttps[HAProxy, VIP: 192.168.67.17, Port 443]-->K8s-Controlplane2-https;
110 -
        HaProxyhttps[HAProxy, VIP: 192.168.67.17, Port 443]-->K8s-Controlplane3-https;
111 -
        HaProxyhttps[HAProxy, VIP: 192.168.67.17, Port 443]-->K8s-Worker1-https;
112 -
        HaProxyhttps[HAProxy, VIP: 192.168.67.17, Port 443]-->K8s-Worker2-https;
113 -
        HaProxyhttps[HAProxy, VIP: 192.168.67.17, Port 443]-->K8s-Worker3-https;
114 -
    end;
115 -
</pre>
116 -
117 -
# VIP IPs mit Keepalived 
118 -
119 -
Die VIPs werden auf der VM07 (HAProxy) per keepdalived hochgefahren. 
120 -
121 -
```
122 -
global_defs {
123 -
    enable_script_security
124 -
    script_user root
125 -
}
126 -
127 -
vrrp_script chk_haproxy {
128 -
    script 'killall -0 haproxy'
129 -
    interval 2
130 -
}
131 -
132 -
vrrp_instance cluster01-api-vip {
133 -
    interface enp0s1
134 -
    state MASTER
135 -
    priority 200
136 -
    virtual_router_id 51
137 -
138 -
    virtual_ipaddress {
139 -
        192.168.64.200/24
140 -
    }
141 -
142 -
    }
143 -
vrrp_instance cluster01-ingress-vip {
144 -
    interface enp0s1
145 -
    state MASTER
146 -
    priority 200
147 -
    virtual_router_id 52
148 -
149 -
    virtual_ipaddress {
150 -
        192.168.67.17/24
151 -
    }
152 -
153 -
    }
154 -
```
155 -
156 -
Die Instancen werden einfach hinzugefügt und dabei die `virtual_router_id` hochgezählt. Die müssen eindeutig sein. 
157 -
Nach einem Restart von Keepalived sind nach ein paar Sekunden die zusätzlichen IPs auf dem Interface hochgefahren: 
158 -
159 -
```
160 -
systemctl restart keepalived.service
161 -
162 -
2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
163 -
    link/ether 52:54:00:73:a6:5c brd ff:ff:ff:ff:ff:ff
164 -
    inet 192.168.64.92/24 metric 100 brd 192.168.64.255 scope global dynamic enp0s1
165 -
       valid_lft 2061sec preferred_lft 2061sec
166 -
    inet 192.168.67.17/24 scope global enp0s1
167 -
       valid_lft forever preferred_lft forever
168 -
    inet 192.168.64.200/24 scope global secondary enp0s1
169 -
       valid_lft forever preferred_lft forever
170 -
```
171 -
172 -
# HAProxy Konfiguration
173 -
174 -
Jetzt kann der HAProxy konfiguriert werden und die einzelnen Services auf die VIPs gebunden werden. 
175 -
176 -
## Global und Default 
177 -
178 -
Der Global und Default Block in der haproxy.cfg sieht ao aus:
179 -
180 -
```
181 -
global
182 -
        log /dev/log    local0
183 -
        log /dev/log    local1 notice
184 -
        chroot /var/lib/haproxy
185 -
        # stats socket /run/haproxy/admin.sock mode 660 level admin
186 -
        stats socket /var/run/haproxy.sock mode 600 level admin
187 -
        stats timeout 30s
188 -
        user haproxy
189 -
        group haproxy
190 -
        daemon
191 -
192 -
        # Default SSL material locations
193 -
        ca-base /etc/ssl/certs
194 -
        crt-base /etc/ssl/private
195 -
196 -
        # See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
197 -
        ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
198 -
        ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
199 -
        ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
200 -
201 -
defaults
202 -
        log     global
203 -
        mode    http
204 -
        option  httplog
205 -
        option  dontlognull
206 -
        timeout connect 5000
207 -
        timeout client  50000
208 -
        timeout server  50000
209 -
        errorfile 400 /etc/haproxy/errors/400.http
210 -
        errorfile 403 /etc/haproxy/errors/403.http
211 -
        errorfile 408 /etc/haproxy/errors/408.http
212 -
        errorfile 500 /etc/haproxy/errors/500.http
213 -
        errorfile 502 /etc/haproxy/errors/502.http
214 -
        errorfile 503 /etc/haproxy/errors/503.http
215 -
        errorfile 504 /etc/haproxy/errors/504.http
216 -
```
217 -
218 -
## Das erste Frontend 
219 -
220 -
Anschliessend werden die Frontends konfiguiert. Frontends sind bei HAProxy die Services, die auf einer IP auf einem bestimmten Port listenen und auf ein Backend verweisen. Zu Backends dann weiter unten mehr. 
221 -
222 -
Als erstes das Frontend für die Kubernetes API auf Port 6443. 
223 -
224 -
```
225 -
frontend k3s-api-frontend
226 -
    bind 192.168.64.200:6443
227 -
    mode tcp
228 -
    option tcplog
229 -
    default_backend k3s-backend
230 -
```
231 -
232 -
##  Das erste Backend
233 -
234 -
Das Backend dazu enthält jetzt aber nicht nur einen Eintrag, sondern bekommt alle Controlplanes des Clusters. 
235 -
236 -
```
237 -
backend k3s-backend
238 -
    mode tcp
239 -
    option tcp-check
240 -
    balance roundrobin
241 -
    default-server inter 10s downinter 5s
242 -
    server controlplane1 192.168.64.91:6443 check
243 -
    server controlplane2 192.168.64.92:6443 check
244 -
    server controlplane3 192.168.64.93:6443 check
245 -
```
246 -
247 -
Damit sind die drei Controlplanes eingetragen und ein Aufruf auf `192.168.64.200:6443` gibt die Ausgabe der Kubernetes API zurück. Diese IP und den Port kann auch so in die Kubeconfig eingetragen werden. 
248 -
Das hat den Vorteil das wir jederzeit einen oder mehrere Controlplanes offline nehmen können und weiter auf die API zugreifen können. 
249 -
250 -
## HTTP/HTTPS Frontend/Backend
251 -
252 -
Das Frontend für HTTP und HTTPs sieht genau so aus. Hier einmal wie es für einen Cluster sein könnte. Anschliessend aber mit weiteren Optionen, da wir ein Frontend haben wollen, welches auf mehrere Backends zeigt. 
253 -
Wir wollen ja extern nur eine IP benutzen. Gerade an einem Anschluss fürs HomeLab mit DSL oder Glasfaser hat man ja nur eine IP. Und IPv6 halten ja zu viele noch für Teufelswerk. 
254 -
255 -
256 -
```
257 -
frontend k8s_http_lb_frontend
258 -
    bind 192.168.64.17:80
259 -
    mode http
260 -
    option httplog
261 -
    log-format "%ci:%cp [%t] %ft %b %s %TR/%Tw/%Tc/%Tr/%Tt %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
262 -
    default_backend k8s_http_lb_backend
263 -
264 -
frontend k8s_https_lb_frontend
265 -
    bind 192.168.64.17:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
266 -
    mode http
267 -
    option httplog
268 -
    log-format "%ci:%cp [%t] %ft %b %s %TR/%Tw/%Tc/%Tr/%Tt %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
269 -
    default_backend k8s_https_lb_backend
270 -
```
271 -
272 -
Und die Backends dazu: 
273 -
274 -
```
275 -
backend k8s_http_lb_backend
276 -
    mode tcp
277 -
    option tcp-check
278 -
    balance roundrobin
279 -
    default-server inter 10s downinter 5s
280 -
    server controlplane1 192.168.64.91:80 check
281 -
    server controlplane2 192.168.64.92:80 check
282 -
    server controlplane3 192.168.64.93:80 check
283 -
    server worker1 192.168.64.94:80 check
284 -
    server worker2 192.168.64.95:80 check
285 -
    server worker3 192.168.64.96:80 check
286 -
287 -
backend k8s_https_lb_backend
288 -
    mode http
289 -
    balance roundrobin
290 -
    default-server inter 10s downinter 5s
291 -
    server controlplane1 192.168.64.91:443 check
292 -
    server controlplane2 192.168.64.92:443 check
293 -
    server controlplane3 192.168.64.93:443 check
294 -
    server worker1 192.168.64.94:443 check
295 -
    server worker2 192.168.64.95:443 check
296 -
    server worker3 192.168.64.96:443 check
297 -
```
298 -
299 -
Damit wäre das ganze lauffähig und wir hätten die API, HTTP und HTTPs Ingress erreichbar. 
300 -
301 -
## Weitere Backends
302 -
303 -
Aber es sind ja mehrere Cluster und die externe IP am Anschluss soll ja auf den HAProxy geleitet werden und dann weiter an den entsprechenden Cluster. 
304 -
305 -
Cluster01 hat die Domain k8s01.example.net und entsprechende Subdomains web1.k8s01.example.net, web2.k8s01.example.net usw. 
306 -
307 -
Cluster01 DEV hat die Domain k8s01-dev.example.net und entsprechende Subdomains web1.k8s01-dev.example.net, web2.k8s01-dev.example.net usw. 
308 -
309 -
Cluster02 DEV hat die Domain k8s02-dev.example.net und entsprechende Subdomains web1.k8s02-dev.example.net, web2.k8s02-dev.example.net usw. 
310 -
311 -
Das ganze kann beliebig weiter getrieben werden und weitere Cluster hinzugüfgt werden. 
312 -
313 -
## Match Domains 
314 -
315 -
Damit das ganze funktioniert müssen wir als erstes das Frontent für HTTP und HTTPs erweitern. 
316 -
317 -
```
318 -
frontend k8s_http_lb_frontend
319 -
    bind 192.168.64.17:80
320 -
    mode http
321 -
    option httplog
322 -
    log-format "%ci:%cp [%t] %ft %b %s %TR/%Tw/%Tc/%Tr/%Tt %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
323 -
    acl is_k8s01_dev hdr(host) -m reg ^[a-zA-Z0-9-]+\.k8s01-dev\.example\.net$
324 -
    acl is_k8s02_dev hdr(host) -m reg ^[a-zA-Z0-9-]+\.k8s02-dev\.example\.net$
325 -
    use_backend http_k8s01_dev_backend  if is_k8s01_dev
326 -
    use_backend http_k8s02_dev_backend  if is_k8s02_dev
327 -
    default_backend k8s_http_lb_backend
328 -
329 -
frontend k8s_https_lb_frontend
330 -
    bind 192.168.64.17:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
331 -
    mode http
332 -
    option httplog
333 -
    log-format "%ci:%cp [%t] %ft %b %s %TR/%Tw/%Tc/%Tr/%Tt %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
334 -
    acl is_k8s01_dev hdr(host) -m reg ^[a-zA-Z0-9-]+\.k8s01-dev\.example\.net$
335 -
    acl is_k8s01_dev req.ssl_sni -m reg ^[a-zA-Z0-9-]+\.k8s01-dev\.example\.net$
336 -
    acl is_k8s02_dev hdr(host) -m reg ^[a-zA-Z0-9-]+\.k8s02-dev\.example\.net$
337 -
    acl is_k8s02_dev req.ssl_sni -m reg ^[a-zA-Z0-9-]+\.k8s02-dev\.example\.net$
338 -
339 -
    use_backend https_k8s01_dev_backend if is_k8s01_dev
340 -
    use_backend https_k8s02_dev_backend if is_k8s02_dev
341 -
342 -
    default_backend k8s_https_lb_backend
343 -
```
344 -
345 -
## Die zusätzlichen Backends 
346 -
347 -
Die beiden Backends der weiteren Cluster anlegen:
348 -
349 -
```
350 -
backend http_k8s01_dev_backend
351 -
    mode tcp
352 -
    option tcp-check
353 -
    balance roundrobin
354 -
    default-server inter 10s downinter 5s
355 -
    server controlplane1 192.168.64.100:80 check
356 -
    server worker1 192.168.64.101:80 check
357 -
358 -
backend https_k8s01_dev_backend
359 -
    mode http
360 -
    balance roundrobin
361 -
    default-server inter 10s downinter 5s
362 -
    server controlplane1 192.168.64.100:443 check
363 -
    server worker1 192.168.64.101:443 check
364 -
365 -
backend http_k8s02_dev_backend
366 -
    mode tcp
367 -
    option tcp-check
368 -
    balance roundrobin
369 -
    default-server inter 10s downinter 5s
370 -
    server controlplane1 192.168.64.110:80 check
371 -
    server worker1 192.168.64.111:80 check
372 -
373 -
backend https_k8s02_dev_backend
374 -
    mode http
375 -
    balance roundrobin
376 -
    default-server inter 10s downinter 5s
377 -
    server controlplane1 192.168.64.110:443 check
378 -
    server worker1 192.168.64.111:443 check
379 -
   
380 -
```
381 -
382 -
Damit würde das ganze jetzt mit dem Production, Dev 1 und Dev 2 funktionieren und die Requests werden je nach Domain auf den richtigen Cluster geleitet. 
383 -
384 -
# TLS-Termination mit Letsencrypt
385 -
386 -
Wer genau gegeuckt hat sieht in den Frontend Blöcken bei der Option `bind` beim Frontent für https `ssl crt /etc/haproxy/certs/ alpn h2,http/1.1`. Der HAProxy macht die TLS-termination, also auch das handling der HTTPs Verbindungen, inklusive der Zertifikaten. Ich habe meine Domains bei Cloudflare und habe dort einen API-Key angelegt, mit dem ich DNS Zonen lesen und bearbeiten kann. 
387 -
388 -
Cludflare DNS auch aus dem Grund, weil man so auch Wildcard Zertifikate erstellen kann, was die ganze Sache sehr viel einfacher macht. Man muss nicht für jeden neuen Host-Eintrag ein neues Zertifikat erstellen. 
389 -
390 -
acme.sh installieren: 
391 -
392 -
```
393 -
curl https://get.acme.sh | sh -s email=youraddress@example.com
394 -
```
395 -
396 -
Anscliessend noch den API-Key von Cloudflare mit dem passenden Account in die Env Vars per expose packen:
397 -
398 -
```
399 -
export CF_Key="763eac4f1bcebd8b5c95e9fc50d010b4"
400 -
export CF_Email="alice@example.com"
401 -
```
402 -
403 -
Die benötigten Zertifikate erstellen: 
404 -
405 -
```
406 -
acme.sh --issue --dns dns_cf -d k8s01.example.net -d '*.k8s01.example.net' --server letsencrypt
407 -
acme.sh --issue --dns dns_cf -d k8s01-dev.example.net -d '*.k8s01-dev.example.net' --server letsencrypt
408 -
acme.sh --issue --dns dns_cf -d k8s02-dev.example.net -d '*.k8s02-dev.example.net' --server letsencrypt
409 -
```
410 -
411 -
Die Zertifikate sind damit auch erledigt und man muss diese jetzt nur noch für HaProxy bereitstellen:
412 -
413 -
```
414 -
cat /root/.acme.sh/k8s01.example.net_ecc/fullchain.cer /root/.acme.sh/k8s01.example.net_ecc/k8s01.example.net.key > /etc/haproxy/certs/k8s01.example.net.pem
415 -
cat /root/.acme.sh/k8s01-dev.example.net_ecc/fullchain.cer /root/.acme.sh/k8s01-dev.example.net_ecc/k8s01-dev.example.net.key > /etc/haproxy/certs/k8s01-dev.example.net.pem
416 -
cat /root/.acme.sh/k8s02-dev.example.net_ecc/fullchain.cer /root/.acme.sh/k8s02-dev.example.net_ecc/k8s02-dev.example.net.key > /etc/haproxy/certs/k8s02-dev.example.net.pem
417 -
```
418 -
419 -
Wenn man noch mehr Cluster und Domains hat muss man die beiden letzten Schritte auch für diese Domains ausführen. 
420 -
421 -
`systemctl restart haproxy.service` und prüfen ob alles ok ist. Dazu kann man auch die Stats Option im HAProxy aktivieren und auch da mit prüfen ob alle Backend eingetragen sind. 
422 -
423 -
# HAProxy Stats 
424 -
425 -
```
426 -
listen stats
427 -
    bind *:9000
428 -
    stats enable
429 -
    stats uri /stats
430 -
    stats refresh 5s
431 -
    stats realm HomeLab\ Statistics
432 -
    stats auth youruser:yoursecretpassword
433 -
```
434 -
435 -
Die IP mit Port 9000 im Browser öffnen und die Stats Seite von HAProxy zeigt alle Frontends und Backends an. 
436 -
437 -
# Trotz TLS in HAProxy kann Cert-Manager genutzt werden
438 -
439 -
Hier wird das SSL-Offloading vom HAProxy gemacht. Das ist nötig, damit HAProxy auch in die Verbindungen gucken kann und anhad ` Host` im Header unterscheiden kann, zu welchem Backend der Request gesendet werden muss. 
440 -
441 -
Ich teste und nutze in Kubernetes auch den Cert-Manager. Das möchte ich auch weiter nutzen. Das ist aber auch kein Problem, da ein Ingress mit TLS, über den Issuer/ClusterIssuer genau so den Cert-Manager triggert wie bis her. 
442 -
Der legt dann den `http-solver` an und den passenden Ingress, der über den Pfad auf den `http-solver` zeigt.
443 -
444 -
Der Request geht dann ganz normal an das externe Interface, zum MacMini, HAProxy und wird dann per HTTP an den richtigen Cluster geleitet. 
445 -
446 -
Sollte ich also den HAProxy für Wartungen offline nehmen müssen, dann ist für mich aktuell nur der Production Cluster relevant. Und dafür kann ich dann einfach in der UDM-Pro einfach auch direkt auf den Cluster leiten lassen. 
447 -
Die Zertifikate sind dort dann auch schon vorhanden und es gibt keine Probleme oder Ausfälle. 
448 -
449 -
# Weitere Anregungen zu HAProxy 
450 -
451 -
Wer nur einen Cluster betreibt muss den SSL Part nicht machen. In dem Fall kann man auch weiter alle Zertifikate nur im Kubernetes mit dem Cert-Manager erstellen und stellt die Verbindungen im Backend, bei der Option `mode`, einfach auf `tcp`. Das `httplog` muss dann auch entfernt werden. 
452 -
453 -
Für Wartungen an Kubernetes Nodes können diese auch einfach ausgetragen werden oder hinter dem `check` trägt man einfach `disabled` zusätzlich ein und macht einen reload. Das setzt setzt den Server auf Maintainance. 
454 -
455 -
HAProxy ist sehr mächtig. Zum Beispiel wird hier einfach nur Roundrobin genutzt. Es Loadbalancer nach roundrobin, leastconn, source IP oder weiteren Loadbalancing-Algorithmen genutzt werden. Genau so kann Sticky Sessions mit Sticky Tables genutzt werden. 
456 -
457 -
Die Beispiele oben leiten bestimmte Sub-Sub-Domains auf Backends um, da auf die Subdomain gematched wird. 
458 -
Wer jetzt überlegt: 
459 -
460 -
> "Ja, aber was mache ich wenn ich alle Domains umziehen möchte, aber ich kann nicht alle auf einmal umziehen?" 
461 -
462 -
Das geht auch sehr einfach und war auch am Anfang meine Überlegung es komplett so zu machen. Dann hätte ich aber jeden Hostname (Alos Sub-Sub-Domain) beim anlegen händisch im HAProxy hinzufügen müssen. Das will ich nicht, da ich einfach schnell Dinge im Kubernetes anlegen will und sie dann sofort funktionieren. 
463 -
464 -
Aber man kann anstatt einem Regex auch mit Domainlisten arbeiten. Oder auch HAProxy Maps einsetzen:
465 -
466 -
Dafür eine Datei anlegen `/etc/haproxy/maps/hosts.map` 
467 -
468 -
```
469 -
#domainname                           backendname
470 -
nginx.k8s02-dev.example.net           https_k8s02_dev_backend
471 -
nginx2.k8s02-dev.example.net          https_k8s02_dev_backend
472 -
nginx.k8s01-dev.example.net           https_k8s01_dev_backend
473 -
ngin2.k8s01-dev.example.net           https_k8s01_dev_backend
474 -
nginx.k8s01.example.net               https_k8s01_backend
475 -
# [...]
476 -
api.k8s01.example.net                 https_k8s01_backend
477 -
```
478 -
479 -
Die Frontend Konfiguration dafür würde dann so ausehen:
480 -
481 -
```
482 -
frontend default
483 -
   bind :80
484 -
   use_backend %[req.hdr(host),lower,map_dom(/etc/haproxy/maps/hosts.map,be_default)]
485 -
```
486 -
487 -
Plus ggf. die IP fürs Bind, Loadbalancing-Algorithmen und weitere Optionen. 
488 -
Domain und Backend Listen können auch im Zusammenspiel mit ALCs genutzt werden. 
489 -
Es können auch bestimmte Routen auf andere Backend umgeleitet werden:
490 -
491 -
`/etc/haproxy/maps/routes.map`
492 -
493 -
```
494 -
/api    be_api
495 -
/login  be_auth
496 -
```
497 -
498 -
Frontend: 
499 -
500 -
```
501 -
frontend www
502 -
  bind :80
503 -
  use_backend %[path,map_beg(/etc/haproxy/maps/routes.map,be_default)]
504 -
```
505 -
506 -
Man sieht, HAProxy ist sehr mächtig und kann sehr viel. Was heute nur noch auf HAProxy Installationen zum einsatz kommt, die man eigentlich abschalten sollte, ist die Weiche für Desktop und Mobile Webseiten. Ja das haben einige früher so gemacht und ich kenne noch ein paar die das immer noch einsetzen müssen, da deren CMS weiter betrieben werden muss, weil keiner die Eier hat auch mal alten Schrott abzuschalten. ;-) 
507 -
gelöscht content/2025-03-31-deltachat-mit-eigenem-mailserver copy.md
+0 −50
@@ -1,50 +0,0 @@
1 -
---
2 -
title: 'Delta Chat mit eigenem Mailserver'
3 -
date: 2025-03-31 08:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2025/03/deltachat.webp"
6 -
featureImage: "/images/posts/2025/03/deltachat.webp"
7 -
tags: [DeltaChat, decentralized, secure, messenger, app]
8 -
categories: 
9 -
    - Messenger
10 -
    - decentralized
11 -
preview: "HomeLab mit mehreren Clustern hinter einer IP."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![Delta Chat](/images/posts/2025/03/deltachat.webp)
20 -
21 -
22 -
[Alexander Lehmann](https://www.threads.net/@alexlehm) hat auf Threads über [Delta Chat](https://delta.chat/de/) [gepostet](https://www.threads.net/@alexlehm/post/DH0m29TtqrT). 
23 -
24 -
Ich dachte natürlich: "Noch ein Messenger?". Aber den Link musste ich anklicken und wenigstens einmal gucken. 
25 -
Ein dezentraler Messenger und sicher soll er sein. Das ist Threema, Singal und Co auch. Aber man kann sich bei einem Chatmail-Server von Delta Chat anmelden oder seinen eigenen Mailserver benutzen. 
26 -
27 -
Und da wurde es dann interessant. Ich habe einfach mal Mailaccounts von 2 Domains von mir in der App eingerichtet. 
28 -
29 -
Ich habe erst einmal einen Account direkt in der App angelegt und dabei aber den Button nicht gefunden (eher übersehen), mit dem man mit einem eigenen Mailserver verbinden kann. 
30 -
31 -
![Anderen Server verwenden](/images/posts/2025/03/deltachat_own_server.png)
32 -
33 -
Beim anlegen ist ganz unten der Punkt "Anderen Server verwenden". Auf diesen geklickt und anschliessend auf "Klassischen E-Mail-Login", erscheinen weitere Einstellungen zum Mailserver und Mailaccount. 
34 -
35 -
![Delta Chat Mail Settings](/images/posts/2025/03/deltachat-mail-settings.png)
36 -
37 -
Alle Daten vom Mailaccount eingetragen und ich könnte zwischen beiden Account Nachrichten senden. 
38 -
Die Nachrichten landeten im Posteingang und in den Chats in Delta Chat. 
39 -
40 -
Die Nachrichten wollte ich aber nicht im Posteingang haben, sondern direkt in den Ordner "DeltaChat" verschieben. Das macht es übersichtlicher und in den Settings von DeltaChat kann man auch einstellen, das nur Nachrichten aus diesem Ordner beachtet werden. 
41 -
42 -
Hier meine Sieve Mailfilter Rule: 
43 -
44 -
    # rule:[deltachat]
45 -
    if anyof (header :contains "Chat-Version" "1.0")
46 -
    {
47 -
            fileinto :create "DeltaChat";
48 -
            stop;
49 -
    }
50 -
gelöscht content/2025-04-29-dex-traefik-forward-auth.md
+0 −146
@@ -1,146 +0,0 @@
1 -
---
2 -
title: 'Dex SSO mit Traefik und forward-auth'
3 -
date: 2025-04-29 15:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2025/04/dex-sso.webp"
6 -
featureImage: "/images/posts/2025/04/dex-sso.webp"
7 -
tags: [SSO, Login, Traefik, Forward-Auth]
8 -
categories: 
9 -
    - SSO
10 -
    - Login
11 -
preview: "SSO mit Dex für Google, Github und andere Accounts."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![Dex SSO-Login](/images/posts/2025/04/dex-sso.webp)
20 -
21 -
Ich benutze Dex für den SSO Login auf mehreren Seiten von mir. Ich habe E-Mail Logins und Github aktuell bei mir aktiviert. Alle anderen Möglichkeiten die Dex bietet, wie LinkedIn, Facebook, Google uns viele mehr habe ich auch alle einmal getestet. 
22 -
23 -
Für die Nutzung von GitHub muss im Github Account eine [OAuth App](https://github.com/settings/developers) angelegt werden. Damit bekommen wir eine Client-ID und ein Client-Secret. Die beiden trägt man in die `values.yaml` für den Dex Helm Chart ein. 
24 -
25 -
    helm repo add dex https://charts.dexidp.io
26 -
    helm repo update dex 
27 -
28 -
Hier eine Beispiel `values.yaml` in der man Domains, Client-ID und Secret noch anpassen muss. 
29 -
30 -
Beispiel values.yaml für Dex:
31 -
32 -
    ingress:
33 -
    enabled: true
34 -
    className: traefik
35 -
    annotations:
36 -
        cert-manager.io/cluster-issuer: letsencrypt-cluster-issuer
37 -
        traefik.ingress.kubernetes.io/router.entrypoints: websecure
38 -
        traefik.ingress.kubernetes.io/router.tls: "true"
39 -
    hosts:
40 -
        - host: dex.example.com
41 -
        paths:
42 -
            - path: /
43 -
            pathType: ImplementationSpecific
44 -
    tls:
45 -
        - secretName: dex.example.com-cert
46 -
        hosts:
47 -
            - dex.example.com
48 -
    config:
49 -
    connectors:
50 -
    - config:
51 -
        clientID: 5J3FvbjYDQm4XeofPKtc
52 -
        clientSecret: iLuvTwVgbtrcLftWjqy2cIWVb0PVRGZG6F39XCEi
53 -
        loadAllGroups: true
54 -
        orgs:
55 -
        - name: exmaple-Org
56 -
        redirectURI: https://dex.example/callback
57 -
        teamNameField: slug
58 -
        useLoginAsID: true
59 -
        id: github
60 -
        name: GitHub
61 -
        type: github
62 -
    enablePasswordDB: true
63 -
    frontend:
64 -
        issuer: kuepper.nrw
65 -
        logoURL: https://blog.example.com/images/avatar.png
66 -
        theme: dark
67 -
    issuer: https://dex.example.com
68 -
    logger:
69 -
        level: debug
70 -
    oauth2:
71 -
        alwaysShowLoginScreen: true
72 -
        skipApprovalScreen: true
73 -
    staticClients:
74 -
    - id: github
75 -
        name: Traefik Forward Auth OIDC Dex App
76 -
        public: false
77 -
        redirectURIs:
78 -
        - https://login.example.com/_oauth
79 -
        - https://dex.example.com/_oauth
80 -
        - https://intern.example.com/_oauth
81 -
        secret: iLuvTwVgbtrcLftWjqy2cIWVb0PVRGZG6F39XCEi
82 -
    staticPasswords:
83 -
    - email: user1@example.com
84 -
        hash: $2y$10$D6QwNsN5j7hWOHOEPsXMcu77FJOT1Ae2bkfsGKjZLyx26kwZ9UA.S
85 -
        userID: 08a8684b-db88-4b73-90a9-3cd1661f5466
86 -
        username: user1
87 -
    storage:
88 -
        config:
89 -
        inCluster: true
90 -
        type: kubernetes
91 -
92 -
Mit dieser values.yaml wird jetzt erst einmal Dex installiert.
93 -
94 -
    helm upgrade -i dex dex/dex -n dex -f values.yaml --create-namespace --namespace dex --wait
95 -
96 -
Damit nachher auch Seiten umgeleitet werden können brauchen wir noch einen forward-auth Service im Cluster. 
97 -
Der kümmert sich um die Umleitung auf dex und den Callback nach dem Login. 
98 -
99 -
Hier hatte ich mir oauth2-proxy einmal angeguckt. Der muss aber dann in jedem Cluster eingerichtet und Konfiguriert werden. Ausserdem muss er in jeden Namespace rein damit es auch mit allen Services funktioniert. 
100 -
101 -
forward-auth ist da viel kleiner und einfacher zu konfigurieren. 
102 -
103 -
    helm repo add kuepper https://helm.9it.eu/
104 -
    helm repo update kuepper 
105 -
106 -
Hier eine Beispiel values.yaml für den forward-auth:
107 -
108 -
    deployment:
109 -
      args:
110 -
        - --secret=iLuvTwVgbtrcLftWjqy2cIWVb0PVRGZG6F39XCEi
111 -
        - --auth-host=login.example.com
112 -
        - --cookie-domain=example.com
113 -
        - --default-provider=oidc
114 -
        - --providers.oidc.issuer-url=https://dex.example.com
115 -
        - --providers.oidc.client-id=github
116 -
        - --providers.oidc.client-secret=iLuvTwVgbtrcLftWjqy2cIWVb0PVRGZG6F39XCEi
117 -
118 -
    ingress:
119 -
      domains:
120 -
        - name: auth.example.com
121 -
        tls: true
122 -
        servicename: forward-auth
123 -
        port: 4181
124 -
        path: /
125 -
        pathtype: Prefix
126 -
127 -
Die values.yaml hat noch mehr Values die angepasse werden können. Ein Liste mit allen Möglichkeiten kann mit `helm values ...` abgerufen werden:
128 -
129 -
    helm show values kuepper/traefik-forward-auth
130 -
131 -
Wenn alles installiert ist kann man einen Service, der mit einem Login versehen werden soll einfach per Treafik Ingress Annotation auf den forward-auth und so auf Dex umleiten. 
132 -
133 -
In einem Ingress einfach folgende Annotaions hinzufügen oder einen Middleware Eintrag erweitern:
134 -
135 -
    apiVersion: networking.k8s.io/v1
136 -
    kind: Ingress
137 -
    metadata:
138 -
      annotations:
139 -
        traefik.ingress.kubernetes.io/router.middlewares: kube-system-forward-auth-dex@kubernetescrd
140 -
      name: gethomepage
141 -
      namespace: gethomepage
142 -
    ...
143 -
144 -
Ruft man jetzt die Seite auf sollte ein Redirect auf Dex erfolgen. Dann kann direkt der Login mit github getestet werden. 
145 -
146 -
gelöscht content/2025-06-14-kubernetes-longhorn-loeschen.md
+0 −73
@@ -1,73 +0,0 @@
1 -
---
2 -
title: 'FIX: Kubernetes Longhorn löschen hängt in Terminating fest'
3 -
date: 2025-06-14 15:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2025/06/fix-problem.webp"
6 -
featureImage: "/images/posts/2025/06/fix-problem.webp"
7 -
tags: [Kubernetes, Longhorn, uninstall]
8 -
categories: 
9 -
    - Kubernetes
10 -
    - Login
11 -
preview: "Longhorn getestet, gelöscht und Namespace hängt im Status Terminating."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![Longhorn Namespace und CRDs unlöschbar](/images/posts/2025/06/fix-problem.webp)
20 -
21 -
### Longhorn-Deinstallationsproblem: Persistierende CRDs und Namespace
22 -
23 -
Bei einem Test von Longhorn als Kubernetes-Storage-Lösung traten Performance-Probleme auf, die zu einer erheblichen Cluster-Verlangsamung führten. Nach der Entscheidung zur Deinstallation wurden zwar Pods und Deployments erfolgreich entfernt, jedoch blieben Custom Resource Definitions (CRDs) und der zugehörige Namespace bestehen.
24 -
25 -
### Problemanalyse:
26 -
27 -
Namespace `longhorn` verbleibt im Status `Terminating`
28 -
CRDs lassen sich nicht über Standard-Löschbefehle entfernen
29 -
Namespace-Löschung wird durch bestehende CRDs blockiert
30 -
31 -
### Ursache:
32 -
33 -
Longhorn-CRDs enthalten Finalizers, die eine automatische Bereinigung verhindern. Dies ist ein dokumentiertes Problem bei der Longhorn-Deinstallation.
34 -
35 -
### Lösungsansatz:
36 -
37 -
Entfernung der Finalizers aus allen Longhorn-CRDs
38 -
Forcierte Löschung der CRDs
39 -
Bereinigung des Namespace
40 -
41 -
### Technische Umsetzung:
42 -
43 -
```bash
44 -
kubectl get crd | grep longhorn | awk '{print $1}' | xargs -I {} kubectl patch crd {} -p '{"metadata":{"finalizers":[]}}' --type=merge
45 -
customresourcedefinition.apiextensions.k8s.io/backups.longhorn.io patched
46 -
customresourcedefinition.apiextensions.k8s.io/engineimages.longhorn.io patched
47 -
customresourcedefinition.apiextensions.k8s.io/engines.longhorn.io patched
48 -
customresourcedefinition.apiextensions.k8s.io/nodes.longhorn.io patched
49 -
customresourcedefinition.apiextensions.k8s.io/replicas.longhorn.io patched
50 -
customresourcedefinition.apiextensions.k8s.io/sharemanagers.longhorn.io patched
51 -
customresourcedefinition.apiextensions.k8s.io/snapshots.longhorn.io patched
52 -
customresourcedefinition.apiextensions.k8s.io/volumeattachments.longhorn.io patched
53 -
customresourcedefinition.apiextensions.k8s.io/volumes.longhorn.io patched
54 -
```
55 -
56 -
Und jetzt noch den Namespace `longhorn`
57 -
58 -
```bash
59 -
kubectl patch namespace longhorn -p '{"metadata":{"finalizers":[]}}' --type=merge
60 -
namespace/foo patched
61 -
62 -
kubectl delete ns longhorn 
63 -
64 -
❯ kubectl get namespace | grep longhorn
65 -
66 -
67 -
```
68 -
69 -
Diese Vorgehensweise löst das persistierende Deinstallationsproblem und ermöglicht eine vollständige Bereinigung der Longhorn-Komponenten.
70 -
71 -
Der Longhorn Namespace ist Geschichte. 
72 -
73 -
gelöscht content/2025-06-15-fluxcd-image-update-automation.md
+0 −303
@@ -1,303 +0,0 @@
1 -
---
2 -
title: 'Vereinfachte GitOps-Pipeline mit FluxCD und automatischen Image-Updates' 
3 -
date: 2025-06-15 10:00:00
4 -
xupdate: 2025-06-15 13:51:00
5 -
update: 2025-06-15 14:51:00
6 -
author: ruediger
7 -
cover: "/images/posts/2025/06/fluxcd-image-update-automation.webp"
8 -
featureImage: "/images/posts/2025/06/fluxcd-image-update-automation.webp"
9 -
tags: [Kubernetes, FluxCD, ImageUpdateAutomation, GitOps]
10 -
categories: 
11 -
  - Kubernetes
12 -
preview: "Die Lösung liegt in der Trennung von Build- und Deployment-Prozessen durch eine GitOps-Architektur. Anstatt alles in einer monolithischen Pipeline zu erledigen, beschränke ich die Build-Pipeline auf das Wesentliche: semantische Versionierung, Docker Image-Erstellung und Push in die Registry. Das Deployment wird komplett an FluxCD delegiert, das kontinuierlich das GitOps-Repository überwacht und automatisch neue Image-Versionen erkennt und ausrollt."
13 -
series: ["FluxCD"] 
14 -
draft: false
15 -
top: false
16 -
type: post
17 -
hide: false
18 -
toc: false
19 -
---
20 -
21 -
![FluxCD Image Update Automation](/images/posts/2025/06/fluxcd-image-update-automation.webp)
22 -
23 -
Traditionelle Build-Pipelines sind oft komplex und fehleranfällig. Sie müssen nicht nur den Anwendungscode verarbeiten, sondern auch Helm Charts verwalten, semantische Versionierung durchführen und das finale Deployment orchestrieren. Wenn dabei ein Schritt fehlschlägt – beispielsweise ein fehlerhafter Helm Chart – bricht die gesamte Pipeline ab, obwohl das Docker Image bereits erfolgreich erstellt wurde. Besonders bei größeren Projekten mit längeren Build-Zeiten ist das frustrierend und ineffizient.
24 -
25 -
Die Lösung liegt in der Trennung von Build- und Deployment-Prozessen durch eine GitOps-Architektur. Anstatt alles in einer monolithischen Pipeline zu erledigen, beschränke ich die Build-Pipeline auf das Wesentliche: semantische Versionierung, Docker Image-Erstellung und Push in die Registry. Das Deployment wird komplett an FluxCD delegiert, das kontinuierlich das GitOps-Repository überwacht und automatisch neue Image-Versionen erkennt und ausrollt.
26 -
27 -
Diese Architektur bietet mehrere Vorteile: Build-Pipelines werden einfacher und stabiler, Deployments erfolgen vollautomatisch ohne manuelle Eingriffe, und durch die stage-spezifische Konfiguration können verschiedene Umgebungen (dev, stage, prod) mit unterschiedlichen Image-Tags versorgt werden. FluxCD übernimmt dabei nicht nur das Deployment, sondern auch die automatische Aktualisierung der Image-Tags im GitOps-Repository.
28 -
29 -
Build Pipeline sehen oft wie folgt aus: 
30 -
31 -
![Build Pipeline sehen oft wie folgt aus](/images/posts/2025/06/build-pipeline.png)
32 -
33 -
Diese Piplelines müssen nicht nur den Code selbst auschecken, sie müssen zusätzlich auch noch den HelmChart auschecken könne. Liegen diese wo anders, benötigt man hier wieder einen Token für Pull und Push. 
34 -
Tritt beim Pull oder des Push des HelmCharts ein Problem auf, oder ist der HelmChart fehlerhaft, dann bricht die komplette Pipeline ab. Gerade bei großen Projekten, bei denen ein Build etwas länger dauert ist das sehr ärgerlich. Da das Image eigentlich schon fertig für das Deployment ist, aber ein Fehler im Chart das verhindert. 
35 -
36 -
Meine Pipeline macht nur noch SemVer und erstellt das Docker Image und push es in die Docker Registry. Sonst wird da nicht mehr gemacht. Der Rest wird an anderer Stelle erledigt. 
37 -
38 -
Ich installiere meine Kubernetes Cluster mit Cloudinit und mache so direkt ein `flux bootstrap`, damit alles in den Clustern installiert wird. 
39 -
40 -
```bash
41 -
# ...
42 -
# other stuff: install kubernete, helm, k9s ....
43 -
# ...
44 -
# FluxCD Bootstrap
45 -
export GITHUB_TOKEN="${github_token}"
46 -
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
47 -
48 -
# Warten bis Kubernetes API verfügbar ist
49 -
while ! kubectl cluster-info &>/dev/null; do
50 -
	echo "Waiting for Kubernetes API..."
51 -
	sleep 10
52 -
done
53 -
54 -
# FluxCD Bootstrap ausführen
55 -
flux bootstrap github \
56 -
--owner=ruedigerp \
57 -
--repository=fluxcd \
58 -
--branch=main \
59 -
--path=clusters/production \
60 -
--personal \
61 -
--components-extra=image-reflector-controller,image-automation-controller
62 -
```
63 -
64 -
Im Repo `gitops` ist für jeden Cluster ein Verzeichnis für die jeweile Konfigurationen. Damit werden Helm Chart Repos, Helm Charts, Applications und weitere Stage spezifische Konfigurationen gemacht. 
65 -
66 -
Im repo ist auch ein Verzeichnis `/apps/, in dem sind Applications die installiert werden sollen. Wie zum Beispiel mein Blog. 
67 -
68 -
```bash
69 -
❯ tree apps/blog
70 -
apps/blog
71 -
├── base
72 -
│   ├── deployment.yaml
73 -
│   ├── ingress-http.yaml
74 -
│   ├── ingress-https.yaml
75 -
│   ├── kustomization.yaml
76 -
│   └── service.yaml
77 -
├── dev
78 -
│   ├── deployment-patch.yaml
79 -
│   └── kustomization.yaml
80 -
├── prod
81 -
│   ├── deployment-patch.yaml
82 -
│   └── kustomization.yaml
83 -
└── stage
84 -
    ├── deployment-patch.yaml
85 -
    └── kustomization.yaml
86 -
```
87 -
88 -
Im Base Verzeichnis sind alle Kubernetes YAML-Files die für die Application benötigt werden. Das Deployment enthält wie üblich ein Docker Image:
89 -
```bash
90 -
grep image apps/blog/base/deployment.yaml
91 -
        image: ghcr.io/ruedigerp/ink-blog.kuepper.nrw:v0.0.1-develop.1
92 -
```
93 -
94 -
Hier ist es egal welche Version eingetragen ist, da der Image Name und Tag je nach Stage ersetzt werden. 
95 -
96 -
Denn im Apps Verzeichnis sind für jeden Cluster/Stage ein weiteres Verzeichnis, welches dann die Konfigurationen enthält, die auf dem Ziel Cluster genutzt werden sollen. 
97 -
Wie auch das Patch für die Images.
98 -
99 -
```bash
100 -
❯ grep image apps/blog/prod/deployment-patch.yaml
101 -
        image: ghcr.io/ruedigerp/ink-blog.kuepper.nrw:v1.9.31 # {"$imagepolicy": "blog:blog-policy"}
102 -
❯ grep image apps/blog/stage/deployment-patch.yaml
103 -
        image: ghcr.io/ruedigerp/ink-blog.kuepper.nrw:v1.9.32-stage.1 # {"$imagepolicy": "blog:blog-policy"}
104 -
❯ grep image apps/blog/dev/deployment-patch.yaml
105 -
        image: ghcr.io/ruedigerp/ink-blog.kuepper.nrw:v1.9.32-develop.2 # {"$imagepolicy": "blog:blog-policy"}
106 -
```
107 -
108 -
Aufgerufen werden sie durch die jeweiligen kustomization.yaml Files in den Cluster/Stage Verzeichnissen. Hier das Beispiel von `prod`: 
109 -
110 -
```yaml
111 -
❯ cat apps/blog/prod/kustomization.yaml
112 -
apiVersion: kustomize.config.k8s.io/v1beta1
113 -
kind: Kustomization
114 -
115 -
resources:
116 -
  - ../base
117 -
118 -
patches:
119 -
  - path: deployment-patch.yaml
120 -
121 -
namespace: blog
122 -
```
123 -
124 -
Das sagt Flux an der Stelle es soll alles aus dem Verzeichnis `../base` anwenden, und das Patch-File für das Deployment anwenden. Hier können auch noch weitere Patches für alles mögliche, wie beispielsweise Änderungen am Ingress, Service, Secrets usw. 
125 -
126 -
Der Patch für das Deployment sieht wie folgt aus:
127 -
128 -
```yaml
129 -
❯ cat apps/blog/prod/deployment-patch.yaml
130 -
# apps/blog/stage/deployment-patch.yaml
131 -
apiVersion: apps/v1
132 -
kind: Deployment
133 -
metadata:
134 -
  name: blog
135 -
  namespace: blog
136 -
spec:
137 -
  template:
138 -
    spec:
139 -
      containers:
140 -
      - name: blog
141 -
        image: ghcr.io/ruedigerp/ink-blog.kuepper.nrw:v1.9.31 # {"$imagepolicy": "blog:blog-policy"}
142 -
```
143 -
144 -
Der Patch nimmt das Deployment `blog` im Namespace `blog` und ersetzt das image welches in `base/deployment.yaml` gesetzt ist. 
145 -
146 -
Wichtig ist in der `deployment.yaml` und `deployment-patch-yaml` der Kommentar hinter dem Image:  `# {"$imagepolicy": "blog:blog-policy"}`.
147 -
148 -
Damit weiß ImageUpdateAutomoation von FluxCD welches Image er ersetzten soll und mit welcher Policy. In diesem Fall `blog-policy` im Namespace `blog`. 
149 -
150 -
```yaml
151 -
# clusters/production/flux-system/kustomizations/private/blog.yaml
152 -
apiVersion: kustomize.toolkit.fluxcd.io/v1
153 -
kind: Kustomization
154 -
metadata:
155 -
  name: blog
156 -
  namespace: flux-system
157 -
spec:
158 -
  dependsOn:
159 -
    - name: infrastructure
160 -
  interval: 5m
161 -
  prune: false
162 -
  path: ./apps/blog/prod
163 -
  sourceRef:
164 -
    kind: GitRepository
165 -
    name: flux-system
166 -
  targetNamespace: blog
167 -
  decryption:
168 -
    provider: sops
169 -
    secretRef:
170 -
      name: sops-age
171 -
# weitere Sachen wie Patch der Replica, ingress Domains usw. 
172 -
# ... 
173 -
```
174 -
175 -
Über weitere Kustomizations lade ich im Verzeichnis `clusters/production` noch viele weitere Sachen wie Helm Repos, Helm Charts, weitere Apps und auch die Konfigurationen der imageUpdates. 
176 -
177 -
```bash
178 -
tree clusters/production/infrastructure/image-updater/
179 -
clusters/production/infrastructure/image-updater/
180 -
├── blog
181 -
│   ├── image-policy.yaml
182 -
│   ├── image-repository.yaml
183 -
│   ├── image-update-automation.yaml
184 -
│   └── kustomization.yaml
185 -
├── image-write-repo.yaml
186 -
├── kustomization.yaml
187 -
├── other-app
188 -
│   ├── image-policy.yaml
189 -
│   ├── image-repository.yaml
190 -
│   ├── image-update-automation.yaml
191 -
│   └── kustomization.yaml
192 -
└── second-other-app
193 -
    ├── image-policy.yaml
194 -
    ├── image-repository.yaml
195 -
    ├── image-update-automation.yaml
196 -
    └── kustomization.yaml
197 -
```
198 -
199 -
Die Image-Update-Automation benötigt für das prüfen auf neue Docker Images, das prüfen ob der Image-Tag für die Stage passt und die Automation selbst drei Konfigurationen. 
200 -
Das Image Repo konfigurieren: 
201 -
202 -
```yaml
203 -
# clusters/production/infrastructure/image-updater/blog/image-repository.yaml
204 -
apiVersion: image.toolkit.fluxcd.io/v1beta2
205 -
kind: ImageRepository
206 -
metadata:
207 -
  name: blog-repo
208 -
  namespace: blog
209 -
spec:
210 -
  image: ghcr.io/ruedigerp/ink-blog.kuepper.nrw
211 -
  interval: 10m
212 -
  provider: generic
213 -
```
214 -
215 -
Damit wird alle 10 Minuten geprüft, ob es ein neues Image gibt. Und die Policy kann da überprüfen welcher Tag auf die entsprechende Stage passt. 
216 -
217 -
```yaml
218 -
# clusters/production/infrastructure/image-updater/blog/image-policy.yaml
219 -
apiVersion: image.toolkit.fluxcd.io/v1beta2
220 -
kind: ImagePolicy
221 -
metadata:
222 -
  name: blog-policy
223 -
  namespace: blog  # Gleicher Namespace
224 -
spec:
225 -
  imageRepositoryRef:
226 -
    name: blog-repo  # Muss mit ImageRepository.name übereinstimmen
227 -
  filterTags:
228 -
    pattern: '^v[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'
229 -
  policy:
230 -
    semver:
231 -
      range: '>=1.0.0'    
232 -
```
233 -
234 -
Der `filterTag` ist entsprechend der Stages jeweils angepasst. Dafür liegt entsprechend des Clusters, bzw. der Stage, in `/cluster/{prod,stage,dev}/infrastructure/image-updater/blog/image-policy.yaml` die passende Policy. 
235 -
236 -
Stage: 
237 -
```yaml
238 -
...
239 -
  filterTags:
240 -
    pattern: '^v[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'
241 -
  policy:
242 -
    semver:
243 -
      range: '>=1.0.0-stage' 
244 -
245 -
...
246 -
```
247 -
248 -
Dev:
249 -
```yaml
250 -
  filterTags:
251 -
    pattern: '^v[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'
252 -
  policy:
253 -
    semver:
254 -
      range: '>=1.0.0-dev' 
255 -
```
256 -
257 -
Die Dateien sind ansonsten identisch. 
258 -
259 -
Wenn es einen neuen Tag gibt, wird diese Änderung mit der `ImageUpdateAutomation` vorgenommen und ins GitOps Repo commited. 
260 -
261 -
```yaml
262 -
# clusters/production/infrastructure/image-updater/blog/image-update-automation.yaml
263 -
apiVersion: image.toolkit.fluxcd.io/v1beta2
264 -
kind: ImageUpdateAutomation
265 -
metadata:
266 -
  name: blog-automation
267 -
  namespace: blog  # Gleicher Namespace
268 -
spec:
269 -
  sourceRef:
270 -
    kind: GitRepository
271 -
    name: flux-system-write
272 -
    namespace: flux-system
273 -
  git:
274 -
    checkout:
275 -
      ref:
276 -
        branch: main
277 -
    commit:
278 -
      author:
279 -
        email: fluxcdbot@users.noreply.github.com
280 -
        name: fluxcdbot
281 -
      messageTemplate: |
282 -
        Automated image update
283 -
284 -
        Automation name: {{ .AutomationObject }}
285 -
286 -
        Images:
287 -
        {{- range .Updated.Images }}
288 -
        - {{.}}
289 -
        {{- end }}
290 -
    push:
291 -
      branch: main
292 -
  interval: 1m
293 -
  update:
294 -
    path: "./apps/blog/prod"  # Anpassen an deinen Pfad
295 -
    strategy: Setters
296 -
```
297 -
298 -
Damit wird dann in `./apps/blog/prod` das image im `deployment-patch.yaml` geändert und ins Git Repo gepusched. Der Patch ändert dann beim `reconcile` der Kustomization das Deployment und applied es in den Cluster. 
299 -
300 -
Ich muss daher keine Änderungen im GitOps Repo machen. Das passiert alles automatisch. 
301 -
Wenn man nach einem Docker Image Build nicht automatisch ausrollen möchte, kann man auch über einen PR die Änderungen machen lassen. So kann man neue Versionen erst ausrollen wenn man es möchte und hat mehr Kontrolle. 
302 -
303 -
gelöscht content/2025-06-15-git-workflow-mit-automatisierter-versionierung-und-deployment.md
+0 −115
@@ -1,115 +0,0 @@
1 -
---
2 -
title: 'Moderne Blog-Entwicklung: Ein durchgängiger Git-Workflow mit automatisierter Versionierung und Deployment'
3 -
date: 2025-06-15 20:00:00
4 -
update: 2025-06-15 20:10:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/06/IMG_0971.webp"
7 -
featureImage: "/images/posts/2025/06/IMG_0971.webp"
8 -
tags: [Git, GitHub, Workflow]
9 -
categories: 
10 -
    - Git
11 -
preview: "In der modernen Softwareentwicklung ist ein sauberer Deployment-Workflow essentiell für die Qualitätssicherung und effiziente Zusammenarbeit. In diesem Artikel stelle ich meinen bewährten Workflow für die Blog-Entwicklung vor, der drei Stages nutzt und durch automatisierte Versionierung sowie GitOps-Prinzipien unterstützt wird."
12 -
series: ["FluxCD"] 
13 -
draft: false
14 -
top: false
15 -
type: post
16 -
hide: false
17 -
toc: false
18 -
---
19 -
20 -
![Links of the week](/images/posts/2025/06/IMG_0971.webp)
21 -
22 -
# Moderne Blog-Entwicklung: Ein durchgängiger Git-Workflow mit automatisierter Versionierung und Deployment
23 -
24 -
In der modernen Softwareentwicklung ist ein sauberer Deployment-Workflow essentiell für die Qualitätssicherung und effiziente Zusammenarbeit. In diesem Artikel stelle ich meinen bewährten Workflow für die Blog-Entwicklung vor, der drei Stages nutzt und durch automatisierte Versionierung sowie GitOps-Prinzipien unterstützt wird.
25 -
26 -
## Die drei Stages: Dev, Stage und Prod
27 -
28 -
Mein Blog-Setup basiert auf drei klar getrennten Umgebungen:
29 -
30 -
- **Dev**: Die Entwicklungsumgebung für neue Features und Experimente
31 -
- **Stage**: Die Staging-Umgebung für finale Tests unter produktionsähnlichen Bedingungen
32 -
- **Prod**: Die Live-Produktionsumgebung für Endnutzer
33 -
34 -
Diese Trennung spiegelt sich direkt in der Git-Branch-Struktur wider. Ich verwende entsprechend benannte Branches `dev`, `stage` und `main` (für Prod), wobei `main` als Hauptbranch fungiert.
35 -
36 -
## Automatisierte Versionierung mit Semantic Versioning
37 -
38 -
Ein Kernstück meines Workflows ist die automatisierte Versionierung durch GitHub Actions. Dabei nutze ich Semantic Versioning (SemVer) in Kombination mit aussagekräftigen Commit-Messages.
39 -
40 -
### Der Entwicklungsprozess
41 -
42 -
Alle Änderungen beginnen im `dev`-Branch. Wenn ich neue Features entwickle oder Bugs behebe, verwende ich spezifische Präfixe in meinen Commit-Messages:
43 -
44 -
```bash
45 -
git commit -m "fix: Behebung des Responsive-Problems im Header"
46 -
# oder
47 -
git commit -m "feat: Neue Kommentarfunktion hinzugefügt"
48 -
```
49 -
50 -
Diese strukturierten Commit-Messages sind nicht nur für Menschen lesbar, sondern triggern auch automatisch die Versionierung in meinen GitHub Actions. Jeder Commit mit `fix:` oder `feat:` erstellt automatisch einen neuen Git-Tag im Format `v1.9.40-dev.1`, `v1.9.40-dev.2`, usw.
51 -
52 -
### Von Dev zu Stage: Der erste Qualitätsfilter
53 -
54 -
Sobald alle Entwicklungsarbeiten in `dev` abgeschlossen und getestet sind, erstelle ich einen Pull Request von `dev` nach `stage`. Dieser Merge-Vorgang ist ein bewusster Schritt, der signalisiert: “Diese Änderungen sind bereit für die finale Testphase.”
55 -
56 -
Der Merge nach `stage` triggert automatisch die Erstellung eines neuen Tags im Format `v1.9.40-stage.1`. Falls weitere Änderungen aus `dev` folgen, werden diese als `v1.9.40-stage.2`, `v1.9.40-stage.3` usw. versioniert.
57 -
58 -
### Der finale Schritt: Stage zu Prod
59 -
60 -
Nach erfolgreichen Tests in der Staging-Umgebung erfolgt der finale Merge von `stage` nach `prod` (main). Dieser Schritt erstellt die finale Produktionsversion, zum Beispiel `v1.9.41` - eine saubere, produktionsreife Versionsnummer ohne Zusätze.
61 -
62 -
### Backward-Merge: Der Kreis schließt sich
63 -
64 -
Ein oft übersehener, aber wichtiger Schritt ist der Backward-Merge. Nach dem Release führe ich einen Merge von `prod` zurück nach `stage` und `dev` durch. Dies stellt sicher, dass alle Branches synchron bleiben und eventuelle Hotfixes oder produktionsrelevante Anpassungen in alle Umgebungen übernommen werden.
65 -
66 -
Nach diesem Backward-Merge beginnt der Zyklus von neuem, jetzt mit der Basis-Version `v1.9.41-dev.1`.
67 -
68 -
## Docker-Images und Container-Orchestrierung
69 -
70 -
Parallel zur Git-Versionierung erstellen meine GitHub Actions automatisch Docker-Images für jede Stage. Diese Images werden entsprechend der Branch-Namen getaggt:
71 -
72 -
- `myblog:v1.9.40-dev.1` für Entwicklungsversionen
73 -
- `myblog:v1.9.40-stage.1` für Staging-Versionen
74 -
- `myblog:v1.9.41` für Produktionsversionen
75 -
76 -
Diese konsistente Tagging-Strategie ermöglicht es, jederzeit nachzuvollziehen, welche Version in welcher Umgebung läuft.
77 -
78 -
## GitOps mit FluxCD: Automatisierte Deployments
79 -
80 -
Der finale Baustein meines Workflows ist die automatisierte Deployment-Pipeline mit FluxCD. Durch ImageUpdateAutomations überwacht FluxCD kontinuierlich meine Container-Registry auf neue Images.
81 -
82 -
Sobald ein neues Image für eine Stage verfügbar ist, aktualisiert FluxCD automatisch die entsprechenden Deployments im Kubernetes-Cluster. Dies bedeutet:
83 -
84 -
- Neue Dev-Images werden automatisch in die Entwicklungsumgebung deployed
85 -
- Stage-Images landen automatisch in der Staging-Umgebung
86 -
- Produktions-Images werden nach erfolgreichem Merge automatisch live geschaltet
87 -
88 -
## Vorteile dieses Workflows
89 -
90 -
### Nachvollziehbarkeit
91 -
92 -
Jede Änderung ist durch die semantische Versionierung klar nachverfolgbar. Ein Blick auf die Git-Tags zeigt sofort, welche Version welche Features oder Fixes enthält.
93 -
94 -
### Qualitätssicherung
95 -
96 -
Der mehrstufige Prozess stellt sicher, dass nur durchgetestete Änderungen in die Produktion gelangen. Die Staging-Umgebung fungiert als wichtige Barriere vor dem Live-System.
97 -
98 -
### Automatisierung reduziert Fehler
99 -
100 -
Durch die Automatisierung von Versionierung und Deployment werden menschliche Fehler minimiert. Vergessene Tags oder manuelle Deployment-Fehler gehören der Vergangenheit an.
101 -
102 -
### Schnelle Iteration
103 -
104 -
Entwickler können sich auf die eigentliche Arbeit konzentrieren, während der Workflow im Hintergrund für konsistente Deployments sorgt.
105 -
106 -
### Rollback-Fähigkeit
107 -
108 -
Durch die klare Versionierung ist es jederzeit möglich, zu einer vorherigen Version zurückzukehren, falls Probleme auftreten.
109 -
110 -
## Fazit
111 -
112 -
Dieser Workflow hat sich in meiner Blog-Entwicklung als äußerst effizient erwiesen. Die Kombination aus strukturierten Git-Branches, automatisierter semantischer Versionierung und GitOps-Prinzipien schafft einen robusten, nachvollziehbaren und wartungsarmen Entwicklungsprozess.
113 -
114 -
Der Schlüssel liegt in der Konsistenz: Jeder Schritt folgt klaren Regeln, jede Version ist eindeutig identifizierbar, und jede Umgebung spiegelt exakt den gewünschten Zustand wider. So kann ich mich auf das Wesentliche konzentrieren - das Erstellen großartiger Inhalte für meinen Blog.
115 -
gelöscht content/2025-06-15-links-der-woche-kw24.md
+0 −57
@@ -1,57 +0,0 @@
1 -
---
2 -
title: 'Links der Woche KW 24'
3 -
date: 2025-06-15 15:54:00
4 -
update: 2025-06-15 15:54:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/06/links-of-the-week.webp"
7 -
featureImage: "/images/posts/2025/06/links-of-the-week.webp"
8 -
tags: [Links]
9 -
categories: 
10 -
    - Links
11 -
preview: "Ein paar der interessante Themen die mir die letzten Tage in die Browser Tabs gespült wurden oder mit denen ich mich beschäfftigt habe."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![Links of the week](/images/posts/2025/06/links-of-the-week.webp)
20 -
21 -
22 -
# Tailscale Your legacy VPN belongs in the past
23 -
  
24 -
Link: [Tailscale](https://tailscale.com) 
25 -
26 -
Tailscale ist ein modernes VPN-System, das auf WireGuard basiert und Geräte automatisch über ein privates Netzwerk verbindet. Es erstellt ein verschlüsseltes Mesh-Netzwerk zwischen deinen Geräten - egal ob Computer, Smartphones oder Server - ohne komplizierte manuelle Konfiguration.
27 -
28 -
Die Hauptvorteile: Einfache Installation über Apps, automatische Peer-to-Peer-Verbindungen (wo möglich), Zero-Trust-Sicherheitsmodell und zentrale Verwaltung über eine Web-Oberfläche. Du meldest dich einfach mit deinem Google/Microsoft/GitHub-Account an, installierst die App auf deinen Geräten, und sie können sich sofort sicher miteinander verbinden - auch wenn sie sich in verschiedenen Netzwerken befinden.
29 -
30 -
Besonders praktisch für Homelab-Setups, Remote-Arbeit oder den sicheren Zugriff auf eigene Dienste von unterwegs.
31 -
32 -
# Kubernetes Cluster API
33 -
34 -
Link: [Kubernetes Cluster API](https://cluster-api.sigs.k8s.io/introduction)
35 -
36 -
Kubernetes Cluster API ist ein deklaratives Tool zur Verwaltung von Kubernetes-Clustern als Code. Es behandelt Cluster-Infrastruktur wie normale Kubernetes-Ressourcen - du definierst Cluster in YAML-Manifesten und die Cluster API erstellt, skaliert und verwaltet sie automatisch.
37 -
38 -
Kernkonzept: Management-Cluster verwaltet Workload-Cluster. Du beschreibst gewünschte Cluster-Konfiguration (Node-Anzahl, VM-Größen, Kubernetes-Version) und die API sorgt für die Umsetzung.
39 -
40 -
Provider-Support: Funktioniert mit AWS, Azure, GCP, vSphere, OpenStack und vielen anderen Infrastrukturen über spezielle Provider.
41 -
42 -
Hauptvorteile: Einheitliche API für alle Cloud-Provider, GitOps-Integration, automatische Lifecycle-Verwaltung (Updates, Patches), und Cluster-Templates für Standardisierung.
43 -
Besonders nützlich für Multi-Cloud-Umgebungen oder wenn du viele Kubernetes-Cluster automatisiert verwalten möchtest.
44 -
45 -
46 -
# CyberChef - Das Cyber-Schweizer-Taschenmesser
47 -
48 -
> **Hinweis:** Vergleichbar mit [IT-Tools](https://it-tools.tech) / [IT-Tools Github](https://github.com/CorentinTh/it-tools)
49 -
50 -
Link: [CyberChef Github](https://github.com/gchq/CyberChef)
51 -
52 -
Demo: [Demo Link](https://gchq.github.io/CyberChef/)
53 -
54 -
CyberChef ist eine einfache, intuitive Web-App für die Durchführung aller Arten von "Cyber"-Operationen innerhalb eines Webbrowsers. Diese Operationen umfassen einfache Kodierungen wie XOR und Base64, komplexere Verschlüsselungen wie AES, DES und Blowfish, das Erstellen von Binär- und Hex-Dumps, Komprimierung und Dekomprimierung von Daten, Berechnung von Hashes und Prüfsummen, IPv6- und X.509-Parsing, Änderung von Zeichenkodierungen und vieles mehr.
55 -
56 -
Das Tool ist darauf ausgelegt, sowohl technischen als auch nicht-technischen Analysten zu ermöglichen, Daten auf komplexe Weise zu manipulieren, ohne sich mit komplexen Tools oder Algorithmen auseinandersetzen zu müssen. Es wurde von einem Analysten in seiner 10%-Innovationszeit über mehrere Jahre hinweg konzipiert, entworfen, entwickelt und schrittweise verbessert.
57 -
gelöscht content/2025-06-15-verschluesselte-Secrets-mit-SOPS.md
+0 −117
@@ -1,117 +0,0 @@
1 -
---
2 -
title: 'SOPS-verschlüsselte Kubernetes Secrets'
3 -
date: 2025-06-15 13:00:00
4 -
author: ruediger
5 -
cover: "/images/posts/2025/06/sops-secret-encryption.webp"
6 -
featureImage: "/images/posts/2025/06/sops-secret-encryption.webp"
7 -
tags: [Kubernetes, Secrets, encrypt, SOPS, GitOps]
8 -
categories: 
9 -
    - Kubernetes
10 -
preview: "SOPS (Secrets OPerationS) ermöglicht die sichere Speicherung von Kubernetes Secrets im Git Repository durch selektive Verschlüsselung der sensitiven Datenblöcke. Mit dem Parameter --encrypted-regex '^(data|stringData)$' werden nur die Secret-Inhalte verschlüsselt, während die Kubernetes-Metadaten lesbar bleiben. Dies bietet eine GitOps-kompatible Alternative zu externen Secret Vaults und ermöglicht vollständige Versionskontrolle der Secret-Konfigurationen. Die AGE-Verschlüsselung stellt dabei sowohl Datenschutz als auch Integrität der gespeicherten Secrets sicher."
11 -
series: ["FluxCD"] 
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: true
17 -
---
18 -
19 -
![SOPS Secret Encryption](/images/posts/2025/06/sops-secret-encryption.webp)
20 -
21 -
# Überblick
22 -
23 -
Bei der Verwaltung von Kubernetes Secrets ohne Verwendung eines Secret Vaults (wie HashiCorp Vault oder Azure Key Vault) ist die Verschlüsselung der Secrets vor der Speicherung im Git Repository essentiell. SOPS (Secrets OPerationS) bietet hierfür eine robuste Lösung.
24 -
25 -
# Verschlüsselungsansatz
26 -
27 -
Da Kubernetes Secrets ihre Metadaten (apiVersion, kind, metadata, type) für die korrekte Funktionalität benötigen, erfolgt die Verschlüsselung selektiv nur auf die sensitiven Datenblöcke:
28 -
29 -
   * data: Base64-kodierte Secret-Werte
30 -
   * stringData: Klartext Secret-Werte (werden automatisch zu data konvertiert)
31 -
32 -
Die Kubernetes-Metadaten bleiben unverschlüsselt, damit das YAML weiterhin als gültiges Kubernetes-Manifest erkannt wird.
33 -
34 -
# SOPS-Verschlüsselungskommando
35 -
36 -
```bash
37 -
sops --encrypt --in-place --encrypted-regex '^(data|stringData)$' \
38 -
    --age <SOPS-AGE-KEY> path/to/docker-secret.yaml
39 -
```
40 -
41 -
## Parameter-Erklärung:
42 -
43 -
   * --encrypt: Verschlüsselungsmodus
44 -
   * --in-place: Überschreibt die ursprüngliche Datei
45 -
   * --encrypted-regex '^(data|stringData)$': Regulärer Ausdruck zur Bestimmung der zu verschlüsselnden Felder
46 -
   * --age <SOPS-AGE-KEY>: Verwendung des AGE-Verschlüsselungsschlüssels
47 -
48 -
# Struktur eines verschlüsselten Docker Registry Secrets
49 -
50 -
```yaml
51 -
apiVersion: v1
52 -
data:
53 -
    .dockerconfigjson: ENC[AES256_GCM,data:EXAMPLE_ENCRYPTED_DATA_PLACEHOLDER_DO_NOT_USE_IN_PRODUCTION,iv:EXAMPLE_IV_PLACEHOLDER,tag:EXAMPLE_TAG_PLACEHOLDER,type:str]
54 -
kind: Secret
55 -
metadata:
56 -
    name: my-docker-registry-secret
57 -
    namespace: my-namespace
58 -
type: kubernetes.io/dockerconfigjson
59 -
sops:
60 -
    age:
61 -
        - recipient: age1example123456789abcdefghijklmnopqrstuvwxyz0123456789abcdef
62 -
          enc: |
63 -
            -----BEGIN AGE ENCRYPTED FILE-----
64 -
            EXAMPLE_AGE_ENCRYPTED_CONTENT_PLACEHOLDER
65 -
            DO_NOT_USE_THIS_IN_PRODUCTION
66 -
            THIS_IS_ONLY_AN_EXAMPLE
67 -
            -----END AGE ENCRYPTED FILE-----
68 -
    lastmodified: "2025-01-15T10:30:00Z"
69 -
    mac: ENC[AES256_GCM,data:EXAMPLE_MAC_PLACEHOLDER_FOR_DEMONSTRATION_PURPOSES_ONLY,iv:EXAMPLE_MAC_IV,tag:EXAMPLE_MAC_TAG,type:str]
70 -
    encrypted_regex: ^(data|stringData)$
71 -
    version: 3.10.2
72 -
```
73 -
74 -
## SOPS-Metadaten Erklärung
75 -
76 -
Nach der Verschlüsselung fügt SOPS automatisch einen sops-Block hinzu:
77 -
AGE-Verschlüsselung
78 -
79 -
   * recipient: Der öffentliche AGE-Schlüssel für die Verschlüsselung
80 -
   * enc: Der verschlüsselte Master-Schlüssel im AGE-Format
81 -
82 -
## Integritätssicherung
83 -
84 -
   * mac: Message Authentication Code zur Verifikation der Datenintegrität
85 -
   * lastmodified: Zeitstempel der letzten Änderung
86 -
   * encrypted_regex: Bestätigung des verwendeten Verschlüsselungsmusters
87 -
   * version: SOPS-Version
88 -
89 -
# Vorteile dieses Ansatzes
90 -
91 -
   1. GitOps-Kompatibilität: Secrets können sicher im Git Repository gespeichert werden
92 -
   2. Kubernetes-Kompatibilität: Metadaten bleiben lesbar für Kubernetes
93 -
   3. Selektive Verschlüsselung: Nur sensitive Daten werden verschlüsselt
94 -
   4. Audit-Trail: Git-History für Secret-Änderungen verfügbar
95 -
   5. Schlüsselrotation: AGE-Schlüssel können rotiert werden
96 -
97 -
# Entschlüsselung und Anwendung
98 -
99 -
## Entschlüsselung zur Ansicht
100 -
101 -
```bash
102 -
sops --decrypt path/to/docker-secret.yaml
103 -
```
104 -
105 -
## Direkte Anwendung auf Kubernetes
106 -
107 -
```bash
108 -
sops --decrypt path/to/docker-secret.yaml | kubectl apply -f -
109 -
```
110 -
111 -
# Sicherheitshinweise
112 -
113 -
   * AGE-Private-Keys müssen sicher außerhalb des Repositories gespeichert werden
114 -
   * Regelmäßige Rotation der Verschlüsselungsschlüssel
115 -
   * Verwendung unterschiedlicher Schlüssel für verschiedene Umgebungen (Dev/Staging/Prod)
116 -
   * Backup-Strategie für Verschlüsselungsschlüssel implementieren
117 -
gelöscht content/2025-06-16-fluxcd-image-update-mit-pull-request.md
+0 −130
@@ -1,130 +0,0 @@
1 -
---
2 -
title: 'FluxCD Image Update mit Pull Request'
3 -
date: 2025-06-16 01:00:00
4 -
xdate: 2025-06-16 01:00:00
5 -
update: 2025-06-16 06:40:00
6 -
author: ruediger
7 -
cover: "/images/posts/2025/06/fluxcd-image-update-automation.webp"
8 -
featureImage: "/images/posts/2025/06/fluxcd-image-update-automation.webp"
9 -
tags: [Kubernetes, FluxCD, ImageUpdateAutomation, GitOps]
10 -
categories: 
11 -
    - Kubernetes
12 -
preview: ""
13 -
series: ["FluxCD"] 
14 -
draft: false
15 -
top: false
16 -
type: post
17 -
hide: false
18 -
toc: true
19 -
---
20 -
21 -
![FluxCD Image Update Automation](/images/posts/2025/06/fluxcd-image-update-automation.webp)
22 -
23 -
In meinem vorherigen Artikel zu [FluxCD und Image Update Automation](https://blog.kuepper.nrw/posts/2025-06-15-fluxcd-image-update-automation) habe ich die direkte Implementierung von automatischen Container-Image-Updates demonstriert. Während diese Lösung für Development-Umgebungen praktikabel ist, erfordert eine Production-Umgebung typischerweise einen kontrollierten Review-Prozess vor dem Deployment.
24 -
25 -
# Problem der direkten Automation
26 -
27 -
Die ursprüngliche Konfiguration pushed Image-Updates direkt auf den main Branch, wodurch Änderungen sofort ohne manuellen Review-Prozess deployed werden. Für kritische Production-Workloads ist dieser Ansatz oft zu risikoreich.
28 -
29 -
Lösung: Pull Request-basierter Workflow
30 -
Durch eine geringfügige Modifikation der ImageUpdateAutomation-Konfiguration lässt sich ein Pull Request-basierter Approval-Workflow implementieren. Der entscheidende Parameter ist die Änderung des Target-Branch von main zu einem dedizierten Update-Branch:
31 -
32 -
33 -
34 -
```yaml
35 -
# Ursprünglich: direkter Push auf main
36 -
push:
37 -
  branch: main
38 -
39 -
# Modifiziert: Push auf separaten Branch für PR-Workflow  
40 -
push:
41 -
  branch: flux-updates-source
42 -
```
43 -
44 -
# Technische Implementierung
45 -
46 -
## Personal Access Token konfigurieren:
47 -
48 -
   * GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
49 -
   * Erforderliche Scopes: `repo` (Full control) und `workflow` (Update workflows)
50 -
   * Token als Repository Secret `PAT_TOKEN` hinterlegen
51 -
52 -
## GitHub Actions Workflow erstellen:
53 -
   * Datei: .github/workflows/create-pr-on-flux-updates.yml
54 -
55 -
```yaml
56 -
name: Create PR for Flux Image Updates
57 -
58 -
on:
59 -
  push:
60 -
    branches:
61 -
      - flux-updates-source
62 -
63 -
permissions:
64 -
  contents: write
65 -
  pull-requests: write
66 -
67 -
jobs:
68 -
  create-pr:
69 -
    runs-on: ubuntu-latest
70 -
    steps:
71 -
      - name: Checkout flux-updates-source
72 -
        uses: actions/checkout@v4
73 -
        with:
74 -
          ref: flux-updates-source
75 -
          fetch-depth: 0
76 -
          token: ${{ secrets.PAT_TOKEN }}
77 -
78 -
      - name: Create and push PR branch
79 -
        run: |
80 -
          # Erstelle einen neuen Branch basierend auf flux-updates-source
81 -
          git checkout -b flux-image-updates-$(date +%Y%m%d-%H%M%S)
82 -
          
83 -
          # Push den neuen Branch
84 -
          git push origin HEAD
85 -
          
86 -
          # Speichere Branch-Name für nächsten Step
87 -
          echo "PR_BRANCH=$(git branch --show-current)" >> $GITHUB_ENV
88 -
89 -
      - name: Create Pull Request
90 -
        uses: actions/github-script@v7
91 -
        with:
92 -
          github-token: ${{ secrets.PAT_TOKEN }}
93 -
          script: |
94 -
            const { data: pullRequest } = await github.rest.pulls.create({
95 -
              owner: context.repo.owner,
96 -
              repo: context.repo.repo,
97 -
              title: '🤖 Automated Image Update',
98 -
              head: process.env.PR_BRANCH,
99 -
              base: 'main',
100 -
              body: `## Automated Image Update
101 -
              
102 -
              This PR was automatically created by Flux CD image automation.
103 -
              
104 -
              **Changes:**
105 -
              - Updated container images in production environment
106 -
              
107 -
              **Source:** flux-updates-source
108 -
              **Timestamp:** ${new Date().toISOString()}`,
109 -
            });
110 -
            
111 -
            // Labels hinzufügen
112 -
            await github.rest.issues.addLabels({
113 -
              owner: context.repo.owner,
114 -
              repo: context.repo.repo,
115 -
              issue_number: pullRequest.number,
116 -
              labels: ['automated', 'flux', 'image-update']
117 -
            });
118 -
            
119 -
            console.log(`Pull Request created: ${pullRequest.html_url}`);
120 -
```
121 -
122 -
## Automatisierter PR-Erstellungsprozess:
123 -
124 -
Der Workflow reagiert auf Push-Events zum `flux-updates-source` Branch und erstellt automatisch einen Pull Request mit den Image-Updates. Dies ermöglicht Code-Review, automatisierte Tests und kontrollierte Deployment-Zyklen.
125 -
126 -
## Branch-Management:
127 -
128 -
Optional kann automatisches Branch-Cleanup nach PR-Merge in den Repository-Settings aktiviert werden (Settings → General → "Automatically delete head branches").
129 -
Diese Implementierung kombiniert die Effizienz der automatischen Image-Erkennung mit den Governance-Anforderungen von Production-Umgebungen und bietet dabei vollständige Traceability über Git-History und PR-Metadaten.
130 -
gelöscht content/2025-06-17-Automatisierte-Kubernetes-Volume-Backups.md
+0 −94
@@ -1,94 +0,0 @@
1 -
---
2 -
title: 'Automatisierte Kubernetes Volume-Backups'
3 -
date: 2025-06-18 12:00:00
4 -
update: 2025-06-18 12:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/06/k8s-pv-backup.webp"
7 -
featureImage: "/images/posts/2025/06/k8s-pv-backup.webp"
8 -
tags: [Kubernetes, Volumes, Backup]
9 -
categories: 
10 -
    - Kubernetes
11 -
preview: ""
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: true
17 -
---
18 -
19 -
![Automatisierte Kubernetes Volume-Backups](/images/posts/2025/06/k8s-pv-backup.webp)
20 -
21 -
Ich betreibe meine Kubernetes Cluster bei Hetzner und habe in den Projekten zusätzlichen einen NFS-Server, der in Kubernetes die Volumes mit dem `nfs-subdir-external-provisioner` bereitstellt. 
22 -
23 -
Das gleiche Setup habe ich auch zuhause in meheren VMs. So das ich auch dort das gleiche Setup habe und lokale Services oder auch zum testen vorhanden habe wie im Live-Betrieb. 
24 -
25 -
Ich kann so zwischen Dev, Stage und Prod Daten bei Hetzner schnell hin und her kopieren. Oder über VPN auch mal die Daten nach Hause ziehen um Migrationen oder Änderungen zu testen. 
26 -
27 -
Daten können dann so auch schnell wieder hergestellt werden. 
28 -
29 -
Durch dieses Setup kann ich auch jeden Cluster einfach neu aufsetzen, mit FluxCD alle Kubernetes Resourcen installieren lassen und die Daten kommen von den NFS-Servern. 
30 -
31 -
Diese Daten kann ich an andere Orte synchronisieren und habe damit auch das Backup. 
32 -
Trotzdem sichere ich die Daten für die jeweiligen Custer noch auf den jeweiligen Kubernetes Clustern noch einmal auf den NFS-Servern. Das Backup ist für schnelles Recovery und dann im Einsatz wenn etwas getestet oder aktualisiert wird. Geht einmal etwas schief, kann ich die Daten direkt zurück spielen. 
33 -
34 -
# Der Backup Job
35 -
36 -
Das mache ich mit einem Backup Cronjob den ich vorher einmal manuell triggern kann. Er sichert dann alle PV Daten in einem Backup-Job. 
37 -
38 -
Da ich NFS mit dem  `nfs-subdir-external-provisioner` nutze und die PV/PVC mit dem AccessMode ReadWriteMany eingerichtet sind  können diese Volumes einfach vom Backup-Job gemounted werden. 
39 -
40 -
# Der Backup Job mit ReadWriteOnce
41 -
42 -
Das Problem sind immer Volumes mit dem AccessMode ReadWriteOnce. Das Volume kann nicht von anderen Pods gemounted werden. 
43 -
44 -
Um diese Volumes zu sichern muss 
45 -
46 -
* Der Pod der Application über das Deployment, Statefulset oder Daemonset einmal herunter skaliert werden.
47 -
* Ein Pod gestartet werden, der das Volume und das Backupziel mounted.
48 -
* Das Backup erstellt werden.
49 -
* Backup Pod stoppen.
50 -
* Deployment, Statefulset oder Daemonset wieder hoch skalieren.
51 -
52 -
Das kann man für 1-2 Deyployments manuell machen. Aber wenn im Cluster viele Services laufen wird diese Aufgabe recht langwierig. Das möchte man weg automatisieren. 
53 -
54 -
# Mein k8s-pv-backup Tool
55 -
56 -
Ich möchte mich um das Backup nicht kümmern. Auch möchte ich nicht nach jeder Installation von neuen Services auch noch die Backup Config anpassen müssen. Genau das gleiche, wenn ein Service nicht mehr benutzt wird und vom Cluster entfernt wurde. 
57 -
58 -
k8s-pv-backup läuft als Cronjob im Cluster und prüft als erstes alle PV im Cluster und sucht dazu das passende PVC. Dabei wird auch noch der AccessMode geprüft. 
59 -
60 -
Anhand des AccessModes wird entschieden ob ein Deployment, Statefulset oder Daemonset auf 0 skaliert werden muss oder nicht (ReadWriteMany).
61 -
62 -
Dann wird erst einmal RBAC entsprechend konfiguriert und ein PVC in dem Namespace des zu sichernden Service erstellt, mit dem PV der Application. Jetzt wird noch ein Job für das eigentliche Backup angelegt, der dann mit dem neuen PVC und dem Backup-NFS PVC das Backup erstellt. 
63 -
64 -
Ist der Job fertig wird für diesen einen Service das RBAC und PVC wieder gelöscht und der Job für den nächste Service wird angelegt. RBAC/PVC erstellen, Backup erstellen und aufräumen. 
65 -
66 -
Beim herunter und rauf skalieren der Deployment, Statefulset oder Daemonset wird immer auf den Wert gesetzt der vorher gesetzt gewesen ist. 
67 -
68 -
So hat man komplett automatisiert ein Backup. Zero-Downtime bei ReadWriteMany und kurze Downtime beim ReadWriteOnce. 
69 -
70 -
# k8s-pv-backup benutzen
71 -
72 -
Installation einfach per Helm. Es kann aber auch lokal ausgeführt werden. 
73 -
74 -
75 -
```bash
76 -
helm repo add ruedigerp https://ruedigerp.github.io/helm-charts/
77 -
helm repo update ruedigerp 
78 -
79 -
helm upgrade --install k8s-pv-backup ruedigerp/k8s-pv-backup --namespace backup-system --create-namespace --wait -f values.yaml
80 -
```
81 -
82 -
Beispiel values.yaml 
83 -
84 -
```yaml
85 -
nfs_server: "10.0.10.7"
86 -
nfs_path: "/srv/nfs/k8s-pv/production/k8s-backup"
87 -
storage_class: "nfs-client"
88 -
```
89 -
90 -
`nfs_server` und `nfs_path` entsprechend anpassen. 
91 -
`storage_class` ist aktuell für "nfs-client" ausgelegt. Das wird sich in Zukunft aber noch ändern, da natürlich auch andere Backupziele möglich sein sollen. 
92 -
93 -
94 -
gelöscht content/2025-06-19-git-merge-script.md
+0 −298
@@ -1,298 +0,0 @@
1 -
---
2 -
title: 'Git Merge Script für Deployment Workflow'
3 -
date: 2025-06-19 08:00:00
4 -
update: 2025-06-19 10:50:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/06/git-merge-script.webp"
7 -
featureImage: "/images/posts/2025/06/git-merge-script.webp"
8 -
tags: [Git, Merge, Workflow, Merge. Braches]
9 -
categories: 
10 -
    - Development
11 -
preview: "Dieses Script automatisiert den gesamten Merge-Prozess zwischen verschiedenen Branches in einem Git-Repository und nutzt dabei die GitHub CLI für Pull Request Management. Es ist speziell für Teams entwickelt, die einen strukturierten Deployment-Workflow verwenden."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![Automatisierte Kubernetes Volume-Backups](/images/posts/2025/06/git-merge-script.webp)
20 -
21 -
# Git Merge Automation Script
22 -
23 -
Ein Bash-Script zur Automatisierung von Git-Merge-Workflows über GitHub Pull Requests.
24 -
25 -
## 🎯 Zweck
26 -
27 -
Dieses Script automatisiert den gesamten Merge-Prozess zwischen verschiedenen Branches in einem Git-Repository und nutzt dabei die GitHub CLI für Pull Request Management. Es ist speziell für Teams entwickelt, die einen strukturierten Deployment-Workflow verwenden.
28 -
29 -
## 📋 Voraussetzungen
30 -
31 -
- **Git** installiert und konfiguriert
32 -
- **GitHub CLI (gh)** installiert und authentifiziert
33 -
- Berechtigung zum Erstellen und Mergen von Pull Requests im Repository
34 -
- Bash-Shell (Linux/macOS/WSL)
35 -
36 -
### GitHub CLI Installation
37 -
38 -
```bash
39 -
# macOS (Homebrew)
40 -
brew install gh
41 -
42 -
# Ubuntu/Debian
43 -
sudo apt install gh
44 -
45 -
# Windows (Chocolatey)
46 -
choco install gh
47 -
```
48 -
49 -
### GitHub CLI Authentifizierung
50 -
51 -
```bash
52 -
gh auth login
53 -
```
54 -
55 -
## 🚀 Installation
56 -
57 -
* Script herunterladen und ausführbar machen:
58 -
59 -
<script src="https://gist.github.com/ruedigerp/810aa03b35118f14d7c8d9b8cd99e955.js"></script>
60 -
61 -
```bash
62 -
chmod +x merge.sh
63 -
```
64 -
65 -
* Optional: In ein Verzeichnis im PATH verschieben:
66 -
67 -
```bash
68 -
sudo mv merge.sh /usr/local/bin/merge
69 -
```
70 -
71 -
## 📖 Verwendung
72 -
73 -
### Grundlegende Syntax
74 -
75 -
```bash
76 -
./merge.sh <command>
77 -
```
78 -
79 -
### Verfügbare Commands
80 -
81 -
#### 1. `dev-stage` - Development zu Staging
82 -
83 -
Merged den `dev` Branch in den `stage` Branch.
84 -
85 -
```bash
86 -
./merge.sh dev-stage
87 -
```
88 -
89 -
**Was passiert:**
90 -
- Erstellt einen Pull Request von `dev` → `stage`
91 -
- PR-Titel: "Deploy dev to stage - YYYY-MM-DD"
92 -
- Merged den PR automatisch nach erfolgreichen Checks
93 -
94 -
#### 2. `stage-main` - Staging zu Production
95 -
96 -
Merged den `stage` Branch in den `main` Branch (Production).
97 -
98 -
```bash
99 -
./merge.sh stage-main
100 -
```
101 -
102 -
**Was passiert:**
103 -
- Erstellt einen Pull Request von `stage` → `main`
104 -
- PR-Titel: "Deploy stage to main - YYYY-MM-DD"
105 -
- Merged den PR automatisch für Production-Release
106 -
107 -
#### 3. `back-merge` - Rück-Synchronisation
108 -
109 -
Synchronisiert den `main` Branch zurück zu `stage` und `dev` nach einem Production-Release.
110 -
111 -
```bash
112 -
./merge.sh back-merge
113 -
```
114 -
115 -
**Was passiert:**
116 -
1. Holt den neuesten Tag (Release-Version)
117 -
2. Erstellt PR: `main` → `stage` (Back-merge)
118 -
3. Erstellt PR: `main` → `dev` (Back-merge)
119 -
4. Beide PRs werden mit `[skip ci]` Flag gemerged
120 -
121 -
#### 4. `anywhere` - Flexibler Merge
122 -
123 -
Merged einen beliebigen Branch in einen anderen.
124 -
125 -
```bash
126 -
./merge.sh anywhere <target-branch> <source-branch>
127 -
```
128 -
129 -
**Beispiele:**
130 -
```bash
131 -
./merge.sh anywhere stage dev        # dev → stage
132 -
./merge.sh anywhere main hotfix     # hotfix → main
133 -
./merge.sh anywhere feature dev     # dev → feature
134 -
```
135 -
136 -
## 🔄 Typischer Workflow
137 -
138 -
### Standard Development Cycle
139 -
140 -
```bash
141 -
# 1. Development → Staging
142 -
./merge.sh dev-stage
143 -
144 -
# 2. Testing auf Staging...
145 -
146 -
# 3. Staging → Production
147 -
./merge.sh stage-main
148 -
149 -
# 4. Back-merge nach Release
150 -
./merge.sh back-merge
151 -
```
152 -
153 -
### Hotfix Workflow
154 -
155 -
```bash
156 -
# 1. Hotfix direkt zu Production
157 -
./merge.sh anywhere main hotfix-branch
158 -
159 -
# 2. Back-merge
160 -
./merge.sh back-merge
161 -
```
162 -
163 -
## 🎛️ Branch-Struktur
164 -
165 -
Das Script ist für folgende Branch-Struktur optimiert:
166 -
167 -
```
168 -
main (Production)
169 -
├── stage (Staging/Testing)
170 -
└── dev (Development)
171 -
    ├── feature/xyz
172 -
    ├── bugfix/abc
173 -
    └── hotfix/urgent
174 -
```
175 -
176 -
## ⚙️ Funktionsweise
177 -
178 -
### Pull Request Erstellung
179 -
180 -
- **Automatische Titel**: Datum-basierte PR-Titel
181 -
- **Beschreibungen**: Vordefinierte, aussagekräftige Beschreibungen
182 -
- **Auto-Merge**: PRs werden automatisch gemerged wenn alle Checks bestehen
183 -
184 -
### Back-Merge Besonderheiten
185 -
186 -
- **Tag-Detection**: Automatische Erkennung des neuesten Release-Tags
187 -
- **CI Skip**: Back-Merges verwenden `[skip ci]` um unnötige Builds zu vermeiden
188 -
- **Synchronisation**: Stellt sicher, dass alle Branches auf dem gleichen Stand sind
189 -
190 -
## 🛠️ Fehlerbehebung
191 -
192 -
### Häufige Probleme
193 -
194 -
#### GitHub CLI nicht authentifiziert
195 -
```bash
196 -
gh auth status
197 -
gh auth login
198 -
```
199 -
200 -
#### Merge-Konflikte
201 -
- Das Script stoppt bei Konflikten
202 -
- Löse Konflikte manuell im GitHub Web-Interface
203 -
- Oder löse sie lokal und push erneut
204 -
205 -
#### Fehlende Berechtigung
206 -
```bash
207 -
# Prüfe Repository-Berechtigung
208 -
gh repo view
209 -
```
210 -
211 -
#### Branch existiert nicht
212 -
```bash
213 -
# Verfügbare Branches anzeigen
214 -
git branch -a
215 -
```
216 -
217 -
### Debug-Modus
218 -
219 -
Für detaillierte Ausgabe:
220 -
```bash
221 -
bash -x ./merge.sh dev-stage
222 -
```
223 -
224 -
## 🔒 Sicherheitshinweise
225 -
226 -
- **Branch Protection**: Aktiviere Branch Protection Rules für `main` und `stage`
227 -
- **Required Reviews**: Konfiguriere erforderliche Code-Reviews
228 -
- **Status Checks**: Stelle sicher, dass CI/CD-Checks aktiviert sind
229 -
- **Auto-Merge**: Funktioniert nur wenn alle konfigurierten Checks bestehen
230 -
231 -
## 📝 Anpassungen
232 -
233 -
### Custom Branch Namen
234 -
235 -
Passe die Branch-Namen im Script an deine Naming-Convention an:
236 -
237 -
```bash
238 -
# Ändere im Script:
239 -
--base stage    # zu deinem Staging-Branch
240 -
--head dev      # zu deinem Development-Branch
241 -
```
242 -
243 -
### Custom PR-Titel
244 -
245 -
Ändere die PR-Titel-Templates:
246 -
247 -
```bash
248 -
--title "Deploy dev to stage - $(date +%Y-%m-%d)"
249 -
```
250 -
251 -
### Custom Commit Messages
252 -
253 -
Ändere die Merge-Commit-Messages:
254 -
255 -
```bash
256 -
--subject "Release stage"
257 -
```
258 -
259 -
## 🤝 Best Practices
260 -
261 -
1. **Teste immer auf Staging** bevor du zu Production merged
262 -
2. **Führe Back-Merges regelmäßig durch** um Branches synchron zu halten
263 -
3. **Prüfe CI/CD-Status** vor dem Merge
264 -
4. **Verwende aussagekräftige Commit-Messages** in deinen Feature-Branches
265 -
5. **Erstelle Tags** für Production-Releases
266 -
267 -
## 📊 Monitoring
268 -
269 -
### PR-Status prüfen
270 -
271 -
```bash
272 -
# Alle offenen PRs anzeigen
273 -
gh pr list
274 -
275 -
# Specific PR-Status
276 -
gh pr view <PR-NUMBER>
277 -
```
278 -
279 -
### Recent Merges
280 -
281 -
```bash
282 -
# Letzten 5 Commits auf main
283 -
git log --oneline -5 main
284 -
285 -
# Tags anzeigen
286 -
git tag --sort=-version:refname | head -5
287 -
```
288 -
289 -
## 🆘 Support
290 -
291 -
Bei Problemen:
292 -
293 -
1. Prüfe die Logs des Scripts
294 -
2. Verifiziere GitHub CLI Authentication
295 -
3. Prüfe Repository-Berechtigungen
296 -
297 -
298 -
<!-- <div x_data-comment-post-id="2025-06-19-git-merge-script"></div> -->
gelöscht content/2025-06-20-blog-kommentar-system-self-hosted.md
+0 −175
@@ -1,175 +0,0 @@
1 -
---
2 -
title: 'Mein Blog Kommentarsystem Self-Hosted'
3 -
date: 2025-06-25 08:00:00
4 -
update: 2025-06-25 08:50:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/06/comments.webp"
7 -
featureImage: "/images/posts/2025/06/comments.webp"
8 -
tags: [Kommentare, Blog, Static, InkProjek, Jekyll, Hugo, Gatsby]
9 -
categories: 
10 -
    - Development
11 -
preview: "Externe Kommentarsysteme wie Disqus bringen durchaus Vorteile mit sich: Sie sind schnell eingerichtet, bieten umfangreiche Funktionen und kümmern sich um Spam-Schutz und Moderation. Dennoch haben sie entscheidende Nachteile ..."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![Automatisierte Kubernetes Volume-Backups](/images/posts/2025/06/comments.webp)
20 -
21 -
# TLDR; 
22 -
23 -
[Github Repo](https://github.com/ruedigerp/comments)
24 -
25 -
26 -
# Ein eigenes Kommentarsystem für statische Blogs: Warum ich auf Go setze
27 -
28 -
Statische Website-Generatoren wie Hugo, Jekyll oder Gatsby erfreuen sich großer Beliebtheit - und das zu Recht. Sie bieten schnelle Ladezeiten, hohe Sicherheit und einfaches Hosting. Doch wenn es um interaktive Funktionen wie Kommentare geht, stoßen sie schnell an ihre Grenzen. Während WordPress-Nutzer auf bewährte Plugins zurückgreifen können, müssen Betreiber statischer Blogs oft auf externe Anbieter wie Disqus ausweichen.
29 -
30 -
## Das Problem mit externen Kommentaranbietern
31 -
32 -
Externe Kommentarsysteme wie Disqus bringen durchaus Vorteile mit sich: Sie sind schnell eingerichtet, bieten umfangreiche Funktionen und kümmern sich um Spam-Schutz und Moderation. Dennoch haben sie entscheidende Nachteile:
33 -
34 -
**Datenschutz und Kontrolle:** Externe Anbieter sammeln oft umfangreiche Nutzerdaten und zeigen Werbung an. Als Website-Betreiber hat man wenig Kontrolle über diese Aspekte und muss sich auf die Datenschutzrichtlinien Dritter verlassen.
35 -
36 -
**Abhängigkeiten:** Was passiert, wenn der Anbieter seinen Service einstellt oder die Preise drastisch erhöht? Alle Kommentare könnten verloren gehen.
37 -
38 -
<!-- **Performance:** Externe Skripte können die Ladezeit der Website negativ beeinflussen und zusätzliche HTTP-Requests verursachen. -->
39 -
40 -
**Design-Integration:** Oft lassen sich externe Kommentarsysteme nur begrenzt an das eigene Website-Design anpassen.
41 -
42 -
## Die Lösung: Ein eigenes Kommentarsystem in Go
43 -
44 -
Aus diesen Gründen habe ich mich entschieden, ein eigenes Kommentarsystem zu entwickeln. Die Wahl fiel auf Go als Backend-Sprache, da sie sich hervorragend für Web-Services eignet und sowohl performant als auch ressourcenschonend ist.
45 -
46 -
### Architektur und Design-Entscheidungen
47 -
48 -
Das System basiert auf einer klaren Trennung zwischen dem statischen Blog und der Kommentarfunktionalität:
49 -
50 -
**Separate Domain:** Das Kommentarsystem läuft unter einer eigenen Domain, getrennt vom Hauptblog. Diese Architektur bietet mehrere Vorteile: Bessere Skalierbarkeit, einfachere Wartung und die Möglichkeit, das System für mehrere Websites zu nutzen.
51 -
52 -
**Go-Backend:** Der Server wurde in Go implementiert und stellt eine REST-API zur Verfügung. Go eignet sich perfekt für solche Aufgaben - es ist schnell, hat eine hervorragende Standard-Bibliothek für Web-Services und benötigt nur minimale Systemressourcen.
53 -
54 -
**JavaScript-Frontend:** Die Integration in den Blog erfolgt über ein JavaScript-Widget, das die Kommentare dynamisch lädt und darstellt. Dies ermöglicht eine nahtlose Integration in jedes statische Website-System.
55 -
56 -
### Integration in das Blog-System
57 -
58 -
Die Einbindung könnte nicht einfacher sein. Im Blog-Theme wird im Header einfach das JavaScriipt vom Kommentar Server geladen und lediglich ein `<div>`-Container mit einer eindeutigen ID platziert:
59 -
60 -
```html
61 -
<html>
62 -
    <head>
63 -
        <script src="https://comments.example.com/static/js/comment-widget.js"></script>
64 -
    </head>
65 -
...
66 -
67 -
```html
68 -
# Date + Title
69 -
<div data-comment-post-id="2025-06-19-git-merge-script"></div>
70 -
# or Title
71 -
<div data-comment-post-id="git-merge-script"></div>
72 -
# or URL Path 
73 -
<div data-comment-post-id="posts/2025-06-19-git-merge-script.html"></div>
74 -
```
75 -
76 -
Mit Blog-ID bei der Nutzung auf mehreren Seite (siehe oben): 
77 -
78 -
```html
79 -
# Blogname + Date + Title
80 -
<div data-comment-post-id="blog-example-net/2025-06-19-git-merge-script"></div>
81 -
# or Blogname + Title
82 -
<div data-comment-post-id="blog-example-net/git-merge-script"></div>
83 -
# or Blogname + URL Path 
84 -
<div data-comment-post-id="blog-example-net/posts/2025-06-19-git-merge-script.html"></div>
85 -
```
86 -
87 -
oder: 
88 -
89 -
```html
90 -
# Blog-ID + Date + Title
91 -
<div data-comment-post-id="123/2025-06-19-git-merge-script"></div>
92 -
# or Blog-ID + Title
93 -
<div data-comment-post-id="123/git-merge-script"></div>
94 -
# or Blog-ID + URL Path 
95 -
<div data-comment-post-id="123/posts/2025-06-19-git-merge-script.html"></div>
96 -
```
97 -
98 -
Das JavaScript-Widget erkennt diesen Container automatisch und lädt die entsprechenden Kommentare. Dabei kann die Integration sowohl post-spezifisch als auch global im Theme erfolgen - je nach gewünschter Flexibilität.
99 -
100 -
Wenn Kommentare global in allen Artikeln aktivieren möchte, kann man auch einfach folgenden Code an der entsprechenden Stelle im Theme einfügen. 
101 -
102 -
Das `{{.Link}}` ist hier speziefisch für [InkPaper, a static blog generator](https://github.com/InkProject/ink) . Je nach eingesetztem CMS muss diese Variable angepasst werden. 
103 -
104 -
```html
105 -
<script>
106 -
    CommentWidget.init({{.Link}});
107 -
</script>
108 -
```
109 -
110 -
Oder auch hier wieder mit eine Blog-ID: 
111 -
112 -
```html
113 -
<script>
114 -
    CommentWidget.init(blog-example-net/{{.Link}});
115 -
</script>
116 -
```
117 -
118 -
Kommentar Form: 
119 -
![1](/images/posts/2025/06/comments-1.png)
120 -
121 -
### Technische Vorteile
122 -
123 -
**Performance:** Da das System speziell für die eigenen Anforderungen entwickelt wurde, ist es schlank und schnell. Keine unnötigen Features bedeuten weniger Code und bessere Performance.
124 -
125 -
**Datenschutz:** Alle Daten bleiben unter eigener Kontrolle. Es werden nur die notwendigen Informationen gespeichert, und die Einhaltung der DSGVO liegt in den eigenen Händen.
126 -
127 -
**Anpassbarkeit:** Das Design lässt sich vollständig an die Website anpassen. CSS-Styles können frei definiert werden, ohne auf die Vorgaben eines externen Anbieters angewiesen zu sein.
128 -
129 -
**Skalierbarkeit:** Go ist bekannt für seine hervorragende Concurrent-Performance. Das System kann problemlos viele gleichzeitige Anfragen verarbeiten.
130 -
131 -
## Funktionsumfang und Features
132 -
133 -
Das selbst entwickelte System muss nicht weniger können als kommerzielle Alternativen. Typische Features umfassen:
134 -
135 -
- **Moderation:** Administrative Oberfläche zur Verwaltung und Freischaltung von Kommentaren
136 -
137 -
Adminpanel: 
138 -
![2](/images/posts/2025/06/comments-2.png)
139 -
140 -
### ToDos: 
141 -
142 -
   * **Spam-Schutz:** Implementierung eigener Spam-Filter oder Integration bestehender Lösungen
143 -
   * **Antwort-Funktionen:** Verschachtelte Kommentare und Antworten auf bestehende Beiträge
144 -
   * **Benachrichtigungen:** E-Mail-Benachrichtigungen bei neuen Kommentaren
145 -
   * **Rate-Limiting:** Schutz vor Spam durch Begrenzung der Kommentar-Frequenz
146 -
147 -
## Deployment und Betrieb
148 -
149 -
Ein weiterer Vorteil von Go ist die einfache Deployment-Strategie. Go-Programme werden zu einzelnen, ausführbaren Dateien kompiliert, die keine zusätzlichen Dependencies benötigen. Das macht das Deployment auf jedem Server unkompliziert.
150 -
151 -
Das System kann auf einem einfachen VPS betrieben werden und benötigt nur minimale Ressourcen. Für die Datenspeicherung wir ValKey (Redis) eingesetzt. 
152 -
153 -
Im Github Repository kann jederzeit das aktuelle [Release](https://github.com/ruedigerp/comments/releases) herunterladen werden. Die Version wird auch im Helm Chart immer aktualisiert, das das ein `helm upgrade ...` ausreicht für ein update oder bei FluxCD einfach automatisch per ImageUpdateAutomation. 
154 -
155 -
## Dokumentation und Installation
156 -
157 -
Installation mit einem Binary, als Docker Container, Helm, FluxCD ist unter den folgenden Links beschrieben.
158 -
Genau so wie die API Dokumentation und hilfreiche Redis Befehle, falls man mal etwas debuggen möchte. 
159 -
160 -
   * Installation: [Install doc](https://github.com/ruedigerp/comments/blob/main/docs/README.md)
161 -
   * Docker: [Docker-compose](https://github.com/ruedigerp/comments/blob/main/docs/docker-compose/README.md)
162 -
   * Kuberenetes (Noch in Arbeit) 
163 -
   * Helm: [helm](https://github.com/ruedigerp/comments/blob/main/docs/helm/README.md)
164 -
   * FluxCD: [FluxCD Installation](https://github.com/ruedigerp/comments/blob/main/docs/fluxcd/)
165 -
   * API: [API Docs](https://github.com/ruedigerp/comments/blob/main/docs/api/README.md)
166 -
   * Redis: [Redis Commands](https://github.com/ruedigerp/comments/blob/main/docs/redis/README.md)
167 -
168 -
## Fazit
169 -
170 -
Die Entwicklung eines eigenen Kommentarsystems mag zunächst nach Mehraufwand aussehen, bietet aber langfristig entscheidende Vorteile. Vollständige Kontrolle über Daten und Funktionalität, bessere Performance und die Unabhängigkeit von externen Anbietern rechtfertigen den initialen Entwicklungsaufwand.
171 -
172 -
Go erweist sich dabei als ideale Wahl für das Backend - die Sprache ist nicht nur performant und ressourcenschonend, sondern auch gut zu lernen und zu warten. In Kombination mit einem flexiblen JavaScript-Frontend entsteht so ein System, das sowohl technisch überzeugt als auch den eigenen Anforderungen perfekt entspricht.
173 -
174 -
Für Betreiber statischer Blogs, die Wert auf Datenschutz, Performance und Kontrolle legen, ist ein eigenes Kommentarsystem eine durchaus lohnenswerte Alternative zu externen Lösungen.
175 -
gelöscht content/2025-06-23-aws-console-eks-kubectl-in-console.md
+0 −31
@@ -1,31 +0,0 @@
1 -
---
2 -
title: 'AWS EKS kubectl in Web-Console'
3 -
date: 2025-06-23 11:00:00
4 -
update: 2025-06-23 11:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/06/aws-els-console-kubeconfig.webp"
7 -
featureImage: "/images/posts/2025/06/aws-els-console-kubeconfig.webp"
8 -
tags: [aws, eks, kubernetes, kubeconfig, console]
9 -
categories: 
10 -
    - Kubernetes
11 -
preview: "AWS Web Console und schnell mal eben auf einem Kubernetes Cluster etwas überprüfen."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![Automatisierte Kubernetes Volume-Backups](/images/posts/2025/06/aws-els-console-kubeconfig.webp)
20 -
21 -
Da ich gerade genau das einmal wieder machen musste, nicht direkt an die KubeConfig gekommen bin, habe ich kurz über die Shell in der AWS Console nachgeschaut. 
22 -
Und da man so etwas immer wieder vergisst und suchen muss wie man es machen, einfach mal hier kurz festgehalten. 
23 -
24 -
In der Shell ist erst einmal keine `./kube/config` vorhanden. Diese kann man sich aber schnell in die Shell importieren. 
25 -
26 -
```bash
27 -
aws eks update-kubeconfig --region eu-central-1 --name my-cluster
28 -
```
29 -
30 -
Anschliessend kann man direkt mit kubectl auf den Cluster zugreifen. 
31 -
gelöscht content/2025-06-26-links-der-woche-kw25.md
+0 −57
@@ -1,57 +0,0 @@
1 -
---
2 -
title: 'Links der Woche KW 25'
3 -
date: 2025-06-26 10:00:00
4 -
update: 2025-06-26 10:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/06/links-of-the-week.webp"
7 -
featureImage: "/images/posts/2025/06/links-of-the-week.webp"
8 -
tags: [Links]
9 -
categories: 
10 -
    - Links
11 -
preview: "Ein paar der interessante Themen die mir die letzten Tage in die Browser Tabs gespült wurden oder mit denen ich mich beschäfftigt habe."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![Links of the week](/images/posts/2025/06/links-of-the-week.webp)
20 -
21 -
22 -
# Kubernetes Context und Namespace in tmux Staus
23 -
  
24 -
Link: [Kube tmux](https://github.com/jonmosco/kube-tmux) 
25 -
26 -
kube-tmux: Kubernetes-Kontext und Namespace-Status für tmux
27 -
Ein Skript, das es dir ermöglicht, den aktuellen Kubernetes-Kontext und Namespace, der in kubectl konfiguriert ist, zu deiner tmux-Statuszeile hinzuzufügen.
28 -
Inspiriert von kube-ps1, ist dies eine Portierung für tmux, die alle Funktionen enthält, die kube-ps1 effizient machen, und bringt sie in die tmux-Statuszeile.
29 -
30 -
# Beliebige Inhalte in deine macOS-Menüleiste einfügen
31 -
32 -
Link: [xbar App](https://xbarapp.com)
33 -
34 -
xbar (der BitBar-Neustart) ermöglicht es dir, die Ausgabe von jedem Skript/Programm in deine macOS-Menüleiste zu setzen.
35 -
36 -
Github Repo: [xbar](https://github.com/matryer/xbar)
37 -
38 -
# karakeep - The Bookmark Everything App (self-hosted)
39 -
40 -
Ich selbst benutze Linkwarden für meine Bookmarks. Bin aber die Tage auf diese App gestossen und werde es auch mal installieren und testen. 
41 -
42 -
Eine selbst-hostbare App zum Speichern von allem (Links, Notizen und Bilder) mit KI-basierter automatischer Verschlagwortung und Volltextsuche
43 -
44 -
Du kannst die Demo unter https://try.karakeep.app aufrufen. Melde dich mit folgenden Zugangsdaten an:
45 -
46 -
```
47 -
E-Mail: demo@karakeep.app
48 -
Passwort: demodemo
49 -
```
50 -
51 -
Die Demo ist mit einigen Inhalten gefüllt, aber im Nur-Lese-Modus, um Missbrauch zu verhindern.
52 -
53 -
# Kommentar System for static pages (self-hosted)
54 -
55 -
Wo wir schon bei Self-Hosted sind, da mache ich auch mal auf was eigenes aufmerksam. 
56 -
57 -
Wie ja [hier](https://blog.kuepper.nrw/posts/2025-06-25-2025-06-20-blog-kommentar-system-self-hosted.html) schon beschrieben habe ich das Kommentarsystem fertig und online gestellt. Der Code und die Dokumentation ist auf [Github Repository](https://github.com/ruedigerp/comments). 
\ No newline at end of file
gelöscht content/2025-07-05-automatische-bereinigung-der-github-container-registry-mit-einer-action.md.md
+0 −481
@@ -1,481 +0,0 @@
1 -
---
2 -
title: 'Automatische Bereinigung der GitHub Container Registry mit einer eigenen Action'
3 -
date: 2025-07-05 14:00:00
4 -
update: 2025-07-05 14:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/07/container-registry-cleanup.webp"
7 -
featureImage: "/images/posts/2025/07/container-registry-cleanup.webp"
8 -
tags: [github, ghcr, container, docker, images, registry, cleanup]
9 -
categories: 
10 -
    - Development
11 -
preview: "Die GitHub Container Registry (ghcr.io) ist ein praktischer Service zum Hosten von Docker Images direkt bei GitHub. Bei aktiver Entwicklung sammeln sich jedoch schnell hunderte oder sogar tausende alte Container-Versionen an, die wertvollen Speicherplatz verbrauchen und die Übersicht erschweren."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![ghcr.io container registry cleanup](/images/posts/2025/07/container-registry-cleanup.webp)
20 -
21 -
Die GitHub Container Registry (ghcr.io) ist ein praktischer Service zum Hosten von Docker Images direkt bei GitHub. Bei aktiver Entwicklung sammeln sich jedoch schnell hunderte oder sogar tausende alte Container-Versionen an, die wertvollen Speicherplatz verbrauchen und die Übersicht erschweren. 
22 -
23 -
In diesem Artikel zeige ich, wie ich eine GitHub Action entwickelt habe, die automatisch alte Container Images bereinigt, dabei aber wichtige Versionen schützt.
24 -
25 -
## Das Problem: Explodierender Container-Speicher
26 -
27 -
Bei einem meiner Projekte hatte sich die Anzahl der Container-Versionen auf über 1000 angehäuft:
28 -
29 -
```
30 -
✓ Total versions: 1041
31 -
```
32 -
33 -
Jeder Push in verschiedene Branches erzeugte neue Images mit Tags wie:
34 -
- `v1.9.64-dev.5`
35 -
- `v1.9.64-stage.2`
36 -
- `v1.9.63-develop.1`
37 -
- Untagged Versionen von gescheiterten Builds
38 -
39 -
Während aktuelle Production-Tags wie `latest` oder `v1.9.66` natürlich erhalten bleiben sollen, können alte Development- und Staging-Versionen problemlos gelöscht werden.
40 -
41 -
## Die Lösung: Container Registry Cleanup Action
42 -
43 -
Ich habe eine GitHub Action entwickelt, die diese Aufgabe automatisiert. Die Action berücksichtigt dabei mehrere wichtige Aspekte:
44 -
45 -
### ✨ Hauptfunktionen
46 -
47 -
- **🗑️ Zeitbasierte Bereinigung**: Löscht Container-Versionen, die älter als X Tage sind
48 -
- **🛡️ Tag-Schutz**: Wichtige Tags wie `latest`, `main` oder Release-Versionen bleiben erhalten
49 -
- **📊 Mindestanzahl**: Behält immer eine konfigurierbare Mindestanzahl alter Versionen
50 -
- **⚡ Batch-Verarbeitung**: Löscht pro Lauf nur eine begrenzte Anzahl, um API-Limits zu respektieren
51 -
- **🔒 Sichere Löschung**: Detaillierte Logs und mehrfache Sicherheitsprüfungen
52 -
53 -
### 🔧 Konfigurierbare Parameter
54 -
55 -
Die Action bietet umfangreiche Konfigurationsmöglichkeiten:
56 -
57 -
| Parameter | Beschreibung | Standard | Beispiel |
58 -
|-----------|--------------|----------|----------|
59 -
| `package-name` | Name des Container-Packages | *erforderlich* | `my-app` |
60 -
| `token` | GitHub Token mit `packages:write` | *erforderlich* | `${{ secrets.PAT_TOKEN }}` |
61 -
| `days-old` | Lösche Versionen älter als X Tage | `21` | `14` |
62 -
| `min-versions-to-keep` | Mindestanzahl alter Versionen behalten | `3` | `5` |
63 -
| `max-versions-per-run` | Maximale Löschungen pro Lauf | `10` | `20` |
64 -
| `protected-tags` | Regex-Pattern für geschützte Tags | `latest\|main\|master\|develop\|dev` | `latest\|stable` |
65 -
| `delete-untagged-only` | Nur untagged Versionen löschen | `false` | `true` |
66 -
67 -
## 🛡️ Intelligenter Tag-Schutz
68 -
69 -
Das Herzstück der Action ist der intelligente Tag-Schutz. Über das `protected-tags` Parameter können Sie mit Regex-Patterns definieren, welche Tags niemals gelöscht werden sollen:
70 -
71 -
### Standard-Schutz
72 -
```yaml
73 -
protected-tags: 'latest|main|master|develop|dev'
74 -
```
75 -
76 -
### Erweiteter Schutz für Release-Versionen
77 -
```yaml
78 -
protected-tags: 'latest|main|v[0-9]+\\.[0-9]+\\.[0-9]+$'
79 -
```
80 -
Dies schützt Semantic Versioning Tags wie `v1.2.3`, aber nicht `v1.2.3-beta.1`.
81 -
82 -
### Minimaler Schutz
83 -
```yaml
84 -
protected-tags: 'latest|production'
85 -
```
86 -
87 -
## 📝 Praktische Anwendungsbeispiele
88 -
89 -
### Basis-Setup für tägliche Bereinigung
90 -
91 -
92 -
```yaml
93 -
name: Container Registry Cleanup
94 -
95 -
on:
96 -
  schedule:
97 -
    - cron: '0 2 * * *'  # Täglich um 2 Uhr
98 -
  workflow_dispatch:      # Manueller Start möglich
99 -
100 -
jobs:
101 -
  cleanup:
102 -
    runs-on: ubuntu-latest
103 -
    steps:
104 -
    - name: Cleanup old container images
105 -
      uses: ruedigerp/container-registry-cleanup@v1.1
106 -
      with:
107 -
        package-name: 'my-app'
108 -
        token: ${{ secrets.PAT_TOKEN }}
109 -
        days-old: 21
110 -
        min-versions-to-keep: 3
111 -
```
112 -
113 -
114 -
### Aggressive Bereinigung für Development
115 -
116 -
```yaml
117 -
- name: Cleanup development images
118 -
  uses: ruedigerp/container-registry-cleanup@v1.1
119 -
  with:
120 -
    package-name: 'my-app'
121 -
    token: ${{ secrets.PAT_TOKEN }}
122 -
    days-old: 7           # Nur 1 Woche behalten
123 -
    min-versions-to-keep: 1
124 -
    protected-tags: 'latest|production'
125 -
    max-versions-per-run: 50
126 -
```
127 -
128 -
### Sichere Bereinigung (nur untagged)
129 -
130 -
```yaml
131 -
- name: Safe cleanup - untagged only
132 -
  uses: ruedigerp/container-registry-cleanup@v1.1
133 -
  with:
134 -
    package-name: 'my-app'
135 -
    token: ${{ secrets.PAT_TOKEN }}
136 -
    delete-untagged-only: true
137 -
```
138 -
139 -
### Mehrere Packages bereinigen
140 -
141 -
```yaml
142 -
jobs:
143 -
  cleanup:
144 -
    runs-on: ubuntu-latest
145 -
    strategy:
146 -
      matrix:
147 -
        package: ['frontend', 'backend', 'worker', 'database']
148 -
    steps:
149 -
    - name: Cleanup ${{ matrix.package }}
150 -
      uses: ruedigerp/container-registry-cleanup@v1.1
151 -
      with:
152 -
        package-name: ${{ matrix.package }}
153 -
        token: ${{ secrets.PAT_TOKEN }}
154 -
```
155 -
156 -
## 🔑 Token-Setup
157 -
158 -
Die Action benötigt einen Personal Access Token (PAT) mit entsprechenden Berechtigungen:
159 -
160 -
### 1. PAT erstellen
161 -
1. GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
162 -
2. Erforderliche Scopes auswählen:
163 -
   - `read:packages`
164 -
   - `write:packages` 
165 -
   - `delete:packages`
166 -
167 -
### 2. Token als Repository Secret hinzufügen
168 -
1. Repository → Settings → Secrets and variables → Actions
169 -
2. New repository secret: `PAT_TOKEN`
170 -
3. Token-Wert einfügen
171 -
172 -
## 📊 Praktische Ergebnisse
173 -
174 -
Bei meinem Projekt mit über 1000 Container-Versionen:
175 -
176 -
**Vor der Bereinigung:**
177 -
```
178 -
✓ Total versions: 1041
179 -
Old versions found: 293
180 -
```
181 -
182 -
**Nach mehreren Läufen:**
183 -
```
184 -
✓ Total versions: 751
185 -
Successfully deleted: 20 versions (untagged + old tagged)
186 -
```
187 -
188 -
Die Action löscht systematisch alte Development-Tags wie:
189 -
- `v1.0.233-amd64` ✅ gelöscht
190 -
- `v1.0.232-stage.2` ✅ gelöscht  
191 -
- `v1.9.15-develop.1` ✅ gelöscht
192 -
- `latest` ❌ geschützt
193 -
- `v1.9.66` ❌ geschützt (aktuell)
194 -
195 -
## 🚀 Automatisierung und Best Practices
196 -
197 -
### Empfohlene Scheduler-Konfiguration
198 -
199 -
```yaml
200 -
on:
201 -
  schedule:
202 -
    - cron: '0 2 * * 0'  # Sonntags um 2 Uhr (wöchentlich)
203 -
  workflow_dispatch:
204 -
```
205 -
206 -
### Monitoring mit Outputs
207 -
208 -
```yaml
209 -
- name: Cleanup old images
210 -
  id: cleanup
211 -
  uses: ruedigerp/container-registry-cleanup@v1.1
212 -
  with:
213 -
    package-name: 'my-app'
214 -
    token: ${{ secrets.PAT_TOKEN }}
215 -
216 -
- name: Report results
217 -
  run: |
218 -
    echo "Deleted: ${{ steps.cleanup.outputs.deleted-count }} versions"
219 -
    echo "Total versions: ${{ steps.cleanup.outputs.total-versions }}"
220 -
    echo "Old versions found: ${{ steps.cleanup.outputs.old-versions }}"
221 -
```
222 -
223 -
### Staging/Production Unterscheidung
224 -
225 -
```yaml
226 -
# Staging - aggressiv
227 -
- name: Cleanup staging images
228 -
  if: github.ref == 'refs/heads/develop'
229 -
  uses: ruedigerp/container-registry-cleanup@v1.1
230 -
  with:
231 -
    package-name: 'my-app-staging'
232 -
    token: ${{ secrets.PAT_TOKEN }}
233 -
    days-old: 3
234 -
    min-versions-to-keep: 1
235 -
236 -
# Production - konservativ  
237 -
- name: Cleanup production images
238 -
  if: github.ref == 'refs/heads/main'
239 -
  uses: ruedigerp/container-registry-cleanup@v1.1
240 -
  with:
241 -
    package-name: 'my-app'
242 -
    token: ${{ secrets.PAT_TOKEN }}
243 -
    days-old: 30
244 -
    min-versions-to-keep: 10
245 -
    protected-tags: 'latest|stable|v[0-9]+\\.[0-9]+\\.[0-9]+$'
246 -
```
247 -
248 -
## 🔍 Troubleshooting
249 -
250 -
### Häufige Probleme
251 -
252 -
**403 Forbidden**: 
253 -
- Prüfen Sie die PAT-Berechtigungen
254 -
- Stellen Sie sicher, dass das Package zugänglich ist
255 -
256 -
**Keine Versionen gelöscht**:
257 -
- `min-versions-to-keep` könnte zu hoch sein
258 -
- Alle Versionen könnten durch `protected-tags` geschützt sein
259 -
- Keine Versionen älter als `days-old` vorhanden
260 -
261 -
### Debug-Modus
262 -
263 -
```yaml
264 -
- name: Debug package info
265 -
  run: |
266 -
    gh api /user/packages/container/my-app | jq
267 -
    gh api /user/packages/container/my-app/versions | jq '.[0:3]'
268 -
  env:
269 -
    GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
270 -
```
271 -
272 -
## 💡 Fazit
273 -
274 -
Die Container Registry Cleanup Action automatisiert eine zeitaufwändige Maintenance-Aufgabe und bietet dabei maximale Flexibilität und Sicherheit. Durch die intelligente Tag-Filterung bleiben wichtige Versionen erhalten, während alte Development- und Staging-Versionen systematisch entfernt werden.
275 -
276 -
**Vorteile:**
277 -
- ✅ Reduzierter Storage-Verbrauch
278 -
- ✅ Bessere Übersicht in der Registry
279 -
- ✅ Automatisierte Wartung
280 -
- ✅ Schutz wichtiger Versionen
281 -
- ✅ Konfigurierbar für verschiedene Szenarien
282 -
283 -
Die Action ist Open Source verfügbar und kann direkt über den GitHub Marketplace eingebunden werden.
284 -
285 -
---
286 -
287 -
## 📚 Vollständige README
288 -
289 -
Hier die komplette Dokumentation der Action:
290 -
291 -
---
292 -
293 -
# Container Registry Cleanup Action
294 -
295 -
A GitHub Action to automatically cleanup old container images from GitHub Container Registry (ghcr.io).
296 -
297 -
## Features
298 -
299 -
- 🗑️ Delete old container images based on age
300 -
- 🛡️ Protect important tags (latest, main, master, etc.)
301 -
- 📊 Keep minimum number of versions
302 -
- ⚡ Configurable batch processing
303 -
- 🔒 Safe deletion with detailed logging
304 -
- 🎯 Support for both tagged and untagged versions
305 -
306 -
## Usage
307 -
308 -
### Basic Example
309 -
310 -
```yaml
311 -
name: Cleanup Container Registry
312 -
313 -
on:
314 -
  schedule:
315 -
    - cron: '0 2 * * *'  # Daily at 2 AM
316 -
  workflow_dispatch:
317 -
318 -
jobs:
319 -
  cleanup:
320 -
    runs-on: ubuntu-latest
321 -
    steps:
322 -
    - name: Cleanup old container images
323 -
      uses: ruedigerp/container-registry-cleanup@v1.1
324 -
      with:
325 -
        package-name: 'my-app'
326 -
        token: ${{ secrets.PAT_TOKEN }}
327 -
        days-old: 21
328 -
        min-versions-to-keep: 3
329 -
```
330 -
331 -
### Advanced Example
332 -
333 -
```yaml
334 -
name: Advanced Container Cleanup
335 -
336 -
on:
337 -
  workflow_dispatch:
338 -
339 -
jobs:
340 -
  cleanup:
341 -
    runs-on: ubuntu-latest
342 -
    steps:
343 -
    - name: Cleanup multiple packages
344 -
      uses: ruedigerp/container-registry-cleanup@v1.1
345 -
      with:
346 -
        package-name: 'my-app'
347 -
        token: ${{ secrets.PAT_TOKEN }}
348 -
        days-old: 14
349 -
        min-versions-to-keep: 5
350 -
        max-versions-per-run: 20
351 -
        protected-tags: 'latest|stable|v[0-9]+\\.[0-9]+\\.[0-9]+'
352 -
        delete-untagged-only: false
353 -
```
354 -
355 -
### Multiple Packages
356 -
357 -
```yaml
358 -
jobs:
359 -
  cleanup:
360 -
    runs-on: ubuntu-latest
361 -
    strategy:
362 -
      matrix:
363 -
        package: ['frontend', 'backend', 'worker']
364 -
    steps:
365 -
    - name: Cleanup ${{ matrix.package }}
366 -
      uses: ruedigerp/container-registry-cleanup@v1.1
367 -
      with:
368 -
        package-name: ${{ matrix.package }}
369 -
        token: ${{ secrets.PAT_TOKEN }}
370 -
```
371 -
372 -
## Inputs
373 -
374 -
| Input | Description | Required | Default |
375 -
|-------|-------------|----------|---------|
376 -
| `package-name` | Name of the container package to cleanup | Yes | - |
377 -
| `token` | GitHub token with `packages:write` permission | Yes | - |
378 -
| `days-old` | Delete versions older than this many days | No | `21` |
379 -
| `min-versions-to-keep` | Minimum number of old versions to keep | No | `3` |
380 -
| `max-versions-per-run` | Maximum versions to delete per run | No | `10` |
381 -
| `protected-tags` | Regex pattern for protected tags (pipe-separated) | No | `latest\|main\|master\|develop\|dev` |
382 -
| `delete-untagged-only` | Only delete untagged versions | No | `false` |
383 -
384 -
## Outputs
385 -
386 -
| Output | Description |
387 -
|--------|-------------|
388 -
| `deleted-count` | Number of versions deleted |
389 -
| `total-versions` | Total versions found |
390 -
| `old-versions` | Number of old versions found |
391 -
392 -
## Token Setup
393 -
394 -
1. Create a Personal Access Token (PAT):
395 -
   - Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
396 -
   - Select scopes: `read:packages`, `write:packages`, `delete:packages`
397 -
398 -
2. Add the token as a repository secret:
399 -
   - Repository → Settings → Secrets and variables → Actions
400 -
   - Name: `PAT_TOKEN`
401 -
   - Value: Your created token
402 -
403 -
## Protected Tags
404 -
405 -
By default, these tags are protected and won't be deleted:
406 -
- `latest`
407 -
- `main`
408 -
- `master` 
409 -
- `develop`
410 -
- `dev`
411 -
412 -
You can customize this with the `protected-tags` input using regex patterns.
413 -
414 -
## Safety Features
415 -
416 -
- **Minimum versions**: Always keeps a minimum number of old versions
417 -
- **Batch processing**: Limits deletions per run to avoid overwhelming the API
418 -
- **Protected tags**: Prevents deletion of important tags
419 -
- **Detailed logging**: Shows exactly what's being deleted and why
420 -
- **Dry-run capability**: Set `max-versions-per-run: 0` to see what would be deleted
421 -
422 -
## Examples by Use Case
423 -
424 -
### Conservative Cleanup (Untagged Only)
425 -
```yaml
426 -
- uses: ruedigerp/container-registry-cleanup@v1.1
427 -
  with:
428 -
    package-name: 'my-app'
429 -
    token: ${{ secrets.PAT_TOKEN }}
430 -
    delete-untagged-only: true
431 -
```
432 -
433 -
### Aggressive Cleanup (Keep Only Latest Releases)
434 -
```yaml
435 -
- uses: ruedigerp/container-registry-cleanup@v1.1
436 -
  with:
437 -
    package-name: 'my-app'
438 -
    token: ${{ secrets.PAT_TOKEN }}
439 -
    days-old: 7
440 -
    min-versions-to-keep: 1
441 -
    protected-tags: 'latest|v[0-9]+\\.[0-9]+\\.[0-9]+'
442 -
```
443 -
444 -
### Large Repository Cleanup
445 -
```yaml
446 -
- uses: ruedigerp/container-registry-cleanup@v1.1
447 -
  with:
448 -
    package-name: 'my-app'
449 -
    token: ${{ secrets.PAT_TOKEN }}
450 -
    max-versions-per-run: 50
451 -
    days-old: 30
452 -
```
453 -
454 -
## Troubleshooting
455 -
456 -
### Common Issues
457 -
458 -
1. **403 Forbidden**: Check that your PAT has the correct permissions
459 -
2. **Package not found**: Ensure the package name is correct and accessible
460 -
3. **No versions deleted**: Check that versions exist and meet the age criteria
461 -
462 -
### Debug Mode
463 -
464 -
Add this step before the cleanup to debug:
465 -
466 -
```yaml
467 -
- name: Debug package info
468 -
  run: |
469 -
    gh api /user/packages/container/my-app | jq
470 -
    gh api /user/packages/container/my-app/versions | jq '.[0:3]'
471 -
  env:
472 -
    GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
473 -
```
474 -
475 -
## License
476 -
477 -
MIT License - see [LICENSE](https://github.com/ruedigerp/container-registry-cleanup/blob/main/LICENSE) file for details.
478 -
479 -
## Contributing
480 -
481 -
Contributions welcome! Please read [CONTRIBUTING](https://github.com/ruedigerp/container-registry-cleanup) for guidelines.
gelöscht content/2025-07-05-schnell-vorkonfigurierte-vms-mit-qemu-erstellen.md
+0 −367
@@ -1,367 +0,0 @@
1 -
---
2 -
title: 'Schnell vorkonfigurierte VMs mit QEMU erstellen'
3 -
date: 2025-07-05
4 -
update: 2025-07-05
5 -
author: ruediger
6 -
cover: "/images/posts/2025/07/BC13E6DB-AC08-4445-A5E3-65CA6C1A2EE4.webp"
7 -
featureImage: "/images/posts/2025/07/BC13E6DB-AC08-4445-A5E3-65CA6C1A2EE4.webp"
8 -
tags: [VM, server, cloudinit]
9 -
categories: 
10 -
    - DevOps
11 -
preview: "Wer kennt das nicht? Man braucht mal eben eine saubere Testumgebung, will ein neues Tool ausprobieren oder ein Kubernetes-Cluster aufsetzen. Normalerweise bedeutet das: VM aufsetzen, OS installieren, Updates fahren, Tools installieren – und schon sind ein paar Stunden weg."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: false
17 -
---
18 -
19 -
![VM mit Qemu und Cloudinit erstellen](/images/posts/2025/07/BC13E6DB-AC08-4445-A5E3-65CA6C1A2EE4.webp)
20 -
21 -
22 -
Wer kennt das nicht? Man braucht mal eben eine saubere Testumgebung, will ein neues Tool ausprobieren oder ein Kubernetes-Cluster aufsetzen. Normalerweise bedeutet das: VM aufsetzen, OS installieren, Updates fahren, Tools installieren – und schon sind ein paar Stunden weg.
23 -
24 -
Mit QEMU und Cloud-Init geht das deutlich eleganter. Einmal konfiguriert, startet man eine vollständig vorkonfigurierte VM in wenigen Minuten. Hier zeige ich, wie das geht.
25 -
26 -
## Warum QEMU und Cloud-Init?
27 -
28 -
QEMU ist ein mächtiger Virtualisierer, der auf praktisch allen Plattformen läuft. Cloud-Init ist das Schweizer Taschenmesser für VM-Konfiguration – es kann beim ersten Boot automatisch User anlegen, SSH-Keys installieren, Software nachinstallieren und sogar komplette Skripte ausführen.
29 -
30 -
Die Kombination macht’s möglich: VM starten, kurz warten, fertig konfigurierte Umgebung nutzen.
31 -
32 -
## QEMU installieren
33 -
34 -
**macOS (mit Homebrew):**
35 -
36 -
```bash
37 -
brew install qemu
38 -
```
39 -
40 -
**Ubuntu/Debian:**
41 -
42 -
```bash
43 -
sudo apt update
44 -
sudo apt install qemu-system-aarch64 qemu-utils
45 -
```
46 -
47 -
**CentOS/RHEL/Fedora:**
48 -
49 -
```bash
50 -
sudo dnf install qemu-system-aarch64 qemu-img
51 -
```
52 -
53 -
## Das Base-Image besorgen
54 -
55 -
Wir verwenden ein fertiges Debian ARM64 Cloud-Image als Basis:
56 -
57 -
```bash
58 -
wget https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-arm64.qcow2
59 -
```
60 -
61 -
## Working Copy erstellen
62 -
63 -
Das Original-Image behalten wir als Template und erstellen eine Arbeitskopie:
64 -
65 -
```bash
66 -
cp debian-12-generic-arm64.qcow2 debian-testserver.qcow2
67 -
qemu-img resize debian-testserver.qcow2 20G
68 -
```
69 -
70 -
So kann man das Original-Image immer wieder für neue VMs verwenden.
71 -
72 -
## Cloud-Init konfigurieren
73 -
74 -
Cloud-Init braucht drei Dateien, die wir in einem eigenen Ordner sammeln:
75 -
76 -
```bash
77 -
mkdir cloud-init-data
78 -
cd cloud-init-data/
79 -
```
80 -
81 -
### user-data - Das Herzstück
82 -
83 -
Hier passiert die ganze Magie. Diese Datei definiert, wie die VM aussehen soll:
84 -
85 -
```yaml
86 -
cat <<EOF > user-data
87 -
#cloud-config
88 -
89 -
# User anlegen
90 -
users:
91 -
  - name: debian
92 -
    plain_text_passwd: testpass
93 -
    lock_passwd: false
94 -
    sudo: ALL=(ALL) NOPASSWD:ALL
95 -
    shell: /bin/bash
96 -
    ssh_authorized_keys:
97 -
      - ssh-ed25519 AAAAC3...DeinSSHKey...7iFVL
98 -
99 -
# SSH mit Passwort erlauben
100 -
ssh_pwauth: true
101 -
102 -
# Debug-Modus für Troubleshooting
103 -
debug: true
104 -
105 -
# Standard-Pakete installieren
106 -
packages:
107 -
  - htop
108 -
  - curl
109 -
  - git
110 -
  - vim
111 -
  - wget
112 -
113 -
# System updaten
114 -
package_update: true
115 -
package_upgrade: true
116 -
117 -
# Installationsskript vorbereiten
118 -
write_files:
119 -
  - path: /tmp/install-k3s.sh
120 -
    permissions: '0755'
121 -
    content: |
122 -
      #!/bin/bash
123 -
      set -e
124 -
      
125 -
      echo "K3s wird installiert..."
126 -
      curl -sfL https://get.k3s.io | sh -s - server --cluster-init
127 -
      echo "export KUBECONFIG=/etc/rancher/k3s/k3s.yaml" >> /root/.bashrc
128 -
      
129 -
      echo "k9s wird installiert..."
130 -
      wget https://github.com/derailed/k9s/releases/download/v0.32.7/k9s_Linux_arm64.tar.gz
131 -
      tar xzf k9s_Linux_arm64.tar.gz
132 -
      mv k9s /usr/local/bin/
133 -
      
134 -
      echo "Helm wird installiert..."
135 -
      curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
136 -
      chmod 700 get_helm.sh
137 -
      ./get_helm.sh
138 -
      
139 -
      echo "FluxCD CLI wird installiert..."
140 -
      curl -s https://fluxcd.io/install.sh | sudo bash
141 -
      
142 -
      echo "kubectl wird installiert..."
143 -
      curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl"
144 -
      sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
145 -
      
146 -
      # Praktische Aliases
147 -
      echo 'alias k="kubectl"' >> /root/.bashrc
148 -
      echo 'alias kgp="kubectl get pods"' >> /root/.bashrc
149 -
      
150 -
      # Warten bis Kubernetes läuft
151 -
      echo "Warte auf Kubernetes API..."
152 -
      while ! kubectl cluster-info &>/dev/null; do
153 -
        echo "Kubernetes startet noch..."
154 -
        sleep 10
155 -
      done
156 -
      
157 -
      echo "K3s Installation abgeschlossen!"
158 -
159 -
# Skript nach der Installation ausführen
160 -
runcmd:
161 -
  - /tmp/install-k3s.sh
162 -
EOF
163 -
```
164 -
165 -
### meta-data - Server-Metadaten
166 -
167 -
```bash
168 -
cat <<EOF > meta-data
169 -
instance-id: server-001
170 -
local-hostname: testserver
171 -
EOF
172 -
```
173 -
174 -
### network-config - Netzwerk festlegen
175 -
176 -
```bash
177 -
cat <<EOF > network-config
178 -
version: 2
179 -
ethernets:
180 -
  enp0s1:
181 -
    addresses: [192.168.74.10/24]
182 -
    gateway4: 192.168.74.1
183 -
    nameservers:
184 -
      addresses: [8.8.8.8, 1.1.1.1]
185 -
    dhcp4: false
186 -
EOF
187 -
```
188 -
189 -
## Cloud-Init ISO erstellen
190 -
191 -
Aus den drei Dateien basteln wir ein ISO-Image:
192 -
193 -
### macOS
194 -
195 -
```bash
196 -
cd ..
197 -
hdiutil makehybrid -iso -joliet -default-volume-name "cidata" -o seed.iso cloud-init-data/
198 -
```
199 -
200 -
### Linux
201 -
202 -
```bash
203 -
cd ..
204 -
# Mit genisoimage (meist vorinstalliert)
205 -
genisoimage -output seed.iso -volid cidata -joliet -rock cloud-init-data/
206 -
207 -
# Oder mit xorriso
208 -
xorriso -as mkisofs -V cidata -o seed.iso cloud-init-data/
209 -
```
210 -
211 -
## VM starten
212 -
213 -
Jetzt kommt der spannende Teil – die VM starten:
214 -
215 -
```bash
216 -
qemu-system-aarch64 \
217 -
    -name "testserver" \
218 -
    -machine type=virt,accel=hvf \
219 -
    -cpu cortex-a72 \
220 -
    -smp cores=4,threads=1 \
221 -
    -m 4G \
222 -
    -drive file=debian-testserver.qcow2,if=virtio,index=0,media=disk,format=qcow2 \
223 -
    -drive file=seed.iso,if=virtio,index=1,media=cdrom \
224 -
    -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
225 -
    -device virtio-net-pci,netdev=net0 \
226 -
    -bios /opt/homebrew/share/qemu/edk2-aarch64-code.fd \
227 -
    -nographic \
228 -
    -serial mon:stdio
229 -
```
230 -
231 -
**Was passiert hier?**
232 -
233 -
- `-accel=hvf`: Hardware-Beschleunigung (macOS), unter Linux nimmt man `kvm`
234 -
- `-m 4G`: 4 GB RAM
235 -
- `-smp cores=4`: 4 CPU-Kerne
236 -
- `hostfwd=tcp::2222-:22`: SSH über Port 2222 erreichbar
237 -
- `hostfwd=tcp::8080-:80`: HTTP über Port 8080 erreichbar
238 -
- `-nographic`: Läuft in der Konsole
239 -
240 -
## Netzwerk anpassen
241 -
242 -
Je nach Einsatzzweck kann man verschiedene Netzwerk-Modi nutzen:
243 -
244 -
### User-Modus (Standard)
245 -
246 -
```bash
247 -
-netdev user,id=net0,hostfwd=tcp::2222-:22
248 -
```
249 -
250 -
- Einfachste Variante
251 -
- VM kann ins Internet, ist aber von außen nicht direkt erreichbar
252 -
- Perfekt für Tests
253 -
254 -
### Bridge-Modus
255 -
256 -
```bash
257 -
-netdev bridge,id=net0,br=br0
258 -
```
259 -
260 -
- VM bekommt IP aus dem Host-Netzwerk
261 -
- Direkte Kommunikation möglich
262 -
- Braucht Bridge-Setup auf dem Host
263 -
264 -
### Host-Only
265 -
266 -
```bash
267 -
-netdev socket,id=net0,listen=:1234
268 -
```
269 -
270 -
- VM nur vom Host erreichbar
271 -
- Maximale Isolation
272 -
- Gut für Sicherheitstests
273 -
274 -
## Nach dem Start
275 -
276 -
### Per SSH einloggen
277 -
278 -
```bash
279 -
ssh -p 2222 debian@localhost
280 -
```
281 -
282 -
### Direkte Konsole nutzen
283 -
284 -
Falls SSH mal nicht klappt:
285 -
286 -
- `Ctrl+A, C` für QEMU-Monitor
287 -
- `info network` zeigt Netzwerk-Status
288 -
- `Ctrl+A, X` beendet QEMU
289 -
290 -
## Wenn’s nicht läuft
291 -
292 -
### Cloud-Init checken
293 -
294 -
```bash
295 -
# In der VM
296 -
sudo cloud-init status --wait
297 -
sudo cloud-init logs
298 -
```
299 -
300 -
### Netzwerk prüfen
301 -
302 -
```bash
303 -
# In der VM
304 -
ip addr show
305 -
ping google.com
306 -
```
307 -
308 -
### Services testen
309 -
310 -
```bash
311 -
# K3s Status
312 -
sudo systemctl status k3s
313 -
kubectl get nodes
314 -
```
315 -
316 -
## Erweiterte Tricks
317 -
318 -
### Mehrere VMs parallel
319 -
320 -
Einfach verschiedene Cloud-Init-Konfigurationen erstellen:
321 -
322 -
```bash
323 -
# Zweite VM
324 -
cp debian-12-generic-arm64.qcow2 debian-testserver-2.qcow2
325 -
# Neue cloud-init-data-2/ mit angepassten Einstellungen
326 -
# Andere Ports verwenden: 2223, 8081, etc.
327 -
```
328 -
329 -
### Automatisierung
330 -
331 -
Ein kleines Skript macht das Leben leichter:
332 -
333 -
```bash
334 -
#!/bin/bash
335 -
# vm-create.sh
336 -
VM_NAME=$1
337 -
SSH_PORT=$2
338 -
HTTP_PORT=$3
339 -
340 -
echo "Erstelle VM: $VM_NAME"
341 -
cp debian-12-generic-arm64.qcow2 $VM_NAME.qcow2
342 -
343 -
# Cloud-Init anpassen
344 -
mkdir cloud-init-$VM_NAME
345 -
sed "s/testserver/$VM_NAME/g" cloud-init-data/meta-data > cloud-init-$VM_NAME/meta-data
346 -
cp cloud-init-data/user-data cloud-init-$VM_NAME/
347 -
cp cloud-init-data/network-config cloud-init-$VM_NAME/
348 -
349 -
# ISO erstellen
350 -
hdiutil makehybrid -iso -joliet -default-volume-name "cidata" -o $VM_NAME-seed.iso cloud-init-$VM_NAME/
351 -
352 -
echo "VM $VM_NAME ist bereit!"
353 -
```
354 -
355 -
## Fazit
356 -
357 -
Mit dieser Methode hat man in wenigen Minuten eine vollständig konfigurierte VM am Start. Das Setup ist einmal Arbeit, aber dann kann man beliebig viele VMs aus dem Template erstellen.
358 -
359 -
Perfekt für:
360 -
361 -
- Schnelle Entwicklungsumgebungen
362 -
- CI/CD-Testing
363 -
- Kubernetes-Experimente
364 -
- Sicherheitstests
365 -
- Schulungen
366 -
367 -
Die ganze Konfiguration lässt sich versionieren und an verschiedene Projekte anpassen. Einmal erstellt, hat man immer eine saubere Testumgebung parat – ohne stundenlanges Setup.
gelöscht content/2025-07-08-von-linkwarden-nach-karakeep-migriert.md
+0 −67
@@ -1,67 +0,0 @@
1 -
---
2 -
title: 'Von Linkwarden zu Karakeep: Warum weniger manchmal mehr ist'
3 -
date: 2025-07-08
4 -
update: 2025-07-08
5 -
author: ruediger
6 -
cover: "/images/posts/2025/07/linkwarden-karakeep.webp"
7 -
featureImage: "/images/posts/2025/07/linkwarden-karakeep.webp"
8 -
tags: [bookmarks, linkwarden, karakeep, kuberentes]
9 -
categories: 
10 -
    - Bookmarks
11 -
preview: "Als jemand, der seine Links und Bookmarks professionell organisiert, bin ich kürzlich von Linkwarden zu Karakeep gewechselt. Nach einigen Monaten mit dem neuen Setup kann ich sagen: Es war die richtige Entscheidung. Hier meine Erfahrungen und warum dieser Wechsel für mich so erfolgreich war."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: true
17 -
---
18 -
19 -
![Von Linkwarden zu Karakeep: Warum weniger manchmal mehr ist](/images/posts/2025/07/linkwarden-karakeep.webp)
20 -
21 -
22 -
Als jemand, der seine Links und Bookmarks professionell organisiert, bin ich kürzlich von Linkwarden zu Karakeep gewechselt. Nach einigen Monaten mit dem neuen Setup kann ich sagen: Es war die richtige Entscheidung. Hier meine Erfahrungen und warum dieser Wechsel für mich so erfolgreich war.
23 -
24 -
## Die Ausgangssituation mit Linkwarden
25 -
26 -
Linkwarden ist zweifellos ein mächtiges Tool. Die Möglichkeit, vollständige Screenshots und Snapshots von Webseiten zu speichern, klingt zunächst sehr verlockend. In der Praxis stellte ich jedoch fest, dass ich diese Funktion kaum nutzte. Stattdessen wurde sie zu einem unnötigen Overhead, der Ressourcen verbrauchte, ohne mir einen echten Mehrwert zu bieten.
27 -
28 -
Das größere Problem lag jedoch in der Infrastruktur: Linkwarden benötigt eine PostgreSQL-Datenbank, was bedeutete, dass ich mich nicht nur um die Anwendung selbst kümmern musste, sondern auch um die Wartung, Updates und Backups der Datenbank. In meinen Kubernetes-Clustern war das ein zusätzlicher Komplexitätsgrad, den ich gerne vermeiden wollte.
29 -
30 -
## Warum Karakeep die bessere Wahl war
31 -
32 -
### Schlankheit und Performance
33 -
34 -
Der Wechsel zu Karakeep brachte sofort spürbare Verbesserungen mit sich. Die Anwendung ist deutlich schlanker und läuft erheblich schneller in meinen Kubernetes-Clustern. Ohne die Notwendigkeit für umfangreiche Screenshot-Funktionen und komplexe Archivierungslogik startet Karakeep schneller und verbraucht weniger Speicher.
35 -
36 -
### Einfachere Datenhaltung
37 -
38 -
Einer der größten Vorteile: Karakeep verzichtet auf PostgreSQL. Stattdessen nutzt es eine einfachere Datenhaltung, die über ein Data Directory läuft. Dieses Directory kann ich einfach über Persistent Volume Claims (PVC) und Persistent Volumes (PV) in Kubernetes mounten. Die Datensicherung wird dadurch zu einem Kinderspiel – ich muss nur noch das Storage-Backend regelmäßig sichern, anstatt mich um komplexe Datenbank-Backups zu kümmern.
39 -
40 -
### Ressourceneffizienz zahlt sich aus
41 -
42 -
Durch die gesparten Ressourcen konnte ich eine Funktion aktivieren, die ich bei Linkwarden vermisst hatte: automatisches AI-Tagging. Da Karakeep weniger CPU und RAM benötigt, blieb genug Headroom für diese intelligente Funktion, die meine Links automatisch kategorisiert und verschlagwortet. Das spart mir viel manuelle Arbeit und macht die Organisation meiner Bookmarks noch effizienter.
43 -
44 -
## Praktische Vorteile im Kubernetes-Setup
45 -
46 -
### Vereinfachte Deployments
47 -
48 -
Mein Kubernetes-Deployment für Karakeep ist deutlich einfacher geworden:
49 -
- Nur ein Container statt separater Datenbank-Pods
50 -
- Einfachere Konfiguration ohne Datenbank-Credentials
51 -
- Weniger Netzwerk-Komplexität zwischen Services
52 -
53 -
### Bessere Skalierbarkeit
54 -
55 -
Ohne den Overhead einer externen Datenbank skaliert Karakeep besser in meiner Container-Umgebung. Die Anwendung startet schneller und reagiert flüssiger, besonders bei mehreren parallelen Instanzen.
56 -
57 -
### Backup-Strategie
58 -
59 -
Die Backup-Strategie ist jetzt viel einfacher: Anstatt Datenbank-Dumps zu erstellen und zu verwalten, sichere ich einfach das Storage-Backend, auf dem das Data Directory liegt. Das ist wartungsärmer und weniger fehleranfällig.
60 -
61 -
## Fazit: Weniger ist mehr
62 -
63 -
Der Wechsel von Linkwarden zu Karakeep hat mir gezeigt, dass es nicht immer die Feature-reichste Lösung sein muss. Oft ist es besser, ein Tool zu wählen, das genau das macht, was man braucht – und das gut und effizient.
64 -
65 -
Karakeep bietet mir alles, was ich für die Link-Organisation benötige, ohne unnötigen Ballast. Die gesparten Ressourcen kann ich für Features investieren, die mir wirklich helfen, wie das automatische AI-Tagging. Und die vereinfachte Infrastruktur bedeutet weniger Wartungsaufwand und mehr Zeit für die wichtigen Dinge.
66 -
67 -
Für alle, die ihre Bookmarks in Kubernetes betreiben und dabei Wert auf Effizienz und Einfachheit legen, kann ich Karakeep wärmstens empfehlen. Manchmal ist weniger wirklich mehr.
\ No newline at end of file
gelöscht content/2025-07-10-rant-produktivitaet-verbrennen-mit-microsoft.md
+0 −92
@@ -1,92 +0,0 @@
1 -
---
2 -
title: 'RANT - Produktivität verbrennen mit Microsoft'
3 -
date: 2025-07-10 12:00:00
4 -
update: 2025-07-10 12:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/07/microsoft-rant.webp"
7 -
featureImage: "/images/posts/2025/07/microsoft-rant.webp"
8 -
tags: [Microsoft, Teams, Sharepoint, Drive, Outlook]
9 -
categories: 
10 -
    - Microsoft
11 -
preview: "5€ pro User? Die versteckten Kosten durch verlorene Produktivität, Frustration und kaputte Teamdynamik sind um ein Vielfaches höher."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: true
17 -
---
18 -
19 -
![RANT - Produktivität verbrennen mit Microsoft](/images/posts/2025/07/microsoft-rant.webp)
20 -
21 -
22 -
Visual Studio Code, Azure Cloud – alles Dinge, die von Microsoft sind und dabei auch noch gut funktionieren. Ja, bei der Azure Cloud kann man auch an einigen Stellen fluchen und fragen warum. Aber das kann man bei jedem Hyperscaler, die tun sich da alle nichts. Was sie anbieten funktioniert, und jeder davon hat "historisch" gewachsene Strukturen, die sehr wahrscheinlich auch die Anbieter selbst gerne anders machen würden.
23 -
24 -
Aber darum geht es nicht. Was mich seit einiger Zeit wirklich nervt, und damit bin ich nicht alleine, sind diese ganzen Tools wie Outlook, SharePoint (oder war es jetzt OneDrive?) und Teams.
25 -
26 -
## Teams – Das Produktivitätsgrab
27 -
28 -
Teams ist das Schlimmste, was Entscheider wählen können. Ja, Corporate, ihr habt ja alles von Microsoft und da will man keinen Zoo verwalten. Die, die das entscheiden, haben eh nachher nichts mehr damit zu tun. Sie müssen damit nachher auch kaum arbeiten oder es gar verwalten und pflegen. Sie benutzen es einfach, wie sie es benutzen, und wissen oft gar nicht, was andere in der Firma benötigen und was es leisten muss. Und weil dann interne IT-Abteilungen auch gerne per zentraler Klick-UI stundenlang alle Einstellungen vornehmen, wissen sie auch nicht, dass andere Teams komplett anders arbeiten.
29 -
30 -
### Code-Blöcke? Fehlanzeige!
31 -
32 -
Schon mal in einem Meeting gesessen, bei dem es gerade um ein Deployment geht und Ansible, Terraform, ein Shell Script o.ä. einen Fehler wirft? In Slack oder anderen Programmen kann man Code-Blöcke auswählen oder per Markdown einfach starten, Code reinkopieren und abfeuern. Das Ganze ist dann sauber formatiert und jeder kann es schnell lesen – oft ist ein Problem schnell von jemandem erkannt.
33 -
34 -
Teams: Kein Code-Block, kein Markdown. Da kann man die Shell-Ausgabe reinkopieren und es sieht aus wie reingerotzt. Selbst Newlines werden entfernt. Wenn man das da nicht rauskopiert und in anderen Tools dann irgendwie ansatzweise lesbar macht – was auch unnötig Zeit kostet –, ist das Lesen ungemein schwierig bis unmöglich.
35 -
36 -
### Wo ist die spontane Kommunikation?
37 -
38 -
In Slack, Discord und einer Menge anderer Programme kann man sich Huddles, Working Threads oder wie sie sonst so heißen anlegen. Pro Team, pro Projekt, team-/projektübergreifend, sodass sich alle, die es müssen, schnell finden. Aber man kann auch selbst schnell mit 2-3 Personen spontan einen Chat oder Video-Call-Raum aufmachen. Man sieht, wer drin ist, wer davon online ist, und kann auch mal spontan fragen.
39 -
40 -
In Teams sieht man davon nichts. Keine Channels, keine Rooms, nicht wer online ist. Ich will nicht erst einmal aus irgendwelchen Chats raus und nach Personen suchen. Ich will auch gar nicht überlegen, welche Person ich aus irgendeinem Team ansprechen müsste. Weil man oft gar nicht so schnell weiß, wer überhaupt alles in einem bestimmten Team ist.
41 -
42 -
Man möchte höchstens auf den Channel gehen, der für die Kommunikation eingerichtet ist, und da dann sofort die Mitgliederliste sehen. Selbst wenn der Großteil davon auf "Offline" oder "Abwesend" ist – wenn da nur eine Person anwesend ist, schreibt man in den Chat oder die Person direkt an, um Hilfe oder Infos zu bekommen. Und selbst wenn alle offline sind, bekommen sie umgehend Benachrichtigungen.
43 -
44 -
### Benachrichtigungen? Glückssache!
45 -
46 -
Sehr oft erleben wir es bei Teams:
47 -
1. Überhaupt keine Benachrichtigungen kommen – gerade wenn man Teams geschlossen hat.
48 -
2. Es werden E-Mails versendet. Die kommen dann aber 5-8 Stunden nachdem irgendjemand eine Nachricht in Teams gesendet hat.
49 -
50 -
Bei Teams mal eben mit einer oder gar mehreren Personen chatten oder einen Call machen – wieso geht das nicht mal eben spontan? Und damit meine ich nicht "auf neue Nachricht klicken und Leute zusammensuchen". Wieso gibt es keine Channels, die immer verfügbar sind?
51 -
52 -
Wir kennen es von Slack. Dort können Huddles angelegt werden, und wenn man etwas Bestimmtes macht, was für andere interessant sein könnte, geht man da rein. Andere werden kurz benachrichtigt und können dazukommen. Oder auch nur, weil man gerade im Homeoffice Tasks macht, die auch mit einer lockeren Unterhaltung funktionieren.
53 -
54 -
## Der Kommunikationskollaps
55 -
56 -
Genau so entstehen teamintern und teamübergreifend Austausch, der wichtig für jede Firma ist. Gerade in großen Unternehmen fördert man damit viel mehr, als manchem bewusst ist.
57 -
58 -
Und das wird oft in vielen Unternehmen komplett zerstört. Erst kürzlich in einem Projekt erlebt. Dort war Slack im Einsatz und wurde mit der Begründung "Muss wegen Corporate-Blabla jetzt Teams sein" abgelöst. Wenn das Corporate wäre, dann würde man diesen Schritt nicht gehen. Das ist Ignoranz, Faulheit, Bequemlichkeit und einige andere Sachen, die dazu führen.
59 -
60 -
Und wozu führt das Ganze? Die Kommunikation ist innerhalb von kürzester Zeit auf nahezu NULL gesunken. Calls oder einfach nur Unterhaltungen, also Austausch zu Projektthemen oder auch Zwischenmenschliches sind komplett weg.
61 -
62 -
## SharePoint/OneDrive – Das Mysterium
63 -
64 -
SharePoint oder OneDrive – keine Ahnung, wann und wo manche Dokumente überhaupt wegen welcher Bedingungen landen. Und wenn ich mir so manche IT-Admin-Gruppen im Netz und Social Media angucke, wissen das sehr oft so manche IT-Admins auch nicht so recht. Das ist ein Mysterium, welches sehr oft nur Verzweiflung bringt. Und auch hier, wie auch bei Teams, ist das Teilen von Informationen nicht immer sehr einfach.
65 -
66 -
Gerade im Company-Umfeld kommt es nicht selten vor, dass man mit mehreren Firmen an etwas arbeitet und zentral eine Stelle haben möchte, in der alle gemeinsam auf Dokumente zugreifen können. Wenn nicht schon durch die interne IT und irgendwelche Policies komplett vernagelt und somit überhaupt nicht möglich, scheitert es selbst dann, wenn man es nicht selbst komplett schlecht konfiguriert hat. Schon mal versucht, eine Connection zwischen zwei Teams von zwei Firmen zu verknüpfen oder User, die nicht im Tenant sind... ach, lassen wir das.
67 -
68 -
Es ist grausam. Bei uns sollte ein Werksstudent Zugriff auf einen Ordner bekommen. Erst wollte es überhaupt nicht, dann klappte es dann doch, und zwei Tage später war die komplette Freigabe wieder weg. Keiner wusste wieso, und es war auch nicht ersichtlich warum.
69 -
70 -
## Das wahre Problem: Versteckte Kosten
71 -
72 -
Da werden Stunden verbrannt, und das nicht gerade wenige. Alles in allem verbrennt das Zeug so viel Geld – da frage ich mich: Wieso höre ich immer nur "Aber das alles kostet doch nur 5€ pro User und da ist alles drin"?
73 -
74 -
Ja, da ist alles drin. Aber auch eine Menge Zeit, die tagtäglich in zig Firmen einfach so verbrannt wird. Und es ist nicht nur die Zeit, die verbrennt. Da verbrennt Geld, da verbrennt gute Laune, da verbrennt Zwischenmenschlichkeit.
75 -
76 -
Die Teambuilding-Fahne wird von vielen Entscheidern immer wieder hochgehalten. Die gleichen Entscheider, die dann diesen ganzen Mist einführen, durchdrücken und meistens auf berechtigte Hinweise NULL reagieren.
77 -
78 -
## Outlook – Wenn die Suche versagt
79 -
80 -
Selbst wenn man Probleme und Funktionsmängel aufzeigt, werden sie sehr wahrscheinlich kurz gesehen und man will sie ernsthaft beachten. Wenn das per E-Mail gesendet wurde, dann ist es sehr wahrscheinlich weg. Selbst wenn man sich daran erinnert und sich ernsthaft damit auseinandersetzen möchte – die E-Mail wird man sehr wahrscheinlich nicht im Postfach finden.
81 -
82 -
Erst kürzlich gehabt: Man wusste genau, um was es in der E-Mail ging, und beide haben in ihren Postfächern nach diesen E-Mails gesucht. Und da man wusste, um was es ging, und auch dabei um ein Thema ging, bei dem man gezielt nach bestimmten Begriffen suchen konnte... die Suche von Outlook hat bei beiden keine einzige E-Mail gefunden.
83 -
84 -
Durch Zufall hat einer dann die E-Mail bei sich gefunden, die E-Mail-Adresse vom Systemaccount per Chat gesendet und siehe da – mit der konnte Outlook dann auch mal diese E-Mails bei allen finden.
85 -
86 -
Selbst das 30 Jahre alle Mutt findet meine Mails schneller und kann noch viele Sachen einfach viel besser als Outlook.
87 -
Wie zum Beispiel der Shortcut: "Suche alle Mails die mit Tickets zutun haben, bei denen eine Mail mit Closed reinkam und verschiebe alle dazu gehörigen in einen bestimmten Ordner" 
88 -
Der Code dazu sieht zwar anders aus als hier beschrieben, aber mit einem Tastendruck unnötig und erledigt Mails aus der Inbox zubekommen hat was. Oder was meint Ihr wieso bei mir Zero-Inbox überhaupt funktioniert? ;-) 
89 -
90 -
---
91 -
92 -
*Fazit: 5€ pro User? Die versteckten Kosten durch verlorene Produktivität, Frustration und kaputte Teamdynamik sind um ein Vielfaches höher.*
\ No newline at end of file
gelöscht content/2025-07-11-mutt-mailclient-wird-30-Jahre-oder-mehr.md
+0 −310
@@ -1,310 +0,0 @@
1 -
---
2 -
title: 'Der Mutt Mailclient wird 30 oder mehr Jahre alt'
3 -
date: 2025-07-11 17:00:00
4 -
update: 2025-07-11 17:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/07/mutt-30-years.webp"
7 -
featureImage: "/images/posts/2025/07/mutt-30-years.webp"
8 -
tags: [Mail, Mutt, IMAP, Client]
9 -
categories: 
10 -
    - Software
11 -
preview: "Happy Birthday Mutt Mail Client. 30 Jahre ohne Schnick-Schnack einfach Mails abrufen, lesen, schreiben und versenden."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: true
17 -
---
18 -
19 -
![Happy Birthday Mutt Mail Client](/images/posts/2025/07/mutt-30-years.webp)
20 -
21 -
## Mutt Mail client
22 -
23 -
Da ich vorhin den Mailclient Mutt in einem Artikel erwähnt habe und wissen wollte, wie alt Mutt überhaupt ist, habe ich etwas im Internet recherchiert. Wann wurde es veröffentlicht, wann gestartet?
24 -
25 -
1995 wurde Mutt veröffentlicht. Also ist Mutt jetzt offiziell 30 Jahre alt, wenn man nach dem Release-Jahr geht. Genau eingrenzen lässt es sich nicht, da nirgendwo ein genaues Datum steht. Auch keine Ankündigung zu finden. Oder das Internet hat tatsächlich mal etwas vergessen.
26 -
27 -
Interessant war jedoch die Reise durch das Git-Repository, denn dort kann man immer noch sehen, wie die Reise begonnen hat:
28 -
Vom ersten initialen Commit auf Github kann man jede Änderungen und Verbesserung seit dem anschauen. 
29 -
Ich meine vorher war es in einem SVN Repo. Das habe ich aber nicht mehr gefunden. Auch keine Hinweise in Mailinglisten oder auf Internetseiten warun dazu zu finden. 
30 -
31 -
```text
32 -
#### [Initial revision](https://github.com/muttmua/mutt/commit/1a5381e07e97fe482c2b3a7c75f99938f0b105d4 "Initial revision")
33 -
34 -
![author](https://github.githubassets.com/images/gravatars/gravatar-user-420.png?size=32)
35 -
36 -
Thomas Roessler
37 -
38 -
committed on Jun 8, 1998
39 -
```
40 -
41 -
Und die README.md ist auch noch sehr übersichtlich:
42 -
43 -
```markdown
44 -
README for mutt-0.90i
45 -
=======================
46 -
47 -
Installation instructions are detailed in ''INSTALL''.
48 -
49 -
The user manual is in doc/manual.txt.
50 -
51 -
PGP users please read doc/pgp-Notes.txt before proceeding.
52 -
53 -
For more information, see the Mutt home page,
54 -
http://www.cs.hmc.edu/~me/mutt/index.html.
55 -
56 -
The primary distribution point for Mutt is
57 -
ftp://ftp.cs.hmc.edu/pub/me/mutt.  See the home page for mirror sites.
58 -
59 -
Michael Elkins <me@cs.hmc.edu>, January 22, 1998
60 -
Thomas Roessler <roessler@guug.de>, February 3, 1998
61 -
```
62 -
63 -
## Mutt kann 1998 schon gpg/sMime
64 -
65 -
Wenn man das aus dem Jahr 1998 liest, fragt man sich: Warum ist das für Apple, Microsoft und alle anderen heute immer noch so schwer?
66 -
67 -
```text
68 -
- Other than multipart/mixed and PGP/MIME, Mutt should allow the user to
69 -
  specify what to do with other types of multipart messages (i.e., so a user
70 -
  can deal with S/MIME messages reasonably)
71 -
...
72 -
```
73 -
74 -
Ja, Mutt konnte damals schon mit Verschlüsselung und Signieren umgehen. Das Internet wäre so viel besser, wenn das Standard in allen Clients werden würde.
75 -
76 -
Jetzt komme bitte keiner mit "Aber das ist doch alles viel zu kompliziert". Kompliziert ist irgendwie alles. Passwörter landen in einer Notiz-App, Word oder Excel. Mehrfaktor-Authentifizierung für Logins oder Passkeys sind zu kompliziert.
77 -
78 -
Hört auf, ihr seid einfach nur zu faul und zu bequem. Dafür gibt es Apps, die euch das alles abnehmen. Nur komisch finde ich immer, wenn genau das "zu kompliziert" von genau den gleichen Leuten kommt, die Dinge einrichten und installieren, die aus meiner Sicht schon sehr hart an kompliziert sind. Da geht es dann um Accounts, Software, Lizenzen, die über dubiose Wege und mit viel Gefrickel eingerichtet werden müssen, und ich denke nur: "Respekt, aber Passwortmanager und Authenticator-App sind zu schwer."
79 -
80 -
## Wieder mehr Mutt benutzen
81 -
82 -
Aber zurück zu Mutt. Aktuell nutze ich Mutt nicht mehr so oft. Aber das wird sich bald wieder ändern. Gerade jetzt zum 30. Geburtstag wird Mutt einfach mal wieder reaktiviert. Gerade mit vielen Mails in vielen Ordnern ist Mutt einfach unschlagbar. Kein Scrollen durch Ordnerlisten für verschiedene Accounts. Einfach eine Taste jede halbe Stunde drücken und man sieht, in welchen Ordnern neue Mails sind. Man sieht nicht nur, in welchen Ordnern neue Mails sind – Mutt springt einfach mit einer Taste zum nächsten Ordner mit neuen Mails.
83 -
84 -
Mutt ist so mächtig. Und das vermisse ich auch irgendwie bei allen Mail-Clients, die es aktuell so gibt. Einfach mit einem Shortcut alle Mails aus der Inbox verschieben, die mit GitHub-PRs zu tun haben. Oder alle Incident-Mails. Oder man markiert mal eben per Regex alle Mails außer den 2-3, die man noch benötigt, und verschiebt dann einen Batch mit 10 oder mehr Mails.
85 -
86 -
## Meine Mutt Konfiguration
87 -
88 -
Hier einmal meine Konfiguration für 2 IMAP-Mailaccounts, sehr abgespeckt. Das Switchen zwischen den Accounts geht mit den Tasten 1 und 2. Falls die Sidebar mal nicht aktualisieren sollte: einfach 0 drücken.
89 -
90 -
91 -
### Installation
92 -
93 -
```bash
94 -
brew install mutt
95 -
96 -
# mutt_dotlock(1) has been installed, but does not have the permissions to lock
97 -
# spool files in /var/mail. To grant the necessary permissions, run:
98 -
99 -
sudo chgrp mail /opt/homebrew/Cellar/mutt/2.2.14/bin/mutt_dotlock
100 -
sudo chmod g+s /opt/homebrew/Cellar/mutt/2.2.14/bin/mutt_dotlock
101 -
102 -
# Alternatively, you may configure `spoolfile` in your .muttrc to a file inside
103 -
# your home directory.
104 -
```
105 -
106 -
### .muttrc Config File
107 -
108 -
```bash
109 -
cat <<EOF > ~/.muttrc
110 -
folder-hook 'account.com.example.user1' 'source ~/.mutt/account.com.example.user1'
111 -
112 -
folder-hook 'account.com.example.user2' 'source ~/.mutt/account.com.example.user2'
113 -
114 -
# Default account
115 -
source ~/.mutt/account.com.example.user1
116 -
117 -
118 -
macro index 1 '<sync-mailbox><enter-command>source ~/.mutt/account.com.example.user1<enter><enter-command>exec imap-logout-all<enter><enter-command>unset sidebar_visible<enter><enter-command>set sidebar_visible=yes<enter><change-folder>=INBOX<enter>' "Switch to User 1 account"
119 -
120 -
macro index 2 '<sync-mailbox><enter-command>source ~/.mutt/account.com.example.user2<enter><enter-command>exec imap-logout-all<enter><enter-command>unset sidebar_visible<enter><enter-command>set sidebar_visible=yes<enter><change-folder>=INBOX<enter>' "Switch to User 2 account"
121 -
122 -
macro index 0 '<enter-command>unset sidebar_visible<enter><enter-command>set sidebar_visible=yes<enter><enter-command>set sidebar_width=25<enter><refresh>' "Full sidebar reset"
123 -
124 -
# Fetch mail shortcut
125 -
bind index G imap-fetch-mail
126 -
127 -
set mail_check = 60 # Prüfe alle 60 Sekunden
128 -
set imap_check_subscribed = yes # Nur abonnierte Ordner prüfen
129 -
set imap_list_subscribed = yes # Nur abonnierte Ordner anzeigen
130 -
set imap_passive = no
131 -
set imap_idle = yes
132 -
set mail_check_stats = yes
133 -
set mail_check_stats_interval = 60
134 -
135 -
# Seitenleiste mit Ordnern (optional):
136 -
137 -
set sidebar_format = "%B%?F? [%F]?%* %?N?%N/?%S"
138 -
set folder_format = "%2C %t %N %F %2l %-8.8u %-8.8g %8s %d %f"
139 -
set sort_browser = alpha
140 -
set sidebar_visible = yes
141 -
set sidebar_width = 25
142 -
set sidebar_short_path = yes
143 -
# folder indent wer auch dort einrückungen möchte 
144 -
# set sidebar_folder_indent = yes
145 -
# set sidebar_delim_chars = "/."
146 -
set sidebar_new_mail_only = no
147 -
set sidebar_next_new_wrap = yes
148 -
149 -
bind index,pager K sidebar-prev # K = Nach oben
150 -
bind index,pager J sidebar-next # J = Nach unten
151 -
bind index,pager L sidebar-open # L = Öffnen
152 -
bind index,pager ü sidebar-page-up # ü = Seite hoch
153 -
bind index,pager ö sidebar-page-down # ü = Seite runter
154 -
bind index,pager B sidebar-toggle-visible
155 -
  
156 -
# Alle Header erstmal ausblenden
157 -
158 -
ignore *
159 -
# Nur wichtige Header anzeigen (in dieser Reihenfolge)
160 -
unignore from: to: cc: bcc: date: subject: reply-to:
161 -
unignore organization: user-agent: x-mailer:
162 -
unignore list-id: x-mailing-list:
163 -
164 -
# Header-Reihenfolge festlegen
165 -
166 -
hdr_order from: to: cc: bcc: subject: date: reply-to: organization:
167 -
168 -
# === PAGER-KONFIGURATION (E-Mail-Ansicht) ===
169 -
170 -
# Anzahl der Index-Zeilen über der E-Mail anzeigen
171 -
172 -
set pager_index_lines = 10 # Zeigt 10 E-Mails über der aktuellen
173 -
174 -
# Pager-Verhalten
175 -
176 -
set pager_stop = yes # Stoppe am Ende der Nachricht
177 -
set pager_context = 3 # 3 Zeilen Kontext beim Scrollen
178 -
set menu_scroll = yes # Scrollen statt Seitenweise
179 -
set smart_wrap = yes # Intelligenter Zeilenumbruch
180 -
set markers = no # Keine '+' Zeichen bei umgebrochenen Zeilen
181 -
set pager_index_lines = 10
182 -
183 -
# Aliases / Addressbook 
184 -
set alias_file = ~/.mutt/aliases
185 -
set sort_alias = alias
186 -
set reverse_alias = yes
187 -
set reverse_name = yes
188 -
set reverse_realname = yes
189 -
source ~/.mutt/aliases
190 -
set alias_format = "%4n %2f %t %-15a %-25r"
191 -
192 -
193 -
set charset = "utf-8"
194 -
set send_charset = "utf-8"
195 -
set assumed_charset = "utf-8"
196 -
197 -
# Für bessere Anzeige beim E-Mail schreiben:
198 -
199 -
set compose_format = "-- Mutt: Compose [Approx. msg size: %l Atts: %a]%>-"
200 -
201 -
# === SCHÖNERE E-MAIL-LISTE ===
202 -
# Index-Format (E-Mail-Liste) anpassen
203 -
set index_format = "%4C %Z %{%b %d} %-15.15L (%?l?%4l&%4c?) %s"
204 -
205 -
EOF
206 -
```
207 -
208 -
209 -
### Accounts anlegen 
210 -
211 -
```bash
212 -
mkdir -p ~/.mutt/cache/com.example.user1/{bodies,header}
213 -
mkdir -p ~/.mutt/cache/com.example.user2/{bodies,header}
214 -
```
215 -
216 -
#### User 1:
217 -
218 -
Datei: ~/.mutt/account.com.example.user1
219 -
220 -
221 -
```bash
222 -
cat <<EOF > .mutt/account.com.example.user1
223 -
unmailboxes *
224 -
225 -
set ssl_starttls=yes  
226 -
set ssl_force_tls=yes  
227 -
set from = 'user1@example.com'
228 -
set use_from = yes
229 -
set imap_user = 'user1@example.com'
230 -
set imap_pass = 'yourpass' 
231 -
set smtp_pass = 'yourpass'
232 -
set realname='Bob Mayer'  
233 -
set folder = "imaps://mail.example.com:993"
234 -
set spoolfile = "+INBOX"
235 -
set postponed = "+Drafts"
236 -
237 -
set record = "+Sent Messages"
238 -
set trash = "+Deleted Messages"
239 -
 
240 -
set header_cache = "~/.mutt/cache/com.example.user1/headers"  
241 -
set message_cachedir = "~/.mutt/cache/com.example.user1/bodies"  
242 -
set certificate_file = "~/.mutt/certificates"  
243 -
set smtp_url = 'smtp://user1@mail.example.com:587/'
244 -
245 -
set smtp_authenticators = "plain"
246 -
set move = no  
247 -
set imap_keepalive = 900
248 -
249 -
set ssl_use_sslv3 = no
250 -
set ssl_use_tlsv1 = no
251 -
set ssl_use_tlsv1_1 = no
252 -
set ssl_use_tlsv1_2 = yes
253 -
set ssl_use_tlsv1_3 = yes
254 -
set ssl_verify_dates = yes
255 -
set ssl_verify_host = no
256 -
EOF
257 -
```
258 -
259 -
#### User 2:
260 -
261 -
Datei: Datei: ~/.mutt/
262 -
263 -
```bash
264 -
cat <<EOF > .mutt/account.com.example.user1
265 -
unmailboxes *
266 -
267 -
set ssl_starttls=yes  
268 -
set ssl_force_tls=yes  
269 -
set from = 'user2@example.com'
270 -
set use_from = yes
271 -
set imap_user = 'user2@example.com'
272 -
set imap_pass = 'yourpass' 
273 -
set smtp_pass = 'yourpass'
274 -
set realname='Bob Mayer'  
275 -
set folder = "imaps://mail.example.com:993"
276 -
set spoolfile = "+INBOX"
277 -
set postponed = "+Drafts"
278 -
279 -
set record = "+Sent Messages"
280 -
set trash = "+Deleted Messages"
281 -
 
282 -
set header_cache = "~/.mutt/cache/com.example.user2/headers"  
283 -
set message_cachedir = "~/.mutt/cache/com.example.user2/bodies"  
284 -
set certificate_file = "~/.mutt/certificates"  
285 -
set smtp_url = 'smtp://user2@mail.example.com:587/'
286 -
287 -
set smtp_authenticators = "plain"
288 -
set move = no  
289 -
set imap_keepalive = 900
290 -
291 -
set ssl_use_sslv3 = no
292 -
set ssl_use_tlsv1 = no
293 -
set ssl_use_tlsv1_1 = no
294 -
set ssl_use_tlsv1_2 = yes
295 -
set ssl_use_tlsv1_3 = yes
296 -
set ssl_verify_dates = yes
297 -
set ssl_verify_host = no
298 -
EOF
299 -
```
300 -
301 -
### Mutt Alias / Adressbuch Datei
302 -
303 -
Alias / Adressbuch:
304 -
305 -
```bash
306 -
~/.mutt/aliases
307 -
alias bob "Bob Mayer" <user1@example.com>
308 -
alias Alice "Alice Müller" <user1@example.com>
309 -
```
310 -
gelöscht content/2025-07-14-links-der-woche-kw28.md
+0 −47
@@ -1,47 +0,0 @@
1 -
---
2 -
title: 'Links der Woche KW 28'
3 -
date: 2025-07-14 13:00:00
4 -
update: 2025-07-14 13:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/06/links-of-the-week.webp"
7 -
featureImage: "/images/posts/2025/06/links-of-the-week.webp"
8 -
tags: [Links]
9 -
categories: 
10 -
    - Links
11 -
preview: "Ein paar der interessante Themen die mir die letzten Tage in die Browser Tabs gespült wurden oder mit denen ich mich beschäfftigt habe."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: true
17 -
---
18 -
19 -
![Links of the week](/images/posts/2025/06/links-of-the-week.webp)
20 -
21 -
22 -
23 -
24 -
## Quick Reference - cheatsheets and quick references
25 -
  
26 -
Quick Reference
27 -
28 -
Hier sind einige Spickzettel und Schnellreferenzen, die von Open-Source-Engeln beigesteuert wurden.
29 -
30 -
Link: [Quick Reference](https://quickref.me/) 
31 -
32 -
33 -
## CodeImage - Code-Screenshots
34 -
  
35 -
36 -
Ein Tool, um deine Code-Screenshots zu verschönern.
37 -
Verwalte deine Code-Snippets sofort, mache sie schön lesbar und teile sie mit allen.
38 -
39 -
Link: [CodeImage](https://codeimage.dev/) 
40 -
41 -
## DevDocs
42 -
43 -
DevDocs kombiniert mehrere API-Dokumentationen in einer schnellen, organisierten und durchsuchbaren Benutzeroberfläche.
44 -
45 -
Link: [DevDocs](https://devdocs.io/)
46 -
47 -
gelöscht content/2025-07-16-unifi-network-3.9.md
+0 −128
@@ -1,128 +0,0 @@
1 -
---
2 -
title: 'UniFi Network 9.3: Was ist neu und lohnt sich das Update?'
3 -
date: 2025-07-16 09:00:00
4 -
update: 2025-07-16 09:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/07/unifi-dashboard.webp"
7 -
featureImage: "/images/posts/2025/07/unifi-dashboard.webp"
8 -
tags: [Unifi, UDM, Network, Update]
9 -
categories: 
10 -
    - Network
11 -
preview: "Ubiquiti hat UniFi Network 9.3 veröffentlicht und ich hab mir die neuen Features mal genauer angeschaut. Spoiler: Es gibt einige wirklich nützliche Verbesserungen, auch wenn nicht alles revolutionär ist."
12 -
draft: false
13 -
top: false
14 -
type: post
15 -
hide: false
16 -
toc: true
17 -
---
18 -
19 -
![Links of the week](/images/posts/2025/07/unifi-dashboard.webp)
20 -
21 -
22 -
Ubiquiti hat UniFi Network 9.3 veröffentlicht und ich hab mir die neuen Features mal genauer angeschaut. Spoiler: Es gibt einige wirklich nützliche Verbesserungen, auch wenn nicht alles revolutionär ist.
23 -
24 -
## Die neue Client-Tabelle - endlich übersichtlich
25 -
26 -
Das erste, was mir aufgefallen ist: Die Client-Tabelle wurde komplett überarbeitet. Wer schon mal versucht hat, in einem größeren Netzwerk einen bestimmten Client zu finden, weiß wie nervig das bisher war.
27 -
28 -
**Was sich geändert hat:**
29 -
- Filtern nach Broadcast-Typ, Access Point, Funkband, WiFi-Generation oder Herstellern
30 -
- Echtzeitaktualisierungen (endlich!)
31 -
- Deutlich schneller, auch bei vielen Clients
32 -
33 -
Besonders praktisch finde ich die Herstellerfilterung. Wenn du wissen willst, welche Apple-Geräte gerade im Netz sind oder alle Samsung-Smartphones auf einmal anzeigen möchtest, geht das jetzt mit einem Klick.
34 -
35 -
Die Performance ist tatsächlich spürbar besser geworden. Selbst in meinem Testnetzwerk mit über 200 Clients lädt die Tabelle schnell und reagiert flüssig. Das war früher definitiv ein Schwachpunkt.
36 -
37 -
## DHCP Manager - überfällige Verbesserung
38 -
39 -
Der neue DHCP Manager ist ehrlich gesagt längst überfällig gewesen. Bisher musstest du für jeden VLAN separat schauen, welche IP-Adressen vergeben sind. Jetzt siehst du alles zentral an einem Ort.
40 -
41 -
**Was mir gut gefällt:**
42 -
- Alle aktiven Leases in einer Übersicht
43 -
- Einfache Verwaltung von statischen Zuweisungen
44 -
- Funktioniert auch bei mehreren Netzwerken problemlos
45 -
46 -
Ich nutze das hauptsächlich, um zu schauen, welche Geräte welche IPs haben und um bei Bedarf statische Zuweisungen zu machen. Geht jetzt deutlich schneller als vorher.
47 -
48 -
## Alarm Manager - nützlich, aber nicht perfekt
49 -
50 -
Der neue Alarm Manager ist eine interessante Ergänzung. Du kannst jetzt spezifische Geräte überwachen und dir Benachrichtigungen schicken lassen, wenn bestimmte Bedingungen erfüllt sind.
51 -
52 -
**Was funktioniert gut:**
53 -
- Überwachung einzelner Geräte mit eigenen Regeln
54 -
- Verschiedene Benachrichtigungsarten (E-Mail, etc.)
55 -
- Export zu externen Systemen möglich
56 -
57 -
**Wo noch Luft nach oben ist:**
58 -
Die Konfiguration ist etwas umständlich und die Dokumentation könnte besser sein. Für einfache Anwendungsfälle (Server offline, hohe Bandbreitennutzung) funktioniert es aber gut.
59 -
60 -
## System-Logs - deutlich besser geworden
61 -
62 -
Die System-Logs wurden komplett überarbeitet und sind jetzt wesentlich brauchbarer. Früher war das oft ein Krampf, relevante Informationen zu finden.
63 -
64 -
**Verbesserungen:**
65 -
- Viel mehr Details zu Ereignissen
66 -
- Bessere Suchfunktion
67 -
- CEF-Format für SIEM-Integration (falls du sowas nutzt)
68 -
69 -
Besonders für die Fehlersuche ist das eine echte Verbesserung. Die Logs sind jetzt strukturierter und man findet schneller, was man sucht.
70 -
71 -
## Content-Filterung - endlich granular
72 -
73 -
Die Content-Filterung wurde erweitert und ist jetzt deutlich flexibler. Du kannst pro Netzwerksegment verschiedene Filter erstellen und sogar Zeitpläne definieren.
74 -
75 -
**Neue Möglichkeiten:**
76 -
- Unbegrenzte Filter pro Netzwerk
77 -
- Integrierte Ad-Blocking-Funktion
78 -
- Zeitbasierte Regeln
79 -
80 -
Das ist besonders praktisch, wenn du unterschiedliche Benutzergruppen hast. Gäste-WLAN kann andere Regeln haben als das Mitarbeiter-Netzwerk, und das lässt sich jetzt viel einfacher umsetzen.
81 -
82 -
## CyberSecure Protection - Marketing oder Mehrwert?
83 -
84 -
Ubiquiti bewirbt die erweiterten Sicherheitsfeatures ziemlich stark. Die Realität ist: Es gibt tatsächlich Verbesserungen, aber die Grundfunktionen waren auch vorher schon solide.
85 -
86 -
**Was neu ist:**
87 -
- Proofpoint IDS/IPS Integration
88 -
- Cloudflare-basierte Echtzeit-Filterung
89 -
- Kontinuierliche Threat-Updates
90 -
91 -
Ob das in der Praxis einen großen Unterschied macht, hängt stark von deinem Anwendungsfall ab. Für die meisten kleineren Netzwerke ist es nice-to-have, aber kein Game-Changer.
92 -
93 -
## Multi-WAN Support - für die, die es brauchen
94 -
95 -
Die Multi-WAN-Funktionen wurden erweitert. Du kannst jetzt SLAs definieren und intelligenteres Load-Balancing betreiben.
96 -
97 -
**Neue Features:**
98 -
- Anpassbare SLAs für verschiedene Uplinks
99 -
- Policy-basiertes Routing
100 -
- Bessere Failover-Mechanismen
101 -
102 -
Das ist hauptsächlich für Leute interessant, die mehrere Internetverbindungen haben. Für normale Setups mit einem Provider ist das weniger relevant.
103 -
104 -
## Mein Fazit nach dem Testen
105 -
106 -
UniFi Network 9.3 ist ein solides Update mit einigen wirklich nützlichen Verbesserungen. Die überarbeitete Client-Tabelle allein macht das Update schon lohnenswert, wenn du regelmäßig mit der Verwaltung zu tun hast.
107 -
108 -
**Was mir besonders gut gefällt:**
109 -
- Client-Tabelle ist endlich brauchbar
110 -
- DHCP Manager spart Zeit
111 -
- System-Logs sind deutlich informativer
112 -
113 -
**Was noch verbesserungswürdig ist:**
114 -
- Alarm Manager könnte einfacher zu konfigurieren sein
115 -
- Manche Features fühlen sich noch etwas "beta" an
116 -
- Dokumentation ist teilweise lückenhaft
117 -
118 -
**Solltest du updaten?**
119 -
Ja, aber nicht sofort. Ich würde empfehlen, noch ein paar Wochen zu warten, bis die ersten Kinderkrankheiten ausgebügelt sind. Dann ist es definitiv ein lohnenswertes Update.
120 -
121 -
Aber die meisten die ich kenne werden es eh jetzt installieren oder schon installiert haben. 
122 -
123 -
Die meisten Verbesserungen sind praktische Alltagserleichterungen und keine revolutionären Neuerungen. Aber genau das macht ein gutes Update aus - es macht die tägliche Arbeit einfacher, ohne dabei neue Probleme zu schaffen.
124 -
125 -
Übrigens: Das Update ist kostenlos und funktioniert mit der bestehenden Hardware. Keine versteckten Kosten oder Abo-Fallen, was bei Ubiquiti auch nicht anders zu erwarten war.
126 -
127 -
Was denkst du über die neuen Features? Hast du schon Erfahrungen mit 9.3 gemacht? Lass es mich in den Kommentaren wissen!
128 -
gelöscht content/2025-08-15-wasser-predigen-wein-trinken-telekoms-mailserver-doppelmoral.md
+0 −119
@@ -1,119 +0,0 @@
1 -
---
2 -
title: 'Wasser predigen, Wein trinken: Telekoms Mailserver-Doppelmoral'
3 -
date: 2025-08-15 12:00:00
4 -
update: 2025-08-15 12:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/08/telekom-mail-fail.webp"
7 -
featureImage: "/images/posts/2025/08/telekom-mail-fail.webp"
8 -
# images: 
9 -
#   - /images/posts/2025/08/telekom-mail-fail.webp
10 -
tags: [Telekom, mailserver, reputation, fail]
11 -
categories: 
12 -
    - Mailserver
13 -
preview: "Wasser predigen, Wein trinken: Telekoms Mailserver-Doppelmoral. Und die Telekom E-Mail Engineers können anscheinend nicht mal `dig` bedienen."
14 -
draft: false
15 -
top: false
16 -
type: post
17 -
hide: false
18 -
toc: false
19 -
---
20 -
21 -
<!-- 
22 -
![Telekom Mail Fail](/images/posts/2025/08/telekom-mail-fail.webp) 
23 -
-->
24 -
25 -
26 -
Und die Telekom E-Mail Engineers können anscheinend nicht mal `dig` bedienen.
27 -
28 -
Wenn ich Spam oder Attacken auf meine Mailserver feststelle, dann ist das Erste, was ich mache, natürlich blocken. Anschließend wird geguckt, woher der Mailserver kommt, also Provider, Serverbesitzer, Domainbesitzer. Oft kommt es ja von einer Domain, auf der auch eine Internetseite betrieben wird. Dann kann man halt über das Impressum gehen.
29 -
30 -
Wenn das aber nicht so einfach zu finden ist, dann geht man halt über [postmaster@domain.tld](mailto:postmaster@domain.tld), die sollten immer erreichbar sein. Reagiert da keiner, hilft ein `dig soa domain.tld` und man schreibt den Zonemaster an, der ja wissen sollte, welchem Kunden der MX gehört. Bei großen Providern gibt es eine Abuse-Abteilung, die man kontaktieren kann.
31 -
32 -
Jetzt meinte die Telekom vorletzte Woche, eine Mail von mir abzuweisen. Ich maile nicht oft an t-online.de-Adressen, weil die meisten Gott sei Dank keine mehr haben. Aber es kam halt mal wieder vor.
33 -
34 -
```bash
35 -
<[**********@t-online.de](mailto:S-W-B@t-online.de)>: host [mx03.t-online.de](http://mx03.t-online.de/)[194.25.134.73] refused to talk to  
36 -
   me: 554 IP=23.88.46.137 - Dialup/transient IP not allowed. Use a  
37 -
   mailgateway or contact [toda@rx.t-online.de](mailto:toda@rx.t-online.de) if obsolete. (DIAL)  
38 -
Reporting-MTA: dns; [mail01.9it.de](http://mail01.9it.de/)  
39 -
X-Postfix-Queue-ID: B72DF44A35  
40 -
X-Postfix-Sender: rfc822; [ruediger@kuepper.nrw](mailto:ruediger@kuepper.nrw)  
41 -
Arrival-Date: Tue, 12 Aug 2025 09:12:53 +0000 (UTC)  
42 -
  
43 -
Final-Recipient: rfc822; [**********@t-online.de](mailto:**********@t-online.de)  
44 -
Original-Recipient: rfc822;[**********@t-online.de](mailto:**********@t-online.de)  
45 -
Action: failed  
46 -
Status: 4.0.0  
47 -
Remote-MTA: dns; [mx03.t-online.de](http://mx03.t-online.de/)  
48 -
Diagnostic-Code: smtp; 554 IP=23.88.46.137 - Dialup/transient IP not allowed.  
49 -
   Use a mailgateway or contact [toda@rx.t-online.de](mailto:toda@rx.t-online.de) if obsolete. (DIAL)
50 -
```
51 -
Der MX mx03.t-online.de meint also, es ist eine Dialup-IP, also von einem Einwahl-DSL-, Kabel- oder Glasfaseranschluss. Nein, ist sie nicht. Es ist eine IP bei einem großen deutschen Hostinganbieter.
52 -
53 -
Ich habe dann erst einmal selbst ein paar Sachen geprüft. Hätte ich nicht machen brauchen, weil ich wusste schon vorher, dass alles passt.
54 -
55 -
   * Vom Mailserver passte im DNS der A-Record, 
56 -
   * bei der IP die zurückgeliefert wurde passte der PTR genau auf den A-Record vom Mailserver.
57 -
   * TXT-Records für SPF: Correct.
58 -
   * DKIM: Correct
59 -
   * DMARC: Correct 
60 -
61 -
Die Telekom verwies in der Antwort auf: postmaster.t-online.de
62 -
63 -
Alles, was sie verlangten, war ok, außer dass keine Kontaktdaten hinterlegt sind. Was man aber mit `dig SOA 9it.de` oder einer einfachen Mail an [postmaster@9it.de](mailto:postmaster@9it.de) hätte gar nicht benötigt. Damit aber bald wieder, wenn doch mal wieder nötig, an eine t-online.de-Mailadresse gemailt werden könnte, habe ich die Mailadressen auf die Seite gepackt. War auch nicht genug, also ist da jetzt ein Link zu einem Impressum.
64 -
65 -
Lustigerweise meinte einer der Engineers der Telekom zu bemängeln, dass es ja auch nicht bei der mail01.9it.de gegeben sei. Jetzt mal im Ernst. mail01.9it.de und andere Hosts von mir sind reine Mailserver. Genau so betreibt es auch die Telekom und alle anderen Provider. Reine Mailserver, da ist kein Webserver, kein DNS-Server drauf. Sie machen reine Mailserver.
66 -
67 -
Sollen jetzt mal alle Mailadmins sich einfach mal genau so verhalten und es genau so begründen? Dann kann die Telekom die nächsten Wochen gerne auch mal damit rumschlagen, um ihre Mails loszuwerden.
68 -
69 -
```bash
70 -
mail03:/etc/nginx# dig +short MX rx.t-online.de
71 -
10 rx.t-online.de.
72 -
mail03:/etc/nginx# dig +short MX t-online.de
73 -
10 mx01.t-online.de.
74 -
10 mx02.t-online.de.
75 -
10 mx03.t-online.de.
76 -
10 mx00.t-online.de.
77 -
mail03:/etc/nginx# dig +short MX telekom.de
78 -
100 mailin12.telekom.de.
79 -
100 mailout32.telekom.de.
80 -
100 mailin42.telekom.de.
81 -
100 mailin32.telekom.de.
82 -
100 mailin22.telekom.de.
83 -
```
84 -
Alle Hostnames für diese MX sind alle nicht per HTTP erreichbar.
85 -
86 -
Nimmt man sich jetzt einfach mal eine Mail der Telekom:
87 -
```bash
88 -
2025-07-24T08:50:26.239134+00:00 localhost postfix/smtpd[1207115]: 3A5444167F: client=awmail151.telekom.de[194.25.225.223]
89 -
2025-07-24T08:50:26.277338+00:00 localhost postfix/cleanup[1207118]: 3A5444167F: message-id=<-2014779266.1753347025112.JavaMail.rechnung-online@telekom.de>
90 -
2025-07-24T08:50:26.591807+00:00 localhost postfix/qmgr[960119]: 3A5444167F: from=<rechnungonline@telekom.de>, size=162701, nrcpt=1 (queue active)
91 -
2025-07-24T08:50:26.640058+00:00 localhost postfix/lmtp[1207119]: 3A5444167F: to=<********@9it-server.de>, relay=mail01.9it.de[private/dovecot-lmtp], delay=0.43, delays=0.38/0/0.02/0.03, dsn=2.0.0, status=sent (250 2.0.0 <=<********@9it-server.de> oGl1JNLzgWhpaxIA0J78UA Saved)
92 -
2025-07-24T08:50:26.640423+00:00 localhost postfix/qmgr[960119]: 3A5444167F: 
93 -
```
94 -
95 -
Man kann Glück haben und man erreicht durch Zufall den richtigen Mitarbeiter, der es an die richtige Abteilung leitet. Denn man könnte ja dabei einfach auf telekom.de gehen, das Impressum anklicken und sein Glück versuchen. Denn die Kontaktdaten dort sind alles Kontaktdaten, Formulare und Chats, die für Endkunden ausgelegt sind. Kommt da mal mit Mailserver-Logs und Hinweisen zu Spam-Mails oder sonstigen Themen, die technisch sind und nichts mit "Mein DSL ist kaputt" zu tun haben. Eine direkte Kontaktmöglichkeit zu den E-Mail-Engineers findet man auf der Seite nirgendwo.
96 -
97 -
Andersherum ballern hier auch täglich sehr viele Mails auf meine Mailserver ein, die über Telekom-Infrastruktur versendet werden, die unerwünscht sind und sogar reine Spam-Mails sind. Dabei ist ein Marketinganbieter, bei dem die Telekom auch Technologiepartner ist. Aber auch Versender, die die Infrastruktur der Telekom nutzen. Die Domains, die genutzt werden, sind oft überhaupt nicht erreichbar. Da muss auch jeder andere Mailadmin auch mal `host` und `dig` anwerfen, um herauszufinden, dass ein MX bei der Telekom betrieben wird.
98 -
99 -
Der Mailserver, bzw. die IP, soll jetzt wieder resettet werden.
100 -
101 -
`Wir werden veranlassen, dass die Reputation dieser IP-Adresse bei unserem System resettet wird.`
102 -
103 -
Interessant war in einer vorherigen Mail dieser Satz:
104 -
105 -
`Von der genannten IP-Adresse war lange Zeit keine Aktivität bei uns feststellbar. Aus Sicherheitsgründen nehmen unsere Systeme von solchen IPs erst nach Prüfung und Reset der Reputation E-Mails entgegen.`
106 -
107 -
Richtig, es werden kaum Mails an Telekom-Mailadressen versendet. Das sollte ja ein Zeichen dafür sein, dass meine MX sauber sind und die Reputation sollte gut sein. Heißt das jetzt, ich muss einfach regelmäßig Mails an die Telekom-Adressen schicken, um nicht wieder aus deren Liste zu fliegen und ich mich somit wieder unnötig mit der Telekom auseinandersetzen muss?
108 -
109 -
Ok, als Kunde der Telekom kann man sich ja eine Mailadresse anlegen und einfach jeden Tag eine sinnlose Mail hinschicken lassen.
110 -
111 -
Obwohl ich ja kurz überlegt hatte, einfach alles, was an Schrott von der Telekom kommt und von meinen Mailservern geblockt oder als Spam erkannt wird, einfach jedes Mal bei der Telekom selbst zu reporten. Die Auswertungen laufen eh automatisiert und es wäre nur eine kleine Erweiterung der Tools, damit es einfach an [abuse@telekom.de](mailto:abuse@telekom.de) geht.
112 -
113 -
Aber sehr wahrscheinlich würde dann wieder jemand bei der Telekom auf seinem hohen Ross einfach nach ein paar Tagen alles löschen und einfach die IP komplett auf eine Blacklist packen. Selbst Spammern eine Plattform liefern und dann so reagieren, aber wenn andere eigentlich alles richtig machen, kommen sie mit ihren Reputationslisten und wird bestraft, wenn man eben keine Mails und somit Spam einliefert.
114 -
115 -
Das ist das gleiche Verhalten, wie es Jahre lang von Hotmail.com betrieben wurde. Jeden Tag sind von denen Millionen von Spam-Mails eingetroffen, aber selbst aufführen, als wäre man die Internet-Polizei und man kann anderen vorschreiben, was zu machen ist.
116 -
117 -
Kriegt erst einmal alle eure eigenen Sachen in den Griff. Dann können wir gerne über Mailsecurity reden.
118 -
119 -
gelöscht content/2025-10-17-debugging-von-distroless-containern-in-kubernetes.md
+0 −106
@@ -1,106 +0,0 @@
1 -
---
2 -
title: 'Debugging von Distroless-Containern in Kubernetes'
3 -
date: 2025-10-17 08:00:00
4 -
update: 2025-10-17 08:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/10/debugging-von-distroless-containern-in-kubernetes.webp"
7 -
featureImage: "/images/posts/2025/10/debugging-von-distroless-containern-in-kubernetes.webp"
8 -
# images: 
9 -
#   - /images/posts/2025/08/telekom-mail-fail.webp
10 -
tags: [Kubernetes, Debugging, Distroless-Containern]
11 -
categories: 
12 -
  - Kubernetes
13 -
preview: "Weil es keine Shell im Container gibt! Daher können Sie weder `ps`, `curl`, `netstat` noch andere nützliche Tools ausführen, um den Produktionsfehler zu debuggen. Lösung: Ephemeral Containers in Kubernetes"
14 -
draft: false
15 -
top: false
16 -
type: post
17 -
hide: false
18 -
toc: false
19 -
---
20 -
21 -
Distroless Container Images sind schnell, sicher und perfekt für die Produktion, können aber beim Debugging zum Albtraum werden.
22 -
23 -
In diesem Blog erfährst Du, warum Distroless Container Images so leistungsfähig sind, warum ihr Debugging schwierig ist und wie Ephemeral Containers in Kubernetes das Live-Debugging wieder einfach machen, ohne Ihre Anwendung neu zu starten.
24 -
25 -
# Was sind Distroless Images?
26 -
27 -
Distroless-Container sind Docker-Images, die keine Linux-Distribution (wie Ubuntu oder Alpine) enthalten. Sie beinhalten nur:
28 -
29 -
* Ihre Anwendung
30 -
* Deren Laufzeitumgebung (z.B. Java, Node.js, Go)
31 -
32 -
# Was fehlt darin?
33 -
34 -
* Keine Shell (sh, bash)
35 -
* Kein Paketmanager (apt, apk)
36 -
* Keine Debug-Tools (curl, ping, ps)
37 -
38 -
# Warum Distroless Images verwenden?
39 -
40 -
Distroless Images sind für Sicherheit, Performance und Einfachheit optimiert und werden aufgrund folgender Vorteile für den Einsatz in Produktionsumgebungen empfohlen:
41 -
42 -
* Schnellere Downloads und Deployments durch kleinere Docker-Image-Größe, wodurch Cloud-Infrastrukturkosten sowohl für  Netzwerk als auch Storage gespart werden
43 -
* Reduzierte Angriffsfläche durch weniger Binaries und Bibliotheken
44 -
* Kein Shell-Zugriff bedeutet, dass niemand per exec in den Container gelangen kann
45 -
46 -
# Das Debugging-Dilemma
47 -
48 -
Stellen Dir sich vor, Deine Node.js-App läuft in einem Distroless Container Image und wirft 500-Fehler. Um dies zu debuggen, haben Du versucht:
49 -
50 -
```bash
51 -
kubectl exec -it my-production-application -- sh
52 -
```
53 -
54 -
erhälst jedoch folgende Fehlermeldung:
55 -
56 -
```bash
57 -
error: unable to upgrade connection: container not found or shell not available
58 -
```
59 -
60 -
Warum? Weil es keine Shell im Container gibt! Daher können Sie weder `ps`, `curl`, `netstat` noch andere nützliche Tools ausführen, um den Produktionsfehler zu debuggen.
61 -
62 -
## Lösung: Ephemeral Containers in Kubernetes
63 -
64 -
Ephemeral Containers in Kubernetes ermöglichen es Dir, einen temporären Debug-Container in einen laufenden Pod zu injizieren, ohne Deine Anwendung zu stoppen, neu zu erstellen oder neu zu starten, um den Fehler im Anwendungs-Pod zu debuggen.
65 -
66 -
### Schritte:
67 -
68 -
1. Erstelle Dir einen Beispiel-Anwendungs-Pod mit dem Distroless Container Image
69 -
70 -
```yaml
71 -
apiVersion: v1
72 -
kind: Pod
73 -
metadata:
74 -
 name: my-app
75 -
spec:
76 -
 containers:
77 -
 — name: app
78 -
 image: gcr.io/distroless/static
79 -
 command: ["sleep", "3600"]
80 -
```
81 -
82 -
```bash
83 -
kubectl apply -f my-app.yaml
84 -
```
85 -
86 -
2. Debug-Container injizieren
87 -
88 -
```yaml
89 -
kubectl debug -it my-app \
90 -
 --target=app \
91 -
 --image=busybox \
92 -
 --name=debugger
93 -
```
94 -
95 -
Jetzt befindest Du Dich im `busybox`-Container, der die Netzwerk-, Prozess- und IPC-Namespaces mit Ihr Deinem  Anwendungs-Pod teilt, was Dir hilft, Dir Anwendungsprobleme zu debuggen.
96 -
97 -
```text
98 -
ps              # Prozesse des nginx-Container-Namespace auflisten
99 -
ls /            # Dateisystem durchsuchen
100 -
cat /etc/hosts  # Netzwerkkonfiguration anzeigen
101 -
ping 8.8.8.8    # Ausgehende Verbindung testen
102 -
wget <url>      # Falls unterstützt, Downloads testen
103 -
```
104 -
105 -
Und Deine Anwendung läuft ohne Neustart weiter.
106 -
gelöscht content/2025-10-17-fluxcd-globale-vars-fuer-gethomepage.md
+0 −242
@@ -1,242 +0,0 @@
1 -
---
2 -
title: 'FluxCD Globale Variabeln für GetHomepage'
3 -
date: 2025-10-16 20:00:00
4 -
update: 2025-10-16 20:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/10/fluxcd-globale-vars-fuer-gethomepage.webp"
7 -
featureImage: "/images/posts/2025/10/fluxcd-globale-vars-fuer-gethomepage.webp"
8 -
# images: 
9 -
#   - /images/posts/2025/08/telekom-mail-fail.webp
10 -
tags: [Kubernetes, FluxCD, GlobalVars, GetHomepage]
11 -
categories: 
12 -
  - Kubernetes
13 -
preview: "Globale Variabeln in FluxCD für Ressourcen nutzen. Zum Beispiel um in Ingress Annotations für GetHomepage zu setzen."
14 -
series: ["FluxCD"] 
15 -
draft: false
16 -
top: false
17 -
type: post
18 -
hide: false
19 -
toc: false
20 -
---
21 -
22 -
Damit GetHomepage Services anzeigt und in Gruppen zuordnet kann man im Ingress dafür Annotations setzen. 
23 -
Änderungen sollen nicht zu Aufwendig sein, daher habe ich sie als Variabeln in FluxCD gesetzt. 
24 -
Meine Defaults sind enabled, group, pod_selector und icon. Die werden immer gesetzt. 
25 -
Weitere werden in den Applications nachher noch bei Bedarf per Patch hinzugefügt. Oder die Defaults überschrieben. 
26 -
27 -
Aber erst einmal der Reige nach. Ein Ingress Object sieht erst einmal so aus. der Clusterissuer und die Middleware gehören nicht zu GetHomepage, werden aber auch gleich mit gemacht. So können diese auch gleich schnell geändert werden wenn sich z.B. der ClusterIssuer ändert. 
28 -
29 -
```yaml
30 -
apiVersion: networking.k8s.io/v1
31 -
kind: Ingress
32 -
metadata:
33 -
  annotations:
34 -
  clusterissuer: "cf-letsencrypt-prod"
35 -
  middlewares: "kube-system-redirect-scheme@kubernetescrd"
36 -
  gethomepage_enabled: '"true"'
37 -
  gethomepage_group: "Default"
38 -
  gethomepage_pod_selector: "''"
39 -
  gethomepage_icon: "homepage"
40 -
...
41 -
```
42 -
43 -
Diese Annotations, eher die Values werden einfach in einer ConfigMap gespeichert. Auf diese wird später im Ingress verwiesen. 
44 -
45 -
```yaml
46 -
apiVersion: v1
47 -
kind: ConfigMap
48 -
metadata:
49 -
  name: global-vars
50 -
  namespace: flux-system
51 -
data:
52 -
  clusterissuer: "cf-letsencrypt-prod"
53 -
  middlewares: "kube-system-redirect-scheme@kubernetescrd"
54 -
  gethomepage_enabled: '"true"'
55 -
  gethomepage_group: "Default"
56 -
  gethomepage_pod_selector: "''"
57 -
  gethomepage_icon: "homepage"
58 -
``` 
59 -
60 -
Damit die Configmap genutzt wir muss noch die kustomization.yaml in clusters/prod/flux-system/ angepasst werden. 
61 -
62 -
```yaml
63 -
apiVersion: kustomize.config.k8s.io/v1beta1
64 -
kind: Kustomization
65 -
resources:
66 -
- gotk-components.yaml
67 -
- gotk-sync.yaml
68 -
- gitops-repos.yaml 
69 -
- global_vars.yaml
70 -
...
71 -
```
72 -
73 -
Jetzt müssen wir nur noch die einzelnen Applications anpassen. Sie liegen bei mir im GitOps Repository in /apps/<appname>/base/ingress.yaml 
74 -
75 -
```yaml
76 -
apiVersion: networking.k8s.io/v1
77 -
kind: Ingress
78 -
metadata:
79 -
  name: blog
80 -
  annotations:
81 -
    cert-manager.io/cluster-issuer: ${clusterissuer}
82 -
    traefik.ingress.kubernetes.io/router.middlewares: ${middlewares}
83 -
    gethomepage.dev/enabled: ${gethomepage_enabled}
84 -
    gethomepage.dev/group: ${gethomepage_group}
85 -
    gethomepage.dev/pod-selector: ${gethomepage_pod_selector}
86 -
spec:
87 -
  ingressClassName: traefik
88 -
  rules:
89 -
...
90 -
```
91 -
92 -
In der Kustomization der Application muss jetzt noch noch die global_vars.yaml in der App hinzugefügt werden. 
93 -
94 -
```yaml
95 -
apiVersion: kustomize.toolkit.fluxcd.io/v1
96 -
kind: Kustomization
97 -
metadata:
98 -
  name: blog
99 -
  namespace: flux-system
100 -
spec:
101 -
  interval: 2m
102 -
  prune: false
103 -
  path: ./apps/blog/prod
104 -
  sourceRef:
105 -
    kind: GitRepository
106 -
    name: flux-system
107 -
  targetNamespace: blog
108 -
  decryption:
109 -
    provider: sops
110 -
    secretRef:
111 -
      name: sops-age
112 -
  postBuild:
113 -
    substituteFrom:
114 -
      - kind: ConfigMap
115 -
        name: global-vars
116 -
    substitute:
117 -
      ingress_host: blog.kuepper.nrw
118 -
      tls_secret_name: blog.kuepper.nrw-tls
119 -
      middlewares: "kube-system-redirect-scheme@kubernetescrd,blog-redirect-blog-feed@kubernetescrd"
120 -
```
121 -
122 -
Die ConfigMap `global_vars` wird mit substituteFrom geladen und die Variabeln sind verfügbar. In diesem Fall wird die Middleware auch gleich überschrieben. Denn das Blog ein paar Redirects, die aktiviert werden müssen. 
123 -
124 -
Wenn jetzt alles ins Repo gepushed wird, werden nach kurzer Zeit die Annotations in dem Ingress auftauchen. Die Seite wird dann in GetHomepage angezeigt in der Gruppe Default. 
125 -
126 -
Möchte man jetzt ein paar Sachen Ändern oder erweitern geht man in die Kustomization der Application um sie anzupassen. 
127 -
128 -
Ich will beim Blog die Description, die URL für den link und das Icon anpassen.
129 -
130 -
```yaml
131 -
...
132 -
  patches:
133 -
    - patch: |-
134 -
        - op: add
135 -
          path: /metadata/annotations/gethomepage.dev~1description
136 -
          value: 'Blog Küpper'
137 -
        - op: add
138 -
          path: /metadata/annotations/gethomepage.dev~1href
139 -
          value: 'https://blog.kuepper.nrw'
140 -
        - op: add
141 -
          path: /metadata/annotations/gethomepage.dev~1icon
142 -
          value: 'mdi-web'
143 -
      target:
144 -
        kind: Ingress
145 -
        name: blog
146 -
  postBuild:
147 -
...
148 -
```
149 -
150 -
Möchte man die Group `Default` mit `Homepage` überschrieben fügt man einfach den entsprechenden Patch dazu:
151 -
152 -
```yaml
153 -
        - op: add
154 -
          path: /metadata/annotations/gethomepage.dev~1group
155 -
          value: 'Homepages'
156 -
```
157 -
158 -
Alles eingecheckt und FluxCD hat es ausgerollt, sieht der fertige Ingress im Cluster so aus:
159 -
160 -
```yaml
161 -
apiVersion: networking.k8s.io/v1
162 -
kind: Ingress
163 -
metadata:
164 -
  annotations:
165 -
    cert-manager.io/cluster-issuer: cf-letsencrypt-prod
166 -
    gethomepage.dev/description: Blog Küpper
167 -
    gethomepage.dev/enabled: "true"
168 -
    gethomepage.dev/group: Homepage
169 -
    gethomepage.dev/href: https://blog.kuepper.nrw
170 -
    gethomepage.dev/icon: mdi-web
171 -
    gethomepage.dev/pod-selector: ""
172 -
    traefik.ingress.kubernetes.io/router.middlewares: kube-system-redirect-scheme@kubernetescrd,blog-redirect-blog-feed@kubernetescrd
173 -
  labels:
174 -
...
175 -
```
176 -
177 -
Die Variabeln können auch auf mehrere Dateien aufgeteilt werden. Je nachdem wofür sie genutzt werden hat man sie dann auch suaber getrennt. Es ist auch möglich Variabeln die nichz alle User eines Repos sehen sollen aus einem anderen Repo zu laden. Als Beispiel wäre der ClusterIssuer, der nicht angepasst werden darf. Oder Daten die z.B. für einen SecretStore, DNS Api Token für external DNS oder den Certmanager. Die sollten zwar eh mit Age oder anderen Tools verschlüsselt sein, aber angenommen das wäre nicht der Fall, würde man sie einfach an einem anderen Ort ablegen. 
178 -
179 -
```yaml
180 -
apiVersion: source.toolkit.fluxcd.io/v1
181 -
kind: GitRepository
182 -
metadata:
183 -
  name: flux-vars-repo
184 -
  namespace: flux-system
185 -
spec:
186 -
  interval: 5m
187 -
  url: ssh://git@github.com/username/gitops-vars
188 -
  ref:
189 -
    branch: main
190 -
  secretRef:
191 -
    name: gitops-testapps-auth
192 -
```
193 -
194 -
Das ganze muss natürlich noch genutzt werden: 
195 -
196 -
```yaml
197 -
apiVersion: kustomize.toolkit.fluxcd.io/v1
198 -
kind: Kustomization
199 -
metadata:
200 -
  name: flux-vars
201 -
  namespace: flux-system
202 -
spec:
203 -
  interval: 10m
204 -
  sourceRef:
205 -
    kind: GitRepository
206 -
    name: flux-vars-repo
207 -
  path: ./production
208 -
  prune: true
209 -
```
210 -
211 -
```yaml
212 -
apiVersion: kustomize.toolkit.fluxcd.io/v1
213 -
kind: Kustomization
214 -
metadata:
215 -
  name: globalVars
216 -
  namespace: flux-system
217 -
spec:
218 -
  interval: 10m
219 -
  prune: true
220 -
  path: ./vars
221 -
  sourceRef:
222 -
    kind: GitRepository
223 -
    name: flux-vars-repo
224 -
  targetNamespace: flux-system
225 -
```
226 -
227 -
In dem repo `github.com/username/gitops-vars` legt man den Ordner `vars` an und legt dort einfach eine kustomization.yaml an mit folgendem Inhalt: 
228 -
229 -
```yaml
230 -
apiVersion: kustomize.config.k8s.io/v1beta1
231 -
kind: Kustomization
232 -
233 -
resources:
234 -
  - global_vars.yaml
235 -
236 -
namespace: flux-system
237 -
```
238 -
239 -
Die `global_vars.yaml` kopiert man jetzt ins neue Repo unter `vars/global_vars.yaml` und checkt alles ein. 
240 -
241 -
FluxCD fügt nach dem Reconcil das Git Repo hinzu, legt entsprechend alles auf dem Cluster an und die Variabeln kommen aus einem externem Repo. Im Grunde das gleiche wie auch alle anderen Sachen in FluxCD von externen Git Repos genutzt werden können. Das ist ja das schöne an FluxCD. Man kann den Code so anpassen wie man es benötigt. Gerade wenn man immer die gleichen Teile auf mehreren Clustern oder Umgebungen wieder verwendet ist eine Trennung diese Teile sinnvoll. Man muss sie nur einmal anfassen und sie werden auf allen Clustern angewendet. 
242 -
Oder wenn man Infrastruktur, Tools von anderen Sachen trennen möchte. Wenn z.B. Entwickler Ihre Sachen selbst machen sollen, dann haben sie für Ihr Zeug ein eigenes Repo und können dort alles machen was sie wollen. 
gelöscht content/2025-10-18-der-ultimative-guide-zum-caffeinate-befehl-auf-dem-mac.md
+0 −240
@@ -1,240 +0,0 @@
1 -
---
2 -
title: 'Der ultimative Guide zum caffeinate-Befehl auf dem Mac'
3 -
date: 2025-10-18 20:00:00
4 -
update: 2025-10-18 20:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/10/der-ultimative-guide-zum-caffeinate-befehl-auf-dem-mac.webp"
7 -
# images: 
8 -
#   - /images/posts/2025/08/telekom-mail-fail.webp
9 -
featureImage: /images/posts/2025/10/der-ultimative-guide-zum-caffeinate-befehl-auf-dem-mac.webp
10 -
tags: [Mac, caffeinate]
11 -
categories: 
12 -
  - Mac
13 -
preview: "Du lädst gerade eine große Datei herunter, renderst ein Video oder führst ein wichtiges Backup durch – und plötzlich: Der Mac geht in den Schlafmodus. Der Download bricht ab, das Rendering stoppt, und du musst von vorne beginnen. Frustrierend, oder?"
14 -
draft: false
15 -
top: false
16 -
type: post
17 -
hide: false
18 -
toc: false
19 -
---
20 -
21 -
# Schluss mit ungewolltem Schlafmodus: Der ultimative Guide zum caffeinate-Befehl auf dem Mac
22 -
23 -
## Die Situation kennt jeder Mac-Nutzer
24 -
25 -
Du lädst gerade eine große Datei herunter, renderst ein Video oder führst ein wichtiges Backup durch – und plötzlich: Der Mac geht in den Schlafmodus. Der Download bricht ab, das Rendering stoppt, und du musst von vorne beginnen. Frustrierend, oder?
26 -
27 -
Sicher, du könntest jedes Mal in die Systemeinstellungen gehen und die Energiesparoptionen anpassen. Aber mal ehrlich: Wer denkt daran, das danach wieder zurückzustellen? Und wer möchte ständig in den Einstellungen herumklicken?
28 -
29 -
Die Lösung liegt näher, als du denkst – und sie heißt **caffeinate**.
30 -
31 -
## Was ist caffeinate überhaupt?
32 -
33 -
Der Name ist Programm: caffeinate (vom englischen "to caffeinate" – mit Koffein versorgen) hält deinen Mac wach, als hättest du ihm einen doppelten Espresso spendiert. Es ist ein in macOS integriertes Kommandozeilentool, das seit OS X 10.8 Mountain Lion standardmäßig dabei ist.
34 -
35 -
Das Schöne daran: Du musst nichts installieren, keine zusätzliche Software kaufen oder komplizierte Konfigurationen vornehmen. caffeinate ist bereits da und wartet nur darauf, genutzt zu werden.
36 -
37 -
## Die Basics: So einfach geht's
38 -
39 -
### Der Schnellstart
40 -
41 -
Öffne das Terminal (zu finden über Spotlight mit ⌘ + Leertaste, dann "Terminal" eingeben) und tippe:
42 -
43 -
```bash
44 -
caffeinate
45 -
```
46 -
47 -
Das war's schon! Dein Mac bleibt nun wach, bis du:
48 -
- Das Terminal-Fenster schließt
49 -
- Den Befehl mit `Ctrl + C` beendest
50 -
- Den Mac neu startest
51 -
52 -
### Zeit ist Geld: Der Timer-Modus
53 -
54 -
Manchmal weißt du genau, wie lange dein Mac wach bleiben soll. Hier kommt der `-t` Parameter ins Spiel:
55 -
56 -
```bash
57 -
caffeinate -t 3600
58 -
```
59 -
60 -
Diese Zeile hält deinen Mac für genau 3600 Sekunden (= 1 Stunde) wach. Danach kehrt er automatisch zu den normalen Energiespareinstellungen zurück. Praktisch, nicht wahr?
61 -
62 -
Weitere Beispiele:
63 -
- 30 Minuten: `caffeinate -t 1800`
64 -
- 2 Stunden: `caffeinate -t 7200`
65 -
- 8 Stunden (eine Arbeitstag): `caffeinate -t 28800`
66 -
67 -
## Die Profi-Optionen: Was caffeinate noch kann
68 -
69 -
### Die verschiedenen Modi
70 -
71 -
caffeinate bietet verschiedene Flags, mit denen du genau steuern kannst, *wie* dein Mac wach bleibt:
72 -
73 -
**`-d` (Display)**: Verhindert, dass das Display schlafen geht
74 -
```bash
75 -
caffeinate -d
76 -
```
77 -
Perfekt für Präsentationen oder wenn du ein Tutorial-Video anschaust.
78 -
79 -
**`-i` (Idle)**: Verhindert den Idle-Sleep (System bleibt aktiv)
80 -
```bash
81 -
caffeinate -i
82 -
```
83 -
Ideal für Server-Anwendungen oder lange Berechnungen.
84 -
85 -
**`-m` (Disk)**: Verhindert, dass die Festplatte in den Ruhezustand geht
86 -
```bash
87 -
caffeinate -m
88 -
```
89 -
Nützlich bei kontinuierlichen Lese-/Schreibvorgängen.
90 -
91 -
**`-s` (System)**: Hält das System wach, auch wenn das Display aus ist
92 -
```bash
93 -
caffeinate -s
94 -
```
95 -
Gut für Downloads über Nacht.
96 -
97 -
**`-u` (User)**: Simuliert Benutzeraktivität
98 -
```bash
99 -
caffeinate -u -t 10
100 -
```
101 -
Dieser spezielle Modus simuliert für 10 Sekunden Benutzeraktivität und kann helfen, wenn andere Modi nicht greifen.
102 -
103 -
### Kombinationen für maximale Kontrolle
104 -
105 -
Du kannst mehrere Flags kombinieren:
106 -
107 -
```bash
108 -
caffeinate -dims -t 3600
109 -
```
110 -
Dies hält Display, System und Festplatte für eine Stunde wach und verhindert den Idle-Sleep.
111 -
112 -
## Praktische Anwendungsfälle
113 -
114 -
### 1. Downloads über Nacht
115 -
116 -
```bash
117 -
caffeinate -s curl -O https://example.com/grossedatei.zip
118 -
```
119 -
caffeinate läuft hier nur so lange, wie der Download dauert.
120 -
121 -
### 2. Backup-Prozesse
122 -
123 -
```bash
124 -
caffeinate -i rsync -av /Quelle/ /Ziel/
125 -
```
126 -
Stellt sicher, dass dein Backup vollständig durchläuft.
127 -
128 -
### 3. Video-Rendering
129 -
130 -
```bash
131 -
caffeinate -di ffmpeg -i input.mov output.mp4
132 -
```
133 -
Hält Display und System während der Videokonvertierung wach.
134 -
135 -
### 4. Präsentationsmodus
136 -
137 -
```bash
138 -
caffeinate -d -t 5400
139 -
```
140 -
90 Minuten lang bleibt das Display an – perfekt für längere Meetings.
141 -
142 -
### 5. Software-Updates
143 -
144 -
```bash
145 -
caffeinate -i softwareupdate -ia
146 -
```
147 -
Installiert alle verfügbaren Updates, ohne dass der Mac zwischendurch einschläft.
148 -
149 -
## Pro-Tipps für Power-User
150 -
151 -
### Tipp 1: Alias erstellen
152 -
153 -
Füge diese Zeilen zu deiner `~/.zshrc` oder `~/.bash_profile` hinzu:
154 -
155 -
```bash
156 -
alias awake="caffeinate -d"
157 -
alias awake1h="caffeinate -d -t 3600"
158 -
alias awake2h="caffeinate -d -t 7200"
159 -
```
160 -
161 -
Nun kannst du einfach `awake1h` tippen für eine Stunde Wachzeit.
162 -
163 -
### Tipp 2: Mit Assertion-Namen arbeiten
164 -
165 -
Du kannst deinen caffeinate-Sessions Namen geben:
166 -
167 -
```bash
168 -
caffeinate -i -w $$ &
169 -
```
170 -
171 -
Dies erstellt eine Assertion, die mit deiner aktuellen Shell-Session verknüpft ist.
172 -
173 -
### Tipp 3: Status überprüfen
174 -
175 -
Willst du wissen, welche Prozesse deinen Mac wach halten?
176 -
177 -
```bash
178 -
pmset -g assertions
179 -
```
180 -
181 -
Dieser Befehl zeigt dir alle aktiven "Wachhalter" an.
182 -
183 -
### Tipp 4: caffeinate im Hintergrund
184 -
185 -
```bash
186 -
caffeinate -i &
187 -
```
188 -
189 -
Das `&` am Ende lässt caffeinate im Hintergrund laufen. Du kannst das Terminal weiter nutzen. Mit `fg` holst du es wieder in den Vordergrund, um es mit Ctrl+C zu beenden.
190 -
191 -
### Tipp 5: Integration in Skripte
192 -
193 -
```bash
194 -
#!/bin/bash
195 -
# Mein Backup-Skript
196 -
197 -
caffeinate -i bash << 'EOF'
198 -
    echo "Backup startet..."
199 -
    rsync -av ~/Documents/ /Volumes/Backup/Documents/
200 -
    echo "Backup abgeschlossen!"
201 -
EOF
202 -
```
203 -
204 -
## Troubleshooting: Wenn's mal nicht klappt
205 -
206 -
**Problem**: caffeinate scheint nicht zu funktionieren
207 -
- **Lösung**: Überprüfe mit `pmset -g` deine Energieeinstellungen. Manche Unternehmens-Policies können caffeinate überschreiben.
208 -
209 -
**Problem**: Terminal schließt sich versehentlich
210 -
- **Lösung**: Nutze `nohup caffeinate &` um caffeinate auch nach dem Schließen des Terminals weiterlaufen zu lassen.
211 -
212 -
**Problem**: Unsicher, ob caffeinate läuft
213 -
- **Lösung**: `pgrep caffeinate` zeigt dir die Prozess-ID, wenn caffeinate aktiv ist.
214 -
215 -
## Alternativen zu caffeinate
216 -
217 -
Falls du eine GUI bevorzugst, gibt es auch Apps:
218 -
- **Amphetamine** (kostenlos im App Store)
219 -
- **Caffeine** (klassische Menubar-App)
220 -
- **KeepingYouAwake** (Open Source Alternative)
221 -
222 -
Aber ehrlich: Warum eine zusätzliche App installieren, wenn caffeinate schon da ist?
223 -
224 -
## Fazit: Ein unterschätztes Power-Tool
225 -
226 -
caffeinate ist eines dieser Tools, von dem viele Mac-Nutzer nie erfahren – dabei kann es den Arbeitsalltag erheblich erleichtern. Keine abgebrochenen Downloads mehr, keine unterbrochenen Backups, keine schwarzen Bildschirme während wichtiger Präsentationen.
227 -
228 -
Das Beste daran: Es ist bereits auf deinem Mac installiert, komplett kostenlos und unglaublich einfach zu bedienen. Ein simples `caffeinate` im Terminal, und schon bleibt dein Mac so lange wach, wie du es brauchst.
229 -
230 -
Also, das nächste Mal, wenn du deinen Mac für eine wichtige Aufgabe wach halten musst, denk an caffeinate. Dein digitaler Espresso wartet schon im Terminal auf dich.
231 -
232 -
---
233 -
234 -
**Bonus-Einzeiler für die Kommandozeile:**
235 -
236 -
```bash
237 -
echo "☕ Mac stays awake!" && caffeinate -d -t 3600 && echo "💤 Back to sleep mode!"
238 -
```
239 -
240 -
Happy Caffeinating! ☕🖥️
gelöscht content/2025-10-23-k3s-system-upgrade-controller-fail-restore-in-5-minuten-mit-fluxcd.md
+0 −41
@@ -1,41 +0,0 @@
1 -
---
2 -
title: 'k3s System-Upgrade-Controller Fail, Restore in 5 Minuten mit FluxCD'
3 -
date: 2025-10-23 15:00:00
4 -
update: 2025-10-23 15:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/10/k3s-fluxcd-k3s.webp"
7 -
# images: 
8 -
#   - /images/posts/2025/08/telekom-mail-fail.webp
9 -
featureImage: /images/posts/2025/10/k3s-fluxcd-k3s.webp
10 -
tags: [Kubernetes, k3s, fluxcd, Recovery, GitOps]
11 -
categories: 
12 -
  - Kubernetes
13 -
preview: "Wenn der k3s System Upgrade Controller eine Recovery-Übung erzwingt: So wie vorletzte Woche, als ich eigentlich einfach nur ein Upgrade von k3s auf die aktuellste Version machen wollte. Nur ist das irgendwie etwas schiefgelaufen. Alle Services liefen noch, die Container waren alle noch da und alles war erreichbar. Das Einzige, was nicht gestartet ist, war k3s."
14 -
draft: false
15 -
top: false
16 -
type: post
17 -
hide: false
18 -
toc: false
19 -
---
20 -
21 -
22 -
Wenn der k3s System Upgrade Controller eine Recovery-Übung erzwingt: So wie vorletzte Woche, als ich eigentlich einfach nur ein Upgrade von k3s auf die aktuellste Version machen wollte.
23 -
Nur ist das irgendwie etwas schiefgelaufen. Alle Services liefen noch, die Container waren alle noch da und alles war erreichbar. Das Einzige, was nicht gestartet ist, war k3s.
24 -
25 -
Kurzes Checken der Logfiles zeigte, dass die Node-IPs nicht zu denen in der Cluster-Config passten. Es wurde versucht, mit der Loadbalancer-IP zu verbinden. Ändern in der Datenbank wollte irgendwie nicht funktionieren. Loadbalancer-IP kurz getrennt, sodass nur noch die Node-IP auf den einzelnen Nodes zu sehen war. Auch damit wollte k3s nicht starten.
26 -
27 -
Also den System-Upgrade-Controller einfach mal zurückrollen lassen. Was dann auch geklappt hat. Alles wieder ok, k3s wieder gestartet und nutzbar. Nur waren im Log noch ein paar Sachen, die etwas stutzig machten. Nichts Kritisches, aber es waren selbst noch diese Einträge zu sehen, nachdem ich eine der Applications, für die Fehler angezeigt wurden, auf 0 skaliert und sogar komplett entfernt hatte.
28 -
29 -
Der Cluster lief danach noch ein paar Tage ohne Probleme. Und da ich mit FluxCD jetzt alles in einem GitOps-GitHub-Repository habe, war eh schon länger geplant, auch meinen privaten Production-Kubernetes-Cluster neu aufzusetzen. Das ist mit den Clustern labor01, dev und stage schon mehrfach gemacht worden. Der Prod-Cluster war zwar schon die ganze Zeit mit im Repo und alle Komponenten migriert, aber der Teufel liegt ja immer im Detail. Habe ich wirklich an alles gedacht und ist wirklich alles im Git?
30 -
31 -
Außerdem: Was ist mit den Daten, die nicht auf dem NFS-Server liegen? Die Daten der Volumes liegen hauptsächlich auf NFS-Shares, außer dem vom Garage S3 Storage. Dafür habe ich dann auch gleich noch ein Backup- und Restore-Tool erstellt. Dazu die Tage noch mehr.
32 -
33 -
Nachdem alle Daten aus dem Garage auch noch gesichert wurden, war die Zeit für das Löschen des Kubernetes-Clusters gekommen. Gefolgt von Server Create plus Cloud-Init. Damit wurde alles wieder erstellt. Das Cloud-Init installiert dann alles, was benötigt wird: k3s, helm, k9s, FluxCD.
34 -
35 -
FluxCD wird dann per Bootstrap automatisch mit dem GitOps-Repo verbunden und installiert dann alle Ressourcen. Nach etwa 3-4 Minuten ist der Cluster wieder komplett gestartet und alles wieder installiert und aktiv. Während der Cert-Manager mit Cloudflare DNS API sich kurz noch um die Zertifikate gekümmert hat, habe ich mich kurz Garage gewidmet. Den Garage-INIT-Job getriggert, der kümmert sich darum, dass sich alle Garage-Nodes gegenseitig kennen. Anschließend das Restore für Garage ausgeführt und alle Buckets mit Daten und die Secrets waren wieder da.
36 -
37 -
Das Ganze war schon sehr gut und war genau so, wie es sein soll. Und ja, es gab 2-3 Kleinigkeiten, die waren noch nicht im Git. Die wurden dann auch gleich noch erledigt. So wird dann bei der nächsten Installation direkt alles fertig sein.
38 -
39 -
Ich kann auch den Cluster aufsetzen, aber beim ersten Start werden die Zertifikate noch gar nicht generiert. So kann ich erst einmal alles prüfen und ein paar Tests machen. Wenn alles ok ist, wird der Cert-Manager aktiv geschaltet und das Loadbalancer-Target auf den neuen geändert. So ist der Cluster innerhalb ein paar Sekunden ausgetauscht.
40 -
41 -
Dass der System-Upgrade-Controller fehlgeschlagen ist, war ärgerlich, aber das war auch irgendwie gut so. Eine Recovery war schon länger geplant, da es bei Test-Clustern im HomeLab und auch für die anderen Stages immer gut lief. Es sind immer ein paar Sachen aufgefallen und behoben worden. Da habe ich aber auch eine Neuinstallation einfach mal so zwischendurch gemacht. Beim Production-Cluster war immer etwas Respekt davor. Aber jetzt musste es einfach gemacht werden. Es lief zwar alles, aber es waren Fehler zu sehen, bei denen ich nicht wusste, woher sie kommen und wieso. Was macht das sonst noch im Hintergrund – könnte es irgendwann doch den ganzen Cluster einfach zerreißen und alles wäre offline?
\ No newline at end of file
gelöscht content/2025-11-01-vm-tracker-automatische-registration-und-monitoring-system.md
+0 −134
@@ -1,134 +0,0 @@
1 -
---
2 -
title: 'VM-Tracker - Automatische Registration and Monitoring-System'
3 -
date: 2025-11-01 05:00:00
4 -
update: 2025-11-10 05:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/11/vm-tracker.webp"
7 -
# images: 
8 -
#   - /images/posts/2025/08/telekom-mail-fail.webp
9 -
featureImage: /images/posts/2025/11/vm-tracker.webp
10 -
tags: [Qemu, VM, Overview]
11 -
categories: 
12 -
  - Internet
13 -
preview: ""
14 -
draft: false
15 -
top: false
16 -
type: post
17 -
hide: false
18 -
toc: false
19 -
---
20 -
21 -
# :satellite: VM-Tracker - das GetHomepage für Server und VMs :sunglasses:
22 -
23 -
## VM-Manager - VM mit Cloud-Init Templates erstellen 
24 -
25 -
Um Qemu-VMs schnell aufsetzen zu können habe ich ein Tool geschrieben mit dem ich schnell neue Server für verschiedene Zwecke erstellen kann. Da ich für Kubernetes, GitHub Runner, Nginx Webserver und andere Server in dem Tool Templates habe sind neue Server schnell aufgesetzt. Die Templates können erweitert werden oder neue erstellt werden. 
26 -
27 -
Wenn Server erstellt werden wird immer eine Serielle-Console erstellt und über ein Webinterface erreichbar gemacht. Das ist natürlich nur intern erreichbar und wenn ich von unterwegs einen Server starte weiß ich die IP erst einmal nicht. Ich kann natürlich über VPN zugreifen, aber manchmal will man einfach etwas starten und dann einfach drauf zugreifen oder wenn es extern erreichbar sein soll, einfach die IP per Port-Forward freigeben. 
28 -
29 -
Der VM-Manger wird demnächst Online gestellt und kann dann von jedem genutzt werden. 
30 -
31 -
## VM-Tracker für bessere Rechner, Server und VM Übersicht :monocle_face:
32 -
33 -
Damit ich sehe welche VMs aktuell auf den Rechnern hier gestartet sind habe ich ein Tool geschrieben das:
34 -
35 -
  * Einfach das default Netzwerkinterface sucht, 
36 -
  * Die IP-Adresse ausliest 
37 -
  * Und dann mit dem Hostname an eine API sendet. 
38 -
39 -
Die API merkt sich alle Server die sich melden. Ein Healthcheck-Tracker prüft die Meldungen alle 30 Sekunden und meldet sich ein Server 60 Sekunden nicht wird er als Offline angezeigt. Die Server können auch aus der List gelöscht werden. Offline Server verschwinden komplett, sie melden sich ja nicht mehr. Server die Online sind melden sich ja regelmässig und werden nach kurzer Zeit wieder auftauchen. 
40 -
41 -
Das Webinterface zeigt alle Server in einer schönen Übersicht an: 
42 -
43 -
![VM-Tracker Overview](/images/posts/2025/11/vm-tracker-overview.webp)
44 -
45 -
## Installation 
46 -
47 -
Update: Links zu den Installationsanleitungen sind in diesem [Blogpost](/posts/2025-11-06-vm-tracker-client-und-api-server-jetzt-self-hosted/)
48 -
49 -
Den VM-Tracker-Client kann man einfach auf den Server kopieren und ausführen. Die Binaries sind für verschiedene Betriebsysteme und Architekturen verfügbar:
50 -
51 -
+ vm-tracker-client-386
52 -
+ vm-tracker-client-amd64
53 -
+ vm-tracker-client-arm64
54 -
+ vm-tracker-client-armv6
55 -
+ vm-tracker-client-armv7
56 -
+ vm-tracker-client-darwin
57 -
+ vm-tracker-client-darwin-amd64
58 -
+ vm-tracker-client-darwin-arm64
59 -
+ vm-tracker-client-freebsd-amd64
60 -
+ vm-tracker-client-windows-386.exe
61 -
+ vm-tracker-client-windows-amd64.exe
62 -
63 -
VM-Tracker Client Ausgeführt:
64 -
65 -
```bash
66 -
./vm-tracker-client-darwin-arm64 -api https://vm-tracker.kuepper.nrw -interface en0 -interval 30
67 -
2025/11/01 09:58:48 VM Tracker Client starting...
68 -
2025/11/01 09:58:48 API Server: https://vm-tracker.kuepper.nrw
69 -
2025/11/01 09:58:48 Interface: en0
70 -
2025/11/01 09:58:48 Update interval: 30s
71 -
2025/11/01 09:58:48 Successfully registered with API server (hostname: mbair-rk.local, IP: 10.0.2.206)
72 -
```
73 -
74 -
Das Interface automatisch setzen lassen:
75 -
76 -
MacOS: 
77 -
```bash
78 -
INTERFACE=$(route get 1.1.1.1 | awk '/interface:/ {print $2; exit}')
79 -
80 -
./vm-tracker-client-darwin-arm64 -api https://vm-tracker.kuepper.nrw -interface ${INTERFACE} -interval 30
81 -
```
82 -
83 -
Linux: 
84 -
```bash
85 -
INTERFACE=$(route get 1.1.1.1 | awk '/dev/ {print $5; exit}')
86 -
87 -
./vm-tracker-client-darwin-arm64 -api https://vm-tracker.kuepper.nrw -interface ${INTERFACE} -interval 30
88 -
```
89 -
90 -
Damit man aber nicht alles manuell kopieren und ausführen muss gibt es auch ein Script für die Installation.
91 -
Die Installation kann dann einfach schnell per SSH ausgeführt werden oder so wie bei mir in den Templates von meinem VM-Tool eingefügt werden. 
92 -
93 -
Manuell ausführen:
94 -
```bash
95 -
wget -O- https://vm-tracker.kuepper.nrw/download/install-tracker.sh | bash
96 -
```
97 -
98 -
Automatisiert in Cloud-Init:
99 -
100 -
```yaml { title = "cloudinit-templates/nginx/user-data/user-data.yaml" }
101 -
...
102 -
runcmd:
103 -
  - wget -O- https://vm-tracker.kuepper.nrw/download/install-tracker.sh | bash
104 -
  - systemctl enable qemu-guest-agent
105 -
  - systemctl start qemu-guest-agent
106 -
  - echo "Cloud-init Konfiguration abgeschlossen" > /var/log/cloudinit-done.log
107 -
...
108 -
```
109 -
110 -
Damit wird der VM-Tracker Client automatisch installiert. Es wird das Binary für die richtige Zielarchitektur heruntergeladen und an die richtige Stelle kopiert. 
111 -
Zusätzlich wird ein Systemd Service angelegt, aktiviert und gestartet. 
112 -
113 -
> Hinweis: Das Installationsscript funktinoiert aktuell nur auf Linus Systemen. MacOS und Windows müssen noch integriert werden. 
114 -
115 -
So bald auch MacOS hinzugefügt ist und weitere Änderungen gemacht sind wird der VM-Tracker auch Public gestellt. 
116 -
Das ist dann aber auch nicht nur der Client, auch die API mit dem Webinterface wird verfügbar sein. 
117 -
Dann kann jeder seinen eigenen Tracker betreiben und so schnell einen Überblick über seine Infrastruktur erhalten, Probleme mit Servern oder VMs sehen. 
118 -
119 -
## VM-Manager und Vm-Tracker in Aktion
120 -
121 -
Es sind zwei Webserver vorhanden, web001 und web002. Jetzt werden 2 weitere benötigt. 
122 -
Die Konfiguration dafür ist schon vorbereitet und die VMs können erstellt werden. Nach dem Start wird dann mit Cloud-Init komplett konfiguriert und auch der VM-Tracker gestartet. So sieht man dann auch nach kurzer Zeit die neuen Server in der Übersicht des VM-Trackers. 
123 -
124 -
125 -
{{< video "/images/posts/2025/11/vm-tracker.mp4" "my-5" >}}
126 -
127 -
{{< rawhtml >}} 
128 -
129 -
<video width=100% controls>
130 -
    <source src="/videos/vm-tracker.mp4"type="video/mp4">
131 -
    Your browser does not support the video tag.  
132 -
</video>
133 -
134 -
{{< /rawhtml >}}
\ No newline at end of file
gelöscht content/2025-11-06-vm-tracker-client-und-api-server-jetzt-self-hosted.md
+0 −144
@@ -1,144 +0,0 @@
1 -
---
2 -
title: 'VM-Tracker - Client und API-server jetzt Self-Hosted'
3 -
date: 2025-11-06 12:00:00
4 -
update: 2025-11-06 12:00:00
5 -
author: ruediger
6 -
cover: "/images/posts/2025/11/vm-tracker.webp"
7 -
# images: 
8 -
#   - /images/posts/2025/08/telekom-mail-fail.webp
9 -
featureImage: /images/posts/2025/11/vm-tracker.webp
10 -
tags: [Qemu, VM, Overview, Self-Hosted]
11 -
categories: 
12 -
  - Internet
13 -
preview: "Jetzt ist alles online und kann installiert werden. So das jeder den VM-Tracker selbst betreiben kann und die eigenen RaspberryPi, VMs, Dedicated-Server, NAS-Systeme oder Shellys Tracken kann."
14 -
draft: false
15 -
top: false
16 -
type: post
17 -
hide: false
18 -
toc: false
19 -
---
20 -
21 -
# :satellite: VM-Tracker - Downloads für Self-Hosted Installationen verfügbar :sunglasses:
22 -
23 -
Im [letzten Post](/posts/2025-11-01-vm-tracker-automatische-registration-und-monitoring-system/) hatte ich den VM-Tracker schon einmal vorgestellt und in den letzten Tagen noch selbst einiges getestet. 
24 -
25 -
Jetzt ist alles online und kann installiert werden. So das jeder den VM-Tracker selbst betreiben kann und die eigenen RaspberryPi, VMs, Dedicated-Server, NAS-Systeme oder Shellys Tracken kann. 
26 -
27 -
Ja, auch Shellys können sich registrieren und so Überwacht werden. 
28 -
Gehe zu Settings → Scripts → Add Script und erstelle:
29 -
30 -
*Den Domainnamen noch anpassen!*
31 -
32 -
```javascript
33 -
function registerDevice() {
34 -
  // Device Info abrufen
35 -
  Shelly.call("Shelly.GetDeviceInfo", {}, function(deviceInfo) {
36 -
    let hostname = deviceInfo.id || "unknown-shelly";  // z.B. "shellyplus1pm-a1b2c3d4"
37 -
    
38 -
    Shelly.call("Shelly.GetStatus", {}, function(result) {
39 -
      let ip_address = null;
40 -
      let interface_name = null;
41 -
      
42 -
      if (result.eth && result.eth.ip) {
43 -
        ip_address = result.eth.ip;
44 -
        interface_name = "eth0";
45 -
      } else if (result.wifi && result.wifi.sta_ip) {
46 -
        ip_address = result.wifi.sta_ip;
47 -
        interface_name = "wlan0";
48 -
      }
49 -
      
50 -
      if (!ip_address) {
51 -
        print("Keine IP gefunden!");
52 -
        return;
53 -
      }
54 -
      
55 -
      Shelly.call(
56 -
        "HTTP.POST",
57 -
        {
58 -
          url: "https://vm-tracker.example.com/api/register",
59 -
          content_type: "application/json",
60 -
          body: JSON.stringify({
61 -
            hostname: hostname,
62 -
            ip_address: ip_address,
63 -
            interface: interface_name
64 -
          })
65 -
        },
66 -
        function(result, error_code, error_message) {
67 -
          if (error_code === 0) {
68 -
            print("✓ Registriert: ", hostname, " - ", ip_address);
69 -
          } else {
70 -
            print("✗ Fehler: ", error_message);
71 -
          }
72 -
        }
73 -
      );
74 -
    });
75 -
  });
76 -
}
77 -
78 -
// Bei Netzwerk-Verbindung ausführen
79 -
Shelly.addEventHandler(function(event) {
80 -
  if (event.component === "wifi" && event.info.status === "got ip") {
81 -
    print("WiFi verbunden, registriere...");
82 -
    Timer.set(2000, false, registerDevice);  // 2s Verzögerung
83 -
  }
84 -
  if (event.component === "eth" && event.info.status === "up") {
85 -
    print("Ethernet verbunden, registriere...");
86 -
    Timer.set(2000, false, registerDevice);
87 -
  }
88 -
});
89 -
90 -
// Zusätzlich alle 10 Minuten
91 -
Timer.set(30000, true, registerDevice);
92 -
```
93 -
94 -
Das Script kann man einfach auf jeden Shelly erstellen und sie melden sich dann einfach an. 
95 -
96 -
![VM-Tracker registrierter Shelly](/images/posts/2025/11/vm-tracker-shelly.webp)
97 -
98 -
# VM-Tracker Server installieren. 
99 -
100 -
Damit man selbst einen Endpunkt für die Clients, unter einer eigenen Domain hat, kann der API-Server jetzt auch Self-Hosted betrieben werden. 
101 -
102 -
Anleitungen gibt es für: 
103 -
104 -
* [Binary Installation](https://vm-tracker.kuepper.nrw/docs/de/api/installation_binary/)
105 -
* [Docker](https://vm-tracker.kuepper.nrw/docs/de/api/installation_docker/)
106 -
* [Kubernetes](https://vm-tracker.kuepper.nrw/docs/de/api/installation_kubernetes/)
107 -
* [Helm](https://vm-tracker.kuepper.nrw/docs/de/api/installation_helm/)
108 -
* [Kustomization](https://vm-tracker.kuepper.nrw/docs/de/api/installation_kustomization/)
109 -
* [FluxCD Kustomization](https://vm-tracker.kuepper.nrw/docs/de/api/installation_fluxcd_kustomization/)
110 -
* [FluxCD Helm Release](https://vm-tracker.kuepper.nrw/docs/de/api/installation_fluxcd_helm_release/)
111 -
112 -
Bei allen Installationen kann man diese ENV-Variabeln setzen:
113 -
114 -
* API_BASE_URL=https://vm-tracker.example.com
115 -
* BASE_URL=https://vm-tracker.example.com
116 -
117 -
Diese werden benutzt für z.B. Ingress, um die API über die Domain erreichbar zu machen. Ausserdem wird damit das Installations-Skript erstellt, damit die Clients sich mit der richtigen API verbinden. 
118 -
Dadurch kann der Client schnell und unkompliziert auf allen Sytemen installiert werden. 
119 -
120 -
# VM-Tracker Client installieren. 
121 -
122 -
Welche Möglichkeiten bei der Client Installation zur Verfügung stehen ist hier beschrieben:
123 -
124 -
* [Binary](https://vm-tracker.kuepper.nrw/docs/de/client/installation_binary/)
125 -
* [Skript](https://vm-tracker.kuepper.nrw/docs/de/client/installation_script/)
126 -
* [Systemd](https://vm-tracker.kuepper.nrw/docs/de/client/installation_systemd/)
127 -
* [Cloud-Init](https://vm-tracker.kuepper.nrw/docs/de/client/installation_cloud_init/)
128 -
* [Shelly Script](https://vm-tracker.kuepper.nrw/docs/de/client/installation_shelly/)
129 -
130 -
Die komplette Dokumentation in deutsch ist [hier](https://vm-tracker.kuepper.nrw/docs/de/) und die englische [hier](https://vm-tracker.kuepper.nrw/docs/en/).
131 -
132 -
133 -
## VM-Manager und Vm-Tracker in Aktion
134 -
135 -
{{< video "/images/posts/2025/11/vm-tracker.mp4" "my-5" >}}
136 -
137 -
{{< rawhtml >}} 
138 -
139 -
<video width=100% controls>
140 -
    <source src="/videos/vm-tracker.mp4"type="video/mp4">
141 -
    Your browser does not support the video tag.  
142 -
</video>
143 -
144 -
{{< /rawhtml >}}
\ No newline at end of file
gelöscht static/images/avatar.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/avatar.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/essen.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/essen.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/essen_old.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/essen_old.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/internet-bak.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/internet-bak.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/internet.jp2
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/internet.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/internet.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/musik.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/musik.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/musik_old.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/musik_old.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/organisation.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/organisation.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/security.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/security.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/technik-bak.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/technik-bak.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/technik.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/technik.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/technik2.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/cat/technik2.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/example-en.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/example-en.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/example.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/example.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-24-23.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-24-23.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-24-34.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-24-34.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-24-53.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-24-53.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-01.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-01.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-38.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-38.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-50.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-50.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-57.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-25-57.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-26-55.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-26-55.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-29-31.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-29-31.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-29-44.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-29-44.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-31-23.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-31-23.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-31-50.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-31-50.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-32-01.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-32-01.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-32-09.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-32-09.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-32-35.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-32-35.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-33-40.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/screen-19-33-40.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-24-23.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-24-23.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-24-34.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-24-34.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-24-53.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-24-53.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-25-01.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-25-01.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-25-38.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-25-38.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-25-50.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-25-50.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-25-57.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-25-57.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-26-55.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-26-55.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-29-31.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-29-31.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-29-44.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-29-44.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-31-23.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-31-23.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-31-50.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-31-50.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-32-01.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-32-01.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-32-09.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-32-09.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-32-35.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-32-35.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-33-40.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Octagon-SF4008-Receiver/thumbs/screen-19-33-40.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/DSC04881.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/DSC04881.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/FullSizeRender-1.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/FullSizeRender-1.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/FullSizeRender.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/FullSizeRender.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/thumbs/DSC04881.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/thumbs/DSC04881.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/thumbs/FullSizeRender-1.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/thumbs/FullSizeRender-1.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/thumbs/FullSizeRender.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/08/Taddl-Volker/thumbs/FullSizeRender.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/DSC04881.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/DSC04881.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/FullSizeRender-1.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/FullSizeRender-1.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/FullSizeRender.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/FullSizeRender.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/thumbs/DSC04881.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/thumbs/DSC04881.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/thumbs/FullSizeRender-1.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/thumbs/FullSizeRender-1.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/thumbs/FullSizeRender.jpg
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2019/thumbs/FullSizeRender.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2021/10/safari-nervige-cookiebanner-automatisch-schliessen/01-super-agent-dashboard.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2021/10/safari-nervige-cookiebanner-automatisch-schliessen/01-super-agent-dashboard.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2021/10/safari-nervige-cookiebanner-automatisch-schliessen/02-super-agent-cookie-settings.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2021/10/safari-nervige-cookiebanner-automatisch-schliessen/02-super-agent-cookie-settings.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2021/10/safari-nervige-cookiebanner-automatisch-schliessen/thumbs/01-super-agent-dashboard.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2021/10/safari-nervige-cookiebanner-automatisch-schliessen/thumbs/01-super-agent-dashboard.webp
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2021/10/safari-nervige-cookiebanner-automatisch-schliessen/thumbs/02-super-agent-cookie-settings.png
+0 −0

Binärdatei – kein Textvergleich möglich.

gelöscht static/images/galleries/2021/10/safari-nervige-cookiebanner-automatisch-schliessen/thumbs/02-super-agent-cookie-settings.webp
+0 −0

Binärdatei – kein Textvergleich möglich.