Skip to content

Ubuntu

install

GUI

Desktop GUI

sudo apt update
sudo apt install ubuntu-desktop-minimal
sudo systemctl set-default graphical.target
sudo systemctl start gdm3

Chrome

# Chrome
wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo gpg --dearmor -o /usr/share/keyrings/google-chrome-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list
sudo apt update
sudo apt install google-chrome-stable

package

https://chatgpt.com/share/5c29bffa-77fa-4399-8c05-82bf52b45153 Package lists in /var/lib/apt/lists/ Package cache in /var/cache/apt/archives/ Status files in /var/lib/dpkg/status

https://chatgpt.com/share/04254bb6-982d-4b57-95ad-80bba922d3e3

apt remove ansible
apt --purge autoremove

prevent kernel upgrade

apt-mark hold $(uname -r)

offiline and local repository

/etc/apt/sources.list
/etc/apt/sources.list.d/
/var/cache/apt/archives/
/usr/share/keyrings/
ls -la /var/cache/apt/archives
apt-get install --download-only abc
sudo dpkg -i *.deb
apt-cache policy
apt-cache policy rocm
apt list --installed

the Ubuntu software repository is organized into four "components" on the basis of the level of support Ubuntu can offer them and whether or not they comply with Ubuntu's Free Software Philosophy. - Main (officially supported software) - Restricted (supported software that is not available under a completely free license) - Universe (community-maintained, i.e. not officially-supported software) - Multiverse (software that is "not free").

deb repo 的 url 組成 - Ubuntu 16.04 建立 APT Mirror site – Mr. 沙先生

deb http://nginx.org/packages/mainline/ubuntu xenial nginx
xenial nginx 從 dists 後的目錄到 binary-amd64, binary-i386, source

dpkg-scanpackages --multiversion . /dev/null | gzip -9c > Packages.gz
dpkg-scanpackages --multiversion . > Packages

Ubuntu Local Repository Setup Script

#!/bin/bash

# Ubuntu Local Repository Setup Script
# This script creates a local APT repository with specified packages including jq

set -e  # Exit on error

# Configuration
REPO_DIR="/var/local-repo"
REPO_NAME="local-ubuntu-repo"
UBUNTU_CODENAME=$(lsb_release -cs)
ARCH=$(dpkg --print-architecture)

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Print colored messages
print_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Check if running as root
if [ "$EUID" -ne 0 ]; then 
    print_error "Please run as root (use sudo)"
    exit 1
fi

print_info "Starting Ubuntu Local Repository Setup"
print_info "Ubuntu Codename: $UBUNTU_CODENAME"
print_info "Architecture: $ARCH"

# Install required tools
print_info "Installing required packages..."
apt-get update
apt-get install -y dpkg-dev apt-utils gnupg

# Create repository directory structure
print_info "Creating repository directory at $REPO_DIR"
mkdir -p "$REPO_DIR"/{pool,dists/$UBUNTU_CODENAME/main/binary-$ARCH}

# Download packages including jq
print_info "Downloading packages to repository..."

# List of packages to include in the repository
PACKAGES=(
    "jq"
)

cd "$REPO_DIR/pool"

# Function to download package and all its dependencies recursively
download_with_deps() {
    local package=$1
    local processed_file="$REPO_DIR/.processed_packages"

    # Skip if already processed
    if grep -qx "$package" "$processed_file" 2>/dev/null; then
        return
    fi

    print_info "Downloading $package..."
    if apt-get download "$package" 2>/dev/null; then
        echo "$package" >> "$processed_file"

        # Get all dependencies
        apt-cache depends "$package" 2>/dev/null | \
            grep -E "^\s+(Depends|PreDepends):" | \
            awk '{print $2}' | \
            grep -v "^<" | \
            while read dep; do
                download_with_deps "$dep"
            done
    else
        print_warning "Could not download $package"
    fi
}

# Initialize processed packages file
rm -f "$REPO_DIR/.processed_packages"
touch "$REPO_DIR/.processed_packages"

for package in "${PACKAGES[@]}"; do
    download_with_deps "$package"
done

# Clean up
rm -f "$REPO_DIR/.processed_packages"

# Generate Packages file
print_info "Generating package index..."
cd "$REPO_DIR"
dpkg-scanpackages pool /dev/null | gzip -9c > dists/$UBUNTU_CODENAME/main/binary-$ARCH/Packages.gz
dpkg-scanpackages pool /dev/null > dists/$UBUNTU_CODENAME/main/binary-$ARCH/Packages

# Generate Release file
print_info "Generating Release file..."
cd "$REPO_DIR/dists/$UBUNTU_CODENAME"

# apt considers it a “metadata change” and refuses to use the repository until you explicitly allow it.
# E: Repository 'file:/var/local-repo noble Release' changed its 'Origin' value from '' to 'Local Ubuntu Repository'
# E: Repository 'file:/var/local-repo noble Release' changed its 'Label' value from '' to 'local-ubuntu-repo'
# N: Repository 'file:/var/local-repo noble Release' changed its 'Suite' value from '' to 'noble'
# E: Repository 'file:/var/local-repo noble Release' changed its 'Codename' value from '' to 'noble'
# N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details.
if [ "$UBUNTU_CODENAME" == "noble" ]; then
cat > $REPO_DIR/apt-ftparchive.conf <<'EOF'
Dir::ArchiveDir "/var/local-repo";
Dir::CacheDir "/tmp";
TreeDefault::Directory "pool/";
Default::Packages::Extensions ".deb";
Default::Packages::Compress ". gzip bzip2 xz zstd";
Default::Sources::Compress ". gzip bzip2 xz zstd";
BinCacheDB "packages-$(SECTION)-$(ARCH).db";
Dir::State "state";
Dir::State::status "/var/lib/dpkg/status";
Tree "dists/noble" {
    Sections "main";
    Architectures "amd64";
    Origin "Local Ubuntu Repository";
    Label "local-ubuntu-repo";
    Suite "noble";
    Codename "noble";
    Description "My personal local repo";
};
EOF
elif [ "$UBUNTU_CODENAME" == "jammy" ]; then
cat > $REPO_DIR/apt-ftparchive.conf <<'EOF'
Dir::ArchiveDir "/var/local-repo";
Dir::CacheDir "/tmp";
TreeDefault::Directory "pool/";
Default::Packages::Extensions ".deb";
Default::Packages::Compress ". gzip bzip2 xz zstd";
Default::Sources::Compress ". gzip bzip2 xz zstd";
BinCacheDB "packages-$(SECTION)-$(ARCH).db";
Dir::State "state";
Dir::State::status "/var/lib/dpkg/status";
Tree "dists/jammy" {
    Sections "main";
    Architectures "amd64";
    Origin "Local Ubuntu Repository";
    Label "local-ubuntu-repo";
    Suite "jammy";
    Codename "jammy";
    Description "My personal local repo";
};
EOF
else
    print_error "Unsupported Ubuntu Codename: $UBUNTU_CODENAME"
    exit 1
fi

apt-ftparchive generate $REPO_DIR/apt-ftparchive.conf
cat > Release.tmp <<EOF
Origin: Local Ubuntu Repository
Label: $REPO_NAME
Suite: $UBUNTU_CODENAME
Codename: $UBUNTU_CODENAME
Architectures: $ARCH
Components: main
Description: Local Ubuntu Repository for offline package installation
EOF
# Add hash information
apt-ftparchive release -c $REPO_DIR/apt-ftparchive.conf . >> Release.tmp
mv Release.tmp Release

# Configure APT to use the local repository
# TODO: Add support for gpg key signing the repository
print_info "Configuring APT sources..."
cat > /etc/apt/sources.list.d/local-repo.list <<EOF
deb [trusted=yes] file://$REPO_DIR $UBUNTU_CODENAME main
EOF

# Update APT cache
print_info "Updating APT cache..."
apt-get update

# Verify all desired packages are available from local repository
print_info "Verifying repository setup for the following packages: ${PACKAGES[*]}"
for pkg in "${PACKAGES[@]}"; do
    if apt-cache policy "$pkg" | grep -q "file:$REPO_DIR"; then
        print_info "SUCCESS: $pkg is available from local repository"
    else
        print_warning "$pkg may not be available from local repository"
    fi
done

# Print summary
print_info "========================================="
print_info "Local Repository Setup Complete!"
print_info "========================================="
print_info "Repository location: $REPO_DIR"
print_info "Repository configuration: /etc/apt/sources.list.d/local-repo.list"
print_info ""
print_info "To install packages from the local repository:"
print_info "  sudo apt-get install jq"
print_info ""
print_info "To add more packages to the repository:"
print_info "  1. Chagne the PACKAGES array in the script to include the new packages"
print_info "  2. Run: bash $0"
print_info "========================================="

# Optional: Display repository contents
print_info "Packages in repository:"
ls -lh "$REPO_DIR/pool/" | grep ".deb" | awk '{print "  - " $9}'

# Compress the repository and configuration into one file
BACKUP_DIR="/tmp"
BACKUP_FILE="$BACKUP_DIR/local-repo-ubuntu-$UBUNTU_CODENAME-$ARCH.tar.gz"

print_info "Compressing repository and configuration..."
tar -czf "$BACKUP_FILE" \
    -C / \
    var/local-repo \
    etc/apt/sources.list.d/local-repo.list

if [ -f "$BACKUP_FILE" ]; then
    print_info "SUCCESS: Repository compressed to:"
    print_info "  $BACKUP_FILE"
    print_info "  Size: $(du -h $BACKUP_FILE | cut -f1)"
    print_info ""
    print_info "To deploy on another system:"
    print_info "  1. Copy $BACKUP_FILE to target system"
    print_info "  2. Extract: sudo tar -xzf $(basename $BACKUP_FILE) -C /"
    print_info "  3. sudo mv /etc/apt/sources.list /etc/apt/sources.list.bak ; sudo touch /etc/apt/sources.list"
    print_info "  4. Optional for Ubuntu 24.04: disable the default Ubuntu sources"
    print_info "     sudo mv /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.disabled"
    print_info "  5. Run: sudo apt-get update"
    print_info "  6. Run: sudo apt-get install ${PACKAGES[*]}"
else
    print_error "Failed to create compressed archive"
fi

exit 0

disable the online repo config in the air-gapped node

sudo mv /etc/apt/sources.list /etc/apt/sources.list.bak ; sudo touch /etc/apt/sources.list
sudo mv /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.disabled

pinning file

  • https://chatgpt.com/share/a7e6b06d-e031-4d58-ad5c-e62d7ea394d7

for local repository

/etc/apt/sources.list.d/localrepo.list

deb [trusted=yes] file:/root/install ./

/etc/apt/preferences.d/rocm-pin-600

Package: *
Pin: origin ""
Pin-Priority: 600

apt proxy

/etc/apt/apt.conf.d/proxy.conf

Acquire::http::Proxy "http://<Proxy_Server_IP>:<Port>/";
Acquire::https::Proxy "http://<Proxy_Server_IP>:<Port>/";

Acquire::http::Proxy "http://user:password@proxy.server:port/";
Acquire::https::Proxy "https://user:password@proxy.server:port/";

dns

Ubuntu systemd-resolved.service用的設定 /etc/systemd/resolved.conf

ISO

Netboot

debootstrap

debootstrap --arch amd64 jammy /tmp/test_ramos http://archive.ubuntu.com/ubuntu/

autoinstall

LiveCD

Test failure

apt install debootstrap mksquashfs grub-efi mtools xorriso
mkdir -p $HOME/live-ubuntu-from-scratch/target
mkdir -p $HOME/live-ubuntu-from-scratch/livecd/{casper,boot/grub,EFI/boot}
debootstrap  --include=linux-image-generic,live-boot --components=main,universe,multiverse --arch=amd64  --variant=minbase jammy $HOME/live-ubuntu-from-scratch/target  http://archive.ubuntu.com/ubuntu

cp $HOME/live-ubuntu-from-scratch/target/boot/vmlinuz-**-**-generic $HOME/live-ubuntu-from-scratch/livecd/casper/vmlinuz
cp $HOME/live-ubuntu-from-scratch/target/boot/initrd.img-**-**-generic $HOME/live-ubuntu-from-scratch/livecd/casper/initrd.img

chroot $HOME/live-ubuntu-from-scratch/target dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee $HOME/live-ubuntu-from-scratch/livecd/casper/filesystem.manifest

mksquashfs $HOME/live-ubuntu-from-scratch/target \
   $HOME/live-ubuntu-from-scratch/livecd/casper/filesystem.squashfs \
   -noappend -no-duplicates -no-recovery \
   -wildcards \
   -comp xz -b 1M -Xdict-size 100% \
   -e "var/cache/apt/archives/*" \
   -e "root/*" \
   -e "root/.*" \
   -e "tmp/*" \
   -e "tmp/.*" \
   -e "swapfile"


sudo tee $HOME/live-ubuntu-from-scratch/livecd/boot/grub/grub.cfg << EOF
search --set=root --file /casper/vmlinuz
insmod all_video
set timeout=30
menuentry "Ubuntu 22.04 Live" {
   linux /casper/vmlinuz boot=casper nopersistent toram quiet splash --
   initrd /casper/initrd.img
}
EOF
grub-mkstandalone \
  --format=x86_64-efi \
  --output=$HOME/live-ubuntu-from-scratch/livecd/EFI/boot/bootx64.efi \
  --locales="" --fonts="" \
   "boot/grub/grub.cfg=$HOME/live-ubuntu-from-scratch/livecd/boot/grub/grub.cfg"

LC_CTYPE=C bash -s << EOF
dd if=/dev/zero of=efiboot.img bs=1M count=3 && \
mkfs.vfat efiboot.img && \
mmd -i efiboot.img efi efi/boot && \
mcopy -i efiboot.img $HOME/live-ubuntu-from-scratch/livecd/EFI/boot/bootx64.efi ::efi/boot/
EOF

xorriso \
  -as mkisofs \
  -iso-level 3 \
  -full-iso9660-filenames \
  -volid "UBUNTU" \
  -output Ubuntu-22.04-LiveCD-x86_64.iso \
  -no-emul-boot -boot-load-size 4 -boot-info-table \
  --eltorito-catalog boot/grub/boot.cat \
  --grub2-boot-info \
  --grub2-mbr /usr/lib/grub/i386-pc/boot_hybrid.img \
  -eltorito-alt-boot -e EFI/efiboot.img -no-emul-boot -append_partition 2 0xef efiboot.img \
  -graft-points "livecd" "/EFI/efiboot.img=efiboot.img"

Autoinstall ISO

Debug

Ubuntu 24 subiquity apt update failed cdrom - Bug #1963725 “subiquity curtin apt-get update fails” : Bugs : subiquity package : Ubuntu - /cdrom permission - Bug #2080745 “Subiquity curtin apt-get install fails from cdrom ...” : Bugs : subiquity package : Ubuntu - Autoinstall from ISO File - Subiquity apt-get insatll fails from cdrom files - Ask Ubuntu