mirror of
https://github.com/ps5-linux/ps5-linux-image.git
synced 2026-07-16 10:10:39 +00:00
Compare commits
20 Commits
feature/ci
...
fix/arch-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc365dda15 | ||
|
|
8160bc649b | ||
|
|
1ea662d598 | ||
|
|
04378b78f4 | ||
|
|
0e1219f422 | ||
|
|
33189d7e7b | ||
|
|
d92e51959b | ||
|
|
01205507fd | ||
|
|
9d65d7a391 | ||
|
|
d55d87e6bd | ||
|
|
4a2aef2e03 | ||
|
|
2d07c87a78 | ||
|
|
4cf616a934 | ||
|
|
142d3913c9 | ||
|
|
a76971ba96 | ||
|
|
3db57b8de7 | ||
|
|
73bfdd288b | ||
|
|
fda932a3a3 | ||
|
|
43d2a65997 | ||
|
|
492e124991 |
@@ -1,7 +1,6 @@
|
||||
linux_deb/
|
||||
linux-bin/
|
||||
work/
|
||||
work-alpine/
|
||||
output/
|
||||
.git/
|
||||
ps5-linux-patches/
|
||||
|
||||
13
.gitattributes
vendored
Normal file
13
.gitattributes
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
* text=auto
|
||||
|
||||
*.sh text eol=lf
|
||||
*.bash text eol=lf
|
||||
*.yaml text eol=lf
|
||||
*.yml text eol=lf
|
||||
*.service text eol=lf
|
||||
|
||||
build_image.sh text eol=lf
|
||||
boot/kexec*.sh text eol=lf
|
||||
distros/**/grow-rootfs text eol=lf
|
||||
distros/shared/zz-update-boot* text eol=lf
|
||||
docker/** text eol=lf
|
||||
197
.github/workflows/build-image.yml
vendored
Normal file
197
.github/workflows/build-image.yml
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
name: Build Image
|
||||
run-name: Build Image (${{ inputs.distro || 'all' }})
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
distro:
|
||||
description: 'Distribution'
|
||||
default: 'ubuntu2604'
|
||||
type: choice
|
||||
options: [all, ubuntu2604, arch, cachyos, kali]
|
||||
workflow_call:
|
||||
inputs:
|
||||
distro:
|
||||
type: string
|
||||
default: 'ubuntu2604'
|
||||
secrets:
|
||||
REMOTE_SSH_KEY:
|
||||
required: true
|
||||
REMOTE_SSH_CONFIG:
|
||||
required: true
|
||||
REMOTE_SSH_KNOWN_HOSTS:
|
||||
required: true
|
||||
R2_ACCESS_KEY_ID:
|
||||
required: true
|
||||
R2_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
R2_ENDPOINT:
|
||||
required: true
|
||||
R2_BUCKET:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
runs-on: self-hosted
|
||||
outputs:
|
||||
distros: ${{ steps.set.outputs.distros }}
|
||||
steps:
|
||||
- id: set
|
||||
run: |
|
||||
INPUT="${{ inputs.distro || 'ubuntu2604' }}"
|
||||
if [ "$INPUT" = "all" ]; then
|
||||
echo 'distros=["ubuntu2604","arch","cachyos"]' >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "distros=[\"$INPUT\"]" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
build:
|
||||
needs: matrix
|
||||
runs-on: self-hosted
|
||||
timeout-minutes: 240
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
distro: ${{ fromJson(needs.matrix.outputs.distros) }}
|
||||
|
||||
env:
|
||||
CACHE_DIR: /home/opc/ccache
|
||||
|
||||
steps:
|
||||
- name: Checkout image builder
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: image
|
||||
|
||||
- name: Build ${{ matrix.distro }} image
|
||||
run: |
|
||||
bash image/build_image.sh --distro "${{ matrix.distro }}"
|
||||
|
||||
- name: Set version info
|
||||
id: version
|
||||
run: |
|
||||
psha=$(git -C image/work/ps5-linux-patches rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||||
kver=$(cat image/linux-bin/VERSION 2>/dev/null || echo "unknown")
|
||||
ts=$(date -u +%Y%m%d-%H%M%S)
|
||||
echo "psha=$psha" >> "$GITHUB_OUTPUT"
|
||||
echo "kver=$kver" >> "$GITHUB_OUTPUT"
|
||||
echo "ts=$ts" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Report
|
||||
run: |
|
||||
ls -lh image/output/*.img
|
||||
sha256sum image/output/*.img
|
||||
|
||||
- name: Compress image
|
||||
run: |
|
||||
xz -T0 -9 -c image/output/ps5-${{ matrix.distro }}.img \
|
||||
> image/output/ps5-${{ matrix.distro }}.img.xz
|
||||
|
||||
- name: Upload to R2
|
||||
if: github.event_name != 'pull_request' && github.event_name != 'pull_request_target'
|
||||
env:
|
||||
RCLONE_CONFIG_R2_TYPE: s3
|
||||
RCLONE_CONFIG_R2_PROVIDER: Cloudflare
|
||||
RCLONE_CONFIG_R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||
RCLONE_CONFIG_R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||
RCLONE_CONFIG_R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
|
||||
RCLONE_CONFIG_R2_NO_CHECK_BUCKET: true
|
||||
run: |
|
||||
rclone copyto image/output/ps5-${{ matrix.distro }}.img.xz \
|
||||
"r2:${{ secrets.R2_BUCKET }}/ps5-${{ matrix.distro }}.img.xz"
|
||||
|
||||
- name: Save build metadata
|
||||
run: |
|
||||
mkdir -p meta
|
||||
sha256sum image/output/ps5-${{ matrix.distro }}.img.xz \
|
||||
| sed 's|image/output/||' > meta/${{ matrix.distro }}.sha256
|
||||
echo "${{ steps.version.outputs.kver }}" > meta/kver
|
||||
echo "${{ steps.version.outputs.psha }}" > meta/psha
|
||||
echo "${{ steps.version.outputs.ts }}" > meta/ts
|
||||
|
||||
- name: Upload build metadata
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: meta-${{ matrix.distro }}
|
||||
path: meta/
|
||||
retention-days: 1
|
||||
|
||||
- name: Upload to remote
|
||||
if: github.event_name != 'pull_request' && github.event_name != 'pull_request_target'
|
||||
env:
|
||||
SSH_KEY: ${{ secrets.REMOTE_SSH_KEY }}
|
||||
SSH_CONFIG: ${{ secrets.REMOTE_SSH_CONFIG }}
|
||||
SSH_KNOWN_HOSTS: ${{ secrets.REMOTE_SSH_KNOWN_HOSTS }}
|
||||
run: |
|
||||
DIR=$(mktemp -d)
|
||||
echo "$SSH_KEY" > "$DIR/key"
|
||||
chmod 600 "$DIR/key"
|
||||
echo "$SSH_CONFIG" > "$DIR/config"
|
||||
sed -i "s|~/.ssh/remote_key|$DIR/key|" "$DIR/config"
|
||||
echo "$SSH_KNOWN_HOSTS" > "$DIR/known_hosts"
|
||||
SSH="ssh -F $DIR/config -o UserKnownHostsFile=$DIR/known_hosts"
|
||||
SCP="scp -F $DIR/config -o UserKnownHostsFile=$DIR/known_hosts"
|
||||
DEST="image-${{ matrix.distro }}-${{ steps.version.outputs.ts }}"
|
||||
$SSH remote mkdir -p "./$DEST"
|
||||
$SCP image/output/*.img.xz "remote:./$DEST/"
|
||||
$SSH remote 'ls -dt image-${{ matrix.distro }}-*/ | tail -n +5 | xargs rm -rf' || true
|
||||
rm -rf "$DIR"
|
||||
|
||||
release:
|
||||
needs: build
|
||||
runs-on: self-hosted
|
||||
if: github.event_name != 'pull_request' && github.event_name != 'pull_request_target'
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Download build metadata
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
pattern: meta-*
|
||||
path: meta
|
||||
merge-multiple: true
|
||||
|
||||
- name: Prepare release body
|
||||
id: body
|
||||
run: |
|
||||
KVER=$(cat meta/kver)
|
||||
PSHA=$(cat meta/psha)
|
||||
TS=$(cat meta/ts)
|
||||
SUMS=$(cat meta/*.sha256)
|
||||
|
||||
{
|
||||
echo 'text<<EOF'
|
||||
echo "PS5 Linux images — built from latest \`main\`."
|
||||
echo ""
|
||||
echo "Kernel: \`$KVER\`"
|
||||
echo "Patches: [\`$PSHA\`](https://github.com/ps5-linux/ps5-linux-patches/commit/$PSHA)"
|
||||
echo "Built: \`$TS\`"
|
||||
echo ""
|
||||
echo "| Image | Download |"
|
||||
echo "|-------|----------|"
|
||||
echo "| Ubuntu 26.04 | [\`ps5-ubuntu2604.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-ubuntu2604.img.xz) |"
|
||||
echo "| Arch | [\`ps5-arch.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-arch.img.xz) |"
|
||||
echo "| CachyOS | [\`ps5-cachyos.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-cachyos.img.xz) |"
|
||||
if [ -f meta/kali.sha256 ]; then
|
||||
echo "| Kali | [\`ps5-kali.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-kali.img.xz) |"
|
||||
fi
|
||||
echo ""
|
||||
echo "**SHA256 checksums:**"
|
||||
echo "\`\`\`"
|
||||
echo "$SUMS"
|
||||
echo "\`\`\`"
|
||||
echo 'EOF'
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Create or update release
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag_name: latest
|
||||
name: PS5 Linux Image (latest)
|
||||
body: ${{ steps.body.outputs.text }}
|
||||
make_latest: true
|
||||
18
.github/workflows/dispatch.yml
vendored
18
.github/workflows/dispatch.yml
vendored
@@ -1,18 +0,0 @@
|
||||
name: Dispatch to CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
dispatch:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send repository_dispatch
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.DISPATCH_TOKEN }}
|
||||
repository: ps5-linux/ps5-linux-updates
|
||||
event-type: image-builder-updated
|
||||
client-payload: '{"sha": "${{ github.sha }}"}'
|
||||
172
.github/workflows/test-uploads.yml
vendored
Normal file
172
.github/workflows/test-uploads.yml
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
name: test uploads
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
runs-on: self-hosted
|
||||
outputs:
|
||||
distros: ${{ steps.set.outputs.distros }}
|
||||
steps:
|
||||
- id: set
|
||||
run: echo 'distros=["ubuntu2604","arch","cachyos"]' >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
needs: matrix
|
||||
runs-on: self-hosted
|
||||
timeout-minutes: 10
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
distro: ${{ fromJson(needs.matrix.outputs.distros) }}
|
||||
|
||||
steps:
|
||||
- name: Reset workspace
|
||||
run: sudo rm -rf ./*
|
||||
|
||||
- name: Create fake image
|
||||
run: |
|
||||
mkdir -p image/output
|
||||
dd if=/dev/urandom of=image/output/ps5-${{ matrix.distro }}.img bs=1M count=8
|
||||
|
||||
- name: Compress image
|
||||
run: |
|
||||
xz -T0 -1 -c image/output/ps5-${{ matrix.distro }}.img \
|
||||
> image/output/ps5-${{ matrix.distro }}.img.xz
|
||||
|
||||
- name: Upload to R2
|
||||
env:
|
||||
RCLONE_CONFIG_R2_TYPE: s3
|
||||
RCLONE_CONFIG_R2_PROVIDER: Cloudflare
|
||||
RCLONE_CONFIG_R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||
RCLONE_CONFIG_R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||
RCLONE_CONFIG_R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
|
||||
RCLONE_CONFIG_R2_NO_CHECK_BUCKET: true
|
||||
run: |
|
||||
rclone copyto image/output/ps5-${{ matrix.distro }}.img.xz \
|
||||
"r2:${{ secrets.R2_BUCKET }}/test-${{ matrix.distro }}.img.xz" -v
|
||||
|
||||
- name: Save build metadata
|
||||
run: |
|
||||
mkdir -p meta
|
||||
sha256sum image/output/ps5-${{ matrix.distro }}.img.xz \
|
||||
| sed 's|image/output/||' > meta/${{ matrix.distro }}.sha256
|
||||
echo "6.x.y-test" > meta/kver
|
||||
echo "abc1234" > meta/psha
|
||||
date -u +%Y%m%d-%H%M%S > meta/ts
|
||||
|
||||
- name: Upload build metadata
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: meta-${{ matrix.distro }}
|
||||
path: meta/
|
||||
retention-days: 1
|
||||
|
||||
- name: Upload to remote
|
||||
env:
|
||||
SSH_KEY: ${{ secrets.REMOTE_SSH_KEY }}
|
||||
SSH_CONFIG: ${{ secrets.REMOTE_SSH_CONFIG }}
|
||||
SSH_KNOWN_HOSTS: ${{ secrets.REMOTE_SSH_KNOWN_HOSTS }}
|
||||
run: |
|
||||
DIR=$(mktemp -d)
|
||||
echo "$SSH_KEY" > "$DIR/key"
|
||||
chmod 600 "$DIR/key"
|
||||
echo "$SSH_CONFIG" > "$DIR/config"
|
||||
sed -i "s|~/.ssh/remote_key|$DIR/key|" "$DIR/config"
|
||||
echo "$SSH_KNOWN_HOSTS" > "$DIR/known_hosts"
|
||||
SSH="ssh -F $DIR/config -o UserKnownHostsFile=$DIR/known_hosts"
|
||||
SCP="scp -F $DIR/config -o UserKnownHostsFile=$DIR/known_hosts"
|
||||
$SSH remote mkdir -p ./test-upload
|
||||
$SCP image/output/ps5-${{ matrix.distro }}.img.xz "remote:./test-upload/"
|
||||
rm -rf "$DIR"
|
||||
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: rm -rf image/output meta
|
||||
|
||||
release:
|
||||
needs: build
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Download build metadata
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
pattern: meta-*
|
||||
path: meta
|
||||
merge-multiple: true
|
||||
|
||||
- name: Prepare release body
|
||||
id: body
|
||||
run: |
|
||||
KVER=$(cat meta/kver)
|
||||
PSHA=$(cat meta/psha)
|
||||
TS=$(cat meta/ts)
|
||||
SUMS=$(cat meta/*.sha256)
|
||||
|
||||
{
|
||||
echo 'text<<EOF'
|
||||
echo "PS5 Linux images — built from latest \`main\`."
|
||||
echo ""
|
||||
echo "Kernel: \`$KVER\`"
|
||||
echo "Patches: [\`$PSHA\`](https://github.com/ps5-linux/ps5-linux-patches/commit/$PSHA)"
|
||||
echo "Built: \`$TS\`"
|
||||
echo ""
|
||||
echo "| Image | Download |"
|
||||
echo "|-------|----------|"
|
||||
echo "| Ubuntu 26.04 | [\`ps5-ubuntu2604.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-ubuntu2604.img.xz) |"
|
||||
echo "| Arch | [\`ps5-arch.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-arch.img.xz) |"
|
||||
echo "| CachyOS | [\`ps5-cachyos.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-cachyos.img.xz) |"
|
||||
echo ""
|
||||
echo "**SHA256 checksums:**"
|
||||
echo "\`\`\`"
|
||||
echo "$SUMS"
|
||||
echo "\`\`\`"
|
||||
echo 'EOF'
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Verify release body
|
||||
run: |
|
||||
echo "=== Release body ==="
|
||||
cat <<'EOF'
|
||||
${{ steps.body.outputs.text }}
|
||||
EOF
|
||||
echo ""
|
||||
echo "=== All checksums ==="
|
||||
cat meta/*.sha256
|
||||
|
||||
cleanup-remote:
|
||||
needs: release
|
||||
runs-on: self-hosted
|
||||
if: always()
|
||||
steps:
|
||||
- name: Clean up R2 test files
|
||||
env:
|
||||
RCLONE_CONFIG_R2_TYPE: s3
|
||||
RCLONE_CONFIG_R2_PROVIDER: Cloudflare
|
||||
RCLONE_CONFIG_R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||
RCLONE_CONFIG_R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||
RCLONE_CONFIG_R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
|
||||
RCLONE_CONFIG_R2_NO_CHECK_BUCKET: true
|
||||
run: |
|
||||
for d in ubuntu2604 arch cachyos; do
|
||||
rclone delete "r2:${{ secrets.R2_BUCKET }}/test-${d}.img.xz" -v || true
|
||||
done
|
||||
|
||||
- name: Clean up remote test files
|
||||
env:
|
||||
SSH_KEY: ${{ secrets.REMOTE_SSH_KEY }}
|
||||
SSH_CONFIG: ${{ secrets.REMOTE_SSH_CONFIG }}
|
||||
SSH_KNOWN_HOSTS: ${{ secrets.REMOTE_SSH_KNOWN_HOSTS }}
|
||||
run: |
|
||||
DIR=$(mktemp -d)
|
||||
echo "$SSH_KEY" > "$DIR/key"
|
||||
chmod 600 "$DIR/key"
|
||||
echo "$SSH_CONFIG" > "$DIR/config"
|
||||
sed -i "s|~/.ssh/remote_key|$DIR/key|" "$DIR/config"
|
||||
echo "$SSH_KNOWN_HOSTS" > "$DIR/known_hosts"
|
||||
SSH="ssh -F $DIR/config -o UserKnownHostsFile=$DIR/known_hosts"
|
||||
$SSH remote rm -rf ./test-upload
|
||||
rm -rf "$DIR"
|
||||
26
.github/workflows/trigger-builds.yml
vendored
Normal file
26
.github/workflows/trigger-builds.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: deploy
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request_target:
|
||||
types: [labeled]
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
image:
|
||||
if: github.event.label.name == 'run-ci' || github.event_name != 'pull_request_target'
|
||||
permissions:
|
||||
contents: write
|
||||
uses: ./.github/workflows/build-image.yml
|
||||
with:
|
||||
distro: all
|
||||
secrets:
|
||||
REMOTE_SSH_KEY: ${{ secrets.REMOTE_SSH_KEY }}
|
||||
REMOTE_SSH_CONFIG: ${{ secrets.REMOTE_SSH_CONFIG }}
|
||||
REMOTE_SSH_KNOWN_HOSTS: ${{ secrets.REMOTE_SSH_KNOWN_HOSTS }}
|
||||
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||
R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
|
||||
R2_BUCKET: ${{ secrets.R2_BUCKET }}
|
||||
93
README.md
93
README.md
@@ -1,11 +1,13 @@
|
||||
# PS5 Linux Image Builder
|
||||
|
||||
Builds bootable Linux USB images for PlayStation 5 using Docker containers. Supports Ubuntu 26.04, Arch, CachyOS (Gamescope + Steam), and Alpine, individually or as a multi-distro image with kexec switching.
|
||||
Builds bootable Linux USB images for PlayStation 5 using Docker containers. Supports Ubuntu 26.04, Arch, CachyOS (Gamescope + Steam), and full Kali Linux, individually or as a multi-distro image with kexec switching.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker (with permission to run `--privileged` containers) — install as per your distro's instructions
|
||||
- ~30GB free disk space
|
||||
- ~30GB free disk space for Ubuntu, Arch, or CachyOS; a full Kali build needs
|
||||
substantial working space because it creates a 96GB image and a full rootfs
|
||||
tree (`~150GB` free recommended for a clean Kali build)
|
||||
|
||||
Once Docker is installed, add your user to the docker group and apply it without logging out:
|
||||
|
||||
@@ -27,7 +29,12 @@ OR
|
||||
|
||||
OR
|
||||
|
||||
# Build a multi-distro image (ubuntu2604 + arch + alpine + cachyos)
|
||||
# Build Kali Linux (XFCE + kali-linux-everything)
|
||||
./build_image.sh --distro kali
|
||||
|
||||
OR
|
||||
|
||||
# Build a multi-distro image (ubuntu2604 + arch + cachyos)
|
||||
./build_image.sh --distro all
|
||||
```
|
||||
|
||||
@@ -39,16 +46,75 @@ The script auto-clones the kernel source, applies PS5 patches, compiles, and bui
|
||||
sudo dd if=output/ps5-ubuntu2604.img of=/dev/sdX bs=4M status=progress
|
||||
```
|
||||
|
||||
## Kali First Boot Time Sync
|
||||
|
||||
The Kali image uses UTC by default and enables `ntpsec`. PS5 hardware may boot
|
||||
Linux without a correct real-time clock, so the displayed time can be wrong
|
||||
until a network connection is available. The Kali recipe configures IPv4 NTP
|
||||
sources that were validated through Android USB tethering, because that
|
||||
connection may not provide usable IPv6 routing.
|
||||
|
||||
The Xfce clock's **Time and Date** window is the legacy `time-admin` utility.
|
||||
On Kali it can report that NTP support is not installed even though `ntpsec`
|
||||
is installed and active. Verify or repair synchronization from a terminal:
|
||||
|
||||
```bash
|
||||
systemctl --no-pager status ntpsec
|
||||
ntpq -pn
|
||||
timedatectl status
|
||||
```
|
||||
|
||||
If the PS5 clock is still wrong after the internet connection is active, force
|
||||
one initial correction and restart continuous synchronization:
|
||||
|
||||
```bash
|
||||
sudo systemctl stop ntpsec
|
||||
sudo ntpd -gq -c /etc/ntpsec/ntp.conf
|
||||
sudo systemctl start ntpsec
|
||||
date
|
||||
```
|
||||
|
||||
To use a local timezone after boot, for example Kentucky:
|
||||
|
||||
```bash
|
||||
sudo timedatectl set-timezone America/Kentucky/Louisville
|
||||
timedatectl status
|
||||
```
|
||||
|
||||
The Kali desktop autologin is enabled for local first boot. SSH is installed
|
||||
but disabled by default because the initial local account is `kali` with
|
||||
password `kali`. Before enabling remote access, change that password:
|
||||
|
||||
```bash
|
||||
passwd
|
||||
sudo systemctl enable --now ssh
|
||||
```
|
||||
|
||||
The image holds its installed kernel packages and protects the boot-copy hook
|
||||
from deploying a generic Kali kernel. Do not replace or unhold the PS5 kernel
|
||||
unless you are intentionally testing a new PS5-patched kernel build.
|
||||
|
||||
Ghidra is configured to use JDK 21, its documented supported runtime. Full
|
||||
Kali installations may also contain newer Java versions for other software.
|
||||
|
||||
`kali-linux-everything` installs NFS client components, but the PS5-patched
|
||||
kernel has NFS disabled. A failed `run-rpc_pipefs.mount` unit can therefore be
|
||||
reported at boot; it only indicates that NFS mounts are unavailable. The Kali
|
||||
desktop and security tools are unaffected.
|
||||
|
||||
The full Kali toolset also enables `chkrootkit.timer`; its daily integrity scan
|
||||
can use noticeable CPU time while it runs.
|
||||
|
||||
## Options
|
||||
|
||||
| Flag | Description | Default |
|
||||
|------|-------------|---------|
|
||||
| `--distro` | `ubuntu2604`, `arch`, `cachyos`, `alpine`, or `all` | `ubuntu2604` |
|
||||
| `--kernel` | Path to kernel source directory | auto-clone `v6.19.10` |
|
||||
| `--img-size` | Disk image size in MB | `12000` (`32000` for `all`) |
|
||||
| `--distro` | `ubuntu2604`, `arch`, `cachyos`, `kali`, or `all` | `ubuntu2604` |
|
||||
| `--kernel` | Path to kernel source directory | auto-clone version selected by PS5 patch set |
|
||||
| `--img-size` | Disk image size in MB | `12000` (`32000` for `all`, `98304` for `kali`) |
|
||||
| `--clean` | Remove all cached build artifacts and start fresh | off |
|
||||
| `--kernel-only` | Build and package the kernel only, then exit | off |
|
||||
| `--patches-ref` | Branch, tag, or commit SHA for patches | `v1.0` |
|
||||
| `--patches-ref` | Branch, tag, or commit SHA for patches | `v1.2` |
|
||||
|
||||
## Caching
|
||||
|
||||
@@ -66,7 +132,7 @@ Use `--clean` to wipe everything and rebuild from scratch. The build will also s
|
||||
PS5 Linux Image Builder
|
||||
=======================
|
||||
Distro: all
|
||||
(ubuntu2604 arch alpine cachyos)
|
||||
(ubuntu2604 arch cachyos)
|
||||
Image size: 32000MB
|
||||
Kernel src: /path/to/work/linux
|
||||
|
||||
@@ -91,19 +157,18 @@ All verbose output goes to `build.log`. The terminal shows a spinner with live p
|
||||
| Ubuntu 26.04 (Resolute) | GNOME | `.deb` | systemd |
|
||||
| Arch | Sway | `.pkg.tar.zst` | systemd |
|
||||
| CachyOS | Gamescope + Steam Big Picture (Arch + `[cachyos]` repo, no v3 migration in image build) | `.pkg.tar.zst` | systemd |
|
||||
| Alpine (3.21) | GNOME | extracted from `.deb` | OpenRC |
|
||||
| Kali Linux Rolling | XFCE + `kali-linux-everything` | `.deb` | systemd |
|
||||
|
||||
## Multi-distro Image
|
||||
|
||||
`--distro all` builds a 32GB image with 5 partitions (one EFI boot partition plus four root filesystems):
|
||||
`--distro all` builds a 32GB image with 4 partitions (one EFI boot partition plus three root filesystems):
|
||||
|
||||
| Partition | Type | Label | Content |
|
||||
|-----------|------|-------|---------|
|
||||
| p1 | FAT32 | boot | Shared kernel, per-distro initrds, kexec scripts |
|
||||
| p2 | ext4 | ubuntu2604 | Ubuntu 26.04 rootfs |
|
||||
| p3 | ext4 | arch | Arch rootfs |
|
||||
| p4 | ext4 | alpine | Alpine rootfs |
|
||||
| p5 | ext4 | cachyos | CachyOS rootfs |
|
||||
| p4 | ext4 | cachyos | CachyOS rootfs |
|
||||
|
||||
The boot partition contains kexec scripts to switch between distros at runtime. Ubuntu 26.04 is the default boot target.
|
||||
|
||||
@@ -139,12 +204,12 @@ distros/
|
||||
ubuntu2604/ # Ubuntu 26.04 (Resolute)
|
||||
arch/ # Arch Linux
|
||||
cachyos/ # CachyOS repos + Gamescope/Steam
|
||||
alpine/ # Alpine 3.21
|
||||
kali/ # Kali Linux Rolling
|
||||
shared/ # Kernel postinst hooks (single + multi)
|
||||
boot/
|
||||
cmdline.txt # Kernel cmdline template (__DISTRO__ placeholder)
|
||||
vram.txt # VRAM allocation
|
||||
kexec-{ubuntu2604,arch,alpine,cachyos}.sh
|
||||
kexec-{ubuntu2604,arch,cachyos}.sh
|
||||
work/ # Build artifacts (auto-created)
|
||||
linux-bin/ # Compiled kernel packages
|
||||
output/ # Final .img files
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Switch to Alpine Linux via kexec
|
||||
set -e
|
||||
BOOT=/boot/efi
|
||||
kexec -l "$BOOT/bzImage" --initrd="$BOOT/initrd-alpine.img" --command-line="$(cat $BOOT/cmdline-alpine.txt)"
|
||||
kexec -e
|
||||
@@ -9,20 +9,21 @@ KERNEL_SRC=""
|
||||
CLEAN=false
|
||||
IMG_SIZE=12000
|
||||
KERNEL_ONLY=false
|
||||
PATCHES_REF="v1.0"
|
||||
PATCHES_REF="v1.2"
|
||||
|
||||
MULTI_DISTROS="ubuntu2604 arch alpine cachyos"
|
||||
MULTI_DISTROS="ubuntu2604 arch cachyos"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [--distro <distro>] [--kernel <path>] [--img-size <MB>] [--clean]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --distro Distribution to build: ubuntu2604, arch, cachyos, alpine, all (default: ubuntu2604)"
|
||||
echo " --distro Distribution to build: ubuntu2604, arch, cachyos, kali, all (default: ubuntu2604)"
|
||||
echo " --kernel Path to kernel source directory (default: auto-clone to work/linux/)"
|
||||
echo " --img-size Disk image size in MB (default: 12000, 32000 for --distro all)"
|
||||
echo " --img-size Disk image size in MB (default: 12000, 32000 for --distro all, 98304 for kali)"
|
||||
echo " --clean Remove all cached build artifacts and start from scratch"
|
||||
echo " --clean-only Remove all cached build artifacts and exit"
|
||||
echo " --kernel-only Build and package the kernel only, then exit"
|
||||
echo " --patches-ref Branch, tag, or commit SHA for patches (default: v1.0)"
|
||||
echo " --patches-ref Branch, tag, or commit SHA for patches (default: v1.2)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -32,6 +33,7 @@ while [[ $# -gt 0 ]]; do
|
||||
--kernel) KERNEL_SRC="$2"; shift 2 ;;
|
||||
--img-size) IMG_SIZE="$2"; shift 2 ;;
|
||||
--clean) CLEAN=true; shift ;;
|
||||
--clean-only) CLEAN=true; CLEAN_EXIT=true; shift ;;
|
||||
--kernel-only) KERNEL_ONLY=true; shift ;;
|
||||
--patches-ref) [ -n "$2" ] && PATCHES_REF="$2"; shift 2 ;;
|
||||
-h|--help) usage ;;
|
||||
@@ -62,9 +64,12 @@ DOCKER_NAME="ps5-build-$$"
|
||||
if [ "$DISTRO" = "all" ] && [ "$IMG_SIZE" = "12000" ]; then
|
||||
IMG_SIZE=32000
|
||||
fi
|
||||
if [ "$DISTRO" = "kali" ] && [ "$IMG_SIZE" = "12000" ]; then
|
||||
IMG_SIZE=98304
|
||||
fi
|
||||
|
||||
if [ -z "$FORMAT" ]; then
|
||||
case "$DISTRO" in arch) FORMAT="arch" ;; all) FORMAT="all" ;; *) FORMAT="deb" ;; esac
|
||||
case "$DISTRO" in arch|cachyos) FORMAT="arch" ;; all) FORMAT="all" ;; *) FORMAT="deb" ;; esac
|
||||
fi
|
||||
|
||||
KERNEL_BUILDER_PLATFORM="linux/amd64"
|
||||
@@ -76,14 +81,14 @@ esac
|
||||
BUILD_PID=""
|
||||
|
||||
cleanup() {
|
||||
trap - INT TERM EXIT
|
||||
echo ""
|
||||
echo "Interrupted. Cleaning up..."
|
||||
echo "Cleaning up..."
|
||||
docker kill "$DOCKER_NAME" 2>/dev/null || true
|
||||
[ -n "$BUILD_PID" ] && kill "$BUILD_PID" 2>/dev/null || true
|
||||
wait "$BUILD_PID" 2>/dev/null || true
|
||||
exit 130
|
||||
}
|
||||
trap cleanup INT TERM
|
||||
trap cleanup INT TERM EXIT
|
||||
|
||||
# --- Clean ---
|
||||
if [ "$CLEAN" = true ]; then
|
||||
@@ -94,6 +99,7 @@ if [ "$CLEAN" = true ]; then
|
||||
alpine rm -rf "/parent/$(basename "$dir")"
|
||||
done
|
||||
echo "Done."
|
||||
[ "$CLEAN_EXIT" = true ] && exit 0
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Grows the root partition and filesystem to fill the disk.
|
||||
# Runs once on first boot, then disables itself.
|
||||
set -e
|
||||
|
||||
ROOT_DEV=$(findmnt -no SOURCE /)
|
||||
DISK=$(lsblk -ndo PKNAME "$ROOT_DEV")
|
||||
PART_NUM=$(cat /sys/class/block/$(basename "$ROOT_DEV")/partition)
|
||||
|
||||
growpart "/dev/$DISK" "$PART_NUM" || true
|
||||
partprobe "/dev/$DISK"
|
||||
resize2fs "$ROOT_DEV" || true
|
||||
|
||||
rc-update del grow-rootfs default
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/sbin/openrc-run
|
||||
|
||||
description="Grow root filesystem to fill disk"
|
||||
|
||||
depend() {
|
||||
need localmount
|
||||
}
|
||||
|
||||
start() {
|
||||
ebegin "Growing root filesystem"
|
||||
/usr/local/sbin/grow-rootfs
|
||||
eend $?
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
image:
|
||||
name: ps5-alpine
|
||||
distribution: alpine
|
||||
release: "3.21"
|
||||
description: Alpine Linux with Weston
|
||||
architecture: x86_64
|
||||
|
||||
source:
|
||||
downloader: alpinelinux-http
|
||||
url: https://dl-cdn.alpinelinux.org/alpine
|
||||
skip_verification: true
|
||||
|
||||
packages:
|
||||
manager: apk
|
||||
update: true
|
||||
cleanup: true
|
||||
|
||||
repositories:
|
||||
- name: repositories
|
||||
url: |-
|
||||
https://dl-cdn.alpinelinux.org/alpine/v3.21/main
|
||||
https://dl-cdn.alpinelinux.org/alpine/v3.21/community
|
||||
|
||||
sets:
|
||||
- packages:
|
||||
# Wayland compositor + basics
|
||||
- weston
|
||||
- weston-shell-desktop
|
||||
- weston-backend-drm
|
||||
- weston-xwayland
|
||||
- weston-terminal
|
||||
- foot
|
||||
- xwayland
|
||||
|
||||
# Wayland support
|
||||
- dbus
|
||||
- eudev
|
||||
- elogind
|
||||
- polkit-elogind
|
||||
- seatd
|
||||
|
||||
# Audio / media
|
||||
- pipewire
|
||||
- wireplumber
|
||||
- pipewire-pulse
|
||||
|
||||
# Display / GPU
|
||||
- mesa-gbm
|
||||
- mesa-egl
|
||||
- mesa-gl
|
||||
- mesa-dri-gallium
|
||||
- mesa-va-gallium
|
||||
- mesa-vulkan-ati
|
||||
- libinput
|
||||
- xkeyboard-config
|
||||
|
||||
# Networking
|
||||
- networkmanager
|
||||
- networkmanager-wifi
|
||||
- wpa_supplicant
|
||||
- linux-firmware
|
||||
- linux-firmware-amdgpu
|
||||
- xf86-video-amdgpu
|
||||
|
||||
# System
|
||||
- openrc
|
||||
- openssh
|
||||
- sudo
|
||||
- shadow
|
||||
- nano
|
||||
- bash
|
||||
- coreutils
|
||||
- util-linux
|
||||
- e2fsprogs
|
||||
- e2fsprogs-extra
|
||||
- cloud-utils-growpart
|
||||
- mkinitfs
|
||||
- kmod
|
||||
- kexec-tools
|
||||
- syslog-ng
|
||||
|
||||
# Fonts
|
||||
- font-ubuntu
|
||||
- font-liberation
|
||||
- font-dejavu
|
||||
- fontconfig
|
||||
action: install
|
||||
|
||||
files:
|
||||
- path: /etc/hostname
|
||||
generator: hostname
|
||||
|
||||
- path: /etc/hosts
|
||||
generator: hosts
|
||||
|
||||
- path: /etc/kernel/postinst.d/zz-update-boot
|
||||
generator: copy
|
||||
source: /tmp/build-staging/zz-update-boot
|
||||
mode: "0755"
|
||||
|
||||
- path: /etc/fstab
|
||||
generator: copy
|
||||
source: /tmp/build-staging/fstab
|
||||
|
||||
- path: /usr/local/sbin/grow-rootfs
|
||||
generator: copy
|
||||
source: /tmp/build-staging/grow-rootfs
|
||||
mode: "0755"
|
||||
|
||||
- path: /etc/init.d/grow-rootfs
|
||||
generator: copy
|
||||
source: /tmp/build-staging/grow-rootfs.openrc
|
||||
mode: "0755"
|
||||
|
||||
actions:
|
||||
- trigger: post-unpack
|
||||
action: |-
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
# Retry up to 10 times on transient network errors
|
||||
echo "retries = 10" >> /etc/apk/apk.conf 2>/dev/null || true
|
||||
# dbus post-install chokes on an empty machine-id
|
||||
rm -f /etc/machine-id
|
||||
|
||||
|
||||
- trigger: post-packages
|
||||
action: |-
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
fc-cache -f -v
|
||||
|
||||
# SSH
|
||||
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
|
||||
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
||||
rc-update add syslog-ng default
|
||||
rc-update add udev sysinit
|
||||
rc-update add udev-trigger sysinit
|
||||
rc-update add udev-settle sysinit
|
||||
rc-update add sshd default
|
||||
rc-update add dbus default
|
||||
rc-update add elogind default
|
||||
rc-update add seatd default
|
||||
rc-update add networkmanager default
|
||||
|
||||
- trigger: post-files
|
||||
action: |-
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
rc-update add grow-rootfs default
|
||||
|
||||
# Create default user (ps5/ps5) in groups needed for Wayland/input
|
||||
addgroup ps5
|
||||
adduser -D -s /bin/bash -G ps5 ps5
|
||||
echo "ps5:ps5" | chpasswd
|
||||
addgroup ps5 wheel
|
||||
addgroup ps5 video
|
||||
addgroup ps5 input
|
||||
addgroup ps5 seat
|
||||
echo "%wheel ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/wheel
|
||||
|
||||
# Auto-start weston on tty1 login
|
||||
{
|
||||
echo 'if [ "$(tty)" = "/dev/tty1" ] && [ -z "$WAYLAND_DISPLAY" ]; then'
|
||||
echo ' export XDG_RUNTIME_DIR="/tmp/xdg-runtime-$(id -u)"'
|
||||
echo ' mkdir -p "$XDG_RUNTIME_DIR"'
|
||||
echo ' chmod 700 "$XDG_RUNTIME_DIR"'
|
||||
echo ' exec weston --backend=drm-backend.so'
|
||||
echo 'fi'
|
||||
} >> /home/ps5/.bash_profile
|
||||
chown -R ps5:ps5 /home/ps5
|
||||
|
||||
mkdir -p /boot/efi
|
||||
|
||||
mappings:
|
||||
architecture_map: alpinelinux
|
||||
@@ -118,13 +118,19 @@ actions:
|
||||
action: |-
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
# Pacman 7 Landlock sandbox is unsupported under QEMU; disable it.
|
||||
sed -i '/^\[options\]/a DisableSandbox' /etc/pacman.conf
|
||||
|
||||
# Initialise pacman keyring
|
||||
pacman-key --init
|
||||
pacman-key --populate archlinux
|
||||
|
||||
# Fetch up-to-date HTTPS mirrors ranked by score, force-refresh package DBs
|
||||
curl -fsSL "https://archlinux.org/mirrorlist/?country=all&protocol=https&use_mirror_status=on" \
|
||||
| sed 's/^#Server/Server/' > /etc/pacman.d/mirrorlist
|
||||
# Keep CI on a small stable mirror set. The full active global list can
|
||||
# select slow mirrors and fail pacman's low-speed download timeout.
|
||||
cat > /etc/pacman.d/mirrorlist <<'EOF'
|
||||
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
|
||||
Server = https://mirrors.kernel.org/archlinux/$repo/os/$arch
|
||||
EOF
|
||||
pacman -Syy --noconfirm
|
||||
|
||||
|
||||
@@ -132,21 +138,33 @@ actions:
|
||||
action: |-
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
fc-cache -f -v
|
||||
# fc-cache / systemctl can SIGSEGV under QEMU when image plat is linux/amd64 on arm64 hosts.
|
||||
fc-cache -f 2>/dev/null || true
|
||||
|
||||
symlink_wants() {
|
||||
local src=$1
|
||||
local target=$2
|
||||
[ -e "$src" ] || return 0
|
||||
mkdir -p "/etc/systemd/system/${target}.wants"
|
||||
ln -sf "$src" "/etc/systemd/system/${target}.wants/$(basename "$src")"
|
||||
}
|
||||
|
||||
# SSH
|
||||
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
|
||||
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
||||
systemctl enable sshd
|
||||
systemctl enable NetworkManager
|
||||
systemctl enable seatd
|
||||
systemctl enable pipewire pipewire-pulse wireplumber || true
|
||||
symlink_wants /usr/lib/systemd/system/sshd.service multi-user.target
|
||||
symlink_wants /usr/lib/systemd/system/NetworkManager.service multi-user.target
|
||||
symlink_wants /usr/lib/systemd/system/seatd.service multi-user.target
|
||||
for s in pipewire pipewire-pulse wireplumber; do
|
||||
symlink_wants "/usr/lib/systemd/system/${s}.service" default.target || true
|
||||
done
|
||||
|
||||
- trigger: post-files
|
||||
action: |-
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
systemctl enable grow-rootfs.service
|
||||
mkdir -p /etc/systemd/system/local-fs.target.wants
|
||||
ln -sf /etc/systemd/system/grow-rootfs.service \
|
||||
/etc/systemd/system/local-fs.target.wants/grow-rootfs.service
|
||||
|
||||
# Create default user (ps5/ps5)
|
||||
useradd -m -G wheel,seat -s /bin/bash ps5
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
#!/bin/bash
|
||||
# First-boot interactive setup for CachyOS PS5 image.
|
||||
# Sets the password for the 'steam' user and optionally the hostname,
|
||||
# then creates a sentinel so this script never runs again.
|
||||
set -e
|
||||
# First-boot: dialog wizard on tty1 (timezone, steam password, hostname).
|
||||
# Defaults: UTC, ps5, keep image password (steam:steam). Skips on Cancel use defaults.
|
||||
set -euo pipefail
|
||||
|
||||
# Keep interactive prompts readable on tty1 by suppressing kernel console noise
|
||||
# during setup. Restore the previous setting before exiting.
|
||||
ORIG_PRINTK="$(cat /proc/sys/kernel/printk 2>/dev/null || true)"
|
||||
if [ -n "$ORIG_PRINTK" ]; then
|
||||
echo "1 4 1 7" > /proc/sys/kernel/printk || true
|
||||
@@ -17,57 +14,93 @@ cleanup_printk() {
|
||||
}
|
||||
trap cleanup_printk EXIT
|
||||
|
||||
clear
|
||||
echo "=================================================="
|
||||
echo " Welcome to CachyOS on PS5!"
|
||||
echo "=================================================="
|
||||
echo
|
||||
echo "User: steam (fixed — used for both Gaming Mode and Desktop)"
|
||||
echo
|
||||
export TERM="${TERM:-linux}"
|
||||
|
||||
# --- Password ---
|
||||
while true; do
|
||||
read -rsp "Set a password for 'steam': " PASSWORD; echo
|
||||
read -rsp "Confirm password: " PASSWORD2; echo
|
||||
if [[ -z "$PASSWORD" ]]; then
|
||||
echo "Password cannot be empty."
|
||||
elif [[ "$PASSWORD" != "$PASSWORD2" ]]; then
|
||||
echo "Passwords do not match. Try again."
|
||||
apply_timezone() {
|
||||
local tz="${1:-UTC}"
|
||||
timedatectl set-timezone "$tz" 2>/dev/null || ln -sf "/usr/share/zoneinfo/$tz" /etc/localtime
|
||||
}
|
||||
|
||||
apply_hostname() {
|
||||
local hn="${1:-ps5}"
|
||||
hostnamectl set-hostname "$hn" 2>/dev/null || echo "$hn" > /etc/hostname
|
||||
if grep -q '^127\.0\.1\.1' /etc/hosts; then
|
||||
sed -i "s/^127\.0\.1\.1.*/127.0.1.1 $hn/" /etc/hosts
|
||||
else
|
||||
break
|
||||
echo "127.0.1.1 $hn" >> /etc/hosts
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# --- Hostname ---
|
||||
read -rp "Hostname [ps5]: " HOSTNAME
|
||||
HOSTNAME="${HOSTNAME:-ps5}"
|
||||
main() {
|
||||
if ! command -v dialog >/dev/null 2>&1; then
|
||||
echo "first-boot-setup: dialog not installed" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Applying settings..."
|
||||
clear
|
||||
|
||||
echo "steam:$PASSWORD" | chpasswd
|
||||
local choice
|
||||
choice="$(dialog --stdout --clear --menu \
|
||||
"Welcome to CachyOS on PS5\nUser: steam (Gaming Mode + Desktop)" \
|
||||
17 64 4 \
|
||||
defaults "Use defaults (UTC, hostname ps5, keep password)" \
|
||||
custom "Customize timezone, password, hostname" )" \
|
||||
|| choice="defaults"
|
||||
|
||||
hostnamectl set-hostname "$HOSTNAME" 2>/dev/null || echo "$HOSTNAME" > /etc/hostname
|
||||
# Update /etc/hosts if a 127.0.1.1 line exists, otherwise append one.
|
||||
if grep -q '^127\.0\.1\.1' /etc/hosts; then
|
||||
sed -i "s/^127\.0\.1\.1.*/127.0.1.1 $HOSTNAME/" /etc/hosts
|
||||
else
|
||||
echo "127.0.1.1 $HOSTNAME" >> /etc/hosts
|
||||
fi
|
||||
if [[ "$choice" == "defaults" ]]; then
|
||||
apply_timezone UTC
|
||||
apply_hostname ps5
|
||||
else
|
||||
local zones
|
||||
mapfile -t zones < <(timedatectl list-timezones 2>/dev/null | LC_ALL=C sort -u)
|
||||
local -a menu_args=()
|
||||
local z
|
||||
for z in "${zones[@]}"; do
|
||||
menu_args+=("$z" "$z")
|
||||
done
|
||||
|
||||
# Sentinel — prevents this service from running on subsequent boots.
|
||||
touch /etc/ps5-first-boot-done
|
||||
local tz_pick
|
||||
if ((${#menu_args[@]} == 0)); then
|
||||
apply_timezone UTC
|
||||
elif tz_pick="$(dialog --stdout --clear --menu "Select timezone (Cancel = UTC)" 22 70 15 \
|
||||
"${menu_args[@]}")"; then
|
||||
apply_timezone "$tz_pick"
|
||||
else
|
||||
apply_timezone UTC
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=================================================="
|
||||
echo " Setup complete!"
|
||||
echo "=================================================="
|
||||
echo
|
||||
echo "The system will log in on tty1 and start Steam Gaming Mode (Gamescope)."
|
||||
echo "(No display manager — same pattern as the Arch Sway image in this repo.)"
|
||||
echo
|
||||
echo "Tips:"
|
||||
echo " In Steam: Power > Switch to Desktop → KDE Plasma (X11)"
|
||||
echo " In KDE: Double-click 'Return to Gaming Mode' on the desktop"
|
||||
echo
|
||||
sleep 3
|
||||
if dialog --clear --yesno "Change password for user steam?" 8 55; then
|
||||
local p1 p2
|
||||
while true; do
|
||||
p1="$(dialog --stdout --clear --insecure --passwordbox "New password (empty = skip)" 9 55)" \
|
||||
|| break
|
||||
p2="$(dialog --stdout --clear --insecure --passwordbox "Confirm password" 9 55)" \
|
||||
|| break
|
||||
if [[ -z "$p1" ]]; then
|
||||
dialog --clear --msgbox "Password unchanged (empty)." 7 44
|
||||
break
|
||||
fi
|
||||
if [[ "$p1" != "$p2" ]]; then
|
||||
dialog --clear --msgbox "Passwords do not match. Try again." 7 50
|
||||
continue
|
||||
fi
|
||||
echo "steam:$p1" | chpasswd
|
||||
break
|
||||
done
|
||||
fi
|
||||
|
||||
local hn
|
||||
hn="$(dialog --stdout --clear --inputbox "Hostname (empty = ps5)" 9 50 "ps5")" \
|
||||
|| hn="ps5"
|
||||
hn="${hn:-ps5}"
|
||||
apply_hostname "$hn"
|
||||
fi
|
||||
|
||||
touch /etc/ps5-first-boot-done
|
||||
|
||||
dialog --clear --msgbox \
|
||||
"Setup complete.\n\nYou will log in on tty1 (Steam Gaming Mode).\n\nDesktop: Steam > Power > Switch to KDE\nReturn: double-click the desktop shortcut." \
|
||||
14 62
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -59,6 +59,11 @@ packages:
|
||||
# Networking
|
||||
- networkmanager
|
||||
- linux-firmware
|
||||
# GIO module libgiognutls.so (KDE/Konsole, GVfs, etc.): needs gnutls → nettle (libhogweed).
|
||||
# Explicit install avoids a sparse dependency tree under distrobuilder cleanup: true.
|
||||
- gnutls
|
||||
- nettle
|
||||
- glib-networking
|
||||
|
||||
# System
|
||||
- base
|
||||
@@ -75,6 +80,7 @@ packages:
|
||||
- dbus
|
||||
- kexec-tools
|
||||
- curl
|
||||
- dialog
|
||||
|
||||
# Fonts (Steam UI + KDE) — CJK + emoji avoid "tofu" boxes in Steam Big Picture language list
|
||||
- ttf-dejavu
|
||||
@@ -156,12 +162,8 @@ actions:
|
||||
action: |-
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
# Pacman 7 Landlock/seccomp sandbox breaks under distrobuilder/Docker (unsupported kernel).
|
||||
if grep -q '^#DisableSandbox' /etc/pacman.conf; then
|
||||
sed -i 's/^#DisableSandbox/DisableSandbox/' /etc/pacman.conf
|
||||
elif ! grep -q '^DisableSandbox' /etc/pacman.conf; then
|
||||
sed -i '/^\[options\]/a DisableSandbox' /etc/pacman.conf
|
||||
fi
|
||||
# Pacman 7 Landlock sandbox is unsupported under QEMU; disable it.
|
||||
sed -i '/^\[options\]/a DisableSandbox' /etc/pacman.conf
|
||||
|
||||
CACHYOS_PKG="https://mirror.cachyos.org/repo/x86_64/cachyos"
|
||||
|
||||
@@ -184,8 +186,12 @@ actions:
|
||||
# Enable #[multilib] / #Include block (\\\\ in YAML would break the sed address regex)
|
||||
sed -i '/^#\[multilib\]/,/^#Include/s/^#//' /etc/pacman.conf
|
||||
|
||||
curl -fsSL "https://archlinux.org/mirrorlist/?country=all&protocol=https&use_mirror_status=on" \
|
||||
| sed 's/^#Server/Server/' > /etc/pacman.d/mirrorlist
|
||||
# Keep CI on a small stable mirror set. The full active global list can
|
||||
# select slow mirrors and fail pacman's low-speed download timeout.
|
||||
cat > /etc/pacman.d/mirrorlist <<'EOF'
|
||||
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
|
||||
Server = https://mirrors.kernel.org/archlinux/$repo/os/$arch
|
||||
EOF
|
||||
|
||||
pacman -Syy --noconfirm
|
||||
|
||||
@@ -245,6 +251,8 @@ actions:
|
||||
touch /etc/ps5-use-tty-sessions
|
||||
ln -sf /usr/lib/systemd/system/multi-user.target /etc/systemd/system/default.target
|
||||
ln -sf /dev/null /etc/systemd/system/sddm.service
|
||||
# First-boot wizard handles timezone/password/hostname; avoid duplicate prompts.
|
||||
ln -sf /dev/null /etc/systemd/system/systemd-firstboot.service
|
||||
|
||||
mkdir -p /etc/systemd/system/getty@tty1.service.d
|
||||
printf '%s\n' '[Service]' 'ExecStart=' 'ExecStart=-/sbin/agetty --autologin steam --noclear %I $TERM' \
|
||||
@@ -322,7 +330,7 @@ actions:
|
||||
/etc/mkinitcpio.conf
|
||||
|
||||
if ls /opt/pkgs/*.pkg.tar.zst 1>/dev/null 2>&1; then
|
||||
pacman -U --noconfirm /opt/pkgs/*.pkg.tar.zst
|
||||
pacman -U --noconfirm --ask 4 /opt/pkgs/*.pkg.tar.zst
|
||||
rm -rf /opt/pkgs
|
||||
KVER=$(ls -1t /lib/modules | head -1)
|
||||
mkinitcpio -k "$KVER" -g "/boot/initrd.img-$KVER" || true
|
||||
|
||||
1
distros/kali/cmdline.txt
Normal file
1
distros/kali/cmdline.txt
Normal file
@@ -0,0 +1 @@
|
||||
root=LABEL=__DISTRO__ rw rootwait console=ttyTitania0 console=tty0 mitigations=off idle=halt preempt=full
|
||||
19
distros/kali/grow-rootfs
Normal file
19
distros/kali/grow-rootfs
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
# Grows the root partition and filesystem to fill the disk.
|
||||
# Runs once on first boot, then disables itself.
|
||||
# If resize fails, the service stays enabled and retries next boot.
|
||||
|
||||
ROOT_DEV=$(findmnt -no SOURCE /) || { echo "Cannot find root device"; exit 1; }
|
||||
DISK=$(lsblk -ndo PKNAME "$ROOT_DEV")
|
||||
PART_NUM=$(cat /sys/class/block/$(basename "$ROOT_DEV")/partition 2>/dev/null)
|
||||
|
||||
if [ -z "$DISK" ] || [ -z "$PART_NUM" ]; then
|
||||
echo "Cannot determine disk layout (DISK=$DISK PART_NUM=$PART_NUM)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
growpart "/dev/$DISK" "$PART_NUM" || true
|
||||
partprobe "/dev/$DISK"
|
||||
resize2fs "$ROOT_DEV"
|
||||
|
||||
systemctl disable grow-rootfs.service
|
||||
10
distros/kali/grow-rootfs.service
Normal file
10
distros/kali/grow-rootfs.service
Normal file
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Grow root filesystem to fill disk
|
||||
After=local-fs.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/sbin/grow-rootfs
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
286
distros/kali/image.yaml
Normal file
286
distros/kali/image.yaml
Normal file
@@ -0,0 +1,286 @@
|
||||
image:
|
||||
name: ps5-kali
|
||||
distribution: debian
|
||||
release: kali-rolling
|
||||
description: Kali Linux XFCE desktop
|
||||
architecture: x86_64
|
||||
|
||||
source:
|
||||
downloader: debootstrap
|
||||
url: https://kali.download/kali
|
||||
variant: minbase
|
||||
keyserver: keyserver.ubuntu.com
|
||||
keys:
|
||||
- 0x827C8569F2518CC677FECA1AED65462EC8D5E4C5
|
||||
|
||||
packages:
|
||||
manager: apt
|
||||
update: true
|
||||
cleanup: true
|
||||
|
||||
repositories:
|
||||
- name: sources.list
|
||||
url: |-
|
||||
deb https://kali.download/kali kali-rolling main contrib non-free non-free-firmware
|
||||
architectures:
|
||||
- amd64
|
||||
|
||||
sets:
|
||||
- packages:
|
||||
# Full Kali desktop and toolset
|
||||
- kali-desktop-xfce
|
||||
- kali-linux-everything
|
||||
- kali-defaults
|
||||
- kali-defaults-desktop
|
||||
- kali-themes
|
||||
- kali-wallpapers-2026
|
||||
- kali-wallpapers-all
|
||||
- kali-menu
|
||||
- kali-tweaks
|
||||
- kali-undercover
|
||||
|
||||
# Display / GPU / audio
|
||||
- lightdm
|
||||
- lightdm-gtk-greeter
|
||||
- xserver-xorg
|
||||
- xserver-xorg-video-amdgpu
|
||||
- dbus-x11
|
||||
- x11-xserver-utils
|
||||
- mesa-vulkan-drivers
|
||||
- pipewire
|
||||
- pipewire-pulse
|
||||
- wireplumber
|
||||
- pavucontrol
|
||||
|
||||
# Networking and remote access
|
||||
- network-manager
|
||||
- network-manager-gnome
|
||||
- openssh-server
|
||||
- iputils-ping
|
||||
- ntpsec
|
||||
- iw
|
||||
- wpasupplicant
|
||||
- wireless-regdb
|
||||
|
||||
# Firmware and PS5 boot support
|
||||
- firmware-linux
|
||||
- firmware-linux-nonfree
|
||||
- firmware-amd-graphics
|
||||
- firmware-realtek
|
||||
- firmware-atheros
|
||||
- firmware-mediatek
|
||||
- firmware-misc-nonfree
|
||||
- initramfs-tools
|
||||
- kexec-tools
|
||||
- kmod
|
||||
- busybox
|
||||
- zstd
|
||||
- systemd-zram-generator
|
||||
|
||||
# Base system utilities
|
||||
- sudo
|
||||
- cloud-guest-utils
|
||||
- parted
|
||||
- e2fsprogs
|
||||
- usbutils
|
||||
- pciutils
|
||||
- rfkill
|
||||
- util-linux
|
||||
- curl
|
||||
- wget
|
||||
- git
|
||||
- vim
|
||||
- nano
|
||||
- tmux
|
||||
- firefox-esr
|
||||
# Ghidra 12.1 requires JDK 21. The full Kali set also installs newer JDKs.
|
||||
- openjdk-21-jdk
|
||||
action: install
|
||||
|
||||
files:
|
||||
- path: /etc/hostname
|
||||
generator: hostname
|
||||
|
||||
- path: /etc/hosts
|
||||
generator: hosts
|
||||
|
||||
- path: /etc/machine-id
|
||||
generator: dump
|
||||
|
||||
- path: /etc/kernel/postinst.d/zz-update-boot
|
||||
generator: copy
|
||||
source: /tmp/build-staging/zz-update-boot
|
||||
mode: "0755"
|
||||
|
||||
- path: /etc/fstab
|
||||
generator: copy
|
||||
source: /tmp/build-staging/fstab
|
||||
|
||||
- path: /etc/apt/trusted.gpg.d/kali-archive-keyring.asc
|
||||
generator: copy
|
||||
source: /tmp/build-staging/kali-archive-keyring.asc
|
||||
|
||||
- path: /usr/local/sbin/grow-rootfs
|
||||
generator: copy
|
||||
source: /tmp/build-staging/grow-rootfs
|
||||
mode: "0755"
|
||||
|
||||
- path: /etc/systemd/system/grow-rootfs.service
|
||||
generator: copy
|
||||
source: /tmp/build-staging/grow-rootfs.service
|
||||
|
||||
- path: /opt/debs/
|
||||
generator: copy
|
||||
source: /tmp/build-staging/debs
|
||||
|
||||
actions:
|
||||
- trigger: post-unpack
|
||||
action: |-
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
rm -f /var/lib/apt/lists/*InRelease /var/lib/apt/lists/*Release /var/lib/apt/lists/*Packages* || true
|
||||
echo 'Acquire::Retries "10";' > /etc/apt/apt.conf.d/80retry
|
||||
cat > /etc/apt/trusted.gpg.d/kali-archive-keyring.asc <<'EOF'
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBGgBJJUBEADlMTZVDCjrSXIAuYfL3VZt8OoplUdw3mSPlhIjZQmIo2sdzvAF
|
||||
EMSCQ+vWeD4VqV9tBtiVx6j8VSfyW18YHHAkvajWDRg5hPLf80wGxrtXYu+vj3Ri
|
||||
5dOMhrl9fHKIifPOoV3pFTtOk0dB9lkcmtNzjWgwOJduLbjjraE1BBKqc0uaXDCa
|
||||
RJnPYkQuJQcZxmZVFAo9NP7KSAL1zMvutAd0R3WeMaWpT22nGa3rJj4kj25zV6Kn
|
||||
qGnv5kQaY2cTlQHnp6EbiLe5sCE7zIOp5CjwIJhyCyn4zT8KqGB8Sw8PEi9mYlSY
|
||||
wbGzzfAAbBk7Y8xbmvRrkrHzU74jH0iMK566QVu2yl3Dz0hrlliV6vGn2ZWu7qmh
|
||||
lwXSb+q4u46tDbFjdUjYJG2upx5vOm5SewD9snLB4YN2e2qDeQgY16AfpkJa51+u
|
||||
PwTeDCbfuQu3irLWcGRZgpOBgsxqCtpZBmF6ED7L8tntoyjZ9WeB8FnTcv7hx5J1
|
||||
IPCO4K5TvW0SX6ZKp1Jusbkn5hrrFTjOJHhIDVdioM/wYDKkqJ9e25oGAqPkJYRY
|
||||
euonU1teK+EOLM7ZIbalhukrw0bgYl9UJRxQMLEhZzoiiCLLiv3oWHAQGFclP+1E
|
||||
zXgbLBviFAU4+DMXfhA6vy8BmS9oTpleS1p3/EOwf2rX/yt4qF7IW9ZXuQARAQAB
|
||||
tEBLYWxpIExpbnV4IEFyY2hpdmUgQXV0b21hdGljIFNpZ25pbmcgS2V5ICgyMDI1
|
||||
KSA8ZGV2ZWxAa2FsaS5vcmc+iQJUBBMBCgA+FiEEgnyFafJRjMZ3/soa7WVGLsjV
|
||||
5MUFAmgF7tkCGwMFCQWkfeUFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ7WVG
|
||||
LsjV5MXcjw//XeI6OXY7VcH+hXRcT7W49AwqRfmSaSEWs474G2DQR9UppzvkFCab
|
||||
uiWl5jrlkeGbVFsiBruJfIlCdYMMnPk8gEm/SEhVRqcZVOjYCWcMlSVB6oU+6tgW
|
||||
jKPPRDELiq7mTl8S4sEdvUxpsWoMqEQZ1+CsJsw+p+TARGNIrUUdL9hTOoOUpvue
|
||||
nKNEEfzbKvLk2gj2tKOgr1HcDmVbbmRsL87+UYq1JvA0OzJ0KrhBdTZHJWchAJwa
|
||||
p+UUog2XrzvXYXWBPfQLsNVkFirmVd1B5vonj3OeNlVU51YriRQ4P4onLrwlfha8
|
||||
vUGeNJw/ihXTQFpvmF7fFSRa7Pr5YfWkDZ4BGuEB+kSycu2PMWCXXHdY++cMIlRf
|
||||
uUg/wvzcwAkS99DJ0EAiOun0oypE5+r5HwfaI9IrJlgZMPlFctyBIGVg2DFZCdLH
|
||||
VHG1Voq/CU2tgWvWyuHXHVlUiZiWJoj7BbVa88Gj+VyvB/md1xBh0ScmfH4uGgnX
|
||||
hpLFPIVuR1SJYarovVmtFhAjbqbrAA4Q9utpOeOOVDMD5tuq856/lLh+SWPkRsUy
|
||||
ZJTwz1Nh0rJ/UJOMSo4ljkkr53iR/IM4woAAaP+0hkZoIDSbVVW5Im1Yj461exl4
|
||||
0ltMBMym2KZk/IFOTloSfW7hMmGlqaLfQEH1ryHefIIpkgKJa6WgVxA=
|
||||
=f+tz
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
EOF
|
||||
apt-get update
|
||||
|
||||
- trigger: post-update
|
||||
action: |-
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
passwd -l root
|
||||
|
||||
- trigger: post-packages
|
||||
action: |-
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
# Default user (kali/kali)
|
||||
useradd -m -G sudo -s /bin/bash kali
|
||||
echo "kali:kali" | chpasswd
|
||||
|
||||
# The image is assembled inside Docker, where the generated hostname is
|
||||
# otherwise the temporary container ID. Use a stable PS5 hostname.
|
||||
printf 'ps5\n' > /etc/hostname
|
||||
if grep -q '^127\.0\.1\.1' /etc/hosts; then
|
||||
sed -i 's/^127\.0\.1\.1.*/127.0.1.1 ps5/' /etc/hosts
|
||||
else
|
||||
printf '127.0.1.1 ps5\n' >> /etc/hosts
|
||||
fi
|
||||
|
||||
# Ghidra 12.1 requires JDK 21, while Kali Rolling may select a newer Java
|
||||
# as the system default. Keep its desktop launcher on the supported JDK.
|
||||
test -x /usr/lib/jvm/java-21-openjdk-amd64/bin/java
|
||||
sed -i 's|^JAVA_HOME_OVERRIDE=.*|JAVA_HOME_OVERRIDE=/usr/lib/jvm/java-21-openjdk-amd64|' /usr/share/ghidra/support/launch.properties
|
||||
|
||||
# LightDM autologin into XFCE
|
||||
mkdir -p /etc/lightdm/lightdm.conf.d
|
||||
cat > /etc/lightdm/lightdm.conf.d/50-ps5-autologin.conf <<'EOF'
|
||||
[Seat:*]
|
||||
autologin-user=kali
|
||||
autologin-user-timeout=0
|
||||
user-session=xfce
|
||||
EOF
|
||||
|
||||
# SSH is installed for opt-in remote access. Keep it disabled while the
|
||||
# distributed image still has public default local credentials.
|
||||
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
|
||||
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
||||
|
||||
systemctl set-default graphical.target
|
||||
systemctl disable ssh.service || true
|
||||
systemctl disable ssh.socket || true
|
||||
systemctl enable NetworkManager
|
||||
systemctl enable lightdm
|
||||
|
||||
# PS5 systems may boot without a useful hardware clock. Keep the shared
|
||||
# image timezone-neutral and synchronize after a network connection exists.
|
||||
ln -sf /usr/share/zoneinfo/Etc/UTC /etc/localtime
|
||||
printf 'Etc/UTC\n' > /etc/timezone
|
||||
# Android USB tethering may provide IPv4 only. The default pool returned
|
||||
# one unreachable IPv4 peer in PS5 testing; these independent IPv4 peers
|
||||
# responded and preserve multi-source time validation.
|
||||
sed -i '/^pool [0-3]\.debian\.pool\.ntp\.org /s/^/# PS5 replaced: /' /etc/ntpsec/ntp.conf
|
||||
cat >> /etc/ntpsec/ntp.conf <<'EOF'
|
||||
|
||||
# PS5 USB-tether-friendly IPv4 time sources
|
||||
server -4 time.cloudflare.com iburst
|
||||
server -4 time.google.com iburst
|
||||
server -4 time.apple.com iburst
|
||||
server -4 time.windows.com iburst
|
||||
EOF
|
||||
systemctl enable ntpsec.service
|
||||
|
||||
# zram swap: half of RAM, zstd compressed
|
||||
printf '[zram0]\nzram-size = ram / 2\ncompression-algorithm = zstd\n' > /etc/systemd/zram-generator.conf
|
||||
|
||||
# Avoid PS5 display sleep/blanking during first boot demos.
|
||||
install -d -m 0755 /home/kali/.config/autostart
|
||||
cat > /home/kali/.config/autostart/ps5-display.desktop <<'EOF'
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=PS5 Display Defaults
|
||||
Exec=sh -c 'xset s off -dpms; xset s noblank'
|
||||
X-GNOME-Autostart-enabled=true
|
||||
EOF
|
||||
chown -R kali:kali /home/kali
|
||||
|
||||
- trigger: post-files
|
||||
action: |-
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
systemctl enable grow-rootfs.service
|
||||
mkdir -p /boot/efi
|
||||
|
||||
# This USB image uses zram, not a disk-backed hibernation device. Avoid
|
||||
# embedding a temporary build-container device as a resume target.
|
||||
mkdir -p /etc/initramfs-tools/conf.d
|
||||
printf 'RESUME=none\n' > /etc/initramfs-tools/conf.d/resume
|
||||
|
||||
dpkg -i /opt/debs/*.deb
|
||||
rm -rf /opt/debs
|
||||
# kali-linux-everything installs a generic Kali kernel. Keep updates from
|
||||
# replacing the PS5-patched kernel used by the loader.
|
||||
dpkg-query -W -f='${binary:Package} ${db:Status-Status}\n' 'linux-image-*' 2>/dev/null \
|
||||
| awk '$2 == "installed" { print $1 }' \
|
||||
| xargs -r apt-mark hold
|
||||
apt-mark hold linux-ps5 || true
|
||||
|
||||
KVER=$(ls -1t /lib/modules | head -1)
|
||||
depmod -a "$KVER"
|
||||
grep -qxF amdgpu /etc/initramfs-tools/modules || printf '\namdgpu\n' >> /etc/initramfs-tools/modules
|
||||
printf 'MODULES=most\nBUSYBOX=y\n' > /etc/initramfs-tools/conf.d/ps5-amdgpu
|
||||
update-initramfs -c -k "$KVER"
|
||||
/etc/kernel/postinst.d/zz-update-boot "$KVER"
|
||||
|
||||
mappings:
|
||||
architecture_map: debian
|
||||
29
distros/kali/kali-archive-keyring.asc
Normal file
29
distros/kali/kali-archive-keyring.asc
Normal file
@@ -0,0 +1,29 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBGgBJJUBEADlMTZVDCjrSXIAuYfL3VZt8OoplUdw3mSPlhIjZQmIo2sdzvAF
|
||||
EMSCQ+vWeD4VqV9tBtiVx6j8VSfyW18YHHAkvajWDRg5hPLf80wGxrtXYu+vj3Ri
|
||||
5dOMhrl9fHKIifPOoV3pFTtOk0dB9lkcmtNzjWgwOJduLbjjraE1BBKqc0uaXDCa
|
||||
RJnPYkQuJQcZxmZVFAo9NP7KSAL1zMvutAd0R3WeMaWpT22nGa3rJj4kj25zV6Kn
|
||||
qGnv5kQaY2cTlQHnp6EbiLe5sCE7zIOp5CjwIJhyCyn4zT8KqGB8Sw8PEi9mYlSY
|
||||
wbGzzfAAbBk7Y8xbmvRrkrHzU74jH0iMK566QVu2yl3Dz0hrlliV6vGn2ZWu7qmh
|
||||
lwXSb+q4u46tDbFjdUjYJG2upx5vOm5SewD9snLB4YN2e2qDeQgY16AfpkJa51+u
|
||||
PwTeDCbfuQu3irLWcGRZgpOBgsxqCtpZBmF6ED7L8tntoyjZ9WeB8FnTcv7hx5J1
|
||||
IPCO4K5TvW0SX6ZKp1Jusbkn5hrrFTjOJHhIDVdioM/wYDKkqJ9e25oGAqPkJYRY
|
||||
euonU1teK+EOLM7ZIbalhukrw0bgYl9UJRxQMLEhZzoiiCLLiv3oWHAQGFclP+1E
|
||||
zXgbLBviFAU4+DMXfhA6vy8BmS9oTpleS1p3/EOwf2rX/yt4qF7IW9ZXuQARAQAB
|
||||
tEBLYWxpIExpbnV4IEFyY2hpdmUgQXV0b21hdGljIFNpZ25pbmcgS2V5ICgyMDI1
|
||||
KSA8ZGV2ZWxAa2FsaS5vcmc+iQJUBBMBCgA+FiEEgnyFafJRjMZ3/soa7WVGLsjV
|
||||
5MUFAmgF7tkCGwMFCQWkfeUFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ7WVG
|
||||
LsjV5MXcjw//XeI6OXY7VcH+hXRcT7W49AwqRfmSaSEWs474G2DQR9UppzvkFCab
|
||||
uiWl5jrlkeGbVFsiBruJfIlCdYMMnPk8gEm/SEhVRqcZVOjYCWcMlSVB6oU+6tgW
|
||||
jKPPRDELiq7mTl8S4sEdvUxpsWoMqEQZ1+CsJsw+p+TARGNIrUUdL9hTOoOUpvue
|
||||
nKNEEfzbKvLk2gj2tKOgr1HcDmVbbmRsL87+UYq1JvA0OzJ0KrhBdTZHJWchAJwa
|
||||
p+UUog2XrzvXYXWBPfQLsNVkFirmVd1B5vonj3OeNlVU51YriRQ4P4onLrwlfha8
|
||||
vUGeNJw/ihXTQFpvmF7fFSRa7Pr5YfWkDZ4BGuEB+kSycu2PMWCXXHdY++cMIlRf
|
||||
uUg/wvzcwAkS99DJ0EAiOun0oypE5+r5HwfaI9IrJlgZMPlFctyBIGVg2DFZCdLH
|
||||
VHG1Voq/CU2tgWvWyuHXHVlUiZiWJoj7BbVa88Gj+VyvB/md1xBh0ScmfH4uGgnX
|
||||
hpLFPIVuR1SJYarovVmtFhAjbqbrAA4Q9utpOeOOVDMD5tuq856/lLh+SWPkRsUy
|
||||
ZJTwz1Nh0rJ/UJOMSo4ljkkr53iR/IM4woAAaP+0hkZoIDSbVVW5Im1Yj461exl4
|
||||
0ltMBMym2KZk/IFOTloSfW7hMmGlqaLfQEH1ryHefIIpkgKJa6WgVxA=
|
||||
=f+tz
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
@@ -5,6 +5,23 @@ set -e
|
||||
BOOT_PART="/boot/efi"
|
||||
KVER="$1"
|
||||
[ -z "$KVER" ] && KVER="$(ls -1t /lib/modules | head -1)"
|
||||
|
||||
# Debian-based desktop metapackages may also install a generic kernel. Once
|
||||
# linux-ps5 is present, never deploy another kernel to the PS5 boot partition.
|
||||
if command -v dpkg-query >/dev/null 2>&1 && dpkg-query -W linux-ps5 >/dev/null 2>&1; then
|
||||
PS5_KVER="$(dpkg-query -L linux-ps5 | sed -n 's#^/boot/vmlinuz-##p' | head -1)"
|
||||
if [ -n "$PS5_KVER" ] && [ "$KVER" != "$PS5_KVER" ]; then
|
||||
echo ">> Ignoring non-PS5 kernel $KVER (PS5 kernel is $PS5_KVER)"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "$BOOT_PART/bzImage" ]; then
|
||||
mv "$BOOT_PART/bzImage" "$BOOT_PART/bzImage.old"
|
||||
fi
|
||||
if [ -f "$BOOT_PART/initrd.img" ]; then
|
||||
mv "$BOOT_PART/initrd.img" "$BOOT_PART/initrd.img.old"
|
||||
fi
|
||||
cp "/boot/vmlinuz-$KVER" "$BOOT_PART/bzImage"
|
||||
cp "/boot/initrd.img-$KVER" "$BOOT_PART/initrd.img"
|
||||
echo ">> Kernel $KVER deployed to $BOOT_PART"
|
||||
|
||||
@@ -9,11 +9,30 @@ KVER="$1"
|
||||
DISTRO="unknown"
|
||||
[ -f /etc/ps5-distro ] && DISTRO="$(cat /etc/ps5-distro)"
|
||||
|
||||
# Debian-based desktop metapackages may also install a generic kernel. Once
|
||||
# linux-ps5 is present, never deploy another kernel to the PS5 boot partition.
|
||||
if command -v dpkg-query >/dev/null 2>&1 && dpkg-query -W linux-ps5 >/dev/null 2>&1; then
|
||||
PS5_KVER="$(dpkg-query -L linux-ps5 | sed -n 's#^/boot/vmlinuz-##p' | head -1)"
|
||||
if [ -n "$PS5_KVER" ] && [ "$KVER" != "$PS5_KVER" ]; then
|
||||
echo ">> Ignoring non-PS5 kernel $KVER (PS5 kernel is $PS5_KVER)"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "$BOOT_PART/bzImage" ]; then
|
||||
mv "$BOOT_PART/bzImage" "$BOOT_PART/bzImage.old"
|
||||
fi
|
||||
if [ -f "$BOOT_PART/initrd-${DISTRO}.img" ]; then
|
||||
mv "$BOOT_PART/initrd-${DISTRO}.img" "$BOOT_PART/initrd-${DISTRO}.img.old"
|
||||
fi
|
||||
cp "/boot/vmlinuz-$KVER" "$BOOT_PART/bzImage"
|
||||
cp "/boot/initrd.img-$KVER" "$BOOT_PART/initrd-${DISTRO}.img"
|
||||
|
||||
# Ubuntu 26.04 is default boot — also update the generic initrd.img
|
||||
if [ "$DISTRO" = "ubuntu2604" ]; then
|
||||
if [ -f "$BOOT_PART/initrd.img" ]; then
|
||||
mv "$BOOT_PART/initrd.img" "$BOOT_PART/initrd.img.old"
|
||||
fi
|
||||
cp "/boot/initrd.img-$KVER" "$BOOT_PART/initrd.img"
|
||||
fi
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ set -ex
|
||||
|
||||
IMG_SIZE="${IMG_SIZE:-32000}"
|
||||
SKIP_CHROOT="${SKIP_CHROOT:-false}"
|
||||
DISTROS="${DISTROS:-ubuntu2604 arch alpine cachyos}"
|
||||
DISTROS="${DISTROS:-ubuntu2604 arch cachyos}"
|
||||
STAGING="/tmp/build-staging"
|
||||
EFI_LABEL="boot"
|
||||
IMG="/output/ps5-multi.img"
|
||||
@@ -42,10 +42,6 @@ for DISTRO in $DISTROS; do
|
||||
cp /repo/distros/${DISTRO}/grow-rootfs.service "$STAGING/"
|
||||
cp /kernel-debs/*.deb "$STAGING/debs/"
|
||||
;;
|
||||
alpine)
|
||||
cp /repo/distros/${DISTRO}/grow-rootfs "$STAGING/"
|
||||
cp /repo/distros/alpine/grow-rootfs.openrc "$STAGING/"
|
||||
;;
|
||||
arch)
|
||||
cp /repo/distros/${DISTRO}/grow-rootfs "$STAGING/"
|
||||
cp /repo/distros/arch/grow-rootfs.service "$STAGING/"
|
||||
@@ -87,75 +83,6 @@ for DISTRO in $DISTROS; do
|
||||
echo "$DISTRO" > "$CHROOT/etc/ps5-distro"
|
||||
fi
|
||||
|
||||
# --- Alpine kernel gap: no kernel installed via image.yaml ---
|
||||
# This runs even with --skip-chroot because Alpine's rootfs never includes a kernel;
|
||||
# we must always extract it from the .deb artifacts and generate an initrd.
|
||||
if [ "$DISTRO" = "alpine" ]; then
|
||||
echo "=== Alpine: installing kernel from .deb artifacts ==="
|
||||
|
||||
# Extract modules + vmlinuz from the linux-image .deb
|
||||
ALPINE_STAGING="/tmp/alpine-kernel-staging"
|
||||
rm -rf "$ALPINE_STAGING"
|
||||
mkdir -p "$ALPINE_STAGING"
|
||||
for deb in /kernel-debs/linux-image-*.deb; do
|
||||
[ -f "$deb" ] || continue
|
||||
dpkg-deb -x "$deb" "$ALPINE_STAGING"
|
||||
done
|
||||
|
||||
# Identify kernel version from the extracted .deb before copying
|
||||
KVER=$(ls -1 "$ALPINE_STAGING/lib/modules" 2>/dev/null | head -1)
|
||||
|
||||
if [ -n "$KVER" ]; then
|
||||
# Resolve the real modules path inside the chroot.
|
||||
# Alpine may use usr-merge (/lib -> usr/lib), so we must follow
|
||||
# symlinks to find the actual directory on disk.
|
||||
if [ -L "$CHROOT/lib" ]; then
|
||||
MODDIR="$CHROOT/usr/lib/modules"
|
||||
else
|
||||
MODDIR="$CHROOT/lib/modules"
|
||||
fi
|
||||
mkdir -p "$MODDIR"
|
||||
# Remove any stale modules from a previous build
|
||||
rm -rf "$MODDIR/$KVER"
|
||||
cp -a "$ALPINE_STAGING/lib/modules/$KVER" "$MODDIR/"
|
||||
mkdir -p "$CHROOT/boot"
|
||||
cp "$ALPINE_STAGING/boot/vmlinuz-$KVER" "$CHROOT/boot/vmlinuz-$KVER"
|
||||
echo ">> Alpine: modules copied to $MODDIR/$KVER"
|
||||
ls -la "$MODDIR/"
|
||||
fi
|
||||
rm -rf "$ALPINE_STAGING"
|
||||
|
||||
if [ -n "$KVER" ]; then
|
||||
echo "=== Alpine: generating initrd ==="
|
||||
chroot "$CHROOT" depmod -a "$KVER" 2>/dev/null || true
|
||||
|
||||
# Bind-mount essentials and run mkinitfs inside the alpine chroot
|
||||
mount --bind /dev "$CHROOT/dev"
|
||||
mount --bind /proc "$CHROOT/proc"
|
||||
mount --bind /sys "$CHROOT/sys"
|
||||
chroot "$CHROOT" mkinitfs -k "$KVER" -o "/boot/initrd.img-$KVER" "$KVER" || true
|
||||
umount "$CHROOT/sys" "$CHROOT/proc" "$CHROOT/dev"
|
||||
|
||||
# Populate /boot/efi/ for boot partition assembly
|
||||
mkdir -p "$CHROOT/boot/efi"
|
||||
cp "$CHROOT/boot/vmlinuz-$KVER" "$CHROOT/boot/efi/bzImage"
|
||||
# mkinitfs may output as initramfs-<flavor> — find whatever was generated
|
||||
if [ -f "$CHROOT/boot/initrd.img-$KVER" ]; then
|
||||
cp "$CHROOT/boot/initrd.img-$KVER" "$CHROOT/boot/efi/initrd.img"
|
||||
else
|
||||
# mkinitfs default output: /boot/initramfs-vanilla or similar
|
||||
INITRD=$(ls -1t "$CHROOT"/boot/initramfs-* "$CHROOT"/boot/initrd* 2>/dev/null | head -1)
|
||||
if [ -n "$INITRD" ]; then
|
||||
cp "$INITRD" "$CHROOT/boot/efi/initrd.img"
|
||||
else
|
||||
echo "WARNING: No initrd found for alpine after mkinitfs"
|
||||
fi
|
||||
fi
|
||||
echo ">> Alpine: kernel $KVER staged to boot/efi/"
|
||||
else
|
||||
echo "WARNING: No kernel modules found in .deb for alpine, skipping initrd generation"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# ======================================================================
|
||||
@@ -259,9 +186,6 @@ for DISTRO in $DISTROS; do
|
||||
cp "$EFIDIR/initrd.img" "/tmp/mnt_boot/initrd-${DISTRO}.img"
|
||||
elif [ -n "$KVER" ] && [ -f "$BOOTDIR/initrd.img-$KVER" ]; then
|
||||
cp "$BOOTDIR/initrd.img-$KVER" "/tmp/mnt_boot/initrd-${DISTRO}.img"
|
||||
elif [ -f "$BOOTDIR/initramfs-vanilla" ]; then
|
||||
# Alpine mkinitfs names its output initramfs-vanilla
|
||||
cp "$BOOTDIR/initramfs-vanilla" "/tmp/mnt_boot/initrd-${DISTRO}.img"
|
||||
fi
|
||||
|
||||
# Clean up /boot/efi contents from the rootfs (they're on the boot partition now)
|
||||
|
||||
@@ -10,6 +10,10 @@ EFI_LABEL="boot"
|
||||
CHROOT="/build/chroot"
|
||||
IMG="/output/ps5-${DISTRO}.img"
|
||||
|
||||
if [ "$DISTRO" = "kali" ]; then
|
||||
ROOT_LABEL="kali-root"
|
||||
fi
|
||||
|
||||
if [ "$SKIP_CHROOT" = "true" ] && [ -d "$CHROOT/bin" ]; then
|
||||
echo "=== Reusing cached $DISTRO rootfs ==="
|
||||
else
|
||||
@@ -34,9 +38,11 @@ EOF
|
||||
cp /repo/distros/${DISTRO}/grow-rootfs.service "$STAGING/"
|
||||
cp /kernel-debs/*.deb "$STAGING/debs/"
|
||||
;;
|
||||
alpine)
|
||||
cp /repo/distros/${DISTRO}/grow-rootfs "$STAGING/"
|
||||
cp /repo/distros/alpine/grow-rootfs.openrc "$STAGING/"
|
||||
kali)
|
||||
cp /repo/distros/${DISTRO}/grow-rootfs "$STAGING/"
|
||||
cp /repo/distros/${DISTRO}/grow-rootfs.service "$STAGING/"
|
||||
cp /repo/distros/${DISTRO}/kali-archive-keyring.asc "$STAGING/"
|
||||
cp /kernel-debs/*.deb "$STAGING/debs/"
|
||||
;;
|
||||
arch)
|
||||
cp /repo/distros/${DISTRO}/grow-rootfs "$STAGING/"
|
||||
@@ -62,6 +68,11 @@ EOF
|
||||
;;
|
||||
esac
|
||||
|
||||
find "$STAGING" -type f \
|
||||
! -path "$STAGING/debs/*" \
|
||||
! -path "$STAGING/pkgs/*" \
|
||||
-exec sed -i 's/\r$//' {} +
|
||||
|
||||
# --- Build rootfs ---
|
||||
rm -rf "$CHROOT"/* "$CHROOT"/.[!.]* 2>/dev/null || true
|
||||
|
||||
@@ -77,69 +88,12 @@ case "$DISTRO" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- Alpine kernel gap: no kernel installed via image.yaml ---
|
||||
# Extract kernel from .deb, copy modules + bzImage, then chroot to run mkinitfs
|
||||
if [ "$DISTRO" = "alpine" ]; then
|
||||
echo "=== Alpine: installing kernel from .deb artifacts ==="
|
||||
|
||||
ALPINE_STAGING="/tmp/alpine-kernel-staging"
|
||||
rm -rf "$ALPINE_STAGING"
|
||||
mkdir -p "$ALPINE_STAGING"
|
||||
for deb in /kernel-debs/linux-image-*.deb; do
|
||||
[ -f "$deb" ] || continue
|
||||
dpkg-deb -x "$deb" "$ALPINE_STAGING"
|
||||
done
|
||||
|
||||
KVER=$(ls -1 "$ALPINE_STAGING/lib/modules" 2>/dev/null | head -1)
|
||||
|
||||
if [ -n "$KVER" ]; then
|
||||
# Resolve the real modules path (Alpine may use usr-merge: /lib -> usr/lib)
|
||||
if [ -L "$CHROOT/lib" ]; then
|
||||
MODDIR="$CHROOT/usr/lib/modules"
|
||||
else
|
||||
MODDIR="$CHROOT/lib/modules"
|
||||
fi
|
||||
mkdir -p "$MODDIR"
|
||||
rm -rf "$MODDIR/$KVER"
|
||||
cp -a "$ALPINE_STAGING/lib/modules/$KVER" "$MODDIR/"
|
||||
mkdir -p "$CHROOT/boot"
|
||||
cp "$ALPINE_STAGING/boot/vmlinuz-$KVER" "$CHROOT/boot/vmlinuz-$KVER"
|
||||
echo ">> Alpine: modules copied to $MODDIR/$KVER"
|
||||
fi
|
||||
rm -rf "$ALPINE_STAGING"
|
||||
|
||||
if [ -n "$KVER" ]; then
|
||||
chroot "$CHROOT" depmod -a "$KVER" 2>/dev/null || true
|
||||
|
||||
mount --bind /dev "$CHROOT/dev"
|
||||
mount --bind /proc "$CHROOT/proc"
|
||||
mount --bind /sys "$CHROOT/sys"
|
||||
chroot "$CHROOT" mkinitfs -k "$KVER" -o "/boot/initrd.img-$KVER" "$KVER" || true
|
||||
umount "$CHROOT/sys" "$CHROOT/proc" "$CHROOT/dev"
|
||||
|
||||
# Populate /boot/efi/ for boot partition assembly
|
||||
mkdir -p "$CHROOT/boot/efi"
|
||||
cp "$CHROOT/boot/vmlinuz-$KVER" "$CHROOT/boot/efi/bzImage"
|
||||
if [ -f "$CHROOT/boot/initrd.img-$KVER" ]; then
|
||||
cp "$CHROOT/boot/initrd.img-$KVER" "$CHROOT/boot/efi/initrd.img"
|
||||
else
|
||||
INITRD=$(ls -1t "$CHROOT"/boot/initramfs-* "$CHROOT"/boot/initrd* 2>/dev/null | head -1)
|
||||
if [ -n "$INITRD" ]; then
|
||||
cp "$INITRD" "$CHROOT/boot/efi/initrd.img"
|
||||
else
|
||||
echo "WARNING: No initrd found for alpine after mkinitfs"
|
||||
fi
|
||||
fi
|
||||
echo ">> Alpine: kernel $KVER staged to boot/efi/"
|
||||
else
|
||||
echo "WARNING: No kernel modules found in .deb for alpine"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Create GPT disk image ---
|
||||
echo "=== Creating ${IMG_SIZE}MB disk image ==="
|
||||
TMPIMG="/build/ps5-${DISTRO}.img"
|
||||
dd if=/dev/zero of="$TMPIMG" bs=1M count=$IMG_SIZE conv=fsync status=progress
|
||||
TMPIMG="/output/.ps5-${DISTRO}.img.tmp"
|
||||
rm -f "$TMPIMG"
|
||||
truncate -s "${IMG_SIZE}M" "$TMPIMG"
|
||||
sync
|
||||
|
||||
parted -s "$TMPIMG" mklabel gpt
|
||||
parted -s "$TMPIMG" mkpart primary ext4 500MiB 100%
|
||||
@@ -178,7 +132,9 @@ sync
|
||||
|
||||
echo "=== Assembling boot partition ==="
|
||||
mv /tmp/usb_root/boot/efi/* /tmp/usb_efi/ 2>/dev/null || true
|
||||
sed "s|__DISTRO__|$ROOT_LABEL|" /repo/boot/cmdline.txt > /tmp/usb_efi/cmdline.txt
|
||||
CMDLINE_TEMPLATE="/repo/distros/${DISTRO}/cmdline.txt"
|
||||
[ -f "$CMDLINE_TEMPLATE" ] || CMDLINE_TEMPLATE="/repo/boot/cmdline.txt"
|
||||
sed "s|__DISTRO__|$ROOT_LABEL|" "$CMDLINE_TEMPLATE" > /tmp/usb_efi/cmdline.txt
|
||||
cp /repo/boot/vram.txt /tmp/usb_efi/
|
||||
cp /repo/boot/kexec.sh /tmp/usb_efi/
|
||||
sync
|
||||
|
||||
Reference in New Issue
Block a user