feat: add Vagrant file and provisioning scripts

This commit is contained in:
Emmanuel BENOîT 2024-12-29 18:28:07 +01:00
commit ad2a00a42c
Signed by: Emmanuel BENOîT
SSH key fingerprint: SHA256:l7PFUUF5TCDsvYeQC9OnTNz08dFY7Fvf4Hv3neIqYpg
25 changed files with 4805 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.vagrant

75
Vagrantfile vendored Normal file
View file

@ -0,0 +1,75 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
def env_or_default(key, value)
if ENV.key?(key) then
return ENV[key]
else
return value
end
end
# Read parameters from the environment.
vm_cpus = env_or_default("VM_CPU", 4)
vm_memory = env_or_default("VM_MEMORY", 16 * 1024)
# More parameters from the environment. These are only used during provisioning.
apt_proxy = env_or_default("APT_PROXY", "")
vm_locale = env_or_default("VM_LOCALE", "en_GB.UTF-8")
chezmoi_source = env_or_default("CHEZMOI_SOURCE", "")
vmnet_back_addr = env_or_default("VMNET_BACK_ADDR", "10.0.0.1")
vmnet_front_addr = env_or_default("VMNET_FRONT_ADDR", "10.0.1.1")
vmnet_domain = env_or_default("VMNET_DOMAIN", "envdev.test")
vmnet_bind_key_id = env_or_default("VMNET_BIND_KEY_ID", "terraform.#{vmnet_domain}")
vmnet_bind_key = env_or_default("VMNET_BIND_KEY", "")
Vagrant.configure("2") do |config|
config.vagrant.plugins = ["vagrant-libvirt"]
config.ssh.forward_agent = true
config.ssh.forward_x11 = true
config.vm.box = "generic/debian12"
config.vm.hostname = "workvm"
config.vm.box_check_update = false
config.vm.provider "libvirt" do |lv|
lv.memory = vm_memory
lv.cpus = vm_cpus
lv.graphics_type = "spice"
lv.video_type = "virtio"
lv.nested = true
lv.disk_driver :discard => "unmap"
end
config.vm.provision "shell",
reboot: true,
inline: <<-EOF
export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true;
apt-get remove -y --purge resolvconf
EOF
config.vm.provision "shell",
path: "scripts/00-network.sh",
reboot: true,
env: { "APT_PROXY" => apt_proxy }
config.vm.provision "shell",
path: "scripts/01-os-basics.sh",
reboot: true
config.vm.provision "file",
source: "ansible",
destination: "/var/cache/provision/playbook"
config.vm.provision "shell",
path: "scripts/02-provision.sh",
reboot: true,
privileged: false,
env: {
"VM_LOCALE" => vm_locale,
"CHEZMOI_SOURCE" => chezmoi_source,
"VMNET_BACK_ADDR" => vmnet_back_addr,
"VMNET_FRONT_ADDR" => vmnet_front_addr,
"VMNET_DOMAIN" => vmnet_domain,
"VMNET_BIND_KEY_ID" => vmnet_bind_key_id,
"VMNET_BIND_KEY" => vmnet_bind_key
}
config.vm.synced_folder '.', '/vagrant', :disabled => true
end

2
ansible/ansible.cfg Normal file
View file

@ -0,0 +1,2 @@
[defaults]
inventory = inv.yml

2057
ansible/files/antigen.zsh Normal file

File diff suppressed because it is too large Load diff

6
ansible/files/atuin.toml Normal file
View file

@ -0,0 +1,6 @@
dialect = "uk"
update_check = false
filter_mode_shell_up_key_binding = "session"
style = "compact"
show_preview = true
enter_accept = true

View file

@ -0,0 +1,6 @@
options {
directory "/var/cache/bind";
forward only; // Never try resolving other domains
forwarders { 127.0.0.53; }; // Forward everything to systemd-resolved
dnssec-validation yes; // systemd-resolved *requires* DNSSEC
};

28
ansible/files/domains.j2 Normal file
View file

@ -0,0 +1,28 @@
include "/etc/bind/tf-key.conf"; // Load Terraform key
// Main domain
zone "{{ domain_name }}" in {
type master;
file "/var/lib/bind/db.{{ domain_name }}";
update-policy {
grant {{ update_key }} subdomain {{ domain_name }}. A CNAME;
};
};
// Reverse DNS for {{ back_net }}/24
zone "{{ back_arpa }}" in {
type master;
file "/var/lib/bind/db.{{ back_arpa }}";
update-policy {
grant {{ update_key }} subdomain {{ back_arpa }}. PTR;
};
};
// Reverse DNS for {{ front_net }}/24
zone "{{ front_arpa }}" in {
type master;
file "/var/lib/bind/db.{{ front_arpa }}";
update-policy {
grant {{ update_key }} subdomain {{ front_arpa }}. PTR;
};
};

30
ansible/files/gitconfig Normal file
View file

@ -0,0 +1,30 @@
[pull]
ff = only
[init]
defaultBranch = master
[core]
pager = delta --line-numbers
[delta]
commit-decoration-style = bold box
dark = true
file-decoration-style = none
file-style = omit
hunk-header-decoration-style = "#cfd6ff" box
hunk-header-file-style = bold "#FFFF7F"
hunk-header-line-number-style = bold "#3388ff"
hunk-header-style = file line-number syntax
line-numbers = true
line-numbers-left-style = "#033b5f"
line-numbers-minus-style = "#a61142"
line-numbers-plus-style = "#0d800d"
line-numbers-right-style = "#033b5f"
line-numbers-zero-style = "#cccccc"
minus-emph-style = normal "#80002a"
minus-style = syntax "#1f1f1f"
plus-emph-style = normal "#003300"
plus-style = syntax "#1f1f1f"
side-by-side = false
syntax-theme = Nord

7
ansible/files/iptables Normal file
View file

@ -0,0 +1,7 @@
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT

5
ansible/files/keyboard Normal file
View file

@ -0,0 +1,5 @@
XKBMODEL="pc105"
XKBLAYOUT="fr"
XKBVARIANT="latin9"
XKBOPTIONS=""
BACKSPACE="guess"

15
ansible/files/locale.j2 Normal file
View file

@ -0,0 +1,15 @@
LANG={{ locale }}
LANGUAGE={{ locale }}
LC_CTYPE={{ locale }}
LC_NUMERIC={{ locale }}
LC_TIME={{ locale }}
LC_COLLATE={{ locale }}
LC_MONETARY={{ locale }}
LC_MESSAGES={{ locale }}
LC_PAPER={{ locale }}
LC_NAME={{ locale }}
LC_ADDRESS={{ locale }}
LC_TELEPHONE={{ locale }}
LC_MEASUREMENT={{ locale }}
LC_IDENTIFICATION={{ locale }}
LC_ALL={{ locale }}

1662
ansible/files/p10k.zsh Normal file

File diff suppressed because it is too large Load diff

59
ansible/files/resize.sh Normal file
View file

@ -0,0 +1,59 @@
#!/bin/bash
# Steps:
# 1) Make sure bash is available
# 2) Create udev rule
# - path to new udev rule: /etc/udev/rules.d/50-x-resize.rules
# - udev rule content:
# ACTION=="change",KERNEL=="card0", SUBSYSTEM=="drm", RUN+="/usr/local/bin/x-resize"
# 3) Create /var/log/autores directory
# 4) Create script /usr/local/bin/x-resize (this file) and make executable
# 5) Reload udev rules with `sudo udevadm control --reload-rules`
# 6) Make sure auto-resize is enabled in virt-viewer/spicy
# 7) Make sure qemu-guest-agent spice-vdagent xserver-xspice xserver-xorg-video-qxl are installed
# 8) Make sure spice-vdagentd is loaded and running fine
# Debugging:
# - Watch udev events on resize with `udevadm monitor`
# - Watch dmesg (may not be super useful) with `dmesg -w`
# - Watch autores logs with `tail -f /var/log/autores/autores.log`
# Credits:
# - Credit for Finding Sessions as Root: https://unix.stackexchange.com/questions/117083/how-to-get-the-list-of-all-active-x-sessions-and-owners-of-them
# - Credit for Resizing via udev: https://superuser.com/questions/1183834/no-auto-resize-with-spice-and-virt-manager
## Ensure Log Directory Exists
LOG_DIR=/var/log/autores;
if [ ! -d $LOG_DIR ]; then
mkdir $LOG_DIR;
fi
LOG_FILE=${LOG_DIR}/autores.log
## Function to find User Sessions & Resize their display
function x_resize() {
declare -A disps usrs
usrs=()
disps=()
for i in $(users);do
[[ $i = root ]] && continue # skip root
usrs[$i]=1
done
for u in "${!usrs[@]}"; do
for i in $(sudo ps e -u "$u" | sed -rn 's/.* DISPLAY=(:[0-9]*).*/\1/p');do
disps[$i]=$u
done
done
for d in "${!disps[@]}";do
session_user="${disps[$d]}"
session_display="$d"
session_output=$(sudo -u "$session_user" PATH=/usr/bin DISPLAY="$session_display" xrandr | awk '/ connected/{print $1; exit; }')
echo "Session User: $session_user" | tee -a $LOG_FILE;
echo "Session Display: $session_display" | tee -a $LOG_FILE;
echo "Session Output: $session_output" | tee -a $LOG_FILE;
sudo -u "$session_user" PATH=/usr/bin DISPLAY="$session_display" xrandr --output "$session_output" --auto | tee -a $LOG_FILE;
done
}
echo "Resize Event: $(date)" | tee -a $LOG_FILE
x_resize

View file

@ -0,0 +1,3 @@
[Resolve]
Domains=~{{ domain_name }} ~{{ back_arpa }} ~{{ front_arpa }} {{ domain_name }}
DNS=127.0.0.1

3
ansible/files/ssh_config Normal file
View file

@ -0,0 +1,3 @@
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
LogLevel ERROR

View file

@ -0,0 +1,4 @@
key "{{ update_key }}." {
algorithm hmac-sha512;
secret "{{ lookup( 'env', 'VMNET_BIND_KEY' ) }}";
}

View file

@ -0,0 +1,8 @@
XDG_DESKTOP_DIR="$HOME/"
XDG_DOCUMENTS_DIR="$HOME/"
XDG_DOWNLOAD_DIR="$HOME/Download/"
XDG_MUSIC_DIR="$HOME/"
XDG_PICTURES_DIR="$HOME/"
XDG_PUBLICSHARE_DIR="$HOME/"
XDG_TEMPLATES_DIR="$HOME/"
XDG_VIDEOS_DIR="$HOME/"

View file

@ -0,0 +1,15 @@
$ORIGIN .
$TTL 21600
{{ domain_name }} IN SOA vm-host.{{ domain_name }}. lol.mail.hostmaster.ici.osef. (
1 ; serial
86400 ; refresh (1 day)
3600 ; retry (1 hour)
2419200 ; expire (4 weeks)
360 ; negative ttl (5 minutes)
)
IN NS vm-host.{{ domain_name }}.
IN A {{ ( back_net ~ "/24" ) | ansible.utils.ipaddr("1") | ansible.utils.ipaddr("address") }}
IN MX 1 {{ ( back_net ~ "/24" ) | ansible.utils.ipaddr("1") | ansible.utils.ipaddr("address") }}
$ORIGIN {{ domain_name }}.
vm-host IN A {{ ( back_net ~ "/24" ) | ansible.utils.ipaddr("1") | ansible.utils.ipaddr("address") }}
vm-host-f IN A {{ ( front_net ~ "/24" ) | ansible.utils.ipaddr("1") | ansible.utils.ipaddr("address") }}

View file

@ -0,0 +1,12 @@
$ORIGIN .
$TTL 21600
{{ item.arpa }} IN SOA vm-host.{{ domain_name }}. lol.mail.hostmaster.ici.osef. (
1 ; serial
86400 ; refresh (1 day)
3600 ; retry (1 hour)
2419200 ; expire (4 weeks)
360 ; negative ttl (5 minutes)
)
IN NS vm-host.{{ domain_name }}.
$ORIGIN {{ item.arpa }}.
1 IN PTR {{ item.host }}.{{ domain_name }}.

79
ansible/files/zshrc Normal file
View file

@ -0,0 +1,79 @@
# Path
export PATH=$HOME/.local/bin:$PATH
# Bash-like word boundaries
autoload -U select-word-style
select-word-style bash
# Use antigen
source $HOME/.local/share/zsh/antigen.zsh
# Load various plugins
antigen bundle Aloxaf/fzf-tab
antigen bundle clarketm/zsh-completions
antigen bundle git
antigen bundle mattberther/zsh-pyenv
antigen bundle ellie/atuin@v{{ atuin_version }}
antigen bundle pip
antigen bundle pyenv
antigen bundle zimfw/asdf
antigen bundle zsh-users/zsh-syntax-highlighting
antigen bundle zsh-users/zsh-autosuggestions
# Load the powerlevel10k theme
antigen theme romkatv/powerlevel10k
# Apply plugins
antigen apply
# Powerline10k customization
[[ ! -f ~/.local/share/zsh/p10k.zsh ]] || source ~/.local/share/zsh/p10k.zsh
# History file
HISTFILE=$HOME/.zhistory
SAVEHIST=10000
HISTSIZE=10000
setopt appendhistory
setopt inc_append_history
# Tab completion on empty line
zstyle ':completion:*' insert-tab pending
# Ctrl+Left/Right
bindkey "^[[1;5C" forward-word
bindkey "^[[1;5D" backward-word
# Home/End
bindkey '\e[1~' beginning-of-line
bindkey '\e[4~' end-of-line
# Comments should be ignored
setopt interactivecomments
# LS colors if available
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
fi
# Grep colors
if grep -q --color=auto t 2>/dev/null <<<t
then
alias grep='grep --color=auto'
fi
# The classics
alias ll='ls -l'
alias la='ls -A'
alias l='ls -CF'
alias cp='cp -i'
alias rm='rm -i'
alias mv='mv -i'
# Pyenv venv aliases
export PYENV_VIRTUALENV_DISABLE_PROMPT=1
alias mkvirtualenv="pyenv virtualenv"
alias rmvirtualenv="pyenv virtualenv-delete"
alias workon="pyenv activate"
# Various utilities
alias gl="git log --graph --pretty=format:'%C(yellow)%h%Creset%C(cyan)%C(bold)%d%Creset %C(cyan)(%cr)%Creset %C(green)%ce%Creset %s'"
alias cat="batcat -p"

7
ansible/inv.yml Normal file
View file

@ -0,0 +1,7 @@
all:
hosts:
localhost:
ansible_connection: local
become: true
become_method: sudo
ansible_python_interpreter: /usr/bin/python3

640
ansible/provision.yml Normal file
View file

@ -0,0 +1,640 @@
- hosts: localhost
become: true
vars:
# Debian packages that must be installed
debian_packages:
- acl
- bat
- bind9
- build-essential
- console-common
- console-setup
- containerd.io
- curl
- dialog
- docker-buildx-plugin
- docker-ce
- docker-ce-cli
- docker-compose-plugin
- firefox-esr
- fzf
- gawk
- git
- htop
- ipcalc
- iptables-persistent
- keepassxc
- ldap-utils
- libldap2-dev
- libsasl2-dev
- libvirt-clients
- libvirt-daemon
- libvirt-daemon-config-network
- libvirt-daemon-driver-qemu
- libvirt-daemon-system
- libvirt-daemon-system-systemd
- libvirt-dbus
- lua5.4
- net-tools
- psmisc
- python3-dev
- python3-pip
- qemu-guest-agent
- qemu-kvm
- remmina
- spice-vdagent
- sshpass
- task-xfce-desktop
- unzip
- vim-gtk3
- virt-manager
- zsh
# Version of ASDF itself
asdf_version: 0.15.0
# Tools that will be installed using asdf
asdf_tools:
- java
- golang
- nodejs
- opentofu
- packer
- terragrunt
# If some asdf-installed tools require specific versions, they must be
# listed here. Tools that are not listed will default to the latest
# version.
asdf_tool_versions:
java: openjdk-17
nodejs: 22.12.0
opentofu: 1.8.1
packer: 1.11.0
terragrunt: 0.66.9
# Python packages to install
python_packages:
- ansible>=9,<10
- dnspython
- netaddr
- python-ldap
- xmltodict
- pyvmomi
- requests
- git+https://github.com/vmware/vsphere-automation-sdk-python.git
- pywinrm
# Version of the git-delta utility
git_delta_version: 0.18.2
# Version of the atuin utility
atuin_version: 18.4.0
# Vim plugins that need to be installed
vim_plugins:
- airblade/vim-gitgutter
- bling/vim-airline
- cespare/vim-toml
- ctrlpvim/ctrlp.vim
- elzr/vim-json
- Exafunction/codeium.vim
- fatih/vim-go
- Glench/Vim-Jinja2-Syntax
- hashivim/vim-terraform
- liuchengxu/vim-which-key
- mattn/vim-lsp-settings
- mbbill/undotree
- octol/vim-cpp-enhanced-highlight
- PProvost/vim-ps1
- prabirshrestha/asyncomplete-lsp.vim
- prabirshrestha/asyncomplete.vim
- prabirshrestha/async.vim
- prabirshrestha/vim-lsp
- rbong/vim-flog
- rust-lang/rust.vim
- scrooloose/nerdtree
- Shougo/dein.vim
- skywind3000/asyncrun.vim
- tikhomirov/vim-glsl
- tpope/vim-fugitive
- vim-airline/vim-airline-themes
- vim-perl/vim-perl
- vim-test/vim-test
- wsdjeg/dein-ui.vim
- Xuyuanp/nerdtree-git-plugin
# Various parameters need to be fetched from env variables
domain_name: >-
{{ lookup( "env", "VMNET_DOMAIN" ) }}
update_key: >-
{{ lookup( "env", "VMNET_BIND_KEY_ID" ) }}
back_net: >-
{{ lookup( "env" , "VMNET_BACK_ADDR" ) }}
front_net: >-
{{ lookup( "env" , "VMNET_FRONT_ADDR" ) }}
back_arpa: >-
{{ back_net.split( "." )[0:3] | reverse | join( "." ) }}.in-addr.arpa
front_arpa: >-
{{ front_net.split( "." )[0:3] | reverse | join( "." ) }}.in-addr.arpa
locale: >-
{{ lookup( "env", "VM_LOCALE" ) }}
chezmoi_source: >-
{{ lookup( "env", "CHEZMOI_SOURCE" ) }}
tasks:
# Configure grub
- name: Reduce boot delay to 1s
ansible.builtin.lineinfile:
path: /etc/default/grub
regexp: ^GRUB_TIMEOUT=
line: GRUB_TIMEOUT=1
- name: Update Grub configuration
ansible.builtin.command:
cmd: update-grub2
# Ensure ext4 filesystems are mounted with discard enabled
- name: Add discard option to mount points
loop: [ "/" , "/boot" ]
ansible.builtin.lineinfile:
path: /etc/fstab
backrefs: true
regexp: '^(\S+\s+{{ item }}\s+\S+\s+)(?!(?:\S*,)?discard(?:,\S*)?\s+)(\S+)(\s+.+)$'
line: '\1discard,\2\3'
# Prepare for docker installation
- name: Get APT key for the Docker repo
ansible.builtin.shell:
cmd: wget -O- https://download.docker.com/linux/debian/gpg > /etc/apt/keyrings/docker.asc
- name: Add Docker APT repo
ansible.builtin.shell:
cmd: |
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] http://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
> /etc/apt/sources.list.d/docker.list
# Install various required packages
- name: Remove unnecessary packages
ansible.builtin.command:
cmd: apt-get autoremove -y
- name: Install packages
ansible.builtin.apt:
update_cache: true
name: "{{ debian_packages }}"
# Keyboard / locale configuration
- name: Copy keyboard config
ansible.builtin.copy:
src: files/keyboard
dest: /etc/default/keyboard
force: true
- name: Copy locale config
ansible.builtin.template:
src: files/locale.j2
dest: /etc/default/locale
force: true
- name: Change locale to {{ locale }}
community.general.locale_gen:
name: "{{ locale }}"
state: present
- name: Set timezone
community.general.timezone:
name: Europe/Paris
- name: dpkg-reconfigure
ansible.builtin.shell: >
dpkg-reconfigure -f noninteractive keyboard-configuration &&
localectl set-locale LANG={{ locale }} LANGUAGE={{ locale }} &&
timedatectl set-timezone Europe/Paris &&
update-locale LANG={{ locale }}
# Desktop resizing
- name: Create desktop resizing logs directory
ansible.builtin.file:
path: /var/log/autores
state: directory
mode: "0700"
- name: Copy desktop resizing script
ansible.builtin.copy:
src: files/resize.sh
dest: /usr/local/bin/x-resize
mode: "0755"
- name: Create udev rule
ansible.builtin.copy:
content: >
ACTION=="change",KERNEL=="card0", SUBSYSTEM=="drm", RUN+="/usr/local/bin/x-resize"
dest: /etc/udev/rules.d/50-x-resize.rules
mode: "0644"
- name: Reload udev rules
ansible.builtin.command:
cmd: udevadm control --reload-rules
# Prevent XFCE from creating random dirs in the user home
- name: Create user config directory
ansible.builtin.file:
path: /home/vagrant/.config
state: directory
owner: vagrant
group: vagrant
- name: Configure XDG user dirs
ansible.builtin.copy:
src: files/user-dirs.dirs
dest: /home/vagrant/.config/user-dirs.dirs
owner: vagrant
group: vagrant
# Configure VM networks
- name: Configure dummy module
ansible.builtin.lineinfile:
path: /etc/modprobe.d/local.conf
create: true
line: options dummy numdummies=0
- name: Configure bridge network devices
loop: [0, 1]
ansible.builtin.copy:
content: |
[NetDev]
Name=br{{ item }}
Kind=bridge
dest: /etc/systemd/network/bridge{{ item }}.netdev
- name: Configure bridge networks
loop:
- { id: 0, addr: "{{ back_net }}" }
- { id: 1, addr: "{{ front_net }}" }
ansible.builtin.copy:
content: |
[Match]
Name=br{{ item.id }}
[Network]
ConfigureWithoutCarrier=yes
LinkLocalAddressing=no
Address={{ item.addr }}/24
dest: /etc/systemd/network/bridge{{ item.id }}.network
- name: Configure dummy network devices
loop: [0, 1]
ansible.builtin.copy:
content: |
[NetDev]
Name=dummy{{ item }}
Kind=dummy
dest: /etc/systemd/network/dummy{{ item }}.netdev
- name: Enslave dummy network devices to bridges
loop: [0, 1]
ansible.builtin.copy:
content: |
[Match]
Name=dummy{{ item }}
[Network]
Bridge=br{{ item }}
ConfigureWithoutCarrier=yes
dest: /etc/systemd/network/dummy{{ item }}.network
- name: Ensure IPv4 forwarding is enabled
ansible.builtin.lineinfile:
path: /etc/systemd/network/eth0.network
line: IPForward=ipv4
insertafter: ^\[Network\]$
- name: Configure NAT
ansible.builtin.copy:
src: files/iptables
dest: /etc/iptables/rules.v4
# Configure DNS server
- name: Disable IPv6 for Bind
ansible.builtin.lineinfile:
path: /etc/default/named
line: OPTIONS="-u bind -4"
regexp: ^OPTIONS=
- name: Generate dynamic update key
when: lookup( "env", "VMNET_BIND_KEY" ) == ""
ansible.builtin.shell:
cmd: >-
tsig-keygen -a hmac-sha512 {{ update_key }}.
> /etc/bind/tf-key.conf
creates: /etc/bind/tf-key.conf
- name: Copy dynamic update key
when: lookup( "env", "VMNET_BIND_KEY" ) != ""
ansible.builtin.template:
src: files/tf-key.conf.j2
dest: /etc/bind/tf-key.conf
- name: Configure Bind options
ansible.builtin.template:
src: files/bind-options
dest: /etc/bind/named.conf.options
owner: root
group: bind
- name: Configure local domains
ansible.builtin.template:
src: files/domains.j2
dest: /etc/bind/named.conf.local
owner: root
group: bind
- name: Initialize zone for domain
ansible.builtin.template:
src: files/zf-domain.j2
dest: /var/lib/bind/db.{{ domain_name }}
owner: bind
group: bind
- name: Initialize reverse DNS zones
loop:
- { arpa: "{{ back_arpa }}" , host: vm-host }
- { arpa: "{{ front_arpa }}" , host: vm-host-f }
ansible.builtin.template:
src: files/zf-reverse.j2
dest: /var/lib/bind/db.{{ item.arpa }}
owner: bind
group: bind
- name: Ensure resolution is enabled for external domains
ansible.builtin.lineinfile:
path: /etc/systemd/network/eth0.network
line: Domains=~.
insertafter: ^\[Network\]$
- name: Configure systemd-resolved so it queries the local DNS server
ansible.builtin.template:
src: files/resolved.conf.j2
dest: /etc/systemd/resolved.conf
# Download and install delta. The asdf-provided version doesn't work on
# Debian.
- name: Download git-delta
ansible.builtin.get_url:
url: https://github.com/dandavison/delta/releases/download/{{ git_delta_version }}/git-delta-musl_{{ git_delta_version }}_amd64.deb
dest: /root
- name: Install git-delta
ansible.builtin.command:
cmd: dpkg -i /root/git-delta-musl_{{ git_delta_version }}_amd64.deb
# Download and install atuin.
- name: Download atuin
ansible.builtin.get_url:
url: https://github.com/atuinsh/atuin/releases/download/v{{ atuin_version }}/atuin-x86_64-unknown-linux-gnu.tar.gz
dest: /tmp
- name: Install atuin
ansible.builtin.command:
cmd: tar xzf /tmp/atuin-x86_64-unknown-linux-gnu.tar.gz --strip-components=1 atuin-x86_64-unknown-linux-gnu/atuin
chdir: /usr/local/bin
# Ensure virtualization and docker can be used
- name: Add the vagrant user to various group
ansible.builtin.user:
name: vagrant
groups: kvm,libvirt,docker
append: true
- name: Make the QEMU bridge helper setuid
ansible.builtin.file:
path: /usr/lib/qemu/qemu-bridge-helper
group: kvm
mode: "6750"
- name: Allow QEMU tu use br0
ansible.builtin.copy:
content: allow br0
dest: /etc/qemu/bridge.conf
- name: Disable libvirt security driver
ansible.builtin.lineinfile:
path: /etc/libvirt/qemu.conf
regexp: ^security_driver\s*=
line: >-
security_driver = "none"
# Set the shell to zsh for the vagrant user
- name: Set default shell
ansible.builtin.user:
name: vagrant
shell: /bin/zsh
# "Fix" X11 forwarding
- name: Fix X11 forwarding through SSH
ansible.builtin.copy:
dest: /etc/ssh/sshd_config.d/x11forwarding.conf
content: |
X11UseLocalhost no
- name: Configure user account
become: false
block:
- name: Create directories for zsh and other tools
loop:
- .local/share/zsh
- .local/bin
- .config/atuin
- .ssh
ansible.builtin.file:
state: directory
path: /home/vagrant/{{ item }}
mode: "0755"
owner: vagrant
group: vagrant
# Install ASDF
- name: Install ASDF
ansible.builtin.git:
repo: https://github.com/asdf-vm/asdf.git
dest: /home/vagrant/.asdf
single_branch: true
version: v{{ asdf_version }}
# Install and run Chezmoi
- name: Install chezmoi
ansible.builtin.shell:
cmd: >-
set -e ;
export ASDF_DIR=/home/vagrant/.asdf ;
. $ASDF_DIR/asdf.sh ;
asdf plugin-add chezmoi ;
asdf install chezmoi latest ;
asdf global chezmoi latest
chdir: /home/vagrant
- name: Check for known host
when: >-
chezmoi_source is match( "^ssh://" )
check_mode: true
ansible.builtin.lineinfile:
path: /home/vagrant/.ssh/known_hosts
line: "^{{ chezmoi_source | urlsplit( 'hostname' ) }} "
regex: true
state: absent
register: ssh_key_present
- name: Add SSH key for chezmoi's Git repo
when: >-
chezmoi_source is match( "^ssh://" ) and
ssh_key_present is not changed
ansible.builtin.shell:
cmd: >-
ssh-keyscan {{ chezmoi_source | urlsplit( 'hostname' ) }} \
>> /home/vagrant/.ssh/known_hosts
- name: Check for chezmoi repo
when: chezmoi_source != ""
ansible.builtin.stat:
path: /home/vagrant/.local/share/chezmoi
register: chezmoi_stat
- name: Initialize chezmoi
when: chezmoi_source != "" and not chezmoi_stat.stat.exists
ansible.builtin.shell:
cmd: >-
set -e ;
export ASDF_DIR=/home/vagrant/.asdf ;
. $ASDF_DIR/asdf.sh ;
chezmoi init {{ chezmoi_source }} ;
chezmoi apply
chdir: /home/vagrant
# If there's not .zshrc, use default config files
- name: Check for zshrc
ansible.builtin.stat:
path: /home/vagrant/.zshrc
register: zshrc_stat
- when: not zshrc_stat.stat.exists
block:
# Create the zsh configuration for the vagrant user
- name: Copy configuration files
loop:
- {s: antigen.zsh, d: .local/share/zsh/antigen.zsh}
- {s: p10k.zsh, d: .local/share/zsh/p10k.zsh}
- {s: atuin.toml, d: .config/atuin/config.toml}
- {s: gitconfig, d: .gitconfig}
ansible.builtin.copy:
src: files/{{ item.s }}
dest: /home/vagrant/{{ item.d }}
mode: "0644"
owner: vagrant
group: vagrant
- name: Update configuration files
loop:
- {s: zshrc, d: .zshrc}
ansible.builtin.template:
src: files/{{ item.s }}
dest: /home/vagrant/{{ item.d }}
mode: "0644"
owner: vagrant
group: vagrant
# Initialize shell
- name: Run shell initialization
ansible.builtin.command:
cmd: zsh .zshrc
chdir: /home/vagrant
# Install various tools using asdf
- name: Install asdf plugins
loop: "{{ asdf_tools }}"
ansible.builtin.shell:
cmd: >-
source .zshrc &&
asdf plugin-add {{ item }}
chdir: /home/vagrant
executable: /bin/zsh
register: asdf_out
failed_when: >-
asdf_out.rc != 0 and
'already added' not in asdf_out.stderr
- name: Install tools using asdf
loop: "{{ asdf_tools }}"
ansible.builtin.shell:
cmd: >-
source .zshrc &&
asdf install {{ item }} {{ asdf_tool_versions[ item ] | default( "latest" ) }} &&
asdf global {{ item }} {{ asdf_tool_versions[ item ] | default( "latest" ) }}
chdir: /home/vagrant
executable: /bin/zsh
# Install Ansible 9 and various packages in a Python venv
- name: Ensure vagrant user has a .local directory
loop: [ bin, share ]
ansible.builtin.file:
path: /home/vagrant/.local/{{ item }}
state: directory
- name: Create Ansible virtual environment
ansible.builtin.shell:
executable: /bin/zsh
cmd: >-
source .zshrc && {
[ -d /home/vagrant/.local/share/ansible ] ||
python -m venv /home/vagrant/.local/share/ansible;
}
chdir: /home/vagrant
- name: Install Ansible and related Python packages
ansible.builtin.shell:
executable: /bin/zsh
cmd: >-
source /home/vagrant/.zshrc &&
source /home/vagrant/.local/share/ansible/bin/activate &&
pip install "{{ python_packages | join('" "') }}"
chdir: /home/vagrant/.local/share
- name: List Ansible executables
ansible.builtin.find:
paths: /home/vagrant/.local/share/ansible/bin
file_type: file
patterns: [ "ansible*" ]
register: ansible_exes
- name: Create Ansible symlinks
loop: "{{ ansible_exes.files }}"
ansible.builtin.file:
state: link
src: "{{ item.path }}"
dest: /home/vagrant/.local/bin/{{ item.path | basename }}
# Configure SSH for the vagrant user
- name: Configure SSH for the vagrant user
ansible.builtin.copy:
src: files/ssh_config
dest: /home/vagrant/.ssh/config
# Configure Vim
- name: Remove default vimrc
ansible.builtin.file:
path: /home/vagrant/.vimrc
state: absent
- name: Install vim configuration
ansible.builtin.git:
repo: https://git@git.nocternity.net/tseeker-pub/heavim.git
dest: /home/vagrant/.vim
- name: Create vim cache directory
ansible.builtin.file:
path: /home/vagrant/.cache/vim
state: directory
mode: "0700"
- name: Create vim plugin directories
loop: "{{ vim_plugins | map( 'dirname' ) | unique }}"
ansible.builtin.file:
path: /home/vagrant/.cache/vim/bundles/repos/github.com/{{ item }}
state: directory
- name: Clone vim plugins
loop: "{{ vim_plugins }}"
ansible.builtin.git:
repo: https://github.com/{{ item }}
dest: /home/vagrant/.cache/vim/bundles/repos/github.com/{{ item }}
# Install Rust
- name: Install Rust
ansible.builtin.shell:
cmd: >-
set -e ;
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /tmp/rustinit.sh ;
sh /tmp/rustinit.sh -y -c rust-analyzer,rust-src,rust-analysis

35
scripts/00-network.sh Normal file
View file

@ -0,0 +1,35 @@
#!/bin/sh
set -e
export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true
# APT proxy configuration
if [ -z "$APT_PROXY" ]; then
rm -f /etc/apt/apt.conf.d/90proxy
sub=http:/https:
else
echo "Acquire::http::Proxy \"${APT_PROXY}\";" > /etc/apt/apt.conf.d/90proxy
sub=https:/http:
fi
sed -i "s/$sub/g" /etc/apt/sources.list `find /etc/apt/sources.list.d -name '*.list'`
# Ensure systemd-resolved is actually installed
apt-get update
apt-get install -y systemd-resolved
cat >/etc/systemd/network/eth0.network <<EOF
[Match]
Name=eth0
[Network]
LinkLocalAddressing=no
DHCP=ipv4
EOF
systemctl enable systemd-networkd.service
systemctl enable systemd-resolved.service
rm -f /etc/network/interfaces
dpkg --purge resolvconf
systemctl disable networking.service
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

31
scripts/01-os-basics.sh Normal file
View file

@ -0,0 +1,31 @@
#!/bin/sh
set -e
export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true
# Reset grub configuration
echo "Setting install device to $( grub-mkdevicemap -m - | head -n 1 | awk '{ print $2 }' )"
echo "debconf grub-pc/install_devices string $( grub-mkdevicemap -m - | head -n 1 | awk '{ print $2 }' )" | debconf-set-selections
# Prevent "suggested" packages from being installed automatically
echo 'APT::Install-Suggests "0";' > /etc/apt/apt.conf.d/05disable-suggests
# Replace kernel
apt-get install -uy linux-image-cloud-amd64
apt-get remove -y linux-image-amd64
# Remove various useless packages
apt-get remove -y memcached postfix postfix-cdb
# Full system update
apt-get update -y
apt-get dist-upgrade -uy
apt-get clean
apt-get autoremove -y
# Install Ansible requirements
apt-get install -y python3-venv python-is-python3
# Create a directory for the provisioning playbook
[ -d /var/cache/provision ] || mkdir -p /var/cache/provision
chown -R vagrant:vagrant /var/cache/provision

15
scripts/02-provision.sh Normal file
View file

@ -0,0 +1,15 @@
#!/bin/bash
set -e
export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true
# Create the Ansible venv
if [ ! -d /var/cache/provision/ansible ]; then
python -m venv /var/cache/provision/ansible
fi
source /var/cache/provision/ansible/bin/activate
pip install --upgrade 'ansible>=10,<11' netaddr
# Run the playbook
cd /var/cache/provision/playbook
exec ansible-playbook provision.yml