{"id":50674036,"url":"https://github.com/garretpatten/server-setup-scripts","last_synced_at":"2026-06-08T14:30:37.334Z","repository":{"id":252861994,"uuid":"841692224","full_name":"garretpatten/server-setup-scripts","owner":"garretpatten","description":"Bash automation for headless Ubuntu: CLI tools, dev runtimes, security tooling, shell config, and optional dotfiles—with separate install and config workflows and GitHub Actions CI. Works on servers, cloud VMs, and WSL.","archived":false,"fork":false,"pushed_at":"2026-05-31T14:55:22.000Z","size":2185,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-05-31T16:22:34.943Z","etag":null,"topics":["apt","automation","bash","development-environment","dotfiles","github-actions","linux","neovim","provisioning","server","shell-script","tmux","ubuntu","wsl","zsh"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/garretpatten.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2024-08-12T22:16:50.000Z","updated_at":"2026-05-31T15:00:39.000Z","dependencies_parsed_at":"2024-08-13T01:48:54.200Z","dependency_job_id":"69895619-f48c-45e5-a48c-8a6e495a2f2e","html_url":"https://github.com/garretpatten/server-setup-scripts","commit_stats":null,"previous_names":["garretpatten/wsl-setup-scripts"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/garretpatten/server-setup-scripts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garretpatten%2Fserver-setup-scripts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garretpatten%2Fserver-setup-scripts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garretpatten%2Fserver-setup-scripts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garretpatten%2Fserver-setup-scripts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/garretpatten","download_url":"https://codeload.github.com/garretpatten/server-setup-scripts/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garretpatten%2Fserver-setup-scripts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34067347,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apt","automation","bash","development-environment","dotfiles","github-actions","linux","neovim","provisioning","server","shell-script","tmux","ubuntu","wsl","zsh"],"created_at":"2026-06-08T14:30:31.399Z","updated_at":"2026-06-08T14:30:37.323Z","avatar_url":"https://github.com/garretpatten.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- markdownlint-disable MD033 MD041 --\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cimg\n        src=\"https://img.shields.io/badge/Server%20setup%20scripts-headless%20CLI%20automation-E95420?style=for-the-badge\u0026logo=ubuntu\u0026logoColor=white\"\n        alt=\"Ubuntu-branded badge: headless CLI automation\"\n    /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eServer Setup Scripts\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\u003cstrong\u003eProduction-style Bash provisioning for headless Linux: servers, cloud VMs, and WSL.\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    Split \u003cstrong\u003einstall\u003c/strong\u003e and \u003cstrong\u003econfiguration\u003c/strong\u003e flows, audited helper patterns, submodule-backed dotfiles, and CI you can anchor release gates on—without desktop applications or GUI package managers.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"./LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/garretpatten/server-setup-scripts?style=flat-square\" alt=\"License: MIT\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://ubuntu.com/\"\n        \u003e\u003cimg src=\"https://img.shields.io/badge/platform-Ubuntu%2020.04%2B-E95420?style=flat-square\u0026logo=ubuntu\u0026logoColor=white\" alt=\"Ubuntu 20.04 or newer\"\n    /\u003e\u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/shell-bash-black?style=flat-square\u0026logo=gnu-bash\u0026logoColor=white\" alt=\"Shell: Bash\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/scope-CLI%20only-blue?style=flat-square\u0026logo=gnubash\u0026logoColor=white\" alt=\"Scope: CLI only\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/garretpatten/server-setup-scripts/actions/workflows/test-runner.yaml\"\n        \u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/garretpatten/server-setup-scripts/test-runner.yaml?branch=master\u0026label=Ubuntu%20CI\u0026logo=github\u0026style=flat-square\" alt=\"Test runner workflow status\"\n    /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/garretpatten/server-setup-scripts/actions/workflows/quality-checks.yaml\"\n        \u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/garretpatten/server-setup-scripts/quality-checks.yaml?branch=master\u0026label=quality\u0026logo=github\u0026style=flat-square\" alt=\"Quality checks workflow status\"\n    /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/garretpatten/server-setup-scripts/actions/workflows/security-checks.yaml\"\n        \u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/garretpatten/server-setup-scripts/security-checks.yaml?branch=master\u0026label=security\u0026logo=github\u0026style=flat-square\" alt=\"Security checks workflow status\"\n    /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    ✓ Modular orchestration \u0026nbsp;\n    ✓ Split install/config bundles \u0026nbsp;\n    ✓ Linted Bash + docs in PR \u0026nbsp;\n    ✓ Idempotent, rerunnable phases\n\u003c/p\u003e\n\n\u003c!-- markdownlint-enable MD033 MD041 --\u003e\n\n---\n\n## Overview\n\nServer Setup Scripts automate a **baseline headless engineering stack**: security CLI tooling, shells and terminal configs, development runtimes (Node, Docker, Neovim, and peers), 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, **cloud VMs**, and **WSL2**.\n\nThis repository is the CLI-only sibling of [ubuntu-setup-scripts](https://github.com/garretpatten/ubuntu-setup-scripts). Desktop applications (browsers, office suites, Flatpak GUI apps, GNOME VPN clients, and similar) live there—not here.\n\n## ✨ Features\n\n- **🔧 Automated Setup**: Complete system configuration with a single command\n- **🛡️ Security First**: Built-in security tools, firewall configuration, and safe installation practices\n- **⚡ Optimized Performance**: Batch installations and smart caching for faster execution\n- **🔄 Idempotent**: Safe to run multiple times without issues\n- **📝 Comprehensive Logging**: Detailed progress tracking and error reporting\n- **🎯 Modular Design**: Run individual components or orchestrators (`master.sh`)\n- **⚙️ Install vs configuration**: Category automation is split between\n  `src/scripts/install/` (APT, third-party installers, clones) and\n  `src/scripts/config/` (system defaults, home layout, UFW policy, submodule\n  dotfiles, default shell). Use `npm run installs`, `npm run config`, or `npm run all`,\n  or invoke `run-install.sh` / `run-config.sh` directly.\n\n## 🚀 Quick Start\n\n### Prerequisites\n\n- Ubuntu 20.04+ or Ubuntu-based distribution (including WSL2)\n- Internet connection\n- Sudo privileges\n\n### Installation\n\n1. **Clone the repository**\n\n```bash\ngit clone https://github.com/garretpatten/server-setup-scripts\ncd server-setup-scripts\n```\n\n1. **Install Node deps** (optional; enables `npm run` shortcuts below)\n\n```bash\nnpm install\n```\n\n1. **Update submodules** (for dotfiles)\n\n```bash\ngit submodule update --init --remote --recursive src/dotfiles/\n```\n\n1. **Make scripts executable**\n\n```bash\nchmod +x src/scripts/*.sh \\\n  src/scripts/install/*.sh \\\n  src/scripts/config/*.sh\n```\n\n1. **Run the complete setup**\n\n```bash\nnpm run all\n# or:\n./src/scripts/master.sh\n```\n\n### npm scripts\n\n| Command            | Runs                                                                                                       |\n| ------------------ | ---------------------------------------------------------------------------------------------------------- |\n| `npm run all`      | Full provisioning (`master.sh`): installs interleaved with configuration (see execution flow below).       |\n| `npm run installs` | Install bundle only (`run-install.sh`): packages and installers—no dotfiles/config steps.                  |\n| `npm run config`   | Configuration bundle only (`run-config.sh`): defaults, home layout, UFW defaults, submodule copies, shell. |\n\nBash equivalents:\n\n```bash\nbash src/scripts/run-install.sh\nbash src/scripts/run-config.sh\nbash src/scripts/master.sh\n```\n\nUse **`npm run config`** when packages are already present but dotfiles paths should be refreshed after updating the submodule.\n\n### Granular scripts\n\nEach category exists as **install** and/or **configuration** scripts (paths from repo root):\n\n```bash\nbash src/scripts/install/cli.sh\nbash src/scripts/install/dev.sh\n\nbash src/scripts/config/system-config.sh      # unattended APT + sysctl (no extra packages besides unattended-upgrades)\nbash src/scripts/config/organizeHome.sh\nbash src/scripts/config/dev.sh               # Editors / XDG subtree + Git identity\nbash src/scripts/config/security.sh           # UFW defaults (requires `install/security.sh` first)\nbash src/scripts/config/shell.sh              # Submodule shell + terminal dotfiles (`~/.config/tmux`, etc.)\n```\n\nPrefer 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).\n\n## Project structure\n\n```text\nserver-setup-scripts/\n├── src/\n│   ├── scripts/\n│   │   ├── utils.sh\n│   │   ├── master.sh          # Full run — interleaved installs + configuration\n│   │   ├── run-install.sh      # APT/installers/post-install hooks only\n│   │   ├── run-config.sh       # system defaults, home layout, firewall policy, dotfiles, shell\n│   │   ├── install/\n│   │   │   ├── pre-install.sh\n│   │   │   ├── cli.sh\n│   │   │   ├── dev.sh         # Languages, Docker, NeoVim APT, tooling (no submodule copies)\n│   │   │   ├── security.sh    # CLI security packages, clones (UFW separately)\n│   │   │   ├── shell.sh       # Zsh/Tmux/fonts/Oh My Posh (no GUI terminals)\n│   │   │   └── post-install.sh\n│   │   └── config/\n│   │       ├── system-config.sh\n│   │       ├── organizeHome.sh\n│   │       ├── dev.sh         # submodule `config/*` subsets + Git defaults + Vimrc + VS Code user settings path\n│   │       ├── security.sh    # UFW deny/enable + SSH\n│   │       └── shell.sh       # tmux/modular ~/.config paths, ~/.dotfiles_path, chsh if needed\n│   ├── dotfiles/              # submodule\n│   └── assets/\n└── ...\n```\n\n### Execution flow (`master.sh`)\n\n1. **`install/pre-install.sh`** — essential APT packages, timezone if still UTC\n2. **`config/system-config.sh`** — unattended upgrades, apport/sysctl; GNOME defaults only when a desktop session exists\n3. **`config/organizeHome.sh`** — home folders and permissions\n4. **`install/cli.sh`** — **`btop`** (APT on 22.04+ or **`snap`** on older releases), **`fastfetch`** (PPA), other CLI APT packages\n5. **`install/dev.sh`** — NodeSource Node, NVM, Docker CE, NeoVim PPA, `semgrep`, `src` CLI\n6. **`config/dev.sh`** — copy editor/XDG subsets from **`src/dotfiles/config/`**, Git globals, Vimrc path, VS Code `settings.json` when missing\n7. **`install/security.sh`** — UFW/OpenVPN APT, Proton Pass **CLI**, pen-test packages, clones under `~/Hacking`\n8. **`config/security.sh`** — **`ufw` defaults** after the package exists\n9. **`install/shell.sh`** — Zsh/Tmux/fonts/Oh My Posh installers\n10. **`install/post-install.sh`** — `apt-get upgrade`/docker group/banner\n11. **`config/shell.sh`** — **`home/`** dotfiles, **`~/.dotfiles_path`**, `chsh` when possible\n\n---\n\n## 📋 What gets installed vs configured\n\nThe lists below mirror the **`install/`** and **`config/`** split; open each file for exact commands.\n\n### **`install/` bundle**\n\n#### 🧰 **Bootstrap** (`install/pre-install.sh`)\n\n- APT housekeeping; toolchain packages (`git`, `curl`, `wget`, `gnupg`, etc.).\n- Sets timezone away from **`UTC`** toward **`America/New_York`** when still UTC.\n\n#### 🛠️ **CLI Tools** (`install/cli.sh`)\n\n- Essentials: **`bat`**, **`curl`**, **`eza`**, **`fastfetch`** (PPA),\n  **`fd-find`**, **`git`**, **`htop`**, **`jq`**, **`ripgrep`**, **`vim`**, **`wget`**.\n- **`btop`**: APT on **Ubuntu 22.04+**; on older releases (**e.g. 20.04**), **`snap install btop`**\n  when **`snap`** exists.\n\n#### 💻 **Development packages** (`install/dev.sh`)\n\n- Node.js **`nodejs`** via NodeSource (**24.x** branch), NVM install script when missing,\n  **`@vue/cli`** globally, **`python3`** toolchain, Docker CE repos + Compose plugin,\n  **`neovim`**, **`gh`**, **`shellcheck`**, **`semgrep`** (pip), **`src`** (Sourcegraph).\n\n#### 🔒 **Security packages \u0026 payloads** (`install/security.sh`)\n\n- **`ufw`** and **`openvpn`** APT packages (rules live in **`config/security.sh`**).\n- Proton Pass **CLI** (`protonpass`), **`nmap`**, **`exiftool`**, **OWASP ZAP** (**snap**).\n- Optionally clones **`PayloadsAllTheThings`** / **`SecLists`** into **`~/Hacking`**.\n\n#### 🐚 **Shell tooling** (`install/shell.sh`)\n\nZsh plugins, **`tmux`**, Meslo/Fira/powerline APT fonts plus optional Nerd Font drop,\nuser Oh My Posh binary + theme stash under **`/usr/share/oh-my-posh/themes`** when empty.\n\n#### 🏁 **Post maintenance** (`install/post-install.sh`)\n\n`apt-get upgrade`, Docker systemd + **`docker`** group enrollment, **`ufw`** best-effort enable, and a completion banner (`src/assets/server.txt`).\n\n### **`config/` bundle**\n\n#### 🏠 **Home layout** (`config/organizeHome.sh`)\n\n- Drops empty **`Music`/`Public`/`Templates`** where applicable.\n- Creates **`~/Projects`**, **`~/Hacking`**, **`~/AppImages`**, **`~/Projects/opensource`** / **`personal`**, adjusts **`Scripts`/`Hacking`** permissions.\n\n#### ⚙️ **System defaults** (`config/system-config.sh`)\n\n- **GNOME** (logged-in Desktop / D-Bus only): dark mode, animations, clocks, and related preferences when schemas exist.\n- Installs **`unattended-upgrades`** and drops **`20auto-upgrades`** when missing.\n- Disables Apport; sysctl TCP keepalive drop-in.\n\nHeadless runners and WSL without a desktop session skip **`gsettings`** safely.\n\n#### 💻 **Editor \u0026 Git prefs** (`config/dev.sh`)\n\n- Copies a **focused set** from **`src/dotfiles/config/`** into **`~/.config/`**: **`nvim`**, **`btop`**, **`fastfetch`**, **`alacritty`**, **`kitty`**, **`zellij`** (trees skipped when **`~/.config/\u003capp\u003e/`** already exists).\n- Copies **`home/.vimrc`** and VS Code **`User/settings.json`** when missing (**`~/.config/Code/User`** on Linux).\n- Seeds **`~/.gitconfig`** **only when absent** with global credential helper + identity defaults.\n\n#### 🔒 **UFW posture** (`config/security.sh`)\n\n`ufw reset`, deny incoming / allow outgoing, allow **`ssh`**, force enable (expects **`install/security.sh`** to have installed **`ufw`** first).\n\n#### 🐚 **Shell dotfiles \u0026 terminal configs** (`config/shell.sh`)\n\n- Copies **`Ghostty`**, **`oh-my-posh`**, and the **modular `config/tmux/`** subtree into **`~/.config`** (terminal configs for when you connect from a GUI client; Ghostty itself is not installed here).\n- Copies **`home/.tmux.conf`**, **`home/.zshrc`**, optional **`home/.bashrc`** when missing.\n- Maintains **`~/.dotfiles_path`** so **`home/.zshrc`** resolves **`DOTFILES`**; runs **`chsh`** when possible.\n\n**Full symlink mirror**: from **`src/dotfiles`**, **`./setup.sh --link-xdg-config`** installs every **`config/\u003capp\u003e/`** tree under **`$XDG_CONFIG_HOME`** ([dotfiles README](https://github.com/garretpatten/dotfiles/blob/master/README.md)). Parent **`config/`** scripts still provision the subset above for first-touch machines.\n\n## 🖥️ WSL notes\n\n- Run from your WSL2 Ubuntu distro with **`sudo`** available.\n- **Docker**: enable the Docker Desktop WSL integration or install Docker CE via this repo; log out/in or **`newgrp docker`** after the **`docker`** group is applied.\n- **UFW**: may be limited under WSL depending on kernel/networking; failures are logged but non-fatal.\n- **Default shell**: **`chsh`** may require logging out of Windows Terminal and reopening the WSL session.\n\n## 📊 Monitoring \u0026 Logs\n\nAfter installation, check:\n\n- **Error Log**: `setup_errors.log` - Centralized error tracking\n- **Console Output**: Real-time progress with color-coded messages\n\n## ⚠️ Post-Installation Notes\n\n1. **Restart Required**: Log out and back in for shell and group changes\n1. **Docker**: User added to docker group (logout required for effect)\n1. **Firewall**: UFW enabled with SSH access allowed (on bare-metal/cloud; WSL may vary)\n1. **Desktop apps**: For browsers, office suites, media players, and GNOME tooling, use [ubuntu-setup-scripts](https://github.com/garretpatten/ubuntu-setup-scripts)\n\n## 🔍 Troubleshooting\n\n### Common Issues\n\n**Script fails with permission errors:**\n\n```bash\nchmod +x src/scripts/*.sh \\\n  src/scripts/install/*.sh \\\n  src/scripts/config/*.sh\n```\n\n**Package installation fails:**\n\n```bash\nsudo apt update\n# Then re-run the script\n```\n\n**Docker commands require sudo:**\n\n```bash\nnewgrp docker\n```\n\n**Shell doesn't change to Zsh:**\n\n```bash\nchsh -s $(which zsh)\n# Then log out and back in\n```\n\n### Getting Help\n\n- Check `setup_errors.log` for detailed error information\n- Ensure you're running on a supported Ubuntu version (20.04+)\n- Verify internet connection for package downloads\n\n## 🛡️ Security Features\n\n- **Hash verification** for all downloaded packages\n- **GPG key verification** for third-party repositories\n- **Automatic firewall configuration** with secure defaults\n- **Safe temporary file handling** with automatic cleanup\n- **Principle of least privilege** for directory permissions\n\n## Community\n\n| Resource                                | Use                                         |\n| --------------------------------------- | ------------------------------------------- |\n| [Code of Conduct](./CODE_OF_CONDUCT.md) | Expected behavior in issues and PRs         |\n| [Contributing](./CONTRIBUTING.md)       | Branching, checks, submodule notes          |\n| [Security policy](./SECURITY.md)        | Vulnerability reporting (not public issues) |\n\n## Maintainers\n\n[@garretpatten](https://github.com/garretpatten/).\n\nUse the [issue templates](./.github/ISSUE_TEMPLATE/) for bugs and enhancements.\n\n## License\n\nThis project is licensed under the [MIT License](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarretpatten%2Fserver-setup-scripts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgarretpatten%2Fserver-setup-scripts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarretpatten%2Fserver-setup-scripts/lists"}