111 lines
3.7 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
import os
import sys
import subprocess
import shutil
from pathlib import Path
CHROOT_DIRECTORY = "/srv/chroot/ubuntu"
UBUNTU_RELEASE = "noble"
UBUNTU_MIRROR = "http://archive.ubuntu.com/ubuntu"
def execute_command(command, check=True, shell=False):
if shell:
return subprocess.run(command, shell=True, check=check)
return subprocess.run(command, check=check)
def initialize_chroot():
chroot_path = Path(CHROOT_DIRECTORY)
if chroot_path.exists() and list(chroot_path.iterdir()):
print(f"Chroot directory {CHROOT_DIRECTORY} already exists and is not empty.")
response = input("Reinitialize? This will delete everything. (yes/no): ")
if response.lower() != "yes":
print("Aborting.")
sys.exit(0)
shutil.rmtree(CHROOT_DIRECTORY)
if not shutil.which("debootstrap"):
print("Installing debootstrap...")
execute_command(["apt", "update"])
execute_command(["apt", "install", "-y", "debootstrap"])
if not shutil.which("systemd-nspawn"):
print("Installing systemd-container...")
execute_command(["apt", "update"])
execute_command(["apt", "install", "-y", "systemd-container"])
print(f"Creating chroot directory: {CHROOT_DIRECTORY}")
chroot_path.mkdir(parents=True, exist_ok=True)
print(f"Running debootstrap for {UBUNTU_RELEASE}...")
execute_command([
"debootstrap",
"--variant=minbase",
UBUNTU_RELEASE,
CHROOT_DIRECTORY,
UBUNTU_MIRROR
])
print("Configuring APT sources...")
sources_content = f"""deb {UBUNTU_MIRROR} {UBUNTU_RELEASE} main restricted universe multiverse
deb {UBUNTU_MIRROR} {UBUNTU_RELEASE}-updates main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu {UBUNTU_RELEASE}-security main restricted universe multiverse
"""
(chroot_path / "etc/apt/sources.list").write_text(sources_content)
print("Setting hostname...")
(chroot_path / "etc/hostname").write_text("ubuntu-container\n")
print("Updating APT inside container...")
execute_command([
"systemd-nspawn",
"-D", CHROOT_DIRECTORY,
"--pipe",
"bash", "-c",
"export DEBIAN_FRONTEND=noninteractive && apt update"
])
print(f"\nContainer initialized successfully at {CHROOT_DIRECTORY}")
print(f"To enter: sudo python3 {sys.argv[0]}")
def enter_chroot():
chroot_path = Path(CHROOT_DIRECTORY)
if not chroot_path.exists() or not list(chroot_path.iterdir()):
print(f"Container not initialized. Run: sudo python3 {sys.argv[0]} init")
sys.exit(1)
if not shutil.which("systemd-nspawn"):
print("systemd-nspawn not found. Installing systemd-container...")
execute_command(["apt", "update"])
execute_command(["apt", "install", "-y", "systemd-container"])
print(f"Entering container at {CHROOT_DIRECTORY}...")
os.execvp("/usr/bin/systemd-nspawn", [
"systemd-nspawn",
"-D", CHROOT_DIRECTORY,
"--resolv-conf=bind-host",
"--private-users=pick",
"--drop-capability=CAP_SYS_MODULE,CAP_SYS_TIME,CAP_SYS_BOOT",
"--setenv=DEBIAN_FRONTEND=noninteractive"
])
def main():
if os.geteuid() != 0:
print("This script must be run as root (use sudo)")
sys.exit(1)
if len(sys.argv) == 1:
enter_chroot()
elif len(sys.argv) > 1:
match sys.argv[1]:
case "init":
initialize_chroot()
case _:
print(f"Unknown command: {sys.argv[1]}")
print(f"Usage: {sys.argv[0]} [init]")
sys.exit(1)
if __name__ == "__main__":
main()