Last active
July 12, 2025 00:27
-
-
Save heri16/60acf5b57518cd8518e62f1ce74f14a8 to your computer and use it in GitHub Desktop.
Setup gVisor for rootless podman on Fedora CoreOS (fcos)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Setup podman virtual machine with no bind mounts: `podman machine init -v ''`. | |
# Start podman virtual machine: `podman machine start`. | |
# Connect to podman machine: `podman machine ssh`. | |
# Install latest release of gVisor | |
# See: https://gvisor.dev/docs/user_guide/install/ | |
( | |
set -e | |
ARCH=$(uname -m) | |
URL=https://storage.googleapis.com/gvisor/releases/release/latest/${ARCH} | |
curl --proto '=https' --tlsv1.3 -O "${URL}/runsc" \ | |
-O "${URL}/runsc.sha512" \ | |
-O "${URL}/containerd-shim-runsc-v1" \ | |
-O "${URL}/containerd-shim-runsc-v1.sha512" | |
sha512sum -c runsc.sha512 \ | |
-c containerd-shim-runsc-v1.sha512 | |
rm -f *.sha512 | |
chmod a+rx runsc containerd-shim-runsc-v1 | |
mkdir -p ${HOME}/.local/bin | |
mv runsc containerd-shim-runsc-v1 ${HOME}/.local/bin | |
) | |
# Run a test container with gVisor | |
podman run --runtime=${HOME}/.local/bin/runsc \ | |
--runtime-flag ignore-cgroups \ | |
--security-opt label=disable \ | |
--rm alpine sh -c 'dmesg && echo hello world' | |
# Create wrapper for gVisor's runsc for rootless podman | |
# as containers.conf do not support defining default runtime flags or args | |
cat > "${HOME}/.local/bin/runsc-rootless" << 'EOF' | |
#!/bin/sh | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# https://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
# TODO: https://github.com/containers/podman/issues/25565 - Use --runtime-flag | |
# in containers.conf and delete this wrapper. | |
# TODO: https://github.com/google/gvisor/issues/11543 - Remove -ignore-cgroups | |
# TODO: https://github.com/google/gvisor/issues/10359 - Remove -network=host | |
# TODO: https://github.com/google/gvisor/issues/11794 - Remove -overlay2=none | |
set -euo pipefail | |
# Filter out unsupported flags | |
args=() | |
while [ "$#" -gt 0 ]; do | |
case "$1" in | |
--no-new-keyring) | |
shift ;; # skip this flag | |
create) | |
args+=("--ignore-cgroups") | |
args+=("$1") | |
shift ;; | |
*) | |
args+=("$1") | |
shift ;; | |
esac | |
done | |
exec "$(dirname "$0")/runsc" \ | |
--host-uds=open \ | |
"${args[@]}" | |
EOF | |
chmod a+rx "${HOME}/.local/bin/runsc-rootless" | |
# The wrapper enables access to host's UNIX domain sockets (only required for devcontainer's bootstrap) | |
# See: `runsc flags` | |
# Enable `docker buildx build` (only required for devcontainers with Dockerfile) | |
# See: https://github.com/moby/buildkit/blob/master/docs/rootless.md#docker | |
# podman run --replace --name buildx_buildkit_default --runtime=crun --privileged -v buildx_buildkit_default_state:/var/lib/buildkit:rw,rprivate -d --restart=unless-stopped moby/buildkit:buildx-stable-1 --rootless --oci-worker-rootless | |
podman run --replace --name buildx_buildkit_default \ | |
--runtime=crun \ | |
--security-opt seccomp=unconfined \ | |
--security-opt apparmor=unconfined \ | |
--security-opt systempaths=unconfined \ | |
-v buildx_buildkit_default_state:/var/lib/buildkit:rw,rprivate \ | |
-d --restart=unless-stopped moby/buildkit:rootless | |
# Register gVisor as default runtime (for rootless docker) | |
mkdir -p "${HOME}/.config/docker" | |
tee "${HOME}/.config/docker/daemon.json" << EOF | |
{ | |
"selinux-enabled": false, | |
"runtimes": { | |
"runsc": { | |
"path": "${HOME}/.local/bin/runsc", | |
"runtimeArgs": [ | |
"-ignore-cgroups", | |
"-host-uds=open" | |
] | |
} | |
}, | |
"default-runtime": "runsc" | |
} | |
EOF | |
# Register gVisor as default runtime (for rootless podman) | |
tee -a "${HOME}/.config/containers/containers.conf" << EOF | |
label = false | |
[engine.runtimes] | |
runsc = [ | |
"${HOME}/.local/bin/runsc-rootless", | |
] | |
[engine] | |
runtime = "runsc" | |
EOF | |
# Make buildah (podman build) always run using gVisor | |
tee -a "${HOME}/.bash_profile" << EOF | |
export BUILDAH_RUNTIME=${HOME}/.local/bin/runsc-rootless | |
export BUILDAH_ISOLATION=chroot | |
EOF | |
# Run a test container with rootless gVisor | |
podman run --rm alpine sh -c 'dmesg && echo hello world' | |
# List containers using gVisor's userspace-kernel and runsc runtime | |
runsc list | |
# List all containers and their runtimes | |
podman ps -a --format "table {{.ID}}\t{{.Names}}" | while read id name; do runtime=$(podman inspect --format '{{.OCIRuntime}}' "$id"); echo -e "$id\t$name\t${runtime:-Runtime}"; done | |
# Test a containerized web service with gVisor | |
sudo podman run --runtime=$(command -v runsc) --security-opt label=disable -p 3003:3003 --rm -it alpine sh | |
apk add --no-cache curl libstdc++ | |
PATH="${HOME}/.local/bin:${PATH}" | |
curl --proto '=https' --tlsv1.3 https://mise.run | sh | |
eval "$(mise activate --shims)" | |
mise use -g bun@latest | |
bun init --react ./app && cd ./app | |
env PORT=3003 bun dev | |
exit | |
# Remote Browser Isolation with gVisor | |
# Starts Firefox browser at https://localhost:3001 | |
sudo mkdir -p /var/home/firefox | |
sudo podman run -d \ | |
--name=firefox --replace \ | |
--runtime=$(command -v runsc) \ | |
--security-opt label=disable \ | |
-e PUID=$(id -u) \ | |
-e PGID=$(id -g) \ | |
-e TZ=Etc/UTC \ | |
-e FIREFOX_CLI=https://youtube.com \ | |
-e MOZ_FAKE_NO_SANDBOX=1 \ | |
-p 3000:3000 \ | |
-p 3001:3001 \ | |
-v /var/home/firefox:/config \ | |
--shm-size="1gb" \ | |
--restart unless-stopped \ | |
lscr.io/linuxserver/firefox:latest | |
exit | |
# Useful commands to manage Isolated Firefox Browser | |
podman --connection podman-machine-default-root stats --no-stream | |
podman --connection podman-machine-default-root pause firefox | |
podman --connection podman-machine-default-root unpause firefox | |
podman --connection podman-machine-default-root restart firefox | |
podman --connection podman-machine-default-root logs -f firefox |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Inspired By Sandboxing and Container Escapes:
Inspired By Supply Chain Security: