- Shell 80.5%
- HTML 13.4%
- CSS 4%
- JavaScript 2.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Proxmox cloud-init falls back to the PVE host's own DNS config when --nameserver isn't set explicitly. On a Tailscale-authenticated host (e.g. gem) that default is 100.100.100.100 (Tailscale MagicDNS), which a freshly cloned VM cannot reach until it authenticates Tailscale too -- so every static-IP clone got broken DNS on first boot with no obvious cause (ping to the gateway/internet works fine, only name resolution fails). Default NAMESERVER to the clone's own gateway, matching every other host on this LAN (the gateway doubles as the DNS server). Overridable via NAMESERVER=... for anyone who wants something else. Third fix found while migrating ShowNotes onto gem as the first VM off the new golden template -- the VM had internet connectivity (ping 8.8.8.8 worked) but zero DNS resolution, which is what led here. |
||
| docs-mkdocs | ||
| docs-static | ||
| lib | ||
| proxmox | ||
| .gitignore | ||
| 01-system-update.sh | ||
| 02-install-essentials.sh | ||
| 03-install-docker.sh | ||
| 04-configure-docker-dirs.sh | ||
| 05-configure-docker-user.sh | ||
| 06-configure-docker-logging.sh | ||
| 07-mount-nfs-shares.sh | ||
| 08-configure-fstab.sh | ||
| 09-post-reboot-check.sh | ||
| 09-pre-reboot-check.sh | ||
| 10-setup-docker-directories.sh | ||
| 11-install-tailscale.sh | ||
| 12-install-beszel-agent.sh | ||
| 13-setup-bash-aliases.sh | ||
| 14-setup-compose-templates.sh | ||
| 15-clone-docker-compose-repo.sh | ||
| 16-configure-auto-updates.sh | ||
| 17-system-validation.sh | ||
| 18-install-ai-cli-tools.sh | ||
| 19-install-terminal-tools.sh | ||
| 20-install-cockpit.sh | ||
| 21-setup-ssh-keys.sh | ||
| 22-setup-fastfetch.sh | ||
| 23-setup-claude-config.sh | ||
| config.example.sh | ||
| NFS-SERVER-CONFIGURATION.md | ||
| provision.sh | ||
| README.md | ||
| run-all-setup.sh | ||
Ubuntu Server Setup Scripts
Automated setup for Ubuntu servers as Docker hosts — with NFS mounts, Tailscale, and monitoring. Works three ways:
| Mode | Command | Use case |
|---|---|---|
| Proxmox golden image | proxmox/create-template.sh on tobin |
Build a VM template once, clone new servers in seconds |
| Interactive full setup | ./run-all-setup.sh |
Bare-metal server or hand-made VM, walks through every phase |
| Individual scripts | ./NN-script-name.sh |
Just the piece you need |
Quick Start — Proxmox VM template (recommended for new VMs)
On the Proxmox host (tobin), as root:
git clone https://git.chitekmedia.club/scott/ubuntu-setup-scripts.git
cd ubuntu-setup-scripts/proxmox
./create-template.sh # one-time, ~10-25 min
./clone-vm.sh 201 mynewserver 172.16.1.150/24 172.16.1.1
Then inside the new VM: cd ~/ubuntu-setup-scripts && git pull && ./provision.sh
See proxmox/README.md for full details.
Quick Start — bare metal / existing VM
sudo apt update && sudo apt install git -y
git clone https://git.chitekmedia.club/scott/ubuntu-setup-scripts.git
cd ubuntu-setup-scripts
cp config.example.sh config.sh
nano config.sh # subnet, timezone, Forgejo, NFS mounts
./run-all-setup.sh # interactive, full profile
Profiles and non-interactive mode
run-all-setup.sh supports two profiles:
--profile full(default) — everything, interactively. NFS and the compose defaults (templates + collection repo) are prompt-gated so you only get what you say yes to.--profile base— the generic, identity-free subset that gets baked into the Proxmox template: updates, Docker, Tailscale (install only), aliases, auto-updates, terminal tools, fastfetch, validation.
Any script (and the runner) accepts --yes / -y or ASSUME_YES=true to run
unattended: required confirmations auto-answer yes, optional extras
(zsh, cosmetic choices) auto-answer no. This is what cloud-init uses
during the golden-image bake:
./run-all-setup.sh --profile base --yes
Per-machine provisioning
Everything tied to a machine's identity lives in provision.sh — run it
once on each new server (cloned VM or freshly set-up host):
- Tailscale authentication (
sudo tailscale up) - Beszel agent (needs the per-machine token from the hub)
- NFS mounts via autofs (optional — not every VM needs media access)
- Docker Compose collection repo clone (optional)
- Compose templates: Arcane, Arcane Agent, Dockhand (optional)
It finishes with the homelab bookkeeping checklist (RackPeek, Beszel hub, Obsidian vault).
Configuration
Edit config.sh (copied from config.example.sh):
- TIMEZONE: applied by script 01 (cloud images default to UTC)
- LOCAL_SUBNET: for Tailscale/firewall rules
- Forgejo: server hostname/URL and username
- NFS_MOUNTS: array of mounts, managed by autofs
- Docker directories and repository names
NFS Mount Format
NFS mounts are managed by autofs — they mount on demand and auto-recover after an NFS server restarts (no manual intervention needed).
NFS_MOUNTS=(
"server_ip:/remote/path:/local/mount/path:Display Name"
"172.16.1.162:/mnt/user/media:/mnt/media-chitek:Chitek Media"
)
Rules:
- All local paths must share the same parent directory (all under
/mnt) - Use flat paths like
/mnt/media-chitek, not nested like/mnt/server/media - The basename (
media-chitek) becomes the autofs key — keep each unique - Script 10 derives an
.env.globalvariable from each mount (/mnt/media-chitek→MEDIA_CHITEK)
Scripts Overview
| Script | Purpose | base profile |
|---|---|---|
01-system-update.sh |
Update packages, set timezone | ✓ |
02-install-essentials.sh |
Install core utilities | ✓ |
03-install-docker.sh |
Install Docker Engine | ✓ |
04-configure-docker-dirs.sh |
Set up Docker data directories | ✓ |
05-configure-docker-user.sh |
Add user to docker group | ✓ |
06-configure-docker-logging.sh |
Log rotation + default address pools | ✓ |
07-mount-nfs-shares.sh |
autofs on-demand NFS mounts | per-machine |
08-configure-fstab.sh |
Remove legacy fstab NFS entries | per-machine |
09-pre/post-reboot-check.sh |
Validate around reboot | with NFS |
10-setup-docker-directories.sh |
Compose structure + .env.global |
✓ |
11-install-tailscale.sh |
Install Tailscale (auth is per-machine) | ✓ |
12-install-beszel-agent.sh |
Beszel agent (needs per-machine token) | per-machine |
13-setup-bash-aliases.sh |
Docker/nav aliases in .bashrc | ✓ |
14-setup-compose-templates.sh |
Arcane/Dockhand templates | opt-in |
15-clone-docker-compose-repo.sh |
Clone compose collection repo | opt-in |
16-configure-auto-updates.sh |
Unattended security updates | ✓ |
17-system-validation.sh |
Final validation report | ✓ |
18-install-ai-cli-tools.sh |
AI CLI tools (interactive menu) | opt-in |
19-install-terminal-tools.sh |
Modern CLI tools — interactive picker | ✓ (default set) |
20-install-cockpit.sh |
Cockpit web management | opt-in |
21-setup-ssh-keys.sh |
SSH key management (interactive menu) | opt-in |
22-setup-fastfetch.sh |
Fastfetch login banner (run with sudo) | ✓ |
23-setup-claude-config.sh |
⚠️ untested — Claude CLI + Open Brain MCP | opt-in |
Terminal tools picker (script 19)
Interactive runs show a checklist (whiptail) — pick exactly which tools you
want: basics (bat/ncdu/htop/tmux/jq), eza, fzf, zoxide, neovim, duf, topgrade,
tuptime, lazydocker, flux-cli, zsh+starship. With --yes it installs the
default set (everything except zsh and flux-cli).
Directory Structure
/home/docker/
├── compose/ # Docker Compose files (one dir per service)
│ ├── .env.global # shared vars: TZ, PUID/PGID, APP_DATA, media paths
│ └── shared/ # shared configs and scripts
└── appdata/ # Application data volumes
/mnt/ # autofs NFS mount points (from NFS_MOUNTS)
NFS Server Configuration
For read/write access to NFS mounts, the NFS server must be configured correctly. See NFS-SERVER-CONFIGURATION.md for Unraid and OMV export setup, mount options, and troubleshooting.
Usage Notes
- Idempotent: safe to re-run scripts; they skip already-configured items
lib/common.sh: all prompts go throughconfirm/confirm_optional, which is what makes--yeswork everywhere- Unattended failures abort: with
--yes, any failing script stops the run so a broken template is never silently produced - Forgejo access: scripts 13 and 15 need to reach your Forgejo instance
- Script 22 needs sudo:
sudo ./22-setup-fastfetch.sh(the runner handles this automatically)
License
MIT License - Feel free to modify for your environment.