Production-style Bash provisioning for standardized developer workstations.
Split install and configuration flows, audited helper patterns, submodule-backed dotfiles, and CI you can anchor release gates on—whether you onboard one laptop or fifty.
✓ Modular orchestration ✓ Split install/config bundles ✓ Linted Bash + docs in PR ✓ Idempotent, rerunnable phases
Ubuntu Setup Scripts automate a baseline engineering stack: security tooling, shells and terminals,
development runtimes (Node, Docker, Neovim, and peers), GNOME ergonomics where a desktop session exists,
and a pinned dotfiles submodule for editor and tmux parity across machines. Scripts are tuned for clarity in
reviews and predictable behavior in ubuntu-latest CI.
- 🔧 Automated Setup: Complete system configuration with a single command
- 🛡️ Security First: Built-in security tools, firewall configuration, and safe installation practices
- ⚡ Optimized Performance: Batch installations and smart caching for faster execution
- 🔄 Idempotent: Safe to run multiple times without issues
- 📝 Comprehensive Logging: Detailed progress tracking and error reporting
- 🎯 Modular Design: Run individual components or orchestrators (
master.sh) - ⚙️ Install vs configuration: Category automation is split between
src/scripts/install/(APT/Flatpak, third-party installers, clones) andsrc/scripts/config/(gsettings, home layout, UFW policy, submodule dotfiles, default shell). Usenpm run installs,npm run config, ornpm run all, or invokerun-install.sh/run-config.shdirectly.
- Ubuntu 20.04+ or Ubuntu-based distribution
- Internet connection
- Sudo privileges
- Clone the repository
git clone https://github.com/garretpatten/ubuntu-setup-scripts
cd ubuntu-setup-scripts- Install Node deps (optional; enables
npm runshortcuts below)
npm install- Update submodules (for dotfiles)
git submodule update --init --remote --recursive src/dotfiles/- Make scripts executable
chmod +x src/scripts/*.sh \
src/scripts/install/*.sh \
src/scripts/config/*.sh- Run the complete setup
npm run all
# or:
./src/scripts/master.sh| Command | Runs |
|---|---|
npm run all |
Full provisioning (master.sh): installs interleaved with configuration (see execution flow below). |
npm run installs |
Install bundle only (run-install.sh): packages and installers—no GNOME/dotfiles/config steps. |
npm run config |
Configuration bundle only (run-config.sh): defaults, home layout, UFW defaults, submodule copies, shell. |
Bash equivalents:
bash src/scripts/run-install.sh
bash src/scripts/run-config.sh
bash src/scripts/master.shUse npm run config when packages are already present but GNOME/dotfiles paths should be refreshed after updating the submodule.
Each category exists as install and/or configuration scripts (paths from repo root):
bash src/scripts/install/cli.sh
bash src/scripts/install/dev.sh
bash src/scripts/config/system-config.sh # GNOME + unattended APT + sysctl (no extra packages besides unattended-upgrades)
bash src/scripts/config/organizeHome.sh
bash src/scripts/config/dev.sh # Editors / XDG subtree + Git identity
bash src/scripts/config/security.sh # UFW defaults (requires `install/security.sh` first)
bash src/scripts/config/shell.sh # Submodule shell + terminal dotfiles (`~/.config/tmux`, etc.)Prefer the orchestrators so ordering stays consistent (for example config/security.sh after install/security.sh, config/shell.sh after install/shell.sh, and install/post-install.sh docker/UFW touchpoints ahead of config/shell.sh when running a full provisioning pass).
ubuntu-setup-scripts/
├── src/
│ ├── scripts/
│ │ ├── utils.sh
│ │ ├── master.sh # Full run — interleaved installs + configuration
│ │ ├── run-install.sh # APT/Flatpak/installers/post-install hooks only
│ │ ├── run-config.sh # GNOME, home layout, firewall policy, dotfiles, shell
│ │ ├── install/
│ │ │ ├── pre-install.sh
│ │ │ ├── cli.sh
│ │ │ ├── media.sh
│ │ │ ├── productivity.sh
│ │ │ ├── dev.sh # Languages, Docker, NeoVim APT, tooling (no submodule copies)
│ │ │ ├── security.sh # Packages, Proton/VPN installs, clones (UFW separately)
│ │ │ ├── shell.sh # Terminal packages, Ghostty installer, fonts, Oh My Posh
│ │ │ └── post-install.sh
│ │ └── config/
│ │ ├── system-config.sh
│ │ ├── organizeHome.sh
│ │ ├── dev.sh # submodule `config/*` subsets + Git defaults + Vimrc + VS Code user settings path
│ │ ├── security.sh # UFW deny/enable + SSH
│ │ └── shell.sh # Ghostty/tmux/modular ~/.config paths, ~/.dotfiles_path, chsh if needed
│ ├── dotfiles/ # submodule
│ └── assets/
└── ...
install/pre-install.sh— essential APT packages, timezone if still UTCconfig/system-config.sh— GNOME defaults (when schemas/bus exist), unattended upgrades sysctl/guest login tweaksconfig/organizeHome.sh— home folders and permissionsinstall/cli.sh— Flatpak,btop(APT on 22.04+ orsnapon older releases),fastfetch(PPA), other CLI APT packages, Flathubinstall/media.sh,install/productivity.shinstall/dev.sh— NodeSource Node, NVM, Docker CE, NeoVim PPA, Postman Flatpak,semgrep,srcCLIconfig/dev.sh— copy editor/XDG subsets fromsrc/dotfiles/config/, Git globals, Vimrc path, VS Codesettings.jsonwhen missinginstall/security.sh— UFW/OpenVPN APT, Proton tooling, Signal, pen-test packages, clones under~/Hackingconfig/security.sh—ufwdefaults after the package existsinstall/shell.sh— Zsh/Tmux/fonts/Ghostty/Oh My Posh installersinstall/post-install.sh—apt-get upgrade/docker group/banner (UFW--force enablestays best-effort here too)config/shell.sh—home/dotfiles (home/.tmux.confpulls in~/.config/tmux/includes/base.confonceconfig/tmux/lands under~/.config),~/.dotfiles_pathforhome/zsh/ubuntu.zsh,chshwhen possible
The lists below mirror the install/ and config/ split; open each file for exact commands.
- APT housekeeping; toolchain packages (
git,curl,wget,gnupg, etc.). - Sets timezone away from
UTCtowardAmerica/New_Yorkwhen still UTC.
- Flatpak + Flathub.
- Essentials:
bat,curl,eza,fastfetch(PPA),fd-find,git,htop,jq,ripgrep,vim,wget. btop: APT on Ubuntu 22.04+; on older releases (e.g. 20.04),snap install btopwhensnapexists.
- Node.js
nodejsvia NodeSource (24.x branch), NVM install script when missing,@vue/cliglobally,python3toolchain, Docker CE repos + Compose plugin,neovim,gh,shellcheck,semgrep(pip),src(Sourcegraph), Postman (Flatpak).
Brave, VLC, Spotify (snap where available), multimedia codecs bundles, ubuntu-restricted-extras.
LibreOffice, Zoom (snap), Standard Notes (Flatpak), KeePassXC, Redshift, Flameshot, Balena Etcher AppImage.
ufwandopenvpnAPT packages (rules live inconfig/security.sh).- Proton VPN desktop meta-package, Signal desktop APT repo,
nmap,exiftool, OWASP ZAP (snap), Proton Pass desktop + CLI installers. - Optionally clones
PayloadsAllTheThings/SecListsinto~/Hacking(directory expected fromconfig/organizeHome.shin a typical full run).
Zsh plugins, tmux, Meslo/Fira/powerline APT fonts plus optional Nerd Font drop, ghostty-ubuntu install script,
user Oh My Posh binary + theme stash under /usr/share/oh-my-posh/themes when empty.
apt-get upgrade, Docker systemd + docker group enrollment, ufw best-effort enable, and a completion banner (src/assets/ubuntu.txt, Ubuntu ASCII derived from fastfetch with color tokens removed for plain terminals).
- Drops empty
Music/Public/Templateswhere applicable. - Creates
~/Projects,~/Hacking,~/AppImages,~/Projects/opensource/personal, adjustsScripts/Hackingpermissions.
- GNOME (logged-in Desktop / D-Bus): dark mode, animations, clocks, scrolling, Nautilus, screenshots, Dash to Dock (when schema exists), Night Light, lock/privacy, search providers.
- Installs
unattended-upgradesand drops20auto-upgradeswhen missing. - sudo:
AllowGuest=falsehint ingdm3, tame Apport,logindlid snippet, sysctl TCP keepalive drop-in.
Minimal/CI runners without GNOME skip gsettings safely.
- Copies a focused set from
src/dotfiles/config/into~/.config/:nvim,btop,fastfetch,alacritty,kitty,zellij(trees skipped when~/.config/<app>/already exists). - Copies
home/.vimrcand VS CodeUser/settings.jsonwhen missing (~/.config/Code/Useron Linux). - Seeds
~/.gitconfigonly when absent with global credential helper + identity defaults matching the legacy script behavior.
ufw reset, deny incoming / allow outgoing, allow ssh, force enable (expects install/security.sh to have installed **ufw first`).
- Copies
Ghostty,oh-my-posh, and the modularconfig/tmux/subtree into~/.config(tmuxsource-filelayout — seesrc/dotfiles/README.md). - Copies
home/.tmux.conf,home/.zshrc, optionalhome/.bashrcwhen missing. - Maintains
~/.dotfiles_pathsohome/.zshrcresolvesDOTFILES; runschshwhen possible.
Full symlink mirror: from src/dotfiles, ./setup.sh --link-xdg-config installs every config/<app>/ tree under $XDG_CONFIG_HOME (dotfiles README). Parent config/ scripts still provision the subset above for first-touch machines.
Other runtime actions people often treat as configuration still live with installs for ordering reasons: install/post-install.sh enables Docker/ufw; npm run installs omits config/ entirely so run npm run config afterward for dotfiles parity.
After installation, check:
- Error Log:
setup_errors.log- Centralized error tracking - Summary Report:
setup_summary.txt- Installation status overview - Console Output: Real-time progress with color-coded messages
- Restart Required: Log out and back in for shell and group changes
- GNOME / desktop: Some
config/system-config.shpreferences apply fully after re-login or when running the script from an active desktop session - Docker: User added to docker group (logout required for effect)
- Firewall: UFW enabled with SSH access allowed
- Night Light vs Redshift: If you use GNOME Night Light from
config/system-config.sh, disable or uninstall Redshift frominstall/productivity.shto avoid conflicting color temperature - Manual Setup: Some applications (like 1Password, ProtonVPN) may require additional configuration
Script fails with permission errors:
# Ensure scripts are executable
chmod +x src/scripts/*.sh \
src/scripts/install/*.sh \
src/scripts/config/*.shPackage installation fails:
# Update package lists manually
sudo apt update
# Then re-run the scriptDocker commands require sudo:
# Log out and back in, or run:
newgrp dockerShell doesn't change to Zsh:
# Manually change shell
chsh -s $(which zsh)
# Then log out and back in- Check
setup_errors.logfor detailed error information - Review
setup_summary.txtfor installation status - Ensure you're running on a supported Ubuntu version (20.04+)
- Verify internet connection for package downloads
- Hash verification for all downloaded packages
- GPG key verification for third-party repositories
- Automatic firewall configuration with secure defaults
- Safe temporary file handling with automatic cleanup
- Principle of least privilege for directory permissions
| Resource | Use |
|---|---|
| Code of Conduct | Expected behavior in issues and PRs |
| Contributing | Branching, checks, submodule notes |
| Security policy | Vulnerability reporting (not public issues) |
Use the issue templates for bugs and enhancements.
This project is licensed under the MIT License.