Lesstep
GitHub Actions · Ubuntu 26.04 · Checked November 4, 2026

Postgres never starts in Docker on Ubuntu 26.04: "docker-default//&unconfined"

An AppArmor fix in the Linux kernel (08c2f7c8d4b1, "apparmor: fix unconfined user namespace restriction forced stack") has reached Ubuntu 26.04's newer kernels and Debian 13's 6.12.115. Ubuntu turns on kernel.apparmor_restrict_unprivileged_unconfined=1 by default, and with it the kernel now stacks the container's profile: processes run as docker-default//&unconfined instead of docker-default. Docker's default profile only lets a process signal peers named docker-default, so the processes of one container can no longer signal each other (moby #54099, open).

What it looks like

gosu is written in Go, and Go changes the user of every thread by sending each one a signal. When that signal is denied, it waits forever, which is why the container hangs instead of failing.

Where it was reported

So in GitHub Actions this hits self-hosted runners and third-party runner images that boot one of these kernels. GitHub-hosted runners (image 20261026, kernel 7.0.0-1017-azure on both ubuntu-24.04 and ubuntu-26.04) had no reports as of November 4.

Check a host

uname -r
sysctl kernel.apparmor_restrict_unprivileged_unconfined
docker run --rm busybox:1.36 sh -c 'cat /proc/self/attr/current; sleep 30 & kill -TERM $! && echo SIGNAL_OK || echo SIGNAL_DENIED'

An affected host prints docker-default//&unconfined (enforce) and SIGNAL_DENIED.

Fix for one container: no AppArmor profile

services:
  postgres:
    image: postgres:17
    options: >-
      --security-opt apparmor=unconfined
      --health-cmd pg_isready
      --health-interval 5s

Outside a workflow it is docker run --security-opt apparmor=unconfined. The same option works under container: for a job container. It leaves the host alone and takes AppArmor off that container only. --security-opt seccomp=unconfined does not help, because seccomp is not what denies the signal.

Fix for the host: the sysctl

echo 'kernel.apparmor_restrict_unprivileged_unconfined = 0' | sudo tee /etc/sysctl.d/99-container-signals.conf
sudo sysctl --system

Containers keep docker-default and can signal each other again. On runs-on, one user put the same sysctl in the image's preinstall step and their builds passed (runs-on #116). This turns off a restriction Ubuntu enables on purpose, so prefer the per-container option where you can.

Other ways out

Telling it apart

Other 26.04 failures

See failed jobs from IntelliJ IDEA

Pipeline Inbox for GitHub Actions Workflows, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, lists the runs of all your repositories in an IDE tool window, with their jobs and steps, and your current branch's runs are in the status bar. Reading is free; re-running failed jobs, cancelling, running workflows and reviewing deployments are Pro (US$1.50 a month, with a 30-day trial).

Get it on JetBrains Marketplace

GitHub and GitHub Actions are trademarks of GitHub, Inc.; Ubuntu is a trademark of Canonical Ltd.; Debian is a registered trademark of Software in the Public Interest, Inc.; Docker is a trademark of Docker, Inc.; PostgreSQL is a registered trademark of the PostgreSQL Community Association; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with, sponsored or endorsed by GitHub, Inc., Canonical, Software in the Public Interest, Docker, Inc., the PostgreSQL project or JetBrains.

More: "The ubuntu-latest label will migrate to Ubuntu 26" · bubblewrap on Ubuntu 26.04 · GitHub Actions plugins for IntelliJ IDEA compared · 日本語