did stuff

This commit is contained in:
robojerk 2025-08-26 10:16:43 -07:00
parent cd5396604d
commit 47468f0147
24 changed files with 3361 additions and 0 deletions

281
create-debian-atomic.py Normal file
View file

@ -0,0 +1,281 @@
#!/usr/bin/env python3
"""
Alternative Debian Atomic Solution
Uses debootstrap + ostree instead of apt-ostree to create Debian Atomic systems
"""
import os
import sys
import subprocess
import tempfile
import shutil
import json
import yaml
from pathlib import Path
from typing import List, Dict, Any
class DebianAtomicBuilder:
"""Build Debian Atomic systems using debootstrap + ostree"""
def __init__(self, work_dir: str = None):
self.work_dir = Path(work_dir) if work_dir else Path(tempfile.mkdtemp(prefix="debian-atomic-"))
self.repo_dir = self.work_dir / "repo"
self.rootfs_dir = self.work_dir / "rootfs"
def create_ostree_repo(self) -> bool:
"""Create and initialize OSTree repository"""
try:
print(f"Creating OSTree repository at {self.repo_dir}")
self.repo_dir.mkdir(parents=True, exist_ok=True)
# Initialize OSTree repository
result = subprocess.run([
"ostree", "init", "--repo", str(self.repo_dir), "--mode=bare"
], capture_output=True, text=True, check=True)
print("OSTree repository initialized successfully")
return True
except subprocess.CalledProcessError as e:
print(f"Failed to initialize OSTree repository: {e}")
print(f"stdout: {e.stdout}")
print(f"stderr: {e.stderr}")
return False
except Exception as e:
print(f"Error creating OSTree repository: {e}")
return False
def create_rootfs(self, variant: str = "minimal") -> bool:
"""Create rootfs using debootstrap"""
try:
print(f"Creating rootfs for variant: {variant}")
self.rootfs_dir.mkdir(parents=True, exist_ok=True)
# Get package list based on variant
packages = self.get_packages_for_variant(variant)
# Create minimal rootfs with debootstrap
cmd = [
"debootstrap", "--variant=minbase", "--include=" + ",".join(packages),
"trixie", str(self.rootfs_dir), "http://deb.debian.org/debian"
]
print(f"Running: {' '.join(cmd)}")
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
print("Rootfs created successfully")
return True
except subprocess.CalledProcessError as e:
print(f"Failed to create rootfs: {e}")
print(f"stdout: {e.stdout}")
print(f"stderr: {e.stderr}")
return False
except Exception as e:
print(f"Error creating rootfs: {e}")
return False
def get_packages_for_variant(self, variant: str) -> List[str]:
"""Get package list for a specific variant"""
# Start with minimal set of packages that definitely exist
base_packages = [
"systemd", "dbus", "sudo", "bash",
"coreutils", "util-linux", "procps"
]
if variant == "minimal":
return base_packages + [
"less", "vim-tiny", "wget", "curl", "ca-certificates",
"gnupg", "iproute2", "net-tools", "openssh-client",
"openssh-server", "htop", "rsync", "tar", "gzip", "unzip"
]
elif variant == "gnome":
return base_packages + [
"gnome-shell", "gnome-session", "gnome-terminal",
"gnome-control-center", "gnome-settings-daemon",
"gnome-backgrounds", "gnome-themes-extra",
"adwaita-icon-theme", "gdm3", "gnome-initial-setup",
"nautilus", "gnome-software", "gnome-tweaks"
]
elif variant == "plasma":
return base_packages + [
"plasma-desktop", "plasma-workspace", "plasma-nm",
"plasma-pa", "kde-config", "kde-runtime", "kde-standard",
"sddm", "kwin-x11", "dolphin", "konsole", "kate",
"kdeconnect", "plasma-browser-integration"
]
elif variant == "cosmic":
return base_packages + [
"pop-desktop", "pop-shell", "gnome-shell",
"gnome-session", "gnome-terminal", "gnome-control-center",
"gnome-settings-daemon", "adwaita-icon-theme", "gdm3",
"nautilus", "gnome-software", "pop-gtk-theme"
]
elif variant == "sway":
return base_packages + [
"sway", "swaybg", "swayidle", "swaylock",
"waybar", "wofi", "foot", "grim", "slurp",
"wl-clipboard", "mako", "swaymsg", "sway-input"
]
elif variant == "budgie":
return base_packages + [
"budgie-desktop", "budgie-desktop-view",
"budgie-panel", "budgie-menu", "budgie-run-dialog",
"budgie-screenshot", "budgie-session",
"gnome-session", "gdm3", "adwaita-icon-theme"
]
else:
return base_packages
def create_ostree_commit(self, variant: str, ref: str) -> str:
"""Create OSTree commit from rootfs"""
try:
print(f"Creating OSTree commit for variant: {variant}")
# Create commit
cmd = [
"ostree", "commit", "--repo", str(self.repo_dir),
"--branch", ref, "--tree", f"dir={self.rootfs_dir}",
f"--subject=Debian Atomic {variant} variant",
f"--body=Debian Trixie Atomic system with {variant} desktop"
]
print(f"Running: {' '.join(cmd)}")
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
# Extract commit hash from output
commit_hash = result.stdout.strip()
print(f"OSTree commit created: {commit_hash}")
return commit_hash
except subprocess.CalledProcessError as e:
print(f"Failed to create OSTree commit: {e}")
print(f"stdout: {e.stdout}")
print(f"stderr: {e.stderr}")
return None
except Exception as e:
print(f"Error creating OSTree commit: {e}")
return None
def post_process_rootfs(self, variant: str) -> bool:
"""Post-process rootfs after debootstrap"""
try:
print(f"Post-processing rootfs for {variant} variant")
# Create essential directories
essential_dirs = [
"/etc/apt-ostree",
"/var/lib/apt-ostree",
"/usr/lib/bootc",
"/root/.ssh",
"/etc/systemd/system",
"/etc/systemd/user"
]
for dir_path in essential_dirs:
full_path = self.rootfs_dir / dir_path.lstrip("/")
full_path.mkdir(parents=True, exist_ok=True)
# Set up basic systemd services
if variant in ["gnome", "plasma", "cosmic", "budgie"]:
# Enable display manager
if variant == "plasma":
sddm_service = self.rootfs_dir / "etc/systemd/system/display-manager.service"
sddm_service.write_text("[Unit]\nDescription=SDDM Display Manager\n\n[Service]\nExecStart=/usr/bin/sddm\nRestart=always\n\n[Install]\nWantedBy=graphical.target\n")
elif variant in ["gnome", "cosmic", "budgie"]:
gdm_service = self.rootfs_dir / "etc/systemd/system/display-manager.service"
gdm_service.write_text("[Unit]\nDescription=GDM Display Manager\n\n[Service]\nExecStart=/usr/sbin/gdm3\nRestart=always\n\n[Install]\nWantedBy=graphical.target\n")
# Enable SSH service
ssh_service = self.rootfs_dir / "etc/systemd/system/sshd.service"
ssh_service.write_text("[Unit]\nDescription=OpenSSH Server\n\n[Service]\nExecStart=/usr/sbin/sshd -D\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n")
print("Rootfs post-processing completed")
return True
except Exception as e:
print(f"Error during post-processing: {e}")
return False
def build_variant(self, variant: str) -> bool:
"""Build a complete Debian Atomic variant"""
try:
print(f"Building Debian Atomic variant: {variant}")
# Create OSTree repository
if not self.create_ostree_repo():
return False
# Create rootfs
if not self.create_rootfs(variant):
return False
# Post-process rootfs
if not self.post_process_rootfs(variant):
return False
# Create OSTree commit
ref = f"debian/14/x86_64/{variant}"
commit_hash = self.create_ostree_commit(variant, ref)
if not commit_hash:
return False
print(f"Successfully built {variant} variant")
print(f"Repository: {self.repo_dir}")
print(f"Reference: {ref}")
print(f"Commit: {commit_hash}")
return True
except Exception as e:
print(f"Error building variant {variant}: {e}")
return False
def list_variants(self) -> List[str]:
"""List all supported variants"""
return ["minimal", "gnome", "plasma", "cosmic", "sway", "budgie"]
def cleanup(self):
"""Clean up temporary files"""
try:
if self.work_dir.exists():
shutil.rmtree(self.work_dir)
print(f"Cleaned up {self.work_dir}")
except Exception as e:
print(f"Error during cleanup: {e}")
def main():
"""Main function"""
if len(sys.argv) < 2:
print("Usage: python3 create-debian-atomic.py <variant> [work_dir]")
print("Variants:", ", ".join(DebianAtomicBuilder().list_variants()))
sys.exit(1)
variant = sys.argv[1]
work_dir = sys.argv[2] if len(sys.argv) > 2 else None
builder = DebianAtomicBuilder()
supported_variants = builder.list_variants()
if variant not in supported_variants:
print(f"Unknown variant: {variant}")
print(f"Supported variants: {', '.join(supported_variants)}")
sys.exit(1)
try:
success = builder.build_variant(variant)
if success:
print(f"\n✅ Successfully built Debian Atomic {variant} variant")
print(f"Repository location: {builder.repo_dir}")
print(f"To deploy: ostree admin deploy --os {variant} {builder.repo_dir}")
print(f"To list refs: ostree refs --repo={builder.repo_dir}")
else:
print(f"\n❌ Failed to build Debian Atomic {variant} variant")
sys.exit(1)
finally:
if not work_dir: # Only cleanup if we created a temp directory
builder.cleanup()
if __name__ == "__main__":
main()