diff --git a/.dockerignore b/.dockerignore index ecc0037..504822d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,7 +3,5 @@ /.dotfiles-update .mypy_cache .venv -.git .zcompdump* - .vagrant diff --git a/ansible/aur_packages/README.md b/ansible/aur_packages/README.md new file mode 100644 index 0000000..6d31bb6 --- /dev/null +++ b/ansible/aur_packages/README.md @@ -0,0 +1,17 @@ +# Archlinux User Repository (AUR) + +Role to install [Archlinux User Repository (AUR)](https://aur.archlinux.org/packages) packages. + +Add extra packages to the defaults in [vars/main.yml](vars/main.yml) by providing the `aur_extra` variable: + +```yaml +- hosts: all + + vars: + aur_extra: + - bretellofier + - yay + + roles: + - role: aur-packages +``` diff --git a/ansible/aur_packages/meta/main.yml b/ansible/aur_packages/meta/main.yml new file mode 100644 index 0000000..dac1c52 --- /dev/null +++ b/ansible/aur_packages/meta/main.yml @@ -0,0 +1,6 @@ +--- +collections: + # - { name: community.general, version: 3.1.0 } + - community.general +# dependencies: +# - role: yay diff --git a/ansible/aur_packages/tasks/build_package.yml b/ansible/aur_packages/tasks/build_package.yml new file mode 100644 index 0000000..8c03885 --- /dev/null +++ b/ansible/aur_packages/tasks/build_package.yml @@ -0,0 +1,24 @@ +--- +- debug: + msg: "Installing AUR package: {{ package }}" + +- name: Clone package repo + become: true + become_method: sudo + become_user: nobody + git: + repo: "https://aur.archlinux.org/{{ package }}.git" + dest: "/home/build/{{ package }}" + # version: master + clone: true + force: true + +- name: Build package + become: true + become_method: sudo + become_user: nobody + shell: | + cd "/home/build/{{package}}" + makepkg --force --syncdeps --rmdeps --noconfirm --install + environment: + GOCACHE: /tmp/go_cache/ diff --git a/ansible/aur_packages/tasks/main.yml b/ansible/aur_packages/tasks/main.yml new file mode 100644 index 0000000..7f8e60b --- /dev/null +++ b/ansible/aur_packages/tasks/main.yml @@ -0,0 +1,34 @@ +--- +- name: Create build directory + file: + path: "/home/build" + state: directory + mode: "0700" + owner: nobody + +- name: Install aur packages + block: + - name: Allow nobody user to run pacman + community.general.sudoers: + name: allow-nobody-pacman + user: nobody + commands: + - /usr/sbin/pacman + # noexec: true # required by makepkg + state: present + + - name: Install packages + include_tasks: ./build_package.yml + vars: + package: "{{ item }}" + loop: "{{ aur_packages + aur_extra }} " + + always: + - name: Disallow nobody user to run pacman + community.general.sudoers: + name: allow-nobody-pacman + user: nobody + commands: + - /usr/sbin/pacman + noexec: true + state: absent diff --git a/ansible/aur_packages/vars/main.yml b/ansible/aur_packages/vars/main.yml new file mode 100644 index 0000000..fdcf1bf --- /dev/null +++ b/ansible/aur_packages/vars/main.yml @@ -0,0 +1,4 @@ +aur_packages: + - bretellofier + - yay +aur_extra: [] diff --git a/ansible/dotfiles/README.md b/ansible/dotfiles/README.md new file mode 100644 index 0000000..b7db7cf --- /dev/null +++ b/ansible/dotfiles/README.md @@ -0,0 +1,5 @@ +# dotfiles + +Role to install dotfiles and do initial configuration of a new host. + +Installed packages can be found in [vars/main.yml](vars/main.yml). diff --git a/ansible/dotfiles/meta/main.yml b/ansible/dotfiles/meta/main.yml new file mode 100644 index 0000000..8dd5161 --- /dev/null +++ b/ansible/dotfiles/meta/main.yml @@ -0,0 +1,3 @@ +--- +collections: + - community.general diff --git a/ansible/dotfiles/tasks/main.yml b/ansible/dotfiles/tasks/main.yml new file mode 100644 index 0000000..e7e2d14 --- /dev/null +++ b/ansible/dotfiles/tasks/main.yml @@ -0,0 +1,149 @@ +--- +- name: Install required system packages (debian) + apt: + install_recommends: false + update_cache: true + pkg: "{{ packages + packages_debian }}" + state: present + when: ansible_facts['os_family'] == "Debian" + become: true + +- name: Install required system packages (arch) + pacman: + update_cache: true + name: "{{ packages + packages_archlinux }}" + state: present + when: ansible_facts['os_family'] == "Archlinux" + become: true + +- name: Clone dotfiles repo + git: + repo: https://git.decapod.one/brethil/dotfiles + dest: "{{ dotfiles_path }}" + clone: true + update: false + register: git_clone_result + +- debug: + var: git_clone_result['after'] + when: git_clone_result['before'] == "null" + +- name: Update dotfiles repo + git: + repo: https://git.decapod.one/brethil/dotfiles + dest: "{{ dotfiles_path }}" + clone: false + update: false + when: git_clone_result['before'] != "null" + register: git_update_result + +- debug: + var: git_update_result['after'] + when: git_update_result['before'] != "null" + +- name: directories + file: + dest: "{{ item }}" + state: directory + mode: "0700" + loop: "{{ directories }}" + vars: + directories: + - "$HOME/bin" + - "$HOME/projects" + - "$HOME/git" + - "$HOME/.config/git" + - "$HOME/.ssh/" + - "$HOME/.ssh/sockets" + - "$HOME/.ipython/profile_default" + +- name: Set zsh as default shell + user: + name: "{{ ansible_user }}" + shell: /usr/bin/zsh + become: true + +- name: Update zshrc + blockinfile: + path: $HOME/.zshrc + marker: "# {mark} brethil dotfiles" + block: | + export DOTFILES={{ dotfiles_path }} + source $DOTFILES/brethil_dotfile.sh + create: true + mode: 600 + +- name: Update .ssh/config + blockinfile: + path: $HOME/.ssh/config + marker: "# {mark} brethil dotfiles" + insertbefore: "BOF" + block: | + TCPKeepAlive=yes + ServerAliveCountMax=6 + ## Uncomment to enable compression for all ssh sessions + #Compression=yes + + ControlMaster auto + ControlPath ~/.ssh/sockets/%r@%n:%p + ControlPersist yes + + Host * + ServerAliveInterval 300 + create: true + +- name: dotfiles symlinks + file: + src: "{{ dotfiles_path }}/{{ item.key }}" + dest: "{{ item.value }}" + state: link + force: yes + loop: "{{ files | dict2items }}" + vars: + files: + "tmux.conf": "~/.tmux.conf" + "vim/vimrc": "~/.vimrc" + "pdbrc.py": "~/.pdbrc.py" + "gitignore": "~/.config/git/ignore" + "ipython/profile_default/ipython_config.py": "~/.ipython/profile_default/ipython_config.py" + "ipython/profile_default/startup": "~/.ipython/profile_default/startup" + +- name: Exec vim undodir migration (if required) + command: | + mv ${HOME}/.vim_runtime/temp_dirs/undodir ${HOME}/.vim/undo + args: + removes: .vim_runtime/temp_dirs/undodir + +- name: Install and update vim plugins + command: | + vim -c 'PlugInstall|PlugUpdate|qa!' + environment: + - DOTFILES: "{{ dotfiles_path }}" + args: + creates: .vim/vim-plug + +- name: Get git config facts + community.general.git_config: + name: "include.path" + scope: global + register: config_value + +- name: Set up git config include if required + community.general.git_config: + name: "include.path" + value: "{{ dotfiles_path }}/gitconfig" + scope: global + when: config_value is not defined + +- name: check gitignore migration + stat: path=${HOME}/.gitignore + register: gitignore + +- name: gitignore migration + shell: | + set -eu + + mkdir -p ${HOME}/.config/git + ln -s {{ dotfiles_path }}/gitignore ${HOME}/.config/git/ignore + rm -f ~/.gitignore + when: gitignore.stat.exists diff --git a/ansible/ansible-packages.yml b/ansible/dotfiles/vars/main.yml similarity index 80% rename from ansible/ansible-packages.yml rename to ansible/dotfiles/vars/main.yml index 3559210..dddde0e 100644 --- a/ansible/ansible-packages.yml +++ b/ansible/dotfiles/vars/main.yml @@ -1,3 +1,6 @@ +--- +dotfiles_path: "$HOME/.dotfiles" + packages: - "bmon" - "byobu" @@ -7,26 +10,27 @@ packages: - "git" - "grc" - "htop" + - "iotop" - "nmap" - "ripgrep" - "tmux" - "tree" - "vim" - "zsh" - - "iotop" packages_debian: - - "pylint" + - "bat" - "ipython3" + - "mtr-tiny" - "python3-pip" - "python3-setuptools" - "virtualenv" - - "bat" - - "mtr-tiny" packages_archlinux: - - "man" - - "ipython" - - "python-pylint" - - "python-virtualenv" + - "ansible-language-server" - "bash-language-server" + - "base-devel" - "bat" + - "ipython" + - "man" - "mtr" + - "python-virtualenv" + - "sudo" diff --git a/ansible/playbooks/setup.yml b/ansible/playbooks/setup.yml deleted file mode 100644 index b189ab3..0000000 --- a/ansible/playbooks/setup.yml +++ /dev/null @@ -1,137 +0,0 @@ ---- -- name: Setup dotfiles - hosts: all - vars_files: - - ../ansible-packages.yml - vars: - dotfiles_path: "$HOME/.dotfiles" - - tasks: - - name: Install required system packages (debian) - apt: - install_recommends: no - update_cache: yes - pkg: "{{ packages + packages_debian }}" - when: ansible_facts['os_family'] == "Debian" - become: true - - - name: Install required system packages (arch) - pacman: - update_cache: yes - name: "{{ packages + packages_archlinux }}" - when: ansible_facts['os_family'] == "Archlinux" - become: true - - - name: Clone dotfiles repo - git: - repo: https://git.decapod.one/brethil/dotfiles - dest: "{{ dotfiles_path }}" - when: local_development is not defined - - - name: directories - file: - dest: "{{ item }}" - state: directory - mode: 0700 - loop: "{{ directories }}" - vars: - directories: - - "$HOME/bin" - - "$HOME/projects" - - "$HOME/git" - - "$HOME/.config/git" - - "$HOME/.ssh/" - - "$HOME/.ssh/sockets" - - - name: Install antibody - shell: | - set -euo pipefail - curl -sfL https://git.io/antibody | sh -s - -b $HOME/bin/ - $HOME/bin/antibody bundle "{{ dotfiles_path }}/antibody_plugins.txt" - args: - executable: /bin/bash - creates: bin/antibody - - - name: Set zsh as default shell - user: - name: "{{ ansible_user }}" - shell: /usr/bin/zsh - become: true - - - name: Update zshrc - blockinfile: - path: $HOME/.zshrc - marker: "# {mark} brethil dotfiles" - block: | - export DOTFILES={{ dotfiles_path }} - source $DOTFILES/brethil_dotfile.sh - create: true - mode: 600 - - - name: Update .ssh/config - blockinfile: - path: $HOME/.ssh/config - marker: "# {mark} brethil dotfiles" - insertbefore: "BOF" - block: | - TCPKeepAlive=yes - ServerAliveCountMax=6 - ## Uncomment to enable compression for all ssh sessions - #Compression=yes - - ControlMaster auto - ControlPath ~/.ssh/sockets/%r@%n:%p - ControlPersist yes - - Host * - ServerAliveInterval 300 - create: true - - - name: dotfiles symlinks - file: - src: "{{ dotfiles_path }}/{{ item.key }}" - dest: "{{ item.value }}" - state: link - force: yes - loop: "{{ files | dict2items }}" - vars: - files: - "tmux.conf": "~/.tmux.conf" - "vim/vimrc": "~/.vimrc" - "pdbrc.py": "~/.pdbrc.py" - # "ipython": "~/.ipython" # FIXME: ipython config is more complex - "ansible/ansible.cfg": "~/.ansible.cfg" - "gitignore": "~/.config/git/ignore" - - - name: Exec vim undodir migration (if required) - command: | - mv ${HOME}/.vim_runtime/temp_dirs/undodir ${HOME}/.vim/undo - args: - removes: .vim_runtime/temp_dirs/undodir - - - name: Install vim plugins - command: | - env DOTFILES={{ dotfiles_path }} vim -c 'PlugInstall|qa!' - args: - creates: .vim/vim-plug - - - name: Get git config facts - community.general.git_config: - name: "include.path" - scope: global - register: config_value - - debug: - msg: "Git config include.path={{ config_value }}" - - - name: Set up git config include if required - community.general.git_config: - name: "include.path" - value: "{{ dotfiles_path }}/gitconfig" - scope: global - when: config_value is not defined - - - name: git global .gitignore - copy: - src: ../../gitignore - dest: ~/.gitignore - mode: "0600" diff --git a/ansible/playbooks/update.yml b/ansible/playbooks/update.yml deleted file mode 100644 index 4c1e035..0000000 --- a/ansible/playbooks/update.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- -- hosts: all - become: true - vars: - DOTFILES: "$HOME/.dotfiles" - - tasks: - - name: dotfiles - ansible.builtin.command: git pull --rebase --autostash - args: - chdir: "{{ DOTFILES }}" - - - name: antibody - command: antibody update - - - name: vim - ansible.builtin.shell: DOTFILES={{DOTFILES}} vim -c 'PlugUpdate|qa!' - - - name: check gitignore migration - stat: path=${HOME}/.gitignore - register: gitignore - - - name: gitignore migration - command: mkdir -p ${HOME}/.config/git && ln -s ${DOTFILES}/gitignore ${HOME}/.config/git/ignore && rm -f ~/.gitignore - when: gitignore.stat.exists diff --git a/ansible/playbooks/yay.yaml b/ansible/playbooks/yay.yaml deleted file mode 100644 index aed5f11..0000000 --- a/ansible/playbooks/yay.yaml +++ /dev/null @@ -1,49 +0,0 @@ ---- -- hosts: all - - tasks: - - name: Build directory - shell: - cmd: mkdir /home/build - creates: /home/build - register: build_dir - - - name: Prepare build dir - shell: | - chgrp nobody /home/build - chmod g+ws /home/build - when: - - build_dir is defined - - - name: yay repo - become: yes - become_method: sudo - become_user: nobody - git: - repo: https://aur.archlinux.org/yay.git - dest: /home/build/yay - version: master - register: repo - - - name: Install go (yay dependency) - community.general.pacman: - name: - - go - state: present - - - name: build - become: yes - become_method: sudo - become_user: nobody - shell: | - cd /home/build/yay - makepkg - environment: - - GOCACHE: /home/build - - ANSIBLE_REMOTE_TMP: /home/build - - - name: Install yay - community.general.pacman: - name: - - /home/build/yay/yay-*.tar.zst - state: present diff --git a/ansible/yay/tasks/main.yml b/ansible/yay/tasks/main.yml new file mode 100644 index 0000000..fb78cbe --- /dev/null +++ b/ansible/yay/tasks/main.yml @@ -0,0 +1,53 @@ +--- +- name: Create build directory + file: + path: "/home/build" + state: directory + mode: "0700" + owner: nobody + +- name: Make sure requirements are installed + community.general.pacman: + update_cache: yes + name: + - base-devel + - git + - go + - sudo + state: present + become: true + +- name: Clone yay repo + become: true + become_method: sudo + become_user: nobody + git: + repo: https://aur.archlinux.org/yay.git + dest: /home/build/yay + version: master + clone: true + force: true + +- name: build + become: true + become_method: sudo + become_user: nobody + shell: | + cd /home/build/yay + makepkg -f + environment: + - GOCACHE: /tmp/gocache + - ANSIBLE_REMOTE_TMP: /tmp/ansible + +- name: Get built package + shell: | + ls -rt /home/build/yay/yay*.pkg.tar.zst | grep -v debug | tail -1 + register: yay_package + +- debug: + msg: "Built {{ yay_package.stdout }}" + +- name: Install yay + community.general.pacman: + name: "{{ yay_package.stdout }}" + state: present diff --git a/dev/Dockerfile.archlinux b/dev/Dockerfile.archlinux index 80d2ab5..ff10b66 100644 --- a/dev/Dockerfile.archlinux +++ b/dev/Dockerfile.archlinux @@ -1,16 +1,18 @@ FROM archlinux:latest ENV TERM=xterm-256color -RUN pacman --noconfirm -Syu && pacman --noconfirm -Sy \ - python \ - openssh \ - && rm -rf /var/cache/pacman/* +RUN --mount=type=cache,target=/var/cache/pacman \ + pacman --noconfirm -Syu && pacman --noconfirm -Sy \ + python \ + openssh # uncomment to hardcode ssh_host keys in the image # RUN ssh-keygen -A -COPY id_ed25519.pub /root/.ssh/authorized_keys -WORKDIR /root/ -COPY entrypoint.sh / -VOLUME ["/root/.dotfiles"] -CMD ["bash", "/entrypoint.sh"] +WORKDIR /root/.dotfiles + +COPY . . + +RUN cat dev/id_ed25519.pub >> /root/.ssh/authorized_keys + +CMD ["bash", "dev/entrypoint.sh"] diff --git a/dev/Dockerfile.debian b/dev/Dockerfile.debian index da61e5e..a8daaf8 100644 --- a/dev/Dockerfile.debian +++ b/dev/Dockerfile.debian @@ -1,17 +1,20 @@ FROM debian:unstable ENV TERM=xterm-256color -RUN apt-get update && apt-get install -y --no-install-recommends \ - openssh-server \ - python python3 && \ - rm -rf /var/cache/apt/* /etc/ssh/ssh_host_* + +RUN --mount=type=cache,target=/var/cache/apt \ + apt-get update && apt-get install -y --no-install-recommends \ + openssh-server \ + python python3 \ + && rm -rf /etc/ssh/ssh_host_* # ssh host keys are generated by entrypoint, remove rm /etc/ssh/ssh_host* # to hardcode ssh host keys into the image RUN mkdir /run/sshd -COPY id_ed25519.pub /root/.ssh/authorized_keys -WORKDIR /root/ -COPY entrypoint.sh / -VOLUME ["/root/.dotfiles"] -CMD ["bash", "/entrypoint.sh"] +WORKDIR /root/.dotfiles + +COPY . . +RUN cat dev/id_ed25519.pub >> /root/.ssh/authorized_keys + +CMD ["bash", "dev/entrypoint.sh"] diff --git a/dev/Makefile b/dev/Makefile index ef15579..9483271 100644 --- a/dev/Makefile +++ b/dev/Makefile @@ -25,23 +25,33 @@ arch archlinux: clean build-arch run build: build-arch build-debian: Dockerfile.debian - docker build -t brethil/dotfiles:dev -f Dockerfile.debian . + docker build -t brethil/dotfiles:dev -f Dockerfile.debian .. build-arch: Dockerfile.archlinux - docker build -t brethil/dotfiles:dev -f Dockerfile.archlinux . + docker build -t brethil/dotfiles:dev -f Dockerfile.archlinux .. run: _run echo -e ${GREEN} "***" ${CLEAR} Watching logs from the container. Hit Ctrl+C to stop watching. docker logs -f dotfiles-dev -_run: Dockerfile.archlinux Dockerfile.debian build clean - docker run -d --name=dotfiles-dev -v ${PWD}/..:/root/.dotfiles brethil/dotfiles:dev +_run: clean build + # docker run -d --rm --name=dotfiles-dev -v ${PWD}/..:/root/.dotfiles:ro brethil/dotfiles:dev + docker run -d --rm --name=dotfiles-dev brethil/dotfiles:dev echo -en ${GREEN} "***" ${CLEAR} Started container, listening on echo -e ${BOLD}${WHITE} `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' dotfiles-dev`:22 ${CLEAR} - echo -e ${BLUE} "***" ${CLEAR} Run \`make clean\` to stop and remove the container + echo -e ${BLUE} "***" ${CLEAR} Run \`make clean\` to stop and remove the container, \`make run\` to check the logs. -ansible: ../ansible/playbooks/setup.yml _run - ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i ansible-hosts -e local_development=true ../ansible/playbooks/setup.yml + +ansible: SHELL:=/bin/bash +ansible: ../playbook.yml _run + @ip_address=$$(docker inspect dotfiles-dev --format '{{.NetworkSettings.IPAddress}}'); \ + if [[ -z "$$ip_address" ]]; then \ + echo "ip address is not defined, is your container running?" >&2; \ + exit 1; \ + else \ + sed -i "s/172.18.0.2/$$ip_address/" ansible-hosts; \ + ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i ansible-hosts ../playbook.yml; \ + fi release: build-arch ansible docker commit -m "install and initialize dotfiles (ansible)" dotfiles-dev brethil/dotfiles:latest @@ -55,4 +65,4 @@ release: build-arch ansible clean: echo -e ${GREEN} "***" ${CLEAR} Stopping and removing \"dockerfiles-dev\" container... docker kill dotfiles-dev &>/dev/null &>/dev/null && echo -e ${GREEN} "***" ${CLEAR} Killed container: dotfiles-dev || echo -e ${BLUE} "***" ${CLEAR} no containers to stop - docker rm dotfiles-dev &>/dev/null && echo -e ${GREEN} "***" ${CLEAR} Removed container: dotfiles-dev || echo -e ${BLUE} "***" ${CLEAR} no containers to remove + docker stop dotfiles-dev &>/dev/null && echo -e ${GREEN} "***" ${CLEAR} Removed container: dotfiles-dev || echo -e ${BLUE} "***" ${CLEAR} no containers to remove diff --git a/dev/README.md b/dev/README.md index 2333924..01ab100 100644 --- a/dev/README.md +++ b/dev/README.md @@ -16,15 +16,19 @@ Start a builder in one shell: while true; do make _run; done ``` -_check for the docker IP of the started container_. - -Test the playbook in another shell: +Check for the docker IP of the started container: ```bash -ansible-playbook -v -i ./ansible-hosts playbooks/setup.yml +docker inspect dotfiles-dev --format '{{.NetworkSettings.IPAddress}}' ``` -note: the ip address in `ansible-hosts` might have changed from `172.18.0.2`. +Make sure that this matches the IP in [ansible-hosts](/dev/ansible-hosts) + +Test the playbook: + +```bash +ansible-playbook -v -i ansible-hosts ../playbook.yml +``` ## Docker images @@ -41,14 +45,11 @@ the local repository bind-mounted on `/root/.dotfiles`. To use a custom volume: docker run -v :/root/dofiles` ``` -**IMPORTANT** if bind-mounting an already existing repository, run -`ansible` with `-e local_development=true` to avoid -clobbering the git history if you have unpushed commit (it won't -work if your repo is dirty). - Ansible can now be used to test the installation. - make ansible +```bash +make ansible +``` ## Releasing diff --git a/dev/ansible-hosts b/dev/ansible-hosts index 22283ff..ca9377d 100644 --- a/dev/ansible-hosts +++ b/dev/ansible-hosts @@ -1,2 +1,2 @@ -[dev] -172.18.0.2 ansible_user=root ansible_python_interpreter=python3 DOTFILES=~/.dotfiles +[docker] +172.18.0.2 ansible_user=root ansible_python_interpreter=python3 alias=dotfiles_dev_container diff --git a/ansible/ansible.cfg b/dev/ansible.cfg similarity index 76% rename from ansible/ansible.cfg rename to dev/ansible.cfg index d897379..dde61d0 100644 --- a/ansible/ansible.cfg +++ b/dev/ansible.cfg @@ -1,5 +1,8 @@ [defaults] + forks = 10 strategy=free pipelining = true internal_poll_interval = 0.001 + +roles_path = ../ansible diff --git a/playbook.yml b/playbook.yml new file mode 100644 index 0000000..9c83847 --- /dev/null +++ b/playbook.yml @@ -0,0 +1,9 @@ +--- +- hosts: all + + vars: + archlinux: ansible_facts['os_family'] == "Archlinux" + + roles: + - dotfiles + - { role: aur_packages, when: archlinux, tags: ["aur", "aur-packages"] }