Ubuntu Development Setup
This guide provides comprehensive instructions for setting up a Ghaf development environment on Ubuntu or Debian-based systems. Both automated and manual installation methods are covered.
Prerequisites
Section titled “Prerequisites”Before you begin, ensure your system meets the following requirements:
System Requirements
Section titled “System Requirements”| Requirement | Minimum | Recommended |
|---|---|---|
| Ubuntu Version | 22.04 LTS | 24.04 LTS |
| Architecture | x86_64 | x86_64 |
| RAM | 8 GB | 16 GB or more |
| Disk Space | 50 GB free | 100 GB or more |
| Network | Stable internet | Fast broadband |
Ubuntu 24.04 Users
Section titled “Ubuntu 24.04 Users”Ubuntu 24.04 introduces stricter AppArmor policies that may affect Nix sandboxing. The automated setup script handles this automatically, but if you’re installing manually, see the AppArmor Configuration section.
Automated Installation (Recommended)
Section titled “Automated Installation (Recommended)”The automated setup script handles all installation and configuration steps with interactive prompts for operations requiring elevated privileges.
Quick Start
Section titled “Quick Start”-
Clone the Ghaf repository:
Terminal window git clone https://github.com/tiiuae/ghaf.gitcd ghaf -
Run the setup script:
Terminal window ./scripts/ubuntu-setup.sh -
Activate your shell configuration:
Terminal window source ~/.bashrc # or ~/.zshrc for Zsh users -
Allow direnv for the Ghaf project:
Terminal window direnv allow
Script Options
Section titled “Script Options”| Option | Description |
|---|---|
--accept | Accept all prompts automatically (non-interactive mode) |
--uninstall | Remove Nix and related configurations |
--help | Show help message |
Non-interactive installation (for CI/CD or automated setups):
./scripts/ubuntu-setup.sh --acceptUninstall (removes Nix and configurations):
./scripts/ubuntu-setup.sh --uninstallWhat the Script Does
Section titled “What the Script Does”The automated script performs the following steps:
- System Dependencies: Installs
curl,git, andxz-utilsvia apt - Nix Installation: Installs Nix using the Determinate Systems installer
- Binary Cache: Configures the Ghaf binary cache for faster builds
- direnv Setup: Installs and configures direnv with nix-direnv
- Shell Integration: Adds direnv hook to your shell configuration
- AppArmor (Ubuntu 24.04): Configures user namespaces for Nix sandboxing
- binfmt (Optional): Sets up QEMU for AArch64 emulation
- VSCode (Optional): Creates VSCode configuration files
Manual Installation
Section titled “Manual Installation”If you prefer to install components manually or need more control over the setup process, follow these steps.
Step 1: Install System Dependencies
Section titled “Step 1: Install System Dependencies”Install the required system packages:
sudo apt updatesudo apt install -y curl git xz-utilsStep 2: Install Nix Package Manager
Section titled “Step 2: Install Nix Package Manager”We recommend the Determinate Systems Nix Installer for Ubuntu systems:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- installBenefits:
- ✅ Flakes enabled by default
- ✅ Clean uninstall support (
/nix/nix-installer uninstall) - ✅ Multi-user mode (more secure)
- ✅ Better enterprise support
curl -L https://nixos.org/nix/install | sh -s -- --daemonAfter installation, enable flakes manually:
mkdir -p ~/.config/nixecho "experimental-features = nix-command flakes" >> ~/.config/nix/nix.confAfter installation, restart your terminal or source the Nix profile:
# For Determinate Systems installer. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
# Or restart your terminalVerify the installation:
nix --versionStep 3: Configure Binary Cache
Section titled “Step 3: Configure Binary Cache”Configure the Ghaf binary cache for significantly faster builds. Create or edit ~/.config/nix/nix.conf:
mkdir -p ~/.config/nixcat >> ~/.config/nix/nix.conf << 'EOF'
# Ghaf development configurationexperimental-features = nix-command flakes
# Binary caches for faster buildssubstituters = https://ghaf-dev.cachix.org https://cache.nixos.orgtrusted-public-keys = ghaf-dev.cachix.org-1:S3M8x3no8LFQPBfHw1jl6nmP8A7cVWKntoMKN3IsEQY= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
# Trust the Ghaf binary cacheextra-trusted-substituters = https://ghaf-dev.cachix.org
# Recommended settingskeep-outputs = truekeep-derivations = trueEOFRestart the Nix daemon to apply changes:
sudo systemctl restart nix-daemonStep 4: Install and Configure direnv
Section titled “Step 4: Install and Configure direnv”direnv automatically loads the Ghaf development environment when you enter the project directory.
Install direnv
Section titled “Install direnv”nix profile install nixpkgs#direnvnix profile install nixpkgs#nix-direnvsudo apt install -y direnv
# nix-direnv still needs to be installed via Nixnix profile install nixpkgs#nix-direnvConfigure direnv
Section titled “Configure direnv”Create the direnv configuration file:
mkdir -p ~/.config/direnvcat > ~/.config/direnv/direnvrc << 'EOF'# Use nix-direnv for better caching and performanceif [ -f "${HOME}/.nix-profile/share/nix-direnv/direnvrc" ]; then source "${HOME}/.nix-profile/share/nix-direnv/direnvrc"elif [ -f "/nix/var/nix/profiles/default/share/nix-direnv/direnvrc" ]; then source "/nix/var/nix/profiles/default/share/nix-direnv/direnvrc"fi
# Increase timeout for Nix operationsexport DIRENV_WARN_TIMEOUT=60sEOFAdd Shell Hook
Section titled “Add Shell Hook”Add the direnv hook to your shell configuration:
echo 'eval "$(direnv hook bash)"' >> ~/.bashrcsource ~/.bashrcecho 'eval "$(direnv hook zsh)"' >> ~/.zshrcsource ~/.zshrcecho 'direnv hook fish | source' >> ~/.config/fish/config.fishsource ~/.config/fish/config.fishStep 5: Clone and Set Up Ghaf
Section titled “Step 5: Clone and Set Up Ghaf”git clone https://github.com/tiiuae/ghaf.gitcd ghafdirenv allowThe development environment will now load automatically when you enter the directory.
Optional Configuration
Section titled “Optional Configuration”AppArmor Configuration (Ubuntu 24.04)
Section titled “AppArmor Configuration (Ubuntu 24.04)”Ubuntu 24.04 has stricter AppArmor policies that may affect Nix sandboxing. If you encounter sandbox-related build errors, configure user namespaces:
# Create sysctl configurationecho 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/99-nix-userns.conf
# Apply immediatelysudo sysctl --systemCross-Architecture Support (binfmt)
Section titled “Cross-Architecture Support (binfmt)”For building AArch64 targets via emulation (alternative to cross-compilation):
sudo apt install -y qemu-user-static binfmt-supportsudo update-binfmts --enable qemu-aarch64Remote Build Machines
Section titled “Remote Build Machines”Remote builders allow offloading Nix builds to more powerful machines. This is useful for:
- Building AArch64 targets on native ARM64 hardware (faster than cross-compilation)
- Speeding up builds using dedicated build servers
- Distributed builds across multiple machines
The automated setup script can configure remote builders interactively. For manual configuration:
Prerequisites
Section titled “Prerequisites”- SSH access to the remote build machine
- Nix installed on the remote machine
- Remote machine configured to accept builds (see Remote Build Setup)
Manual Configuration
Section titled “Manual Configuration”- Create the machines file (
/etc/nix/machines):
sudo mkdir -p /etc/nixsudo tee /etc/nix/machines << 'EOF'# Format: ssh://user@host system ssh-key max-jobs speed-factor features mandatory-features public-keyssh://builder@build-server.example.com x86_64-linux /home/user/.ssh/id_ed25519 8 1 nixos-test,benchmark,big-parallel,kvm - -ssh://builder@arm-server.example.com aarch64-linux /home/user/.ssh/id_ed25519 16 1 nixos-test,benchmark,big-parallel,kvm - -EOF- Configure nix.conf to use remote builders:
cat >> ~/.config/nix/nix.conf << 'EOF'
# Remote build machines configurationbuilders = @/etc/nix/machinesbuilders-use-substitutes = trueEOF- Add the remote host to known_hosts:
# Fetch and add the host keyssh-keyscan -t ed25519 build-server.example.com | sudo tee -a /etc/ssh/ssh_known_hosts- Restart the Nix daemon:
sudo systemctl restart nix-daemon- Test the connection:
nix store ping --store ssh://builder@build-server.example.comMachine File Format
Section titled “Machine File Format”Each line in /etc/nix/machines specifies a build machine:
ssh://USER@HOST SYSTEM SSH_KEY MAX_JOBS SPEED_FACTOR FEATURES MANDATORY_FEATURES PUBLIC_KEY| Field | Description | Example |
|---|---|---|
USER@HOST | SSH connection | builder@server.com |
SYSTEM | Target system(s) | x86_64-linux or aarch64-linux |
SSH_KEY | Path to private key | /home/user/.ssh/id_ed25519 |
MAX_JOBS | Parallel build jobs | 8 |
SPEED_FACTOR | Priority (higher = preferred) | 1 |
FEATURES | Supported features | nixos-test,benchmark,big-parallel,kvm |
MANDATORY_FEATURES | Required features | - (none) |
PUBLIC_KEY | Base64 host key | - (use known_hosts) |
VSCode Configuration
Section titled “VSCode Configuration”For the best development experience with VSCode, install the recommended extensions and configure user settings.
Install Extensions
Section titled “Install Extensions”Install the following VSCode extensions:
- Nix IDE (
jnoortheen.nix-ide) - Nix language support - direnv (
mkhl.direnv) - Environment integration - EditorConfig (
editorconfig.editorconfig) - Code style - ShellCheck (
timonwong.shellcheck) - Shell script linting
Install via command line:
code --install-extension jnoortheen.nix-idecode --install-extension mkhl.direnvcode --install-extension editorconfig.editorconfigcode --install-extension timonwong.shellcheckFor VSCodium users, replace code with codium.
Configure User Settings
Section titled “Configure User Settings”Add Nix-specific settings to your VSCode user configuration. The settings file is located at:
- VSCode:
~/.config/Code/User/settings.json - VSCodium:
~/.config/VSCodium/User/settings.json
If the file exists, merge the following settings. If it doesn’t exist, create it:
{ "nix.enableLanguageServer": true, "nix.serverPath": "nixd", "nix.serverSettings": { "nixd": { "formatting": { "command": ["nixfmt"] } } }, "[nix]": { "editor.tabSize": 2, "editor.insertSpaces": true, "editor.formatOnSave": true }, "files.trimTrailingWhitespace": true, "files.insertFinalNewline": true}How It Works
Section titled “How It Works”With the direnv extension installed, VSCode will automatically:
- Detect the
.envrcfile in the Ghaf project directory - Load the Nix development environment
- Make tools like
nixd,nixfmt,treefmtavailable to extensions
You’ll see a notification asking to allow direnv when opening the Ghaf project for the first time.
Verifying Your Setup
Section titled “Verifying Your Setup”After installation, verify that everything is working correctly:
Check Nix Installation
Section titled “Check Nix Installation”# Check Nix versionnix --version
# Check flakes supportnix flake --helpCheck direnv
Section titled “Check direnv”# Check direnv versiondirenv version
# In the Ghaf directory, check that environment loadscd ghafdirenv statusTest a Build
Section titled “Test a Build”cd ghafdirenv allow
# Quick test: build documentation (5-10 minutes)nix build .#doc
# Full test: build VM (45-90 minutes with binary cache)nix build .#packages.x86_64-linux.vm-debugCheck Binary Cache
Section titled “Check Binary Cache”Verify that the binary cache is being used:
# During a build, you should see downloads from ghaf-dev.cachix.orgnix build .#doc --print-build-logs 2>&1 | head -20Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues””experimental feature ‘flakes’ is disabled”
Section titled “”experimental feature ‘flakes’ is disabled””Your Nix configuration doesn’t have flakes enabled. Add to ~/.config/nix/nix.conf:
experimental-features = nix-command flakesThen restart the Nix daemon:
sudo systemctl restart nix-daemon“error: could not set permissions on ‘/nix/var/nix/profiles/per-user’”
Section titled ““error: could not set permissions on ‘/nix/var/nix/profiles/per-user’””This indicates a single-user Nix installation issue. Reinstall Nix in multi-user mode:
# Uninstall (if using Determinate Systems)/nix/nix-installer uninstall
# Reinstallcurl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- installSandbox Errors on Ubuntu 24.04
Section titled “Sandbox Errors on Ubuntu 24.04”If you see errors related to sandboxing or user namespaces:
# Enable unprivileged user namespacesecho 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/99-nix-userns.confsudo sysctl --systemdirenv Not Loading Environment
Section titled “direnv Not Loading Environment”- Ensure direnv hook is in your shell configuration
- Run
direnv allowin the Ghaf directory - Check direnv status:
direnv status
Slow Builds
Section titled “Slow Builds”If builds are taking longer than expected:
-
Verify binary cache is configured:
Terminal window grep "ghaf-dev.cachix.org" ~/.config/nix/nix.conf -
Check network connectivity to the cache:
Terminal window curl -I https://ghaf-dev.cachix.org -
Explicitly use the cache:
Terminal window nix build .#target --option substituters "https://ghaf-dev.cachix.org https://cache.nixos.org"
Getting Help
Section titled “Getting Help”If you encounter issues not covered here:
- Check the Ghaf GitHub Issues
- Review the Nix manual
- Ask in the NixOS Discourse
Development Containers and VMs
Section titled “Development Containers and VMs”For isolated or reproducible development environments, you can use the provided helper scripts to create Docker containers or QEMU virtual machines pre-configured for Ghaf development.
Docker Container
Section titled “Docker Container”The dev-container.sh script creates a Docker container with all Ghaf development tools installed.
Requirements:
- Docker installed (
sudo apt install docker.io) - User in docker group (
sudo usermod -aG docker $USER)
Quick Start:
# Create a container with current directory mounted./scripts/dev-container.sh -m $(pwd) --accept create
# SSH into the container./scripts/dev-container.sh ssh
# Or open a shell directly./scripts/dev-container.sh shellOptions:
| Option | Default | Description |
|---|---|---|
-n, --name | ghaf-dev | Container name |
-m, --mount | (auto) | Directory to mount in container |
-c, --cpus | 4 | Number of CPUs |
-r, --ram | 8g | Memory limit |
-p, --ssh-port | 2222 | SSH port on host |
-P, --password | ghaf | SSH password |
--accept | - | Auto-accept all prompts |
Commands: create, start, stop, shell, ssh, remove, status
QEMU Virtual Machine
Section titled “QEMU Virtual Machine”The dev-vm.sh script creates a full Ubuntu VM for Ghaf development, useful when you need complete isolation or to test the setup process itself.
Requirements:
- QEMU and KVM (
sudo apt install qemu-system-x86 qemu-utils) - cloud-image-utils (
sudo apt install cloud-image-utils) - KVM support (check with
ls /dev/kvm)
Quick Start:
# Create a VM with 120GB disk (recommended for Jetson builds)./scripts/dev-vm.sh -d 120 -r 16 --accept create
# SSH into the VM./scripts/dev-vm.sh ssh
# Stop the VM./scripts/dev-vm.sh stopOptions:
| Option | Default | Description |
|---|---|---|
-n, --name | ghaf-dev-vm | VM name |
-m, --mount | - | Directory to mount via 9p |
-c, --cpus | 4 | Number of CPUs |
-r, --ram | 16 | Memory in GB |
-d, --disk | 120 | Disk size in GB |
-p, --ssh-port | 2223 | SSH port on host |
-P, --password | ghaf | SSH password |
-D, --vm-dir | ~/ghaf-vms | VM files directory |
--accept | - | Auto-accept all prompts |
Commands: create, start, stop, ssh, remove, status
Uninstalling
Section titled “Uninstalling”Using the Setup Script
Section titled “Using the Setup Script”./scripts/ubuntu-setup.sh --uninstallManual Uninstall
Section titled “Manual Uninstall”If you installed Nix with the Determinate Systems installer:
/nix/nix-installer uninstallRemove configuration files:
rm -rf ~/.config/nixrm -rf ~/.config/direnvRemove direnv hook from your shell configuration (~/.bashrc or ~/.zshrc).
Next Steps
Section titled “Next Steps”After setting up your development environment:
- Build and Run Guide - Learn how to build Ghaf images
- Cross Compilation - Build ARM targets from x86_64
- Development Guide - Contributing to Ghaf
- Remote Build Setup - Set up distributed builds