# Philipp Lehmann

Infrastructure engineer in Bochum, Germany. CTO at Nerd Force1 UG (AI-Gruppe) and IT-Security student at Ruhr-Universität Bochum. I write about container platforms, distributed storage, and automating everything that shouldn't be done twice.

This is one page of public article previews, not the complete archive. Follow Next page to continue. Summaries are not the original full articles.

## Running a Self-Hosted Tailscale Control Server Behind a Reverse Proxy

DevFeed: [Running a Self-Hosted Tailscale Control Server Behind a Reverse Proxy](<https://devfeed.tech/articles/running-a-self-hosted-tailscale-control-server-behind-a-reverse-proxy-34104.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/headscale-behind-traefik-no-h2/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-09-15T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [tailscale](<https://devfeed.tech/topics/tailscale.md>), [proxy](<https://devfeed.tech/topics/proxy.md>), [traefik](<https://devfeed.tech/topics/traefik.md>), [TLS (Transport Layer Security)](<https://devfeed.tech/topics/tls.md>), [TLS handshake](<https://devfeed.tech/topics/tls-handshake.md>), [Self-hosted](<https://devfeed.tech/topics/self-hosted.md>), [Homelab](<https://devfeed.tech/topics/homelab.md>)

Tags: [dns](<https://devfeed.tech/tags/dns.md>), [docker](<https://devfeed.tech/tags/docker.md>), [h2](<https://devfeed.tech/tags/h2.md>), [homelab](<https://devfeed.tech/tags/homelab.md>), [networking](<https://devfeed.tech/tags/networking.md>), [proxy](<https://devfeed.tech/tags/proxy.md>), [reverse-proxy](<https://devfeed.tech/tags/reverse-proxy.md>), [security](<https://devfeed.tech/tags/security.md>), [self-hosted](<https://devfeed.tech/tags/self-hosted.md>), [tailscale](<https://devfeed.tech/tags/tailscale.md>), [tls](<https://devfeed.tech/tags/tls.md>), [tls-handshake](<https://devfeed.tech/tags/tls-handshake.md>), [traefik](<https://devfeed.tech/tags/traefik.md>)

### AI overview

This tutorial explains how to run a self-hosted Tailscale control server, Headscale, behind Traefik. It finds that the reverse proxy must use TLS with HTTP/1.1 only because Tailscale's noise handshake expects a full-duplex byte stream and can fail when ALPN negotiates HTTP/2.

### Source excerpt

Headscale behind Traefik: tls.options=no-h2@file with alpnProtocols http/1.1, because the Tailscale noise handshake breaks when ALPN negotiates h2.

## A Daily Digest of What Actually Got Merged, Built from MQTT and a Local LLM

DevFeed: [A Daily Digest of What Actually Got Merged, Built from MQTT and a Local LLM](<https://devfeed.tech/articles/a-daily-digest-of-what-actually-got-merged-built-from-mqtt-and-a-local-llm-34100.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/daily-pr-digest/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-09-14T07:00:00Z

Content type: article

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [pull-requests](<https://devfeed.tech/topics/pull-requests.md>), [MQTT](<https://devfeed.tech/topics/mqtt.md>), [Large Language Model](<https://devfeed.tech/topics/llm.md>), [SQLite](<https://devfeed.tech/topics/sqlite.md>)

Tags: [architecture](<https://devfeed.tech/tags/architecture.md>), [ci-cd](<https://devfeed.tech/tags/ci-cd.md>), [llm](<https://devfeed.tech/tags/llm.md>), [local-llm](<https://devfeed.tech/tags/local-llm.md>), [mqtt](<https://devfeed.tech/tags/mqtt.md>), [observability](<https://devfeed.tech/tags/observability.md>), [pull-requests](<https://devfeed.tech/tags/pull-requests.md>), [python](<https://devfeed.tech/tags/python.md>), [sqlite](<https://devfeed.tech/tags/sqlite.md>)

### AI overview

This article describes a daily digest that uses MQTT merge events, a SQLite subscriber, and a locally run LLM to summarize merged pull requests by repository without sending diffs to a cloud API.

### Source excerpt

paho-mqtt subscriber to SQLite plus a local LLM: a daily digest that summarises merged pull requests per repository from diff stats, no cloud API.

## nginx: The Map Variable That Fixes the URI in proxy\_pass

DevFeed: [nginx: The Map Variable That Fixes the URI in proxy\_pass](<https://devfeed.tech/articles/nginx-the-map-variable-that-fixes-the-uri-in-proxy-pass-34110.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/nginx-map-uri-cache-policy/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-09-14T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [nginx](<https://devfeed.tech/topics/nginx.md>), [proxy](<https://devfeed.tech/topics/proxy.md>), [Caching](<https://devfeed.tech/topics/caching.md>), [configuration](<https://devfeed.tech/topics/configuration.md>)

Tags: [cache-control](<https://devfeed.tech/tags/cache-control.md>), [ci-cd](<https://devfeed.tech/tags/ci-cd.md>), [configuration](<https://devfeed.tech/tags/configuration.md>), [docker](<https://devfeed.tech/tags/docker.md>), [networking](<https://devfeed.tech/tags/networking.md>), [nginx](<https://devfeed.tech/tags/nginx.md>), [observability](<https://devfeed.tech/tags/observability.md>), [proxy](<https://devfeed.tech/tags/proxy.md>), [reverse-proxy](<https://devfeed.tech/tags/reverse-proxy.md>)

### AI overview

This article explains an nginx build failure caused by using a URI-bearing proxy_pass inside a regex location. A newer nginx version treated the previously accepted configuration as an error. The proposed fix uses a bare upstream in the regex location and a map on $uri to apply a path-specific Cache-Control policy.

### Source excerpt

nginx: [emerg] invalid URI prefix in proxy_pass: a regex location needs a bare upstream, and a map on $uri keeps a path-specific Cache-Control header.

## A Backward NTP Clock Step Delayed a Python Scheduler's Measurements by Nine Days

DevFeed: [A Backward NTP Clock Step Delayed a Python Scheduler's Measurements by Nine Days](<https://devfeed.tech/articles/the-ntp-clock-jump-that-made-the-scheduler-skip-a-week-of-measurements-34099.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/clock-jump-scheduler/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-09-14T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [Python](<https://devfeed.tech/topics/python.md>), [Linux](<https://devfeed.tech/topics/linux.md>), [systemd](<https://devfeed.tech/topics/systemd.md>), [Single Board Computer](<https://devfeed.tech/topics/single-board-computer.md>)

Tags: [embedded](<https://devfeed.tech/tags/embedded.md>), [linux](<https://devfeed.tech/tags/linux.md>), [ntp](<https://devfeed.tech/tags/ntp.md>), [python](<https://devfeed.tech/tags/python.md>), [reliability](<https://devfeed.tech/tags/reliability.md>), [scheduler](<https://devfeed.tech/tags/scheduler.md>), [single-board-computer](<https://devfeed.tech/tags/single-board-computer.md>), [systemd](<https://devfeed.tech/tags/systemd.md>), [time](<https://devfeed.tech/tags/time.md>), [wall-clock-time](<https://devfeed.tech/tags/wall-clock-time.md>)

### AI overview

A Python scheduler on an embedded Linux device silently stopped running after NTP corrected the system clock backward by about nine days. Because it used wall-clock time to measure elapsed time, the scheduler waited roughly nine days before running again. The article explains why a monotonic clock is the appropriate fix and mentions testing with an injected clock jump.

### Source excerpt

time.time() vs time.monotonic() in a Python scheduler: a backwards NTP step delayed runs by nine days. Monotonic durations and a jump-injecting test.

## fsGroupChangePolicy: OnRootMismatch and the setgid Invariant That Makes It Sound

DevFeed: [fsGroupChangePolicy: OnRootMismatch and the setgid Invariant That Makes It Sound](<https://devfeed.tech/articles/fsgroupchangepolicy-onrootmismatch-and-the-setgid-invariant-that-makes-it-sound-34103.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/fsgroup-change-policy-root-mismatch/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-09-11T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [container](<https://devfeed.tech/topics/container.md>), [mount](<https://devfeed.tech/topics/mount.md>), [Security](<https://devfeed.tech/topics/security.md>), [Process](<https://devfeed.tech/topics/process.md>)

Tags: [container](<https://devfeed.tech/tags/container.md>), [container-image](<https://devfeed.tech/tags/container-image.md>), [kubernetes](<https://devfeed.tech/tags/kubernetes.md>), [mount](<https://devfeed.tech/tags/mount.md>), [network](<https://devfeed.tech/tags/network.md>), [performance](<https://devfeed.tech/tags/performance.md>), [reliability](<https://devfeed.tech/tags/reliability.md>), [security](<https://devfeed.tech/tags/security.md>), [stateful](<https://devfeed.tech/tags/stateful.md>), [storage](<https://devfeed.tech/tags/storage.md>), [waiting](<https://devfeed.tech/tags/waiting.md>)

### AI overview

This article explains why a stateful pod can remain in ContainerCreating for fifteen minutes when fsGroup triggers a recursive chown across a large network-backed volume. It describes how fsGroupChangePolicy: OnRootMismatch can skip the recursive walk when the volume root group already matches, and discusses the setgid invariant that supports this behavior.

### Source excerpt

Pod stuck in ContainerCreating from fsGroup recursive chown: fsGroupChangePolicy: OnRootMismatch, and why the setgid bit on the volume root makes it safe.

## kube-proxy in iptables Mode and Native nftables Rules in the Forward Chain

DevFeed: [kube-proxy in iptables Mode and Native nftables Rules in the Forward Chain](<https://devfeed.tech/articles/kube-proxy-in-iptables-mode-and-native-nftables-rules-in-the-forward-chain-34106.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/kube-proxy-native-nftables/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-09-08T07:00:00Z

Content type: article

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [proxy](<https://devfeed.tech/topics/proxy.md>), [Kernel](<https://devfeed.tech/topics/kernel.md>), [Virtual Private Network](<https://devfeed.tech/topics/vpn.md>)

Tags: [firewall](<https://devfeed.tech/tags/firewall.md>), [handle](<https://devfeed.tech/tags/handle.md>), [ip](<https://devfeed.tech/tags/ip.md>), [kernel](<https://devfeed.tech/tags/kernel.md>), [kubernetes](<https://devfeed.tech/tags/kubernetes.md>), [linux](<https://devfeed.tech/tags/linux.md>), [networking](<https://devfeed.tech/tags/networking.md>), [proxy](<https://devfeed.tech/tags/proxy.md>), [reliability](<https://devfeed.tech/tags/reliability.md>), [vpn](<https://devfeed.tech/tags/vpn.md>)

### AI overview

The article explains how native nftables rules added by a WireGuard-based mesh agent to the FORWARD chain can cause kube-proxy in iptables mode to abort synchronization silently, leaving service endpoints stale. It describes removing the conflicting rules by handle.

### Source excerpt

kube-proxy iptables-nft sync silently aborts on native nftables rules a mesh agent adds to the FORWARD chain. Fix: nft delete rule by handle, ip and ip6.

## Self-Hosted Platform Build Order: Dependencies from Bare Metal to Model Serving

DevFeed: [Self-Hosted Platform Build Order: Dependencies from Bare Metal to Model Serving](<https://devfeed.tech/articles/the-whole-estate-in-one-article-how-every-layer-fits-together-34108.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/meta-infrastructure-overview/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-09-04T07:00:00Z

Content type: article

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [Self-hosted](<https://devfeed.tech/topics/self-hosted.md>), [Ansible](<https://devfeed.tech/topics/ansible.md>), [Kubernetes](<https://devfeed.tech/topics/kubernetes.md>), [ceph](<https://devfeed.tech/topics/ceph.md>), [observability](<https://devfeed.tech/topics/observability.md>), [model-serving](<https://devfeed.tech/topics/model-serving.md>), [Compose](<https://devfeed.tech/topics/compose.md>)

Tags: [ansible](<https://devfeed.tech/tags/ansible.md>), [architecture](<https://devfeed.tech/tags/architecture.md>), [article](<https://devfeed.tech/tags/article.md>), [ceph](<https://devfeed.tech/tags/ceph.md>), [compose](<https://devfeed.tech/tags/compose.md>), [infrastructure-as-code](<https://devfeed.tech/tags/infrastructure-as-code.md>), [kubernetes](<https://devfeed.tech/tags/kubernetes.md>), [model-serving](<https://devfeed.tech/tags/model-serving.md>), [observability](<https://devfeed.tech/tags/observability.md>), [self-hosted](<https://devfeed.tech/tags/self-hosted.md>)

### AI overview

This article explains the dependency order for building a self-hosted platform. It covers consistent bare-metal inventory, Ansible configuration convergence, networking, Kubernetes, Ceph storage, identity, observability, and model serving.

### Source excerpt

Self-hosted platform build order: why mesh, cluster, Ceph storage, identity and observability must precede model serving, shown with Compose depends_on.

## Documentation as a Repository: Publishing a Wiki.js Site from Reviewed Markdown

DevFeed: [Documentation as a Repository: Publishing a Wiki.js Site from Reviewed Markdown](<https://devfeed.tech/articles/documentation-as-a-repository-publishing-a-wiki-js-site-from-reviewed-markdown-34112.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/opentaberna/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-09-01T07:00:00Z

Content type: opinion

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [Documentation](<https://devfeed.tech/topics/documentation.md>), [Markdown](<https://devfeed.tech/topics/markdown.md>), [pull-requests](<https://devfeed.tech/topics/pull-requests.md>), [Git](<https://devfeed.tech/topics/git.md>), [Wiki](<https://devfeed.tech/topics/wiki.md>), [Open Source](<https://devfeed.tech/topics/open-source.md>)

Tags: [architecture](<https://devfeed.tech/tags/architecture.md>), [ci-cd](<https://devfeed.tech/tags/ci-cd.md>), [documentation](<https://devfeed.tech/tags/documentation.md>), [git](<https://devfeed.tech/tags/git.md>), [markdown](<https://devfeed.tech/tags/markdown.md>), [open-source](<https://devfeed.tech/tags/open-source.md>), [pull-request](<https://devfeed.tech/tags/pull-request.md>), [testing](<https://devfeed.tech/tags/testing.md>), [wiki](<https://devfeed.tech/tags/wiki.md>)

### AI overview

The article argues that keeping documentation as reviewed Markdown in a repository makes changes visible, reviewable, and enforceable alongside code changes. It presents OpenTaberna's Wiki.js documentation workflow as an example.

### Source excerpt

Wiki.js Git storage for docs as code: publish reviewed Markdown and fail a pull request when src/ changes without docs/, checked with git diff.

## Testing Infrastructure Code by Executing Its Real Expressions

DevFeed: [Testing Infrastructure Code by Executing Its Real Expressions](<https://devfeed.tech/articles/testing-infrastructure-code-by-executing-its-real-expressions-34115.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/testing-real-expressions/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-08-28T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [Ansible](<https://devfeed.tech/topics/ansible.md>), [Testing](<https://devfeed.tech/topics/testing.md>), [Pytest](<https://devfeed.tech/topics/pytest.md>), [Ansible Roles](<https://devfeed.tech/topics/ansible-role.md>)

Tags: [ansible](<https://devfeed.tech/tags/ansible.md>), [ci-cd](<https://devfeed.tech/tags/ci-cd.md>), [code](<https://devfeed.tech/tags/code.md>), [infrastructure](<https://devfeed.tech/tags/infrastructure.md>), [infrastructure-as-code](<https://devfeed.tech/tags/infrastructure-as-code.md>), [pytest](<https://devfeed.tech/tags/pytest.md>), [testing](<https://devfeed.tech/tags/testing.md>)

### AI overview

This article explains how to test Ansible infrastructure code by rendering the shipped Jinja expression through Ansible's actual templating machinery. It recommends extracting the expression from the role file, using realistic fixture variables, and asserting on the rendered result instead of duplicating the computation in Python.

### Source excerpt

Ansible Templar in pytest: render the shipped combine(recursive=True) expression from defaults/main.yml instead of a shallow Python paraphrase.

## Keeping Documentation Honest with an OpenAPI Snapshot Diff

DevFeed: [Keeping Documentation Honest with an OpenAPI Snapshot Diff](<https://devfeed.tech/articles/keeping-documentation-honest-with-an-openapi-snapshot-diff-34111.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/openapi-docs-contract-test/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-08-25T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [OpenAPI Specification](<https://devfeed.tech/topics/openapi.md>), [FastAPI](<https://devfeed.tech/topics/fastapi.md>), [ci](<https://devfeed.tech/topics/ci.md>), [Pytest](<https://devfeed.tech/topics/pytest.md>), [Documentation](<https://devfeed.tech/topics/documentation.md>), [JSON](<https://devfeed.tech/topics/json.md>), [test](<https://devfeed.tech/topics/test.md>)

Tags: [api-documentation](<https://devfeed.tech/tags/api-documentation.md>), [ci](<https://devfeed.tech/tags/ci.md>), [ci-cd](<https://devfeed.tech/tags/ci-cd.md>), [documentation](<https://devfeed.tech/tags/documentation.md>), [fastapi](<https://devfeed.tech/tags/fastapi.md>), [json](<https://devfeed.tech/tags/json.md>), [openapi](<https://devfeed.tech/tags/openapi.md>), [pytest](<https://devfeed.tech/tags/pytest.md>), [test](<https://devfeed.tech/tags/test.md>), [testing](<https://devfeed.tech/tags/testing.md>)

### AI overview

The article explains how to keep API documentation aligned with a FastAPI application by generating its OpenAPI schema from the running code, comparing it with a committed snapshot in CI, normalizing the JSON diff, and requiring deliberate snapshot regeneration.

### Source excerpt

FastAPI app.openapi() snapshot test in pytest: fail CI when the live OpenAPI schema drifts from the committed openapi.snapshot.json.

## When Microservice Decomposition Is the Wrong Default

DevFeed: [When Microservice Decomposition Is the Wrong Default](<https://devfeed.tech/articles/when-microservice-decomposition-is-the-wrong-default-34109.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/microservice-decomposition-heuristic/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-08-21T07:00:00Z

Content type: opinion

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [Microservice](<https://devfeed.tech/topics/microservice.md>), [Architecture & Design](<https://devfeed.tech/topics/architecture-design.md>), [Microservices](<https://devfeed.tech/topics/microservices.md>), [FastAPI](<https://devfeed.tech/topics/fastapi.md>)

Tags: [api](<https://devfeed.tech/tags/api.md>), [architecture](<https://devfeed.tech/tags/architecture.md>), [circuit](<https://devfeed.tech/tags/circuit.md>), [docker](<https://devfeed.tech/tags/docker.md>), [microservices](<https://devfeed.tech/tags/microservices.md>), [migration](<https://devfeed.tech/tags/migration.md>), [modular-monolith](<https://devfeed.tech/tags/modular-monolith.md>), [monolith](<https://devfeed.tech/tags/monolith.md>), [openapi](<https://devfeed.tech/tags/openapi.md>), [tracing](<https://devfeed.tech/tags/tracing.md>)

### AI overview

The article argues that splitting a small system into microservices should not be the default. It recommends keeping responsibilities in a modular monolith unless differences in scaling needs, organizational boundaries, or failure isolation justify a network boundary, whose costs include contracts, compatibility management, retries, timeouts, circuit breaking, and distributed tracing.

### Source excerpt

import-linter forbidden contract as a module boundary: a FastAPI modular monolith instead of early microservices, and when a network split pays off.

## Using a Local Proxy to Centralize AI Tool Routing, Logging, and Policy

DevFeed: [Using a Local Proxy to Centralize AI Tool Routing, Logging, and Policy](<https://devfeed.tech/articles/one-local-endpoint-for-every-agent-session-34101.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/data-locality-by-default/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-08-18T07:00:00Z

Content type: article

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [proxy](<https://devfeed.tech/topics/proxy.md>), [API](<https://devfeed.tech/topics/api.md>), [audit](<https://devfeed.tech/topics/audit.md>), [configuration](<https://devfeed.tech/topics/configuration.md>), [Self-hosted](<https://devfeed.tech/topics/self-hosted.md>)

Tags: [api](<https://devfeed.tech/tags/api.md>), [audit](<https://devfeed.tech/tags/audit.md>), [configuration](<https://devfeed.tech/tags/configuration.md>), [llm](<https://devfeed.tech/tags/llm.md>), [proxy](<https://devfeed.tech/tags/proxy.md>), [python](<https://devfeed.tech/tags/python.md>), [security](<https://devfeed.tech/tags/security.md>), [self-hosted](<https://devfeed.tech/tags/self-hosted.md>)

### AI overview

The article proposes routing every model-using tool on a developer machine through one local proxy. This centralizes endpoint selection, request logging, auditing, and enforcement of policies such as keeping sensitive project code on a self-hosted model. It notes that tools with hardcoded or otherwise unsupported upstream configuration can bypass the proxy.

### Source excerpt

OPENAI_BASE_URL=http://localhost:8080/v1 for every AI tool: one local FastAPI proxy that logs each request and refuses internal-only projects.

## Treating Issue Bodies as Untrusted Input

DevFeed: [Treating Issue Bodies as Untrusted Input](<https://devfeed.tech/articles/treating-issue-bodies-as-untrusted-input-34113.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/prompt-injection-untrusted-issues/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-08-14T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [prompt injection](<https://devfeed.tech/topics/prompt-injection.md>), [GitHub](<https://devfeed.tech/topics/github.md>), [JSON Feed](<https://devfeed.tech/topics/json-feed.md>), [Structured-data](<https://devfeed.tech/topics/structured-data.md>), [issue tracker](<https://devfeed.tech/topics/issue-tracker.md>)

Tags: [agents](<https://devfeed.tech/tags/agents.md>), [github](<https://devfeed.tech/tags/github.md>), [implementation](<https://devfeed.tech/tags/implementation.md>), [issue-tracker](<https://devfeed.tech/tags/issue-tracker.md>), [json](<https://devfeed.tech/tags/json.md>), [llm](<https://devfeed.tech/tags/llm.md>), [prompt-injection](<https://devfeed.tech/tags/prompt-injection.md>), [schema](<https://devfeed.tech/tags/schema.md>), [security](<https://devfeed.tech/tags/security.md>), [test](<https://devfeed.tech/tags/test.md>)

### AI overview

The article explains how GitHub issue bodies can carry prompt injection attacks when an agent treats public input as instructions. It recommends fencing untrusted text, clearly labeling it, constraining model output to a fixed JSON action schema, and testing the validation boundary without a live model.

### Source excerpt

Prompt injection via GitHub issue bodies: fence untrusted text and accept model output only as a fixed JSON action schema, tested without a model.

## From a Large Allowlist to Three Denials: Permissions for a Coding Agent

DevFeed: [From a Large Allowlist to Three Denials: Permissions for a Coding Agent](<https://devfeed.tech/articles/from-a-large-allowlist-to-three-denials-permissions-for-a-coding-agent-34096.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/agent-permissions-inversion/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-08-11T07:00:00Z

Content type: opinion

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [coding](<https://devfeed.tech/topics/coding.md>), [Bash](<https://devfeed.tech/topics/bash.md>), [Linux](<https://devfeed.tech/topics/linux.md>), [Authorization](<https://devfeed.tech/topics/authorization.md>), [Kernel](<https://devfeed.tech/topics/kernel.md>), [mount](<https://devfeed.tech/topics/mount.md>), [Network](<https://devfeed.tech/topics/network.md>), [Command-line interface](<https://devfeed.tech/topics/cli.md>)

Tags: [agent](<https://devfeed.tech/tags/agent.md>), [agents](<https://devfeed.tech/tags/agents.md>), [coding](<https://devfeed.tech/tags/coding.md>), [command-line](<https://devfeed.tech/tags/command-line.md>), [curl](<https://devfeed.tech/tags/curl.md>), [kernel](<https://devfeed.tech/tags/kernel.md>), [linux](<https://devfeed.tech/tags/linux.md>), [mount](<https://devfeed.tech/tags/mount.md>), [network](<https://devfeed.tech/tags/network.md>), [permissions](<https://devfeed.tech/tags/permissions.md>), [sandboxing](<https://devfeed.tech/tags/sandboxing.md>), [security](<https://devfeed.tech/tags/security.md>), [shell](<https://devfeed.tech/tags/shell.md>)

### AI overview

The article argues that command allowlists are a poor security boundary for coding agents because the required command set continually expands and command names do not constrain effects. It proposes enforcing limits at the kernel level with Linux namespaces, a read-only root filesystem, scoped writable mounts, and dropped capabilities, allowing a shell to run while restricting its blast radius.

### Source excerpt

bwrap --unshare-net --cap-drop ALL instead of a command allowlist: sandboxing a coding agent's shell so rm -rf and curl cannot leave the workspace.

## Self-Hosted LLM Inference: Serving, Benchmarking and Agent Guardrails

DevFeed: [Self-Hosted LLM Inference: Serving, Benchmarking and Agent Guardrails](<https://devfeed.tech/articles/self-hosted-llm-inference-serving-benchmarking-and-agent-guardrails-34097.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/atlas-agentic-ops/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-08-07T07:00:00Z

Content type: article

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [Self-hosted](<https://devfeed.tech/topics/self-hosted.md>), [Large Language Model](<https://devfeed.tech/topics/llm.md>), [Inference](<https://devfeed.tech/topics/inference.md>), [model-serving](<https://devfeed.tech/topics/model-serving.md>), [benchmarking](<https://devfeed.tech/topics/benchmarking.md>), [LLM evaluation / benchmarking](<https://devfeed.tech/topics/llm-evaluation-benchmarking.md>), [API](<https://devfeed.tech/topics/api.md>)

Tags: [agents](<https://devfeed.tech/tags/agents.md>), [api](<https://devfeed.tech/tags/api.md>), [benchmarking](<https://devfeed.tech/tags/benchmarking.md>), [guardrails](<https://devfeed.tech/tags/guardrails.md>), [inference](<https://devfeed.tech/tags/inference.md>), [llm](<https://devfeed.tech/tags/llm.md>), [ollama](<https://devfeed.tech/tags/ollama.md>), [security](<https://devfeed.tech/tags/security.md>), [self-hosted](<https://devfeed.tech/tags/self-hosted.md>), [testing](<https://devfeed.tech/tags/testing.md>)

### AI overview

This article examines self-hosted LLM inference for infrastructure work, focusing on data locality, local-versus-hosted model tradeoffs, repeatable benchmarking on personal tasks, model serving, and guardrails for agents that can propose or apply changes.

### Source excerpt

Ollama OpenAI-compatible /v1/chat/completions: a repeatable benchmark on your own tasks and a dry-run plus --approve guardrail for infrastructure agents.

## Verifying an Agent's Work Against Reality, Not Its Own Report

DevFeed: [Verifying an Agent's Work Against Reality, Not Its Own Report](<https://devfeed.tech/articles/verifying-an-agent-s-work-against-reality-not-its-own-report-34102.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/evidence-over-assertion/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-08-04T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [coding](<https://devfeed.tech/topics/coding.md>), [out-of-process](<https://devfeed.tech/topics/out-of-process.md>), [ci](<https://devfeed.tech/topics/ci.md>), [Processes](<https://devfeed.tech/topics/processes.md>)

Tags: [agent](<https://devfeed.tech/tags/agent.md>), [agents](<https://devfeed.tech/tags/agents.md>), [ci](<https://devfeed.tech/tags/ci.md>), [ci-cd](<https://devfeed.tech/tags/ci-cd.md>), [out-of-process](<https://devfeed.tech/tags/out-of-process.md>), [repository](<https://devfeed.tech/tags/repository.md>), [testing](<https://devfeed.tech/tags/testing.md>), [tests](<https://devfeed.tech/tags/tests.md>), [verification](<https://devfeed.tech/tags/verification.md>)

### AI overview

The article explains why a coding agent's transcript and successful wrapper exit are not reliable evidence that its task succeeded. It recommends defining observable completion criteria in advance, running verification in a separate process after the agent exits, checking the specific expected result, and reporting empty diffs separately from failing changes.

### Source excerpt

git diff --quiet HEAD and a re-run test command in a separate CI job: verifying a coding agent's work from repository state instead of its own report.

## Testing an Agent Harness Without Ever Calling the Model

DevFeed: [Testing an Agent Harness Without Ever Calling the Model](<https://devfeed.tech/articles/testing-an-agent-harness-without-ever-calling-the-model-34114.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/testing-an-agent-harness/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-07-31T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [Testing](<https://devfeed.tech/topics/testing.md>), [Agent Harness](<https://devfeed.tech/topics/agent-harness.md>), [Pytest](<https://devfeed.tech/topics/pytest.md>), [Unit testing](<https://devfeed.tech/topics/unit-testing.md>), [coding](<https://devfeed.tech/topics/coding.md>)

Tags: [agent](<https://devfeed.tech/tags/agent.md>), [agent-harness](<https://devfeed.tech/tags/agent-harness.md>), [agents](<https://devfeed.tech/tags/agents.md>), [api](<https://devfeed.tech/tags/api.md>), [network](<https://devfeed.tech/tags/network.md>), [permission](<https://devfeed.tech/tags/permission.md>), [pytest](<https://devfeed.tech/tags/pytest.md>), [python](<https://devfeed.tech/tags/python.md>), [recording](<https://devfeed.tech/tags/recording.md>), [testing](<https://devfeed.tech/tags/testing.md>), [unit-testing](<https://devfeed.tech/tags/unit-testing.md>)

### AI overview

This tutorial explains how to unit test a coding agent's tool-call permission layer without calling a model. It recommends separating the decision function from model responses, using recorded real-request fixtures, and keeping the policy module independent of any LLM SDK.

### Source excerpt

Unit testing a coding agent's tool-call permission layer with pytest and recorded fixtures: allow, deny or ask decisions with no model or API key.

## The Label as Contract: Consent and Priority as the Whole Queue

DevFeed: [The Label as Contract: Consent and Priority as the Whole Queue](<https://devfeed.tech/articles/the-label-as-contract-consent-and-priority-as-the-whole-queue-34107.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/label-as-contract/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-07-28T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [issue tracker](<https://devfeed.tech/topics/issue-tracker.md>), [audit trail](<https://devfeed.tech/topics/audit-trail.md>), [coding](<https://devfeed.tech/topics/coding.md>)

Tags: [agents](<https://devfeed.tech/tags/agents.md>), [audit-trail](<https://devfeed.tech/tags/audit-trail.md>), [consent](<https://devfeed.tech/tags/consent.md>), [fifo](<https://devfeed.tech/tags/fifo.md>), [issue-tracker](<https://devfeed.tech/tags/issue-tracker.md>), [priority](<https://devfeed.tech/tags/priority.md>), [security](<https://devfeed.tech/tags/security.md>)

### AI overview

The article argues that an autonomous coding agent should act only on issues carrying a specific human-applied label. Free-form issue content is unauthenticated and cannot establish consent or priority; label actions provide an independent audit trail, and priority should be derived from label transitions.

### Source excerpt

agent-ready label as the only consent gate for a coding agent: FIFO order by label time and a re-read-then-swap claim so two runs never share an issue.

## A Deterministic Daemon That Turns a Labelled Issue Into a Pull Request

DevFeed: [A Deterministic Daemon That Turns a Labelled Issue Into a Pull Request](<https://devfeed.tech/articles/a-deterministic-daemon-that-turns-a-labelled-issue-into-a-pull-request-34105.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/issue-to-pr-daemon/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-07-24T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [Pull Request](<https://devfeed.tech/topics/pull-request.md>), [Git](<https://devfeed.tech/topics/git.md>), [GitHub](<https://devfeed.tech/topics/github.md>), [Python](<https://devfeed.tech/topics/python.md>), [audit](<https://devfeed.tech/topics/audit.md>), [file](<https://devfeed.tech/topics/file.md>)

Tags: [agent](<https://devfeed.tech/tags/agent.md>), [agents](<https://devfeed.tech/tags/agents.md>), [audit-trail](<https://devfeed.tech/tags/audit-trail.md>), [ci-cd](<https://devfeed.tech/tags/ci-cd.md>), [commit](<https://devfeed.tech/tags/commit.md>), [git](<https://devfeed.tech/tags/git.md>), [github](<https://devfeed.tech/tags/github.md>), [pull-request](<https://devfeed.tech/tags/pull-request.md>), [python](<https://devfeed.tech/tags/python.md>)

### AI overview

The article proposes an issue-to-PR daemon in which a model works in an isolated workspace and returns a patch, while deterministic Python code validates and applies the patch, commits it, pushes it, and opens the pull request. This separation improves auditability and avoids giving the model credentials for the real repository.

### Source excerpt

git apply --check before git commit: an issue-to-PR daemon where the model only returns a patch and plain Python commits, pushes and opens the PR.

## Testing That a Canvas Diagram Actually Painted Pixels

DevFeed: [Testing That a Canvas Diagram Actually Painted Pixels](<https://devfeed.tech/articles/testing-that-a-canvas-diagram-actually-painted-pixels-34098.md>)

Original publisher: [Read original article](<https://philipptheserver.com/posts/canvas-pixel-testing/>)

Author: Philipp Lehmann (philipp.lehmann@gruppe.ai)

Published: 2026-07-21T07:00:00Z

Content type: tutorial

Language: en

Sources: [Philipp Lehmann](<https://devfeed.tech/sources/philipp-lehmann.md>)

Topics: [Canvas](<https://devfeed.tech/topics/canvas.md>), [Testing](<https://devfeed.tech/topics/testing.md>), [Playwright](<https://devfeed.tech/topics/playwright.md>), [Document Object Model (DOM)](<https://devfeed.tech/topics/dom.md>), [browser](<https://devfeed.tech/topics/browser.md>)

Tags: [browser](<https://devfeed.tech/tags/browser.md>), [canvas](<https://devfeed.tech/tags/canvas.md>), [frontend](<https://devfeed.tech/tags/frontend.md>), [html5](<https://devfeed.tech/tags/html5.md>), [playwright](<https://devfeed.tech/tags/playwright.md>), [testing](<https://devfeed.tech/tags/testing.md>)

### AI overview

This tutorial explains why DOM-based tests can pass even when an HTML5 canvas renders nothing. Because canvas pixels are not represented in the DOM and jsdom does not provide real canvas rendering, it recommends using Playwright with a real browser and checking pixel data with getImageData.

### Source excerpt

getImageData in Playwright to assert a canvas actually drew pixels, since jsdom has no canvas renderer and DOM assertions pass on a blank canvas.