#cloud-config # Warning: This whole file will be evaluated by Jinja. Escape any special literals # Update and upgrade system packages package_update: true package_upgrade: true disable_root_opts: no-port-forwarding,no-agent-forwarding,no-X11-forwarding # Install required packages packages: - ufw - zsh - git - curl - wget - build-essential - neovim - apt-transport-https - ca-certificates - gnupg users: - name: {{ username }} gecos: "{{ username }} user" shell: /bin/bash groups: sudo,admin,wheel,docker sudo: "ALL=(ALL) NOPASSWD:ALL" ssh_authorized_keys:{% for key in ssh_keys %} - {{ key }} {% endfor %} # Write custom zshrc file write_files: - path: /home/{{ username }}/.zshrc owner: {{ username }}:{{ username }} permissions: '0644' defer: true content: | # Prompt: user@host:dir (green for normal, red after failed command) {% raw %}PROMPT='%F{%(?.green.red)}%n@%m%f:%F{blue}%~%f$ '{% endraw %} # History HISTFILE=~/.zsh_history HISTSIZE=10000 SAVEHIST=10000 setopt SHARE_HISTORY HIST_IGNORE_DUPS HIST_IGNORE_SPACE # Completion autoload -Uz compinit && compinit zstyle ':completion:*' menu select # Key bindings bindkey -e export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 export EDITOR='nvim' export LESS='-R' export PATH="$PATH:/home/{{ username }}/.local/bin" alias vim="nvim" # Run commands after boot runcmd: # Configure UFW firewall - ufw default deny incoming - ufw default allow outgoing - ufw allow OpenSSH - ufw limit ssh - ufw --force enable # Install Docker from official repo (works on both Ubuntu and Debian) - | . /etc/os-release install -m 0755 -d /etc/apt/keyrings curl -fsSL "https://download.docker.com/linux/$ID/gpg" -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/$ID $(. /etc/os-release && echo "$VERSION_CODENAME") stable" > /etc/apt/sources.list.d/docker.list apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin {% if tailscale_enabled %} # Install Tailscale via official script (daemon only, authentication handled by dropkit) - curl -fsSL https://tailscale.com/install.sh | sh {% endif %} # Wait for user to be fully created - | timeout=30 count=0 while ! id {{ username }} >/dev/null 2>&1; do if [ $count -ge $timeout ]; then echo "Timeout waiting for user {{ username }} to be created" exit 1 fi sleep 1 count=$((count + 1)) done echo "User {{ username }} is ready" # Ensure home directory exists and has correct permissions - mkdir -p /home/{{ username }} - chown {{ username }}:{{ username }} /home/{{ username }} # Configure git globally for the user - su {{ username }} -c "git config --global user.name '{{ full_name }}'" - su {{ username }} -c "git config --global user.email '{{ email }}'" # Set Zsh as default shell and ensure ownership - chsh -s /usr/bin/zsh {{ username }} - chown -R {{ username }}:{{ username }} /home/{{ username }} - reboot