Created
August 19, 2026 22:05
-
-
Save BeKnowDo/7fbabcbf498134b0766bed903e862c05 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Ubuntu 26.04 LTS Developer Installation and Configuration Guide | |
| Last updated: August 19, 2026 | |
| Target system: Ubuntu Desktop 26.04 LTS (Resolute Raccoon), standard GNOME desktop, x86-64/amd64 workstation. | |
| This guide is the Ubuntu-native conversion of the Fedora developer workstation walkthrough. It keeps the same general application stack and workflow while replacing Fedora-specific package management, RPM Fusion, SELinux, firewalld, RPM packages, and Nginx conventions with the appropriate Ubuntu equivalents. | |
| Ubuntu 26.04 LTS was released on April 23, 2026 and is supported with standard security and critical maintenance updates through April 2031. | |
| Hardware profile retained from the original workstation guide: | |
| - CPU: AMD Ryzen 9 7900X | |
| - Memory: 128 GiB RAM | |
| - GPU: NVIDIA GeForce RTX 4060 | |
| - Display: ultrawide 3440x1440, high refresh rate | |
| - Desktop: GNOME on Wayland | |
| - Terminal: Terminator | |
| - Storage: multi-drive NVMe/SATA desktop | |
| - Network: Realtek 2.5 GbE plus Wi-Fi | |
| > Important: This guide targets standard Ubuntu Desktop 26.04 LTS, not Ubuntu Cinnamon, Kubuntu, Linux Mint, Pop!_OS, or another Ubuntu derivative. Most command-line steps will still work on derivatives, but desktop settings and third-party vendor support can differ. | |
| --- | |
| ## 1. Application inventory | |
| This guide covers the following applications and tools. | |
| ### Shell and developer base | |
| - Terminator terminal | |
| - Zsh | |
| - Oh My Zsh | |
| - Git and Git LFS | |
| - nvm | |
| - Node.js LTS | |
| - AWS CLI v2 | |
| - AppImage support with FUSE | |
| - Flatpak and Flathub | |
| ### Browser | |
| - Google Chrome Stable | |
| ### IDEs and developer apps | |
| - Visual Studio Code | |
| - Cursor IDE | |
| - Google Antigravity IDE | |
| - Postman | |
| ### Containers | |
| - Docker Engine | |
| - Docker CLI | |
| - Docker Buildx | |
| - Docker Compose plugin | |
| - Docker Desktop | |
| - NVIDIA Container Toolkit for GPU containers | |
| ### NVIDIA and graphics | |
| - Ubuntu restricted driver repository | |
| - NVIDIA proprietary/open kernel driver selected through `ubuntu-drivers` | |
| - NVIDIA settings UI | |
| - Vulkan tools | |
| - OpenGL tools | |
| ### AI and local models | |
| - LM Studio AppImage | |
| - LM Studio applications-menu launcher | |
| ### Communication | |
| - Slack | |
| ### Gaming | |
| - Steam | |
| - Proton and Steam Play | |
| - GameMode | |
| - MangoHud | |
| - Gamescope | |
| ### Hardware and utilities | |
| - Brother HL-L2405W printer setup | |
| - CUPS | |
| - Avahi printer discovery | |
| - Cameractrls | |
| - guvcview | |
| - OBS Studio | |
| - Mission Center | |
| - nvtop | |
| - btop | |
| --- | |
| ## 2. Install Ubuntu Desktop 26.04 LTS | |
| Download Ubuntu Desktop 26.04 LTS from the official Ubuntu download page: | |
| ```text | |
| https://ubuntu.com/download/desktop | |
| ``` | |
| Ubuntu 26.04 LTS is codenamed: | |
| ```text | |
| Resolute Raccoon | |
| ``` | |
| Use one of these methods to create the USB installer: | |
| - Ubuntu's recommended USB-writing workflow | |
| - Rufus on Windows | |
| - balenaEtcher | |
| - Fedora Media Writer if you are creating the installer from your existing Fedora machine | |
| Suggested install choices: | |
| - Install type: fresh install | |
| - Desktop: standard Ubuntu Desktop | |
| - Architecture: amd64/x86-64 | |
| - Enable downloading updates during installation | |
| - Enable third-party software/drivers when the installer offers it | |
| - Use the default guided disk layout unless you specifically need custom partitioning | |
| - Secure Boot: it can remain enabled; Ubuntu supports signed NVIDIA driver packages | |
| - Hostname: something memorable, for example `cesar-ubuntu` | |
| Ubuntu's default desktop filesystem layout normally uses ext4. There is no need to force Btrfs unless you specifically want Btrfs features and are comfortable creating a custom partition layout. | |
| Before installing on a multi-drive machine, identify the intended OS disk carefully from the existing system: | |
| ```bash | |
| lsblk -o NAME,SIZE,MODEL,SERIAL,TYPE,MOUNTPOINTS | |
| ``` | |
| Do not assume `/dev/nvme0n1` is the install target. NVMe numbering can change. | |
| On a workstation with many internal drives, the safest approach is to verify the OS target by **model, size, and serial number**, not by device name alone. | |
| --- | |
| ## 3. First boot checklist | |
| Open the default Ubuntu terminal for the first few commands. Terminator will be installed shortly. | |
| Verify the system: | |
| ```bash | |
| cat /etc/os-release | |
| lsb_release -a | |
| uname -r | |
| hostnamectl | |
| ``` | |
| Check the GPU hardware: | |
| ```bash | |
| lspci | grep -Ei 'nvidia|vga|3d' | |
| ``` | |
| Check whether the current desktop session is Wayland or X11: | |
| ```bash | |
| echo "$XDG_SESSION_TYPE" | |
| echo "$XDG_CURRENT_DESKTOP" | |
| ``` | |
| Create working directories: | |
| ```bash | |
| mkdir -p "$HOME/Code" "$HOME/Applications" "$HOME/.local/bin" | |
| ``` | |
| Add `~/.local/bin` to your login path: | |
| ```bash | |
| grep -q 'HOME/.local/bin' "$HOME/.profile" 2>/dev/null || \ | |
| printf '\nexport PATH="$HOME/.local/bin:$PATH"\n' >> "$HOME/.profile" | |
| ``` | |
| Update Ubuntu immediately: | |
| ```bash | |
| sudo apt update | |
| sudo apt full-upgrade -y | |
| sudo apt autoremove -y | |
| sudo reboot | |
| ``` | |
| After reboot, verify there are no broken packages: | |
| ```bash | |
| sudo dpkg --audit | |
| sudo apt --fix-broken install | |
| ``` | |
| If both commands complete without reporting an unresolved problem, continue. | |
| ### 3.1 Automatically mount additional internal drives | |
| Your desktop has several NVMe and SATA drives. Configure each data partition with a persistent UUID rather than a path such as `/dev/sda1` or `/dev/nvme1n1p1`. Kernel-assigned device names can change after hardware changes, firmware updates, or rebooting. | |
| > Important: These steps mount an existing filesystem. They do not partition or format a drive. Do not run `mkfs`, `fdisk`, `parted`, `wipefs`, or a formatting command on a drive that contains data you want to keep. | |
| #### 3.1.1 Inventory the drives and filesystems | |
| List each disk, partition, filesystem type, label, UUID, model, and current mount point: | |
| ```bash | |
| lsblk -e7 -o NAME,SIZE,FSTYPE,LABEL,UUID,MODEL,MOUNTPOINTS | |
| ``` | |
| Show additional filesystem identifiers: | |
| ```bash | |
| sudo blkid | |
| ``` | |
| Show real mounted filesystems: | |
| ```bash | |
| findmnt --real | |
| ``` | |
| Select the **partition** that contains the filesystem, not merely the parent disk. For example, use `/dev/nvme0n1p1` or `/dev/sda1`, not `/dev/nvme0n1` or `/dev/sda`. | |
| If GNOME Files temporarily mounted the partition below `/media/$USER/...`, inspect it: | |
| ```bash | |
| findmnt -S /dev/DEVICE_PARTITION | |
| ``` | |
| Unmount it before creating the permanent mount: | |
| ```bash | |
| udisksctl unmount -b /dev/DEVICE_PARTITION | |
| ``` | |
| Replace `/dev/DEVICE_PARTITION` with the real partition path. | |
| #### 3.1.2 Create permanent mount points | |
| Use descriptive paths. For example: | |
| ```bash | |
| sudo mkdir -p /mnt/projects | |
| sudo mkdir -p /mnt/models | |
| sudo mkdir -p /mnt/archive | |
| sudo mkdir -p /mnt/games | |
| ``` | |
| Only create the mount points you actually need. | |
| #### 3.1.3 Record the UUID and filesystem type | |
| For each partition, run: | |
| ```bash | |
| sudo blkid -s UUID -s TYPE -o full /dev/DEVICE_PARTITION | |
| ``` | |
| Example: | |
| ```text | |
| /dev/nvme0n1p1: UUID="11111111-2222-3333-4444-555555555555" TYPE="ext4" | |
| ``` | |
| Copy the UUID exactly and note the filesystem type, such as: | |
| - `ext4` | |
| - `xfs` | |
| - `btrfs` | |
| - `ntfs` | |
| - `exfat` | |
| If you have XFS filesystems, install the XFS utilities: | |
| ```bash | |
| sudo apt install -y xfsprogs | |
| ``` | |
| For NTFS tools: | |
| ```bash | |
| sudo apt install -y ntfs-3g | |
| ``` | |
| For exFAT tools: | |
| ```bash | |
| sudo apt install -y exfatprogs | |
| ``` | |
| #### 3.1.4 Back up and edit `/etc/fstab` | |
| Create a timestamped backup: | |
| ```bash | |
| sudo cp -a /etc/fstab "/etc/fstab.backup.$(date +%Y%m%d-%H%M%S)" | |
| sudoedit /etc/fstab | |
| ``` | |
| Add one line per filesystem. | |
| Example for ext4: | |
| ```fstab | |
| UUID=11111111-2222-3333-4444-555555555555 /mnt/projects ext4 defaults,nofail,noatime,x-systemd.device-timeout=10s 0 2 | |
| ``` | |
| Common examples: | |
| ```fstab | |
| # ext4 | |
| UUID=REPLACE_WITH_UUID /mnt/projects ext4 defaults,nofail,noatime,x-systemd.device-timeout=10s 0 2 | |
| # XFS | |
| UUID=REPLACE_WITH_UUID /mnt/models xfs defaults,nofail,noatime,x-systemd.device-timeout=10s 0 0 | |
| # Btrfs data filesystem | |
| UUID=REPLACE_WITH_UUID /mnt/archive btrfs defaults,nofail,noatime,x-systemd.device-timeout=10s 0 0 | |
| ``` | |
| The important options are: | |
| - `nofail`: continue booting if the drive is unavailable | |
| - `noatime`: avoid writing an access timestamp every time a file is read | |
| - `x-systemd.device-timeout=10s`: avoid an excessive boot delay if a device is unavailable | |
| For an internal NTFS or exFAT data partition, first obtain your numeric user and group IDs: | |
| ```bash | |
| id -u | |
| id -g | |
| ``` | |
| They are often `1000` for the first desktop user, but verify rather than assuming. | |
| Examples: | |
| ```fstab | |
| # NTFS using the in-kernel ntfs3 driver | |
| UUID=REPLACE_WITH_UUID /mnt/shared ntfs3 defaults,nofail,uid=1000,gid=1000,umask=0022,x-systemd.device-timeout=10s 0 0 | |
| # exFAT | |
| UUID=REPLACE_WITH_UUID /mnt/shared exfat defaults,nofail,uid=1000,gid=1000,umask=0022,x-systemd.device-timeout=10s 0 0 | |
| ``` | |
| Do not put quotation marks around UUIDs or mount points in `/etc/fstab`. | |
| #### 3.1.5 Validate the configuration before rebooting | |
| Reload systemd's generated mount units: | |
| ```bash | |
| sudo systemctl daemon-reload | |
| ``` | |
| Verify `/etc/fstab`: | |
| ```bash | |
| sudo findmnt --verify --verbose | |
| ``` | |
| Mount all newly configured filesystems: | |
| ```bash | |
| sudo mount -a | |
| ``` | |
| Confirm each expected mount: | |
| ```bash | |
| findmnt /mnt/projects | |
| df -hT /mnt/projects | |
| ``` | |
| Repeat for the other mount points you configured. | |
| If `sudo mount -a` reports an error, fix `/etc/fstab` **before rebooting**. | |
| To restore the most recent backup if necessary: | |
| ```bash | |
| ls -1t /etc/fstab.backup.* | head | |
| ``` | |
| Then restore the correct backup: | |
| ```bash | |
| sudo cp -a /etc/fstab.backup.YYYYMMDD-HHMMSS /etc/fstab | |
| ``` | |
| #### 3.1.6 Set ownership for Linux filesystems | |
| For a newly mounted ext4, XFS, or Btrfs data filesystem that should belong to your user: | |
| ```bash | |
| sudo chown "$USER:$USER" /mnt/projects | |
| sudo chmod 755 /mnt/projects | |
| ``` | |
| This changes only the root directory of the mounted filesystem. | |
| Avoid: | |
| ```bash | |
| sudo chown -R ... | |
| ``` | |
| on an existing data drive unless you intentionally want to rewrite ownership for every file. | |
| #### 3.1.7 Optional home-directory shortcuts | |
| Create symbolic links: | |
| ```bash | |
| ln -s /mnt/projects "$HOME/projects-drive" | |
| ln -s /mnt/models "$HOME/models-drive" | |
| ln -s /mnt/archive "$HOME/archive-drive" | |
| ln -s /mnt/games "$HOME/games-drive" | |
| ``` | |
| Only create a link if the destination name does not already exist. | |
| Verify after reboot: | |
| ```bash | |
| findmnt --real | |
| ls -ld /mnt/projects "$HOME/projects-drive" | |
| ``` | |
| --- | |
| ## 4. Install Terminator | |
| Install Terminator: | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y terminator | |
| ``` | |
| Launch it: | |
| ```bash | |
| terminator | |
| ``` | |
| Ubuntu uses the `x-terminal-emulator` alternatives system for some generic terminal launches. To choose Terminator: | |
| ```bash | |
| sudo update-alternatives --config x-terminal-emulator | |
| ``` | |
| Select the Terminator entry. | |
| GNOME applications are not required to honor this alternative, so the practical approach is also to pin Terminator to the dock and use it as your normal terminal. | |
| Most commands in the rest of this guide assume you are using Terminator. | |
| --- | |
| ## 5. Enable Ubuntu software repository components | |
| Ubuntu does not use RPM Fusion. The equivalent software you need is already available through Ubuntu's standard repository components or through vendor-provided APT repositories. | |
| Install repository-management tools: | |
| ```bash | |
| sudo apt install -y software-properties-common | |
| ``` | |
| Enable the standard components needed by this guide: | |
| ```bash | |
| sudo add-apt-repository -y universe | |
| sudo add-apt-repository -y multiverse | |
| sudo add-apt-repository -y restricted | |
| sudo apt update | |
| ``` | |
| Verify enabled Ubuntu sources: | |
| ```bash | |
| grep -R --no-filename -E '^(Components:|deb )' \ | |
| /etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null | |
| ``` | |
| On modern Ubuntu releases, the main Ubuntu repository configuration commonly lives in: | |
| ```text | |
| /etc/apt/sources.list.d/ubuntu.sources | |
| ``` | |
| --- | |
| ## 6. Install base developer packages | |
| Install the base packages used throughout this guide: | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y \ | |
| zsh git git-lfs curl wget unzip tar gzip ca-certificates gnupg \ | |
| software-properties-common apt-transport-https \ | |
| build-essential gcc g++ make cmake pkg-config libssl-dev \ | |
| python3 python3-pip python3-venv python3-dev pipx \ | |
| fuse3 libfuse2t64 \ | |
| xdg-utils desktop-file-utils \ | |
| inxi fastfetch mesa-utils vulkan-tools \ | |
| ripgrep fd-find jq bat eza htop btop tree tmux neovim shellcheck \ | |
| pciutils usbutils lsb-release mokutil ubuntu-drivers-common | |
| ``` | |
| Enable Git LFS: | |
| ```bash | |
| git lfs install | |
| ``` | |
| Ubuntu packages the `fd` command as `fdfind` and frequently packages `bat` as `batcat`. | |
| Create user-level compatibility links: | |
| ```bash | |
| mkdir -p "$HOME/.local/bin" | |
| command -v fdfind >/dev/null && \ | |
| ln -sfn "$(command -v fdfind)" "$HOME/.local/bin/fd" | |
| command -v batcat >/dev/null && \ | |
| ln -sfn "$(command -v batcat)" "$HOME/.local/bin/bat" | |
| ``` | |
| Verify: | |
| ```bash | |
| fd --version | |
| bat --version | |
| eza --version | |
| ``` | |
| Check AppImage compatibility: | |
| ```bash | |
| dpkg -l | grep -E 'fuse3|libfuse2' | |
| ``` | |
| Ubuntu 26.04 provides `libfuse2t64`, which is useful for AppImages that still require the older FUSE 2 compatibility library. | |
| --- | |
| ## 7. Configure Git | |
| Set your identity: | |
| ```bash | |
| git config --global user.name "Cesar" | |
| git config --global user.email "your-email@example.com" | |
| ``` | |
| Set defaults: | |
| ```bash | |
| git config --global init.defaultBranch main | |
| git config --global pull.rebase false | |
| git config --global core.editor "code --wait" | |
| git config --global fetch.prune true | |
| git config --global rerere.enabled true | |
| ``` | |
| Verify: | |
| ```bash | |
| git --version | |
| git lfs version | |
| git config --global --list | |
| ``` | |
| --- | |
| ## 8. Install Zsh and Oh My Zsh | |
| Zsh was installed with the base packages. | |
| Set Zsh as your default shell: | |
| ```bash | |
| chsh -s "$(command -v zsh)" | |
| ``` | |
| Back up an existing Zsh config if present: | |
| ```bash | |
| [ -f "$HOME/.zshrc" ] && \ | |
| cp "$HOME/.zshrc" "$HOME/.zshrc.backup.$(date +%Y%m%d%H%M%S)" | |
| ``` | |
| Install Oh My Zsh without starting a nested shell: | |
| ```bash | |
| RUNZSH=no CHSH=no sh -c \ | |
| "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" | |
| ``` | |
| Install useful plugins: | |
| ```bash | |
| ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}" | |
| [ -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ] || \ | |
| git clone --depth=1 \ | |
| https://github.com/zsh-users/zsh-autosuggestions \ | |
| "$ZSH_CUSTOM/plugins/zsh-autosuggestions" | |
| [ -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ] || \ | |
| git clone --depth=1 \ | |
| https://github.com/zsh-users/zsh-syntax-highlighting.git \ | |
| "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" | |
| ``` | |
| Enable plugins. Keep `zsh-syntax-highlighting` last: | |
| ```bash | |
| if grep -q '^plugins=' "$HOME/.zshrc"; then | |
| sed -i \ | |
| 's/^plugins=(.*)/plugins=(git aws docker npm ubuntu zsh-autosuggestions zsh-syntax-highlighting)/' \ | |
| "$HOME/.zshrc" | |
| else | |
| printf '\nplugins=(git aws docker npm ubuntu zsh-autosuggestions zsh-syntax-highlighting)\n' \ | |
| >> "$HOME/.zshrc" | |
| fi | |
| ``` | |
| Add local bin to Zsh: | |
| ```bash | |
| grep -q 'HOME/.local/bin' "$HOME/.zshrc" || \ | |
| printf '\nexport PATH="$HOME/.local/bin:$PATH"\n' >> "$HOME/.zshrc" | |
| ``` | |
| Log out and back in, or start Zsh manually: | |
| ```bash | |
| exec zsh | |
| ``` | |
| Verify: | |
| ```bash | |
| echo "$SHELL" | |
| zsh --version | |
| ``` | |
| --- | |
| ## 9. Install nvm and Node.js LTS | |
| As of this guide update, nvm's upstream install documentation uses version `v0.40.6`. | |
| Install nvm into your Zsh profile: | |
| ```bash | |
| curl -o- \ | |
| https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.6/install.sh \ | |
| | PROFILE="$HOME/.zshrc" bash | |
| ``` | |
| Open a new Terminator window or source your config: | |
| ```bash | |
| source "$HOME/.zshrc" | |
| ``` | |
| Verify nvm: | |
| ```bash | |
| command -v nvm | |
| nvm --version | |
| ``` | |
| Install Node.js LTS: | |
| ```bash | |
| nvm install --lts | |
| nvm alias default "lts/*" | |
| ``` | |
| Verify: | |
| ```bash | |
| node --version | |
| npm --version | |
| nvm current | |
| ``` | |
| If the installed Node release ships Corepack and you want pnpm/Yarn shims: | |
| ```bash | |
| corepack enable | |
| ``` | |
| If `corepack` is not present in the selected Node release, install your preferred package manager explicitly instead of assuming it is bundled. | |
| Optional: install the current non-LTS Node release: | |
| ```bash | |
| nvm install node | |
| ``` | |
| Useful commands: | |
| ```bash | |
| nvm ls | |
| nvm current | |
| nvm install --lts | |
| nvm use --lts | |
| ``` | |
| --- | |
| ## 10. Install AWS CLI v2 | |
| Install the official AWS CLI v2 x86-64 bundle: | |
| ```bash | |
| cd /tmp | |
| rm -rf aws awscliv2.zip | |
| curl -fsSL \ | |
| "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \ | |
| -o awscliv2.zip | |
| unzip -q awscliv2.zip | |
| sudo ./aws/install \ | |
| --bin-dir /usr/local/bin \ | |
| --install-dir /usr/local/aws-cli \ | |
| --update | |
| ``` | |
| Verify: | |
| ```bash | |
| aws --version | |
| ``` | |
| Configure with SSO: | |
| ```bash | |
| aws configure sso | |
| ``` | |
| Or configure classic access keys: | |
| ```bash | |
| aws configure | |
| ``` | |
| Verify credentials: | |
| ```bash | |
| aws sts get-caller-identity | |
| ``` | |
| --- | |
| ## 11. Install NVIDIA drivers | |
| Ubuntu's recommended approach is to use `ubuntu-drivers`. It uses the same hardware-selection logic as Ubuntu's Additional Drivers interface and is preferable to manually downloading NVIDIA's `.run` installer. | |
| ### 11.1 Check Secure Boot | |
| ```bash | |
| mokutil --sb-state | |
| ``` | |
| Secure Boot can remain enabled. | |
| Check available NVIDIA driver packages for the detected hardware: | |
| ```bash | |
| sudo ubuntu-drivers list | |
| ``` | |
| See Ubuntu's recommendation: | |
| ```bash | |
| ubuntu-drivers devices | |
| ``` | |
| ### 11.2 Install the recommended NVIDIA driver | |
| Use automatic detection: | |
| ```bash | |
| sudo apt update | |
| sudo ubuntu-drivers install | |
| ``` | |
| Then reboot: | |
| ```bash | |
| sudo reboot | |
| ``` | |
| This approach is preferable to hard-coding a driver branch because Ubuntu can select the current supported branch for your GPU and kernel. | |
| On Ubuntu 26.04, newer NVIDIA branches and open-kernel-module variants may appear in the list. Let `ubuntu-drivers` select the recommended package unless you have a specific compatibility requirement. | |
| ### 11.3 Secure Boot and MOK enrollment | |
| Ubuntu attempts to use signed NVIDIA driver modules when Secure Boot is enabled. | |
| If the package installation presents a Machine Owner Key enrollment prompt: | |
| 1. Create the one-time enrollment password requested by the installer. | |
| 2. Reboot. | |
| 3. On the blue MOK management screen, choose `Enroll MOK`. | |
| 4. Choose `Continue`. | |
| 5. Confirm enrollment. | |
| 6. Enter the password you created. | |
| 7. Reboot again. | |
| After login, verify Secure Boot: | |
| ```bash | |
| mokutil --sb-state | |
| ``` | |
| If no MOK enrollment screen appears and the NVIDIA modules load normally, no manual MOK work is required. | |
| ### 11.4 Verify NVIDIA after reboot | |
| Check the driver: | |
| ```bash | |
| nvidia-smi | |
| ``` | |
| Check loaded kernel modules: | |
| ```bash | |
| lsmod | grep '^nvidia' | |
| ``` | |
| Check the running driver version: | |
| ```bash | |
| cat /proc/driver/nvidia/version | |
| ``` | |
| Check OpenGL: | |
| ```bash | |
| glxinfo -B | grep -E 'OpenGL vendor|OpenGL renderer' | |
| ``` | |
| Check Vulkan: | |
| ```bash | |
| vulkaninfo --summary | grep -Ei 'deviceName|driverName' || true | |
| ``` | |
| Expected result: | |
| - `nvidia-smi` lists the NVIDIA GPU | |
| - `lsmod` lists NVIDIA modules | |
| - OpenGL reports NVIDIA rather than `llvmpipe` | |
| - Vulkan lists the NVIDIA GPU | |
| ### 11.5 NVIDIA settings | |
| Install the settings UI if it was not already pulled in: | |
| ```bash | |
| sudo apt install -y nvidia-settings | |
| ``` | |
| Launch it: | |
| ```bash | |
| nvidia-settings | |
| ``` | |
| On Wayland, some display controls are intentionally handled by GNOME rather than by `nvidia-settings`. | |
| ### 11.6 Suspend and resume | |
| Ubuntu 26.04 includes updated NVIDIA suspend/resume handling. Do not manually enable NVIDIA sleep services unless troubleshooting demonstrates that they are needed. | |
| If suspend or wake problems occur, collect these first: | |
| ```bash | |
| nvidia-smi | |
| systemctl status systemd-suspend.service --no-pager | |
| journalctl -b -1 -k | grep -Ei 'nvidia|suspend|resume|drm' | tail -n 200 | |
| ``` | |
| --- | |
| ## 12. Install Docker Engine and Docker Compose | |
| Use Docker's official Ubuntu APT repository. | |
| > Firewall note: Docker-published container ports can bypass normal UFW filtering. Do not assume that a UFW deny rule protects a port that Docker has published. For internet-facing systems, review Docker's firewall behavior and use the `DOCKER-USER` chain when appropriate. | |
| ### 12.1 Remove conflicting packages | |
| Docker recommends removing packages that can conflict with Docker CE: | |
| ```bash | |
| for pkg in \ | |
| docker.io \ | |
| docker-compose \ | |
| docker-compose-v2 \ | |
| docker-doc \ | |
| docker-buildx \ | |
| podman-docker \ | |
| containerd \ | |
| runc; do | |
| sudo apt remove -y "$pkg" 2>/dev/null || true | |
| done | |
| ``` | |
| ### 12.2 Add Docker's Ubuntu repository | |
| Install prerequisites: | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y ca-certificates curl | |
| ``` | |
| Create the APT keyring directory: | |
| ```bash | |
| sudo install -m 0755 -d /etc/apt/keyrings | |
| ``` | |
| Install Docker's signing key: | |
| ```bash | |
| sudo curl -fsSL \ | |
| https://download.docker.com/linux/ubuntu/gpg \ | |
| -o /etc/apt/keyrings/docker.asc | |
| sudo chmod a+r /etc/apt/keyrings/docker.asc | |
| ``` | |
| Add Docker's repository in deb822 format: | |
| ```bash | |
| sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<EOF | |
| Types: deb | |
| URIs: https://download.docker.com/linux/ubuntu | |
| Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") | |
| Components: stable | |
| Architectures: $(dpkg --print-architecture) | |
| Signed-By: /etc/apt/keyrings/docker.asc | |
| EOF | |
| ``` | |
| Refresh APT: | |
| ```bash | |
| sudo apt update | |
| ``` | |
| Verify Docker packages are coming from Docker's repository: | |
| ```bash | |
| apt-cache policy docker-ce | |
| ``` | |
| ### 12.3 Install Docker Engine, Buildx, and Compose | |
| ```bash | |
| sudo apt install -y \ | |
| docker-ce \ | |
| docker-ce-cli \ | |
| containerd.io \ | |
| docker-buildx-plugin \ | |
| docker-compose-plugin | |
| ``` | |
| Verify service status: | |
| ```bash | |
| sudo systemctl status docker --no-pager | |
| ``` | |
| If needed: | |
| ```bash | |
| sudo systemctl enable --now docker | |
| ``` | |
| Test with sudo first: | |
| ```bash | |
| sudo docker run hello-world | |
| ``` | |
| ### 12.4 Let your user run Docker without sudo | |
| Security note: membership in the `docker` group effectively grants root-level control of the machine. | |
| Add your user: | |
| ```bash | |
| sudo usermod -aG docker "$USER" | |
| ``` | |
| Log out and back in. | |
| For a temporary shell refresh: | |
| ```bash | |
| newgrp docker | |
| ``` | |
| Verify: | |
| ```bash | |
| groups | |
| docker run hello-world | |
| docker compose version | |
| ``` | |
| ### 12.5 Tiny Compose smoke test | |
| ```bash | |
| mkdir -p "$HOME/Code/docker-smoke-test" | |
| cd "$HOME/Code/docker-smoke-test" | |
| cat > compose.yaml <<'YAML' | |
| services: | |
| hello: | |
| image: hello-world | |
| YAML | |
| docker compose up | |
| docker compose down --remove-orphans | |
| cd "$HOME" | |
| rm -rf "$HOME/Code/docker-smoke-test" | |
| ``` | |
| --- | |
| ## 13. Install NVIDIA Container Toolkit | |
| Only do this after `nvidia-smi` works correctly on the host and Docker Engine is working. | |
| Install prerequisites: | |
| ```bash | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| ca-certificates \ | |
| curl \ | |
| gnupg2 | |
| ``` | |
| Add NVIDIA's signing key and production repository: | |
| ```bash | |
| curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \ | |
| sudo gpg --dearmor \ | |
| -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg | |
| curl -s -L \ | |
| https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ | |
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ | |
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list | |
| ``` | |
| Refresh and install: | |
| ```bash | |
| sudo apt-get update | |
| sudo apt-get install -y nvidia-container-toolkit | |
| ``` | |
| Configure Docker: | |
| ```bash | |
| sudo nvidia-ctk runtime configure --runtime=docker | |
| sudo systemctl restart docker | |
| ``` | |
| Test GPU access in a container: | |
| ```bash | |
| docker run --rm --gpus all ubuntu nvidia-smi | |
| ``` | |
| If your group change has not taken effect yet: | |
| ```bash | |
| sudo docker run --rm --gpus all ubuntu nvidia-smi | |
| ``` | |
| --- | |
| ## 14. Install Docker Desktop | |
| Docker Desktop officially supports x86-64 Ubuntu 26.04 LTS. | |
| Docker Desktop can coexist with Docker Engine. It uses a separate `desktop-linux` context and stores its data inside its own Linux VM. | |
| ### 14.1 Install Docker Desktop requirements | |
| Check CPU virtualization: | |
| ```bash | |
| egrep -c '(vmx|svm)' /proc/cpuinfo | |
| ``` | |
| A nonzero result indicates that CPU virtualization extensions are visible. | |
| Check KVM: | |
| ```bash | |
| lsmod | grep kvm | |
| ``` | |
| On the Ryzen 9 7900X, you should normally see: | |
| ```text | |
| kvm_amd | |
| kvm | |
| ``` | |
| If needed: | |
| ```bash | |
| sudo modprobe kvm | |
| sudo modprobe kvm_amd | |
| ``` | |
| Check the KVM device: | |
| ```bash | |
| ls -al /dev/kvm | |
| ``` | |
| Add your user to the `kvm` group: | |
| ```bash | |
| sudo usermod -aG kvm "$USER" | |
| ``` | |
| Log out and back in after changing group membership. | |
| On standard Ubuntu GNOME, Docker Desktop also expects AppIndicator/KStatusNotifierItem support. If the tray integration is missing, install the Ubuntu AppIndicators extension package: | |
| ```bash | |
| sudo apt install -y gnome-shell-ubuntu-extensions | |
| ``` | |
| Log out and back in if GNOME Shell does not pick it up immediately. | |
| ### 14.2 Download and install Docker Desktop DEB | |
| Docker recommends downloading the current DEB package from its Ubuntu Docker Desktop page. | |
| Open the page: | |
| ```bash | |
| xdg-open https://docs.docker.com/desktop/setup/install/linux/ubuntu/ | |
| ``` | |
| Download the current file to `~/Downloads`. | |
| If it is named `docker-desktop-amd64.deb`, install it: | |
| ```bash | |
| cd "$HOME/Downloads" | |
| sudo apt update | |
| sudo apt install -y ./docker-desktop-amd64.deb | |
| ``` | |
| If the downloaded filename contains a version, locate it: | |
| ```bash | |
| DOCKER_DESKTOP_DEB="$( | |
| find "$HOME/Downloads" -maxdepth 1 -type f \ | |
| -iname 'docker-desktop*amd64*.deb' \ | |
| | sort | tail -n 1 | |
| )" | |
| test -n "$DOCKER_DESKTOP_DEB" || { | |
| echo "Download the Docker Desktop Ubuntu DEB first." | |
| exit 1 | |
| } | |
| sudo apt install -y "$DOCKER_DESKTOP_DEB" | |
| ``` | |
| ### 14.3 Launch Docker Desktop | |
| Launch from the Ubuntu applications menu or run: | |
| ```bash | |
| systemctl --user start docker-desktop | |
| ``` | |
| The first launch presents Docker's terms. Docker Desktop will not run until they are accepted. | |
| Enable it at sign-in: | |
| ```bash | |
| systemctl --user enable docker-desktop | |
| ``` | |
| Verify Docker contexts: | |
| ```bash | |
| docker context ls | |
| docker context show | |
| ``` | |
| Switch explicitly to Docker Desktop: | |
| ```bash | |
| docker context use desktop-linux | |
| docker run hello-world | |
| ``` | |
| Switch back to the host Docker Engine: | |
| ```bash | |
| docker context use default | |
| ``` | |
| ### 14.4 Terminator aliases for Docker Desktop | |
| Add helpers to `~/.zshrc`: | |
| ```bash | |
| cat >> "$HOME/.zshrc" <<'EOF_ZSH' | |
| # Docker Desktop helpers | |
| alias ddesktop-start='systemctl --user start docker-desktop' | |
| alias ddesktop-stop='systemctl --user stop docker-desktop' | |
| alias ddesktop-status='systemctl --user status docker-desktop' | |
| alias ddesktop-use='docker context use desktop-linux' | |
| alias docker-engine-use='docker context use default' | |
| alias docker-context='docker context ls' | |
| EOF_ZSH | |
| source "$HOME/.zshrc" | |
| ``` | |
| --- | |
| ## 15. Install Google Chrome | |
| Google provides a 64-bit `.deb` package for Debian and Ubuntu. | |
| ### 15.1 Download and install the official DEB | |
| ```bash | |
| mkdir -p "$HOME/Downloads" | |
| cd "$HOME/Downloads" | |
| curl -fL \ | |
| "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb" \ | |
| -o google-chrome-stable_current_amd64.deb | |
| sudo apt install -y ./google-chrome-stable_current_amd64.deb | |
| ``` | |
| Verify: | |
| ```bash | |
| dpkg -s google-chrome-stable | grep -E 'Status|Version' | |
| google-chrome-stable --version | |
| ``` | |
| The Google package normally adds Google's APT repository for future updates. | |
| Inspect it: | |
| ```bash | |
| grep -R -i 'dl.google.com' \ | |
| /etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null || true | |
| ``` | |
| Launch: | |
| ```bash | |
| google-chrome-stable | |
| ``` | |
| ### 15.2 Optional: make Chrome the default browser | |
| ```bash | |
| xdg-settings set default-web-browser google-chrome.desktop | |
| xdg-settings get default-web-browser | |
| ``` | |
| You can also set the default browser through Ubuntu Settings. | |
| ### 15.3 Troubleshooting | |
| If the DEB is incomplete: | |
| ```bash | |
| rm -f "$HOME/Downloads/google-chrome-stable_current_amd64.deb" | |
| curl -fL \ | |
| "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb" \ | |
| -o "$HOME/Downloads/google-chrome-stable_current_amd64.deb" | |
| sudo apt install -y "$HOME/Downloads/google-chrome-stable_current_amd64.deb" | |
| ``` | |
| If APT reports broken dependencies: | |
| ```bash | |
| sudo apt --fix-broken install | |
| sudo apt install -y "$HOME/Downloads/google-chrome-stable_current_amd64.deb" | |
| ``` | |
| --- | |
| ## 16. Install Visual Studio Code | |
| Use Microsoft's official APT repository. | |
| Install key tools: | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y wget gpg | |
| ``` | |
| Install Microsoft's signing key: | |
| ```bash | |
| wget -qO- https://packages.microsoft.com/keys/microsoft.asc | \ | |
| sudo gpg --dearmor -o /usr/share/keyrings/microsoft.gpg | |
| ``` | |
| Create the deb822 source: | |
| ```bash | |
| sudo tee /etc/apt/sources.list.d/vscode.sources > /dev/null <<'EOF' | |
| Types: deb | |
| URIs: https://packages.microsoft.com/repos/code | |
| Suites: stable | |
| Components: main | |
| Architectures: amd64,arm64,armhf | |
| Signed-By: /usr/share/keyrings/microsoft.gpg | |
| EOF | |
| ``` | |
| Install VS Code: | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y code | |
| ``` | |
| Verify: | |
| ```bash | |
| code --version | |
| ``` | |
| Optional extensions: | |
| ```bash | |
| code --install-extension ms-python.python | |
| code --install-extension ms-python.vscode-pylance | |
| code --install-extension dbaeumer.vscode-eslint | |
| code --install-extension esbenp.prettier-vscode | |
| code --install-extension ms-azuretools.vscode-docker | |
| code --install-extension amazonwebservices.aws-toolkit-vscode | |
| code --install-extension github.vscode-github-actions | |
| ``` | |
| --- | |
| ## 17. Install Cursor IDE | |
| Cursor provides an APT repository for Debian and Ubuntu. | |
| Install GPG tooling if necessary: | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y curl gpg | |
| sudo mkdir -p /etc/apt/keyrings | |
| ``` | |
| Add Cursor's signing key: | |
| ```bash | |
| curl -fsSL https://downloads.cursor.com/keys/anysphere.asc | \ | |
| gpg --dearmor | \ | |
| sudo tee /etc/apt/keyrings/cursor.gpg > /dev/null | |
| ``` | |
| Add the repository: | |
| ```bash | |
| echo \ | |
| "deb [arch=amd64,arm64 signed-by=/etc/apt/keyrings/cursor.gpg] https://downloads.cursor.com/aptrepo stable main" | \ | |
| sudo tee /etc/apt/sources.list.d/cursor.list > /dev/null | |
| ``` | |
| Install: | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y cursor | |
| ``` | |
| Verify: | |
| ```bash | |
| command -v cursor | |
| cursor --version 2>/dev/null | head -n 2 | |
| ``` | |
| If the repository method ever fails, use the Linux download from: | |
| ```bash | |
| xdg-open https://cursor.com/downloads | |
| ``` | |
| --- | |
| ## 18. Install Google Antigravity IDE | |
| Google provides an APT repository for Debian-based distributions. | |
| Create the keyring directory: | |
| ```bash | |
| sudo mkdir -p /etc/apt/keyrings | |
| ``` | |
| Install Google's Antigravity repository signing key: | |
| ```bash | |
| curl -fsSL \ | |
| https://us-central1-apt.pkg.dev/doc/repo-signing-key.gpg | \ | |
| sudo gpg --dearmor --yes \ | |
| -o /etc/apt/keyrings/antigravity-repo-key.gpg | |
| ``` | |
| Add the repository: | |
| ```bash | |
| echo \ | |
| "deb [signed-by=/etc/apt/keyrings/antigravity-repo-key.gpg] https://us-central1-apt.pkg.dev/projects/antigravity-auto-updater-dev/ antigravity-debian main" | \ | |
| sudo tee /etc/apt/sources.list.d/antigravity.list > /dev/null | |
| ``` | |
| Install: | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y antigravity | |
| ``` | |
| Verify: | |
| ```bash | |
| command -v antigravity || true | |
| antigravity --version 2>/dev/null | head -n 2 || true | |
| ``` | |
| --- | |
| ## 19. Install Slack | |
| Slack publishes a Debian/Ubuntu `.deb` package. | |
| Open the official Linux download page: | |
| ```bash | |
| xdg-open https://slack.com/downloads/linux | |
| ``` | |
| Download the `.deb` build. | |
| Then install the newest matching Slack package from `~/Downloads`: | |
| ```bash | |
| SLACK_DEB="$( | |
| find "$HOME/Downloads" -maxdepth 1 -type f \ | |
| -iname 'slack-desktop-*.deb' \ | |
| | sort | tail -n 1 | |
| )" | |
| test -n "$SLACK_DEB" || { | |
| echo "Download the Slack DEB first." | |
| exit 1 | |
| } | |
| sudo apt install -y "$SLACK_DEB" | |
| ``` | |
| Verify: | |
| ```bash | |
| dpkg -l | grep -i slack | |
| command -v slack || true | |
| ``` | |
| ### Flatpak fallback | |
| Install Flatpak if you have not already: | |
| ```bash | |
| sudo apt install -y flatpak | |
| ``` | |
| Add Flathub: | |
| ```bash | |
| flatpak remote-add --if-not-exists \ | |
| flathub https://dl.flathub.org/repo/flathub.flatpakrepo | |
| ``` | |
| Install Slack: | |
| ```bash | |
| flatpak install -y flathub com.slack.Slack | |
| ``` | |
| Launch: | |
| ```bash | |
| flatpak run com.slack.Slack | |
| ``` | |
| Use either the native Slack package or Flatpak unless you intentionally want two installations. | |
| --- | |
| ## 20. Install Postman | |
| Use Postman's official Linux tarball. | |
| ```bash | |
| cd /tmp | |
| curl -L \ | |
| -o postman-linux-x64.tar.gz \ | |
| https://dl.pstmn.io/download/latest/linux64 | |
| sudo rm -rf /opt/Postman | |
| sudo tar -xzf postman-linux-x64.tar.gz -C /opt | |
| sudo ln -sfn /opt/Postman/Postman /usr/local/bin/postman | |
| ``` | |
| Test: | |
| ```bash | |
| postman | |
| ``` | |
| Create an application launcher: | |
| ```bash | |
| mkdir -p "$HOME/.local/share/applications" | |
| cat > "$HOME/.local/share/applications/postman.desktop" <<'DESKTOP' | |
| [Desktop Entry] | |
| Name=Postman | |
| Comment=API development environment | |
| Exec=/opt/Postman/Postman | |
| Icon=/opt/Postman/app/resources/app/assets/icon.png | |
| Terminal=false | |
| Type=Application | |
| Categories=Development;Network; | |
| StartupWMClass=Postman | |
| DESKTOP | |
| chmod +x "$HOME/.local/share/applications/postman.desktop" | |
| update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true | |
| ``` | |
| Optional Zsh alias: | |
| ```bash | |
| cat >> "$HOME/.zshrc" <<'EOF_ZSH' | |
| # Postman | |
| alias postman='/opt/Postman/Postman' | |
| EOF_ZSH | |
| source "$HOME/.zshrc" | |
| ``` | |
| --- | |
| ## 21. Install LM Studio with an applications-menu launcher | |
| LM Studio for Linux is distributed as an AppImage. | |
| ### 21.1 Install AppImage support | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y fuse3 libfuse2t64 | |
| ``` | |
| ### 21.2 Download LM Studio | |
| Open the official Linux download page: | |
| ```bash | |
| xdg-open "https://lmstudio.ai/download?os=linux" | |
| ``` | |
| Download the Linux x64 AppImage. | |
| ### 21.3 Move it into `~/Applications` | |
| ```bash | |
| mkdir -p "$HOME/Applications" | |
| LM_APPIMAGE="$( | |
| find "$HOME/Downloads" -maxdepth 1 -type f \ | |
| \( -iname '*LM*Studio*.AppImage' -o -iname '*LMStudio*.AppImage' \) \ | |
| | sort | tail -n 1 | |
| )" | |
| echo "$LM_APPIMAGE" | |
| test -n "$LM_APPIMAGE" || { | |
| echo "Download the LM Studio AppImage first." | |
| exit 1 | |
| } | |
| install -Dm755 \ | |
| "$LM_APPIMAGE" \ | |
| "$HOME/Applications/LM-Studio.AppImage" | |
| ``` | |
| Test: | |
| ```bash | |
| "$HOME/Applications/LM-Studio.AppImage" | |
| ``` | |
| ### 21.4 Create an Ubuntu applications-menu launcher | |
| ```bash | |
| mkdir -p "$HOME/.local/share/applications" | |
| cat > "$HOME/.local/share/applications/lm-studio.desktop" <<DESKTOP | |
| [Desktop Entry] | |
| Name=LM Studio | |
| Comment=Run local LLMs on your computer | |
| Exec=$HOME/Applications/LM-Studio.AppImage | |
| Terminal=false | |
| Type=Application | |
| Categories=Development;Utility; | |
| StartupWMClass=LM Studio | |
| DESKTOP | |
| chmod +x "$HOME/.local/share/applications/lm-studio.desktop" | |
| update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true | |
| ``` | |
| Search the Ubuntu applications overview for: | |
| ```text | |
| LM Studio | |
| ``` | |
| If it does not appear immediately, log out and back in. | |
| ### 21.5 Optional terminal command | |
| ```bash | |
| mkdir -p "$HOME/.local/bin" | |
| ln -sfn \ | |
| "$HOME/Applications/LM-Studio.AppImage" \ | |
| "$HOME/.local/bin/lmstudio" | |
| grep -q 'export PATH="$HOME/.local/bin:$PATH"' "$HOME/.zshrc" || \ | |
| echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.zshrc" | |
| source "$HOME/.zshrc" | |
| ``` | |
| Test: | |
| ```bash | |
| lmstudio | |
| ``` | |
| --- | |
| ## 22. AppImage general pattern | |
| For any AppImage: | |
| ```bash | |
| sudo apt install -y fuse3 libfuse2t64 | |
| mkdir -p "$HOME/Applications" | |
| mv "$HOME/Downloads/MyApp.AppImage" "$HOME/Applications/" | |
| chmod +x "$HOME/Applications/MyApp.AppImage" | |
| "$HOME/Applications/MyApp.AppImage" | |
| ``` | |
| Create a launcher: | |
| ```bash | |
| mkdir -p "$HOME/.local/share/applications" | |
| cat > "$HOME/.local/share/applications/myapp.desktop" <<DESKTOP | |
| [Desktop Entry] | |
| Name=My App | |
| Comment=AppImage application | |
| Exec=$HOME/Applications/MyApp.AppImage | |
| Terminal=false | |
| Type=Application | |
| Categories=Development;Utility; | |
| DESKTOP | |
| chmod +x "$HOME/.local/share/applications/myapp.desktop" | |
| update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true | |
| ``` | |
| If the AppImage reports a FUSE 2 compatibility error: | |
| ```bash | |
| sudo apt install --reinstall -y libfuse2t64 fuse3 | |
| ``` | |
| If it still fails, try extraction: | |
| ```bash | |
| cd "$HOME/Applications" | |
| ./MyApp.AppImage --appimage-extract | |
| ./squashfs-root/AppRun | |
| ``` | |
| --- | |
| ## 23. Install Steam and gaming tools | |
| Ubuntu 26.04 provides Steam through the `steam-installer` package in Multiverse. | |
| ### 23.1 Enable 32-bit architecture | |
| Steam and many games still use 32-bit libraries: | |
| ```bash | |
| sudo dpkg --add-architecture i386 | |
| sudo apt update | |
| ``` | |
| ### 23.2 Install Steam | |
| ```bash | |
| sudo apt install -y steam-installer | |
| ``` | |
| Launch: | |
| ```bash | |
| steam | |
| ``` | |
| Steam will download its runtime components during first launch. | |
| ### 23.3 Flatpak fallback | |
| ```bash | |
| sudo apt install -y flatpak | |
| flatpak remote-add --if-not-exists \ | |
| flathub https://dl.flathub.org/repo/flathub.flatpakrepo | |
| flatpak install -y flathub com.valvesoftware.Steam | |
| ``` | |
| Launch: | |
| ```bash | |
| flatpak run com.valvesoftware.Steam | |
| ``` | |
| Use native Steam or Flatpak Steam, not both, unless you intentionally want separate installations. | |
| ### 23.4 Enable Steam Play and Proton | |
| In Steam: | |
| ```text | |
| Steam > Settings > Compatibility | |
| ``` | |
| Enable Steam Play/compatibility support for the games you need. | |
| Steam's wording changes occasionally, but the relevant area remains the Compatibility settings. | |
| ### 23.5 Install GameMode, MangoHud, and Gamescope | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y gamemode mangohud gamescope | |
| ``` | |
| Per-game Steam launch option: | |
| ```text | |
| gamemoderun %command% | |
| ``` | |
| With MangoHud: | |
| ```text | |
| mangohud gamemoderun %command% | |
| ``` | |
| Verify GameMode: | |
| ```bash | |
| gamemoded -s | |
| ``` | |
| --- | |
| ## 24. Install system monitoring tools | |
| ### 24.1 Install Flatpak and Flathub | |
| If Flatpak has not been installed yet: | |
| ```bash | |
| sudo apt install -y flatpak | |
| flatpak remote-add --if-not-exists \ | |
| flathub https://dl.flathub.org/repo/flathub.flatpakrepo | |
| ``` | |
| ### 24.2 Mission Center GUI | |
| Install Mission Center: | |
| ```bash | |
| flatpak install -y flathub io.missioncenter.MissionCenter | |
| ``` | |
| Launch: | |
| ```bash | |
| flatpak run io.missioncenter.MissionCenter | |
| ``` | |
| ### 24.3 Terminal monitors | |
| Install: | |
| ```bash | |
| sudo apt install -y nvtop btop | |
| ``` | |
| Use: | |
| ```bash | |
| nvtop | |
| btop | |
| ``` | |
| Recommended pattern: | |
| ```text | |
| Mission Center = general GUI system monitor | |
| nvtop = NVIDIA GPU monitoring | |
| btop = CPU, RAM, disks, network, and processes | |
| ``` | |
| --- | |
| ## 25. Install camera controls | |
| Your EMEET camera uses the standard Linux UVC stack, so V4L2 tools remain appropriate on Ubuntu. | |
| ### 25.1 Install Cameractrls | |
| Make sure Flatpak/Flathub are configured: | |
| ```bash | |
| sudo apt install -y flatpak | |
| flatpak remote-add --if-not-exists \ | |
| flathub https://dl.flathub.org/repo/flathub.flatpakrepo | |
| ``` | |
| Install: | |
| ```bash | |
| flatpak install -y flathub hu.irl.cameractrls | |
| ``` | |
| Launch: | |
| ```bash | |
| flatpak run hu.irl.cameractrls | |
| ``` | |
| ### 25.2 Install command-line camera tools | |
| ```bash | |
| sudo apt install -y v4l-utils | |
| ``` | |
| List cameras: | |
| ```bash | |
| v4l2-ctl --list-devices | |
| ``` | |
| List controls: | |
| ```bash | |
| v4l2-ctl --list-ctrls | |
| ``` | |
| Inspect a camera: | |
| ```bash | |
| v4l2-ctl -d /dev/video0 --all | |
| ``` | |
| Example controls: | |
| ```bash | |
| v4l2-ctl -d /dev/video0 --set-ctrl=brightness=128 | |
| v4l2-ctl -d /dev/video0 --set-ctrl=contrast=128 | |
| v4l2-ctl -d /dev/video0 --set-ctrl=saturation=128 | |
| ``` | |
| Exact control names and ranges depend on the webcam. | |
| ### 25.3 Install guvcview and OBS Studio | |
| ```bash | |
| sudo apt install -y guvcview obs-studio | |
| ``` | |
| Launch: | |
| ```bash | |
| guvcview | |
| obs | |
| ``` | |
| Recommended pattern: | |
| ```text | |
| Cameractrls = daily camera control panel | |
| guvcview = quick preview and fallback controls | |
| OBS Studio = recording, streaming, filters, virtual camera | |
| v4l2-ctl = troubleshooting and scripting | |
| ``` | |
| --- | |
| ## 26. Set up Brother HL-L2405W printer | |
| Try driverless AirPrint/IPP first. | |
| ### 26.1 Install printing and discovery tools | |
| Ubuntu Desktop normally includes CUPS, but install the required packages explicitly: | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y \ | |
| cups \ | |
| cups-client \ | |
| cups-filters \ | |
| printer-driver-all \ | |
| avahi-daemon \ | |
| avahi-utils | |
| ``` | |
| Enable services: | |
| ```bash | |
| sudo systemctl enable --now cups | |
| sudo systemctl enable --now avahi-daemon | |
| ``` | |
| Allow your user to administer printers through the standard `lpadmin` group: | |
| ```bash | |
| sudo usermod -aG lpadmin "$USER" | |
| ``` | |
| Log out and back in before relying on the new group membership. | |
| ### 26.2 Connect the printer | |
| For Wi-Fi, connect the Brother HL-L2405W to the same local network as the Ubuntu workstation. | |
| For USB, connect it directly. | |
| ### 26.3 Discover the printer | |
| ```bash | |
| lpinfo -v | grep -i brother || true | |
| driverless || true | |
| avahi-browse -rt _ipp._tcp | |
| ``` | |
| ### 26.4 Add through Ubuntu Settings | |
| Open: | |
| ```text | |
| Settings > System > Printers | |
| ``` | |
| Depending on the Ubuntu desktop revision, Printers may also appear as its own Settings section. | |
| Prefer a driverless, AirPrint, IPP Everywhere, or similar entry when available. | |
| Suggested queue name: | |
| ```text | |
| Brother_HL_L2405W | |
| ``` | |
| ### 26.5 Add with the command line | |
| List devices: | |
| ```bash | |
| lpinfo -v | |
| ``` | |
| If you have an IPP URI: | |
| ```bash | |
| sudo lpadmin \ | |
| -p Brother_HL_L2405W \ | |
| -E \ | |
| -v "PASTE_PRINTER_URI_HERE" \ | |
| -m everywhere | |
| sudo lpoptions -d Brother_HL_L2405W | |
| ``` | |
| Example by IP: | |
| ```bash | |
| sudo lpadmin \ | |
| -p Brother_HL_L2405W \ | |
| -E \ | |
| -v "ipp://192.168.1.75/ipp/print" \ | |
| -m everywhere | |
| sudo lpoptions -d Brother_HL_L2405W | |
| ``` | |
| Test: | |
| ```bash | |
| lpstat -p -d | |
| echo "Brother HL-L2405W Ubuntu test page" | lp -d Brother_HL_L2405W | |
| ``` | |
| ### 26.6 Brother Linux installer fallback | |
| Only use Brother's vendor driver if driverless IPP does not work. | |
| Brother currently provides both a Linux **DEB printer driver** and a **Driver Install Tool** for the HL-L2405W. | |
| Open: | |
| ```bash | |
| xdg-open \ | |
| "https://support.brother.com/g/b/downloadtop.aspx?c=us&lang=en&prod=hll2405w_us" | |
| ``` | |
| Choose: | |
| ```text | |
| Linux (deb) | |
| ``` | |
| The Driver Install Tool is generally the simplest vendor fallback because it installs the appropriate LPR/CUPSwrapper components. | |
| After downloading the installer archive: | |
| ```bash | |
| cd "$HOME/Downloads" | |
| ls -lh linux-brprinter-installer-*.gz | |
| gunzip linux-brprinter-installer-*.gz | |
| chmod +x linux-brprinter-installer-* | |
| sudo bash linux-brprinter-installer-* HLL2405W | |
| ``` | |
| Follow Brother's prompts. | |
| If asked for the device connection: | |
| - For USB, choose the USB/local option. | |
| - For Wi-Fi or Ethernet, choose the network option and provide the printer's IP address when requested. | |
| After installation: | |
| ```bash | |
| lpstat -t | |
| lpinfo -v | grep -i brother || true | |
| ``` | |
| --- | |
| ## 27. Flatpak application-menu refresh | |
| GNOME normally discovers Flatpak launchers automatically. | |
| List installed Flatpaks: | |
| ```bash | |
| flatpak list | |
| ``` | |
| Check exported launchers: | |
| ```bash | |
| find \ | |
| "$HOME/.local/share/flatpak/exports/share/applications" \ | |
| /var/lib/flatpak/exports/share/applications \ | |
| -name '*.desktop' 2>/dev/null | |
| ``` | |
| Refresh desktop databases if needed: | |
| ```bash | |
| update-desktop-database \ | |
| "$HOME/.local/share/flatpak/exports/share/applications" \ | |
| 2>/dev/null || true | |
| sudo update-desktop-database \ | |
| /var/lib/flatpak/exports/share/applications \ | |
| 2>/dev/null || true | |
| ``` | |
| Log out and back in if an application still does not appear. | |
| Direct launch examples: | |
| ```bash | |
| flatpak run hu.irl.cameractrls | |
| flatpak run io.missioncenter.MissionCenter | |
| flatpak run com.valvesoftware.Steam | |
| flatpak run com.slack.Slack | |
| ``` | |
| --- | |
| ## 28. Repair Ubuntu CA certificates | |
| Use this section if `apt`, `curl`, or another HTTPS client reports certificate-chain errors. | |
| Ubuntu's primary CA bundle is: | |
| ```text | |
| /etc/ssl/certs/ca-certificates.crt | |
| ``` | |
| Check it: | |
| ```bash | |
| ls -l /etc/ssl/certs/ca-certificates.crt | |
| test -r /etc/ssl/certs/ca-certificates.crt && echo "CA bundle is readable" | |
| ``` | |
| Reinstall the CA package: | |
| ```bash | |
| sudo apt update | |
| sudo apt install --reinstall -y ca-certificates | |
| ``` | |
| Regenerate the certificate bundle: | |
| ```bash | |
| sudo update-ca-certificates --fresh | |
| ``` | |
| Verify: | |
| ```bash | |
| ls -lh /etc/ssl/certs/ca-certificates.crt | |
| ``` | |
| Test HTTPS: | |
| ```bash | |
| curl -I https://ubuntu.com | |
| curl -I https://download.docker.com | |
| curl -I https://slack.com | |
| ``` | |
| If `apt update` itself cannot run because of certificate problems, reinstall from the package cache if the package is present: | |
| ```bash | |
| ls /var/cache/apt/archives/ca-certificates_*.deb 2>/dev/null | |
| ``` | |
| Then: | |
| ```bash | |
| sudo dpkg -i /var/cache/apt/archives/ca-certificates_*.deb | |
| sudo update-ca-certificates --fresh | |
| ``` | |
| Do not disable TLS verification as a workaround. | |
| --- | |
| ## 29. Work around slow or failing Ubuntu mirrors | |
| If `apt update` or an install repeatedly times out, first retry with APT's retry setting: | |
| ```bash | |
| sudo apt-get \ | |
| -o Acquire::Retries=5 \ | |
| update | |
| ``` | |
| For a package install: | |
| ```bash | |
| sudo apt-get \ | |
| -o Acquire::Retries=5 \ | |
| install -y PACKAGE_NAME | |
| ``` | |
| Inspect configured Ubuntu mirrors: | |
| ```bash | |
| grep -R -E '^(URIs:|deb )' \ | |
| /etc/apt/sources.list \ | |
| /etc/apt/sources.list.d 2>/dev/null | |
| ``` | |
| On Ubuntu 26.04, the primary Ubuntu configuration commonly uses: | |
| ```text | |
| /etc/apt/sources.list.d/ubuntu.sources | |
| ``` | |
| Before editing it: | |
| ```bash | |
| sudo cp -a \ | |
| /etc/apt/sources.list.d/ubuntu.sources \ | |
| "/etc/apt/sources.list.d/ubuntu.sources.backup.$(date +%Y%m%d-%H%M%S)" | |
| ``` | |
| You can also change the mirror through Ubuntu's graphical software-source settings rather than editing the file manually. | |
| After changing a mirror: | |
| ```bash | |
| sudo apt clean | |
| sudo rm -rf /var/lib/apt/lists/partial/* | |
| sudo apt update | |
| ``` | |
| If only a third-party repository is failing, do not break the main Ubuntu repositories trying to fix it. Inspect the specific vendor source: | |
| ```bash | |
| ls -1 /etc/apt/sources.list.d/ | |
| ``` | |
| Temporarily disable a problematic third-party `.list` file by renaming it: | |
| ```bash | |
| sudo mv \ | |
| /etc/apt/sources.list.d/problem.list \ | |
| /etc/apt/sources.list.d/problem.list.disabled | |
| sudo apt update | |
| ``` | |
| For deb822 `.sources` files, rename the file similarly: | |
| ```bash | |
| sudo mv \ | |
| /etc/apt/sources.list.d/problem.sources \ | |
| /etc/apt/sources.list.d/problem.sources.disabled | |
| sudo apt update | |
| ``` | |
| --- | |
| ## 30. Final verification script | |
| Run this from a fresh Terminator session: | |
| ```bash | |
| cat > /tmp/verify-ubuntu-dev-env.sh <<'VERIFY' | |
| #!/usr/bin/env bash | |
| set -u | |
| section() { | |
| printf '\n== %s ==\n' "$1" | |
| } | |
| section "System" | |
| cat /etc/os-release || true | |
| uname -r || true | |
| hostnamectl | sed -n '1,12p' || true | |
| section "Storage mounts" | |
| lsblk -e7 -o NAME,SIZE,FSTYPE,LABEL,UUID,MODEL,MOUNTPOINTS || true | |
| findmnt --real || true | |
| findmnt --verify --verbose || true | |
| section "Desktop" | |
| echo "XDG_CURRENT_DESKTOP=${XDG_CURRENT_DESKTOP:-unknown}" | |
| echo "XDG_SESSION_TYPE=${XDG_SESSION_TYPE:-unknown}" | |
| echo "DESKTOP_SESSION=${DESKTOP_SESSION:-unknown}" | |
| section "Shell" | |
| echo "SHELL=$SHELL" | |
| zsh --version || true | |
| section "Terminator" | |
| command -v terminator || true | |
| terminator --version 2>/dev/null || true | |
| section "Git" | |
| git --version || true | |
| git lfs version || true | |
| section "AWS CLI" | |
| aws --version || true | |
| section "Node via nvm" | |
| zsh -ic \ | |
| 'command -v nvm && nvm --version && node --version && npm --version' \ | |
| || true | |
| section "NVIDIA" | |
| cat /proc/driver/nvidia/version 2>/dev/null || true | |
| nvidia-smi || true | |
| lsmod | grep '^nvidia' || true | |
| glxinfo -B 2>/dev/null | \ | |
| grep -E 'OpenGL vendor|OpenGL renderer' || true | |
| vulkaninfo --summary 2>/dev/null | \ | |
| grep -Ei 'deviceName|driverName' || true | |
| section "Docker Engine" | |
| docker --version || true | |
| docker compose version || true | |
| docker context ls || true | |
| systemctl status docker --no-pager 2>/dev/null | sed -n '1,12p' || true | |
| section "NVIDIA Container Toolkit" | |
| command -v nvidia-ctk || true | |
| dpkg -l 2>/dev/null | grep nvidia-container-toolkit || true | |
| section "Docker Desktop" | |
| systemctl --user status docker-desktop --no-pager 2>/dev/null | \ | |
| sed -n '1,12p' || true | |
| section "Google Chrome" | |
| command -v google-chrome-stable || true | |
| google-chrome-stable --version 2>/dev/null || true | |
| dpkg -l 2>/dev/null | grep google-chrome-stable || true | |
| section "VS Code" | |
| code --version 2>/dev/null | head -n 2 || true | |
| section "Cursor" | |
| command -v cursor || true | |
| cursor --version 2>/dev/null | head -n 2 || true | |
| section "Antigravity" | |
| command -v antigravity || true | |
| antigravity --version 2>/dev/null | head -n 2 || true | |
| section "Postman" | |
| command -v postman || true | |
| ls /opt/Postman/Postman 2>/dev/null || true | |
| section "LM Studio" | |
| ls "$HOME/Applications"/*Studio*.AppImage 2>/dev/null || true | |
| ls "$HOME/.local/share/applications"/*lm*studio*.desktop \ | |
| 2>/dev/null || true | |
| section "Slack" | |
| command -v slack || true | |
| dpkg -l 2>/dev/null | grep -i slack || true | |
| flatpak list 2>/dev/null | grep -i slack || true | |
| section "Steam and gaming" | |
| command -v steam || true | |
| flatpak list 2>/dev/null | grep -i steam || true | |
| command -v gamemoderun || true | |
| command -v mangohud || true | |
| command -v gamescope || true | |
| section "Monitoring" | |
| command -v nvtop || true | |
| command -v btop || true | |
| flatpak list 2>/dev/null | grep -i mission || true | |
| section "Camera" | |
| command -v v4l2-ctl || true | |
| flatpak list 2>/dev/null | grep -i camera || true | |
| command -v guvcview || true | |
| command -v obs || true | |
| section "Printer" | |
| lpstat -t 2>/dev/null || true | |
| section "APT" | |
| sudo apt-get check || true | |
| apt list --upgradable 2>/dev/null | head -n 30 || true | |
| VERIFY | |
| chmod +x /tmp/verify-ubuntu-dev-env.sh | |
| bash /tmp/verify-ubuntu-dev-env.sh | |
| ``` | |
| --- | |
| ## 31. Maintenance and updates | |
| Update Ubuntu packages: | |
| ```bash | |
| sudo apt update | |
| sudo apt full-upgrade -y | |
| sudo apt autoremove -y | |
| ``` | |
| Update Flatpaks: | |
| ```bash | |
| flatpak update -y | |
| ``` | |
| Update Snaps if you use any: | |
| ```bash | |
| sudo snap refresh | |
| ``` | |
| Update Oh My Zsh: | |
| ```bash | |
| omz update | |
| ``` | |
| Update Node LTS: | |
| ```bash | |
| nvm install --lts | |
| nvm alias default "lts/*" | |
| ``` | |
| Update AWS CLI v2: | |
| ```bash | |
| cd /tmp | |
| rm -rf aws awscliv2.zip | |
| curl -fsSL \ | |
| "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \ | |
| -o awscliv2.zip | |
| unzip -q awscliv2.zip | |
| sudo ./aws/install \ | |
| --bin-dir /usr/local/bin \ | |
| --install-dir /usr/local/aws-cli \ | |
| --update | |
| aws --version | |
| ``` | |
| Update Postman: | |
| ```bash | |
| cd /tmp | |
| curl -L \ | |
| -o postman-linux-x64.tar.gz \ | |
| https://dl.pstmn.io/download/latest/linux64 | |
| sudo rm -rf /opt/Postman | |
| sudo tar -xzf postman-linux-x64.tar.gz -C /opt | |
| sudo ln -sfn /opt/Postman/Postman /usr/local/bin/postman | |
| ``` | |
| Update LM Studio: | |
| 1. Download the newest Linux x64 AppImage. | |
| 2. Replace the existing AppImage: | |
| ```bash | |
| LM_APPIMAGE="$( | |
| find "$HOME/Downloads" -maxdepth 1 -type f \ | |
| \( -iname '*LM*Studio*.AppImage' -o -iname '*LMStudio*.AppImage' \) \ | |
| | sort | tail -n 1 | |
| )" | |
| test -n "$LM_APPIMAGE" || { | |
| echo "Download the new LM Studio AppImage first." | |
| exit 1 | |
| } | |
| install -Dm755 \ | |
| "$LM_APPIMAGE" \ | |
| "$HOME/Applications/LM-Studio.AppImage" | |
| ``` | |
| Update NVIDIA through Ubuntu's normal package flow: | |
| ```bash | |
| sudo apt update | |
| sudo apt full-upgrade -y | |
| ``` | |
| Check whether Ubuntu now recommends a different supported branch: | |
| ```bash | |
| ubuntu-drivers devices | |
| ``` | |
| Do not switch NVIDIA driver branches merely because a numerically newer package exists. Prefer Ubuntu's recommended branch unless you are fixing a specific problem. | |
| Update Docker Engine: | |
| ```bash | |
| sudo apt update | |
| sudo apt install \ | |
| docker-ce \ | |
| docker-ce-cli \ | |
| containerd.io \ | |
| docker-buildx-plugin \ | |
| docker-compose-plugin | |
| ``` | |
| Update Docker Desktop by downloading the latest DEB and installing it over the existing package: | |
| ```bash | |
| sudo apt install ./docker-desktop-amd64.deb | |
| ``` | |
| --- | |
| ## 32. Quick run order for a fresh install | |
| Use this order on a fresh Ubuntu 26.04 LTS workstation: | |
| 1. Install Ubuntu Desktop 26.04 LTS and enable third-party drivers/software during installation. | |
| 2. Fully update Ubuntu and reboot. | |
| 3. Inventory the internal disks and configure UUID-based automatic mounts. | |
| 4. Install Terminator. | |
| 5. Enable Universe, Multiverse, and Restricted. | |
| 6. Install the base developer packages. | |
| 7. Configure Git. | |
| 8. Install Zsh and Oh My Zsh. | |
| 9. Install nvm and Node.js LTS. | |
| 10. Install AWS CLI v2. | |
| 11. Install the NVIDIA driver with `ubuntu-drivers` and reboot. | |
| 12. Verify `nvidia-smi`, OpenGL, and Vulkan. | |
| 13. Install Docker Engine and Compose. | |
| 14. Install NVIDIA Container Toolkit if you need GPU containers. | |
| 15. Install Docker Desktop if you want the GUI. | |
| 16. Install Google Chrome. | |
| 17. Install VS Code, Cursor, Antigravity, and Postman. | |
| 18. Install Slack. | |
| 19. Install LM Studio and its launcher. | |
| 20. Install Steam, GameMode, MangoHud, and Gamescope. | |
| 21. Install Mission Center, nvtop, and btop. | |
| 22. Install camera tools. | |
| 23. Set up the Brother printer. | |
| 24. Run the final verification script. | |
| --- | |
| ## 33. References | |
| Ubuntu: | |
| - Ubuntu Desktop download: https://ubuntu.com/download/desktop | |
| - Ubuntu 26.04 LTS release notes: https://documentation.ubuntu.com/release-notes/26.04/ | |
| - Ubuntu Desktop installation: https://documentation.ubuntu.com/desktop/en/latest/tutorial/install-ubuntu-desktop/ | |
| - Ubuntu package management: https://documentation.ubuntu.com/server/how-to/software/package-management/ | |
| - Ubuntu NVIDIA driver installation: https://ubuntu.com/desktop/docs/en/latest/how-to/graphics/install-nvidia-drivers/ | |
| - Ubuntu Server NVIDIA driver installation: https://ubuntu.com/server/docs/nvidia-drivers-installation/ | |
| - Ubuntu package search: https://packages.ubuntu.com/ | |
| Developer tools: | |
| - Git: https://git-scm.com/install/linux | |
| - Oh My Zsh: https://ohmyz.sh/ | |
| - nvm: https://github.com/nvm-sh/nvm | |
| - AWS CLI v2: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html | |
| - Visual Studio Code Linux install: https://code.visualstudio.com/docs/setup/linux | |
| - Cursor: https://cursor.com/docs/get-started/quickstart | |
| - Google Antigravity Linux install: https://antigravity.google/download/linux | |
| - Postman: https://www.postman.com/downloads/ | |
| Containers and GPU: | |
| - Docker Engine Ubuntu: https://docs.docker.com/engine/install/ubuntu/ | |
| - Docker Desktop Ubuntu: https://docs.docker.com/desktop/setup/install/linux/ubuntu/ | |
| - NVIDIA Container Toolkit: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html | |
| - Docker GPU access: https://docs.docker.com/engine/containers/gpu/ | |
| Desktop applications: | |
| - Google Chrome Linux: https://support.google.com/chrome/a/answer/9025926 | |
| - Slack Linux: https://slack.com/downloads/linux | |
| - LM Studio: https://lmstudio.ai/download?os=linux | |
| - AppImage FUSE troubleshooting: https://docs.appimage.org/user-guide/troubleshooting/fuse.html | |
| - Steam: https://packages.ubuntu.com/resolute/steam-installer | |
| - Mission Center: https://flathub.org/apps/io.missioncenter.MissionCenter | |
| - Cameractrls: https://flathub.org/apps/hu.irl.cameractrls | |
| Printing: | |
| - Brother HL-L2405W support: https://support.brother.com/g/b/downloadtop.aspx?c=us&lang=en&prod=hll2405w_us | |
| - CUPS: https://www.cups.org/doc/admin.html | |
| --- | |
| ## 34. Install and Configure Nginx on Ubuntu Server 26.04 LTS for a DigitalOcean Droplet | |
| These notes target an Ubuntu Server 26.04 LTS DigitalOcean Droplet. | |
| Ubuntu installs Nginx with APT, manages it with systemd, uses UFW as the common host firewall frontend, uses AppArmor rather than SELinux, and follows the Debian-style Nginx layout: | |
| ```text | |
| /etc/nginx/sites-available/ | |
| /etc/nginx/sites-enabled/ | |
| ``` | |
| This section covers: | |
| - Updating Ubuntu | |
| - Installing Nginx | |
| - Starting and enabling the service | |
| - Opening Ubuntu's UFW firewall | |
| - Checking DigitalOcean Cloud Firewall rules | |
| - Creating a website directory | |
| - Configuring an Nginx server block | |
| - Testing and reloading Nginx | |
| - Pointing DNS to the Droplet | |
| - Installing HTTPS with Certbot | |
| - Viewing logs | |
| - Setting up a reverse proxy | |
| - AppArmor-aware troubleshooting | |
| - Common failure checks | |
| ### 34.1 SSH into the Droplet | |
| Use the IP address from the DigitalOcean dashboard. | |
| For root, if root SSH is enabled: | |
| ```bash | |
| ssh root@YOUR_DROPLET_IP | |
| ``` | |
| Prefer a regular sudo-enabled user for normal administration: | |
| ```bash | |
| ssh cesar@YOUR_DROPLET_IP | |
| ``` | |
| ### 34.2 Update Ubuntu | |
| ```bash | |
| sudo apt update | |
| sudo apt full-upgrade -y | |
| sudo apt autoremove -y | |
| ``` | |
| Check whether a reboot is recommended: | |
| ```bash | |
| if [ -f /var/run/reboot-required ]; then | |
| cat /var/run/reboot-required | |
| fi | |
| ``` | |
| If required: | |
| ```bash | |
| sudo reboot | |
| ``` | |
| Reconnect afterward: | |
| ```bash | |
| ssh cesar@YOUR_DROPLET_IP | |
| ``` | |
| ### 34.3 Install Nginx | |
| ```bash | |
| sudo apt install -y nginx | |
| ``` | |
| Verify: | |
| ```bash | |
| nginx -v | |
| dpkg -s nginx | grep -E 'Status|Version' | |
| ``` | |
| ### 34.4 Enable and start Nginx | |
| Ubuntu normally starts Nginx during package installation. | |
| Ensure it is enabled and running: | |
| ```bash | |
| sudo systemctl enable --now nginx | |
| ``` | |
| Check: | |
| ```bash | |
| sudo systemctl status nginx --no-pager | |
| ``` | |
| Expected: | |
| ```text | |
| Active: active (running) | |
| ``` | |
| ### 34.5 Configure UFW for SSH, HTTP, and HTTPS | |
| Install UFW if needed: | |
| ```bash | |
| sudo apt install -y ufw | |
| ``` | |
| Before enabling UFW on a remote server, permit SSH: | |
| ```bash | |
| sudo ufw allow OpenSSH | |
| ``` | |
| List Nginx application profiles: | |
| ```bash | |
| sudo ufw app list | |
| ``` | |
| Allow both HTTP and HTTPS: | |
| ```bash | |
| sudo ufw allow 'Nginx Full' | |
| ``` | |
| If UFW is not already enabled: | |
| ```bash | |
| sudo ufw enable | |
| ``` | |
| Verify: | |
| ```bash | |
| sudo ufw status verbose | |
| ``` | |
| You should see rules allowing OpenSSH and Nginx Full. | |
| > Important: Docker-published ports can bypass normal UFW filtering. If this Droplet also runs Docker, review Docker's firewall behavior separately. | |
| ### 34.6 Check the DigitalOcean Cloud Firewall | |
| DigitalOcean Cloud Firewalls are separate from UFW. If both are in use, both layers need to permit the traffic. | |
| Make sure the Cloud Firewall attached to the Droplet allows: | |
| | Type | Protocol | Port | Source | | |
| | --- | --- | --- | --- | | |
| | SSH | TCP | 22 | Your IP when practical | | |
| | HTTP | TCP | 80 | `0.0.0.0/0`, `::/0` | | |
| | HTTPS | TCP | 443 | `0.0.0.0/0`, `::/0` | | |
| Do not remove SSH access before confirming an alternate path into the server. | |
| ### 34.7 Test the default Nginx page | |
| From your local machine: | |
| ```text | |
| http://YOUR_DROPLET_IP | |
| ``` | |
| Or: | |
| ```bash | |
| curl -I http://YOUR_DROPLET_IP | |
| ``` | |
| A working response should include something similar to: | |
| ```text | |
| HTTP/1.1 200 OK | |
| Server: nginx | |
| ``` | |
| ### 34.8 Create a basic website directory | |
| Replace `example.com` with your domain: | |
| ```bash | |
| sudo mkdir -p /var/www/example.com/html | |
| ``` | |
| Create a test page: | |
| ```bash | |
| sudo tee /var/www/example.com/html/index.html > /dev/null <<'HTML' | |
| <!doctype html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <title>example.com</title> | |
| </head> | |
| <body> | |
| <h1>Nginx is working on Ubuntu 26.04 LTS</h1> | |
| </body> | |
| </html> | |
| HTML | |
| ``` | |
| For a simple static site, make `www-data` the owner: | |
| ```bash | |
| sudo chown -R www-data:www-data /var/www/example.com | |
| ``` | |
| Set normal web permissions: | |
| ```bash | |
| sudo find /var/www/example.com -type d -exec chmod 755 {} \; | |
| sudo find /var/www/example.com -type f -exec chmod 644 {} \; | |
| ``` | |
| If your deployment process needs your user to own the files instead, use a group-based deployment model rather than repeatedly making everything world-writable. | |
| ### 34.9 Ubuntu security model: AppArmor instead of SELinux | |
| The Fedora version required SELinux labeling for custom web roots. Ubuntu does **not** use SELinux labeling by default, so there is no `semanage fcontext` or `restorecon` step here. | |
| Check AppArmor status: | |
| ```bash | |
| sudo aa-status | |
| ``` | |
| For a normal Nginx installation serving `/var/www`, standard Unix file permissions are usually the relevant access control. | |
| If you see an unexpected denial, inspect kernel logs: | |
| ```bash | |
| sudo journalctl -k | grep -i apparmor | tail -n 100 | |
| ``` | |
| Do not disable AppArmor globally as a troubleshooting shortcut. | |
| ### 34.10 Create an Nginx server block | |
| Ubuntu uses `sites-available` and `sites-enabled`. | |
| Create the configuration: | |
| ```bash | |
| sudo nano /etc/nginx/sites-available/example.com | |
| ``` | |
| Add: | |
| ```nginx | |
| server { | |
| listen 80; | |
| listen [::]:80; | |
| server_name example.com www.example.com; | |
| root /var/www/example.com/html; | |
| index index.html; | |
| access_log /var/log/nginx/example.com.access.log; | |
| error_log /var/log/nginx/example.com.error.log; | |
| location / { | |
| try_files $uri $uri/ =404; | |
| } | |
| } | |
| ``` | |
| Enable the site: | |
| ```bash | |
| sudo ln -sfn \ | |
| /etc/nginx/sites-available/example.com \ | |
| /etc/nginx/sites-enabled/example.com | |
| ``` | |
| ### 34.11 Test and reload Nginx | |
| Test syntax: | |
| ```bash | |
| sudo nginx -t | |
| ``` | |
| If successful: | |
| ```bash | |
| sudo systemctl reload nginx | |
| ``` | |
| Check status: | |
| ```bash | |
| sudo systemctl status nginx --no-pager | |
| ``` | |
| ### 34.12 Point your domain to the Droplet | |
| Create DNS records at your DNS provider: | |
| | Type | Name | Value | | |
| | --- | --- | --- | | |
| | A | `@` | `YOUR_DROPLET_IPV4` | | |
| | A | `www` | `YOUR_DROPLET_IPV4` | | |
| | AAAA | `@` | `YOUR_DROPLET_IPV6`, optional | | |
| | AAAA | `www` | `YOUR_DROPLET_IPV6`, optional | | |
| Install DNS tools: | |
| ```bash | |
| sudo apt install -y dnsutils | |
| ``` | |
| Test: | |
| ```bash | |
| dig +short example.com | |
| dig +short www.example.com | |
| ``` | |
| Then: | |
| ```bash | |
| curl -I http://example.com | |
| curl -I http://www.example.com | |
| ``` | |
| ### 34.13 Install HTTPS with Certbot | |
| Install Certbot and the Nginx plugin: | |
| ```bash | |
| sudo apt update | |
| sudo apt install -y certbot python3-certbot-nginx | |
| ``` | |
| Request and configure the certificate: | |
| ```bash | |
| sudo certbot --nginx \ | |
| -d example.com \ | |
| -d www.example.com | |
| ``` | |
| Follow the prompts. | |
| Test: | |
| ```bash | |
| curl -I https://example.com | |
| ``` | |
| Check renewal: | |
| ```bash | |
| sudo certbot renew --dry-run | |
| ``` | |
| Check the timer if your package config uses systemd renewal: | |
| ```bash | |
| systemctl list-timers | grep -i certbot || true | |
| ``` | |
| ### 34.14 Useful Nginx commands | |
| Status: | |
| ```bash | |
| sudo systemctl status nginx --no-pager | |
| ``` | |
| Start: | |
| ```bash | |
| sudo systemctl start nginx | |
| ``` | |
| Stop: | |
| ```bash | |
| sudo systemctl stop nginx | |
| ``` | |
| Restart: | |
| ```bash | |
| sudo systemctl restart nginx | |
| ``` | |
| Reload without a full restart: | |
| ```bash | |
| sudo systemctl reload nginx | |
| ``` | |
| Test configuration: | |
| ```bash | |
| sudo nginx -t | |
| ``` | |
| Version: | |
| ```bash | |
| nginx -v | |
| ``` | |
| Full active configuration: | |
| ```bash | |
| sudo nginx -T | |
| ``` | |
| ### 34.15 Useful log commands | |
| Default access log: | |
| ```bash | |
| sudo tail -f /var/log/nginx/access.log | |
| ``` | |
| Default error log: | |
| ```bash | |
| sudo tail -f /var/log/nginx/error.log | |
| ``` | |
| Custom site logs: | |
| ```bash | |
| sudo tail -f /var/log/nginx/example.com.access.log | |
| sudo tail -f /var/log/nginx/example.com.error.log | |
| ``` | |
| Systemd journal: | |
| ```bash | |
| sudo journalctl -u nginx -f | |
| ``` | |
| Recent service logs: | |
| ```bash | |
| sudo journalctl -u nginx -n 100 --no-pager | |
| ``` | |
| ### 34.16 Basic reverse proxy example | |
| Use this if Nginx should proxy to a local Node.js, Next.js, Strapi, Express, Fastify, Astro, or similar application. | |
| Example application port: | |
| ```text | |
| 3000 | |
| ``` | |
| Create: | |
| ```bash | |
| sudo nano /etc/nginx/sites-available/app.example.com | |
| ``` | |
| Add: | |
| ```nginx | |
| server { | |
| listen 80; | |
| listen [::]:80; | |
| server_name app.example.com; | |
| access_log /var/log/nginx/app.example.com.access.log; | |
| error_log /var/log/nginx/app.example.com.error.log; | |
| location / { | |
| proxy_pass http://127.0.0.1:3000; | |
| proxy_http_version 1.1; | |
| proxy_set_header Host $host; | |
| proxy_set_header X-Real-IP $remote_addr; | |
| proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
| proxy_set_header X-Forwarded-Proto $scheme; | |
| proxy_set_header Upgrade $http_upgrade; | |
| proxy_set_header Connection "upgrade"; | |
| } | |
| } | |
| ``` | |
| Enable: | |
| ```bash | |
| sudo ln -sfn \ | |
| /etc/nginx/sites-available/app.example.com \ | |
| /etc/nginx/sites-enabled/app.example.com | |
| ``` | |
| Test and reload: | |
| ```bash | |
| sudo nginx -t | |
| sudo systemctl reload nginx | |
| ``` | |
| Unlike the Fedora SELinux workflow, there is no `setsebool -P httpd_can_network_connect 1` command on Ubuntu. | |
| Confirm the upstream application is listening: | |
| ```bash | |
| sudo ss -ltnp | grep ':3000' | |
| ``` | |
| Test it locally: | |
| ```bash | |
| curl -I http://127.0.0.1:3000 | |
| ``` | |
| ### 34.17 Remove or disable the default welcome site | |
| Ubuntu enables the default Nginx site through: | |
| ```text | |
| /etc/nginx/sites-enabled/default | |
| ``` | |
| After your real site works, disable it: | |
| ```bash | |
| sudo rm -f /etc/nginx/sites-enabled/default | |
| sudo nginx -t | |
| sudo systemctl reload nginx | |
| ``` | |
| Keep `/etc/nginx/sites-available/default` if you want the packaged example available for reference. | |
| ### 34.18 Quick troubleshooting checklist | |
| #### Nginx is not running | |
| ```bash | |
| sudo systemctl status nginx --no-pager | |
| sudo journalctl -u nginx -n 100 --no-pager | |
| ``` | |
| #### Nginx config has an error | |
| ```bash | |
| sudo nginx -t | |
| ``` | |
| Print the full parsed configuration: | |
| ```bash | |
| sudo nginx -T | |
| ``` | |
| #### UFW is blocking traffic | |
| ```bash | |
| sudo ufw status verbose | |
| sudo ufw app list | |
| ``` | |
| #### Port 80 or 443 is not listening | |
| ```bash | |
| sudo ss -tulpn | grep -E ':(80|443)\b' | |
| ``` | |
| #### DNS is not pointing to the Droplet | |
| ```bash | |
| dig +short example.com | |
| dig +short www.example.com | |
| ``` | |
| #### File permissions may be blocking Nginx | |
| ```bash | |
| namei -l /var/www/example.com/html/index.html | |
| sudo -u www-data test -r /var/www/example.com/html/index.html && \ | |
| echo "www-data can read the file" | |
| ``` | |
| #### AppArmor may be involved | |
| ```bash | |
| sudo aa-status | |
| sudo journalctl -k | grep -i apparmor | tail -n 100 | |
| ``` | |
| Do not disable AppArmor globally. Fix the actual policy or path problem if an AppArmor denial is genuinely present. | |
| #### Reverse proxy upstream is unavailable | |
| ```bash | |
| sudo ss -ltnp | grep ':3000' | |
| curl -v http://127.0.0.1:3000/ | |
| ``` | |
| If the app is in Docker, verify the container and port mapping: | |
| ```bash | |
| docker ps | |
| docker compose ps | |
| ``` | |
| #### DigitalOcean Cloud Firewall is blocking traffic | |
| In DigitalOcean, verify inbound rules for: | |
| - TCP 22 for SSH | |
| - TCP 80 for HTTP | |
| - TCP 443 for HTTPS | |
| Remember that DigitalOcean Cloud Firewall and UFW are independent layers. | |
| ### 34.19 Recommended file layout | |
| Static site: | |
| ```text | |
| /var/www/example.com/html/index.html | |
| /etc/nginx/sites-available/example.com | |
| /etc/nginx/sites-enabled/example.com | |
| /var/log/nginx/example.com.access.log | |
| /var/log/nginx/example.com.error.log | |
| ``` | |
| Reverse proxy: | |
| ```text | |
| /etc/nginx/sites-available/app.example.com | |
| /etc/nginx/sites-enabled/app.example.com | |
| /var/log/nginx/app.example.com.access.log | |
| /var/log/nginx/app.example.com.error.log | |
| ``` | |
| ### 34.20 Nginx and DigitalOcean references | |
| - Ubuntu Nginx documentation: https://ubuntu.com/server/docs/how-to/web-services/configure-nginx/ | |
| - Ubuntu Server documentation: https://ubuntu.com/server/docs/ | |
| - UFW documentation: https://help.ubuntu.com/community/UFW | |
| - DigitalOcean Cloud Firewall: https://docs.digitalocean.com/products/networking/firewalls/how-to/configure-rules/ | |
| - Certbot: https://certbot.eff.org/ | |
| - Nginx documentation: https://nginx.org/en/docs/ | |
| - CUPS administration: https://www.cups.org/doc/admin.html | |
| --- | |
| ## 35. Ubuntu-specific differences from the Fedora walkthrough | |
| For reference, these are the most important platform changes made during this conversion. | |
| | Fedora workflow | Ubuntu 26.04 LTS workflow | | |
| | --- | --- | | |
| | `dnf` | `apt` / `apt-get` | | |
| | RPM packages | DEB packages | | |
| | RPM Fusion | Ubuntu Universe / Multiverse / Restricted | | |
| | `akmod-nvidia` | `ubuntu-drivers install` | | |
| | Manual akmods rebuild | Ubuntu kernel module packages/DKMS as selected by driver packages | | |
| | Fedora MOK/akmods flow | Ubuntu signed modules plus MOK enrollment when prompted | | |
| | `firewalld` | UFW | | |
| | SELinux | AppArmor | | |
| | `/etc/nginx/conf.d/*.conf` as primary site layout | `/etc/nginx/sites-available` + `/etc/nginx/sites-enabled` | | |
| | Nginx worker user `nginx` | Nginx worker user `www-data` | | |
| | `.rpm` Chrome/Slack/Docker Desktop | `.deb` packages | | |
| | RPM Fusion Steam | Ubuntu `steam-installer` from Multiverse | | |
| | `fuse`/`fuse-libs` | `fuse3` + `libfuse2t64` for AppImage compatibility | | |
| | `glx-utils` | `mesa-utils` | | |
| | `kernel-devel` | `linux-headers-$(uname -r)` when specifically needed | | |
| | `rpm -q` | `dpkg -s` / `dpkg -l` / `apt-cache policy` | | |
| The rest of the developer workflow remains broadly the same. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment