Tidy up TF scripts and first run of Ansible configuration. - infra - Terraform IoC for my remote (Hetzner) and local (Incus) servers.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 88aea3aa647f7a1b1e7c69ae731b6e846ba9cf3e
 (DIR) parent 1689e2eba4bdb38eac00a4dc51d5f98335431252
 (HTM) Author: Jay Scott <me@jay.scot>
       Date:   Sat, 28 Jan 2023 20:50:36 +0000
       
       Tidy up TF scripts and first run of Ansible configuration.
       
       Diffstat:
         M README                              |      44 ++++++++++++++++++++++++++++---
         A ansible/group_vars/all.yml          |       3 +++
         A ansible/group_vars/git.yml          |       4 ++++
         A ansible/group_vars/gopher.yml       |      12 ++++++++++++
         A ansible/inventory.yml               |      13 +++++++++++++
         A ansible/main.yml                    |      28 ++++++++++++++++++++++++++++
         A ansible/roles/common/files/sshd_co… |       6 ++++++
         A ansible/roles/common/handlers/main… |       4 ++++
         A ansible/roles/common/tasks/main.yml |      42 +++++++++++++++++++++++++++++++
         A ansible/roles/common/tasks/setup-D… |       5 +++++
         A ansible/roles/common/vars/Debian.y… |       5 +++++
         A ansible/roles/finger/files/list     |       4 ++++
         A ansible/roles/finger/files/log      |       1 +
         A ansible/roles/finger/files/logo.txt |       7 +++++++
         A ansible/roles/finger/files/luser    |      17 +++++++++++++++++
         A ansible/roles/finger/files/nouser   |      11 +++++++++++
         A ansible/roles/finger/tasks/main.yml |      34 +++++++++++++++++++++++++++++++
         A ansible/roles/finger/vars/Debian.y… |       3 +++
         A ansible/roles/git/handlers/main.yml |       6 ++++++
         A ansible/roles/git/tasks/main.yml    |      31 +++++++++++++++++++++++++++++++
         A ansible/roles/git/templates/git-da… |      18 ++++++++++++++++++
         A ansible/roles/git/vars/Debian.yml   |       2 ++
         A ansible/roles/gopher/handlers/main… |      11 +++++++++++
         A ansible/roles/gopher/tasks/main.yml |      58 ++++++++++++++++++++++++++++++
         A ansible/roles/gopher/templates/geo… |      16 ++++++++++++++++
         A ansible/roles/gopher/vars/Debian.y… |       4 ++++
         A ansible/roles/gopher/vars/main.yml  |       5 +++++
         A ansible/roles/stagit/handlers/main… |       5 +++++
         A ansible/roles/stagit/tasks/main.yml |      46 +++++++++++++++++++++++++++++++
         A ansible/roles/stagit/templates/sta… |      32 +++++++++++++++++++++++++++++++
         A ansible/roles/stagit/vars/Debian.y… |       4 ++++
         A ansible/roles/stagit/vars/main.yml  |       5 +++++
         D main.tf                             |      54 -------------------------------
         D terraform.tfvars                    |      41 -------------------------------
         R .terraform.lock.hcl -> terraform/.… |       0 
         A terraform/main.tf                   |      67 +++++++++++++++++++++++++++++++
         A terraform/outputs.tf                |       3 +++
         A terraform/terraform.tfvars          |      45 +++++++++++++++++++++++++++++++
         A terraform/user_data/boot.yml        |      16 ++++++++++++++++
         A terraform/variables.tf              |      21 +++++++++++++++++++++
         D user_data.yml                       |      58 ------------------------------
         D variables.tf                        |      25 -------------------------
       
       42 files changed, 635 insertions(+), 181 deletions(-)
       ---
 (DIR) diff --git a/README b/README
       @@ -1,4 +1,42 @@
       -bootstrap my cloud servers.
        
       -        terraform plan -var="hcloud_token=$HCLOUD_TOKEN"
       -        terraform apply -var="hcloud_token=$HCLOUD_TOKEN"
       +Terraform
       +=========
       +
       +
       +Bootstrap my hetzner cloud servers. If you actually want to use this for
       +yourself then you might need to do the following depending on your
       +requirements.
       +
       +
       + : Change the location of you backend in terraform.tf
       + : Update terraform.tfvars to suit.
       + : Export you personal API token to $HCLOUD_TOKEN
       +
       +
       +        export HCLOUD_TOKEN='thisismylongasstoken'
       +
       +
       +The user_data script is a standard cloud-init yaml config that creates
       +an ansible user for configuring the instances.
       +
       +        terraform plan
       +        terraform apply
       +
       +
       +Ansible
       +=======
       +
       +Playbook to install the following:
       +
       +  gopher
       +  git and git daemon
       +  stagit-gopher
       +  efingerd
       +
       +Apply all:
       +
       +        ansible-playbook -i inventory.yml main.yml
       +
       +Run tags
       +
       +        ansible-playbook -i inventory.yml main.yml --tags <git/gopher/common>
 (DIR) diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
       @@ -0,0 +1,3 @@
       +default:
       +  username: jay
       +  comment: Jay Scott
 (DIR) diff --git a/ansible/group_vars/git.yml b/ansible/group_vars/git.yml
       @@ -0,0 +1,4 @@
       +git:
       +  user: git
       +  group: users
       +  base_path: /srv/git
 (DIR) diff --git a/ansible/group_vars/gopher.yml b/ansible/group_vars/gopher.yml
       @@ -0,0 +1,12 @@
       +geomyidae:
       +  user: jay
       +  group: users
       +  root_path: /srv/gopher
       +  git_branch: v0.69
       +
       +stagit_gopher:
       +  git_branch: 1.2
       +  cron_user: jay
       +  cron_group: users
       +  output_path: /srv/gopher
       +  repo_path: /srv/git
 (DIR) diff --git a/ansible/inventory.yml b/ansible/inventory.yml
       @@ -0,0 +1,13 @@
       +all:
       +  vars:
       +    ansible_user: ansible
       +  children:
       +    finger:
       +      hosts:
       +        jay.scot
       +    gopher:
       +      hosts:
       +        jay.scot
       +    git:
       +      hosts:
       +        jay.scot
 (DIR) diff --git a/ansible/main.yml b/ansible/main.yml
       @@ -0,0 +1,28 @@
       +- hosts: all
       +  become: true
       +  roles:
       +    - role: common
       +  tags:
       +    - common
       +
       +- hosts: git
       +  become: true
       +  roles:
       +    - role: git
       +  tags:
       +    - git
       +
       +- hosts: gopher
       +  become: true
       +  roles:
       +    - role: gopher
       +    - role: stagit
       +  tags:
       +    - gopher
       +
       +- hosts: finger
       +  become: true
       +  roles:
       +    - role: finger
       +  tags:
       +    - finger
 (DIR) diff --git a/ansible/roles/common/files/sshd_config b/ansible/roles/common/files/sshd_config
       @@ -0,0 +1,6 @@
       +PasswordAuthentication no
       +ChallengeResponseAuthentication no
       +UsePAM yes
       +X11Forwarding no
       +Subsystem sftp        /usr/lib/openssh/sftp-server
       +PermitRootLogin no
 (DIR) diff --git a/ansible/roles/common/handlers/main.yml b/ansible/roles/common/handlers/main.yml
       @@ -0,0 +1,4 @@
       +- name: Restart sshd
       +  ansible.builtin.service:
       +    name: sshd
       +    state: restart
 (DIR) diff --git a/ansible/roles/common/tasks/main.yml b/ansible/roles/common/tasks/main.yml
       @@ -0,0 +1,42 @@
       +---
       +
       +- name: Include OS-specific variables
       +  ansible.builtin.include_vars: "{{ ansible_os_family }}.yml"
       +
       +- name: Include OS-specfic tasks
       +  ansible.builtin.include_tasks: "setup-{{ ansible_os_family }}.yml"
       +
       +- name: Install Common Packages
       +  ansible.builtin.package:
       +    name: "{{ common_packages }}"
       +    state: present
       +
       +- name: Add hardened SSH config
       +  ansible.builtin.copy:
       +    dest: /etc/ssh/sshd_config
       +    src: sshd_config
       +    owner: root
       +    group: root
       +    mode: 0600
       +  notify: Restart sshd
       +
       +- name: Add default user
       +  ansible.builtin.user:
       +    name: "{{ default.username }}"
       +    comment: "{{ default.comment }}"
       +    shell: /bin/bash
       +    group: users
       +
       +- name: Set authorized key
       +  ansible.posix.authorized_key:
       +    user: "{{ default.username }}"
       +    state: present
       +    key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"
       +
       +- name: Add default user to sudo
       +  community.general.sudoers:
       +    name: "local-{{ default.username }}"
       +    user: "{{ default.username }}"
       +    state: present
       +    nopassword: true
       +    commands: ALL
 (DIR) diff --git a/ansible/roles/common/tasks/setup-Debian.yml b/ansible/roles/common/tasks/setup-Debian.yml
       @@ -0,0 +1,5 @@
       +- name: Update apt cache.
       +  ansible.builtin.apt:
       +    update_cache: true
       +    upgrade: true
       +    cache_valid_time: 3600
 (DIR) diff --git a/ansible/roles/common/vars/Debian.yml b/ansible/roles/common/vars/Debian.yml
       @@ -0,0 +1,5 @@
       +common_packages:
       +  - htop
       +  - vim
       +  - finger
       +  - lynx
 (DIR) diff --git a/ansible/roles/finger/files/list b/ansible/roles/finger/files/list
       @@ -0,0 +1,4 @@
       +#!/bin/sh
       +
       +cat "/etc/efingerd/logo.txt"
       +printf "\nusers:\n\t%s\n" "$(who -uw | cut -d " " -f 1 | sort | uniq)"
 (DIR) diff --git a/ansible/roles/finger/files/log b/ansible/roles/finger/files/log
       @@ -0,0 +1 @@
       +# nope, no logs
 (DIR) diff --git a/ansible/roles/finger/files/logo.txt b/ansible/roles/finger/files/logo.txt
       @@ -0,0 +1,7 @@
       +     ___  _______  __   __        _______  _______  _______  _______
       +    |   ||   _   ||  | |  |      |       ||       ||       ||       |
       +    |   ||  |_|  ||  |_|  |      |  _____||       ||   _   ||_     _|
       +    |   ||       ||       |      | |_____ |       ||  | |  |  |   |
       + ___|   ||       ||_     _| ___  |_____  ||      _||  |_|  |  |   |
       +|       ||   _   |  |   |  |   |  _____| ||     |_ |       |  |   |
       +|_______||__| |__|  |___|  |___| |_______||_______||_______|  |___|
 (DIR) diff --git a/ansible/roles/finger/files/luser b/ansible/roles/finger/files/luser
       @@ -0,0 +1,17 @@
       +#!/bin/sh
       +
       +if [ "$3" = "root" ]; then
       +        printf "Yeah, not going to happen."
       +elif [ "$3" = "git" ]; then
       +        printf "I am not a git, you are!"
       +else
       +        user_folder="/home/${3}"
       +
       +        if [ -f "${user_folder}/finger.txt" ]; then
       +                printf "\n"
       +                cat "${user_folder}/finger.txt"
       +                printf "\n"
       +        fi
       +fi
       +
       +exit 0
 (DIR) diff --git a/ansible/roles/finger/files/nouser b/ansible/roles/finger/files/nouser
       @@ -0,0 +1,11 @@
       +#!/bin/sh
       +
       +cat <<EOM
       +
       +You tried to finger non-existent user!!!
       +Your attempt is logged and sent to Scotland Yard, MI5 and the DLVA..
       +
       +Expect a visit soon.
       +
       +Just joking, it went to /dev/null
       +EOM
 (DIR) diff --git a/ansible/roles/finger/tasks/main.yml b/ansible/roles/finger/tasks/main.yml
       @@ -0,0 +1,34 @@
       +---
       +- name: Include OS-specific variables
       +  ansible.builtin.include_vars: "{{ ansible_os_family }}.yml"
       +
       +- name: Install required packages
       +  ansible.builtin.package:
       +    name: "{{ common_packages }}"
       +    state: present
       +
       +- name: Create efingerd config directory
       +  ansible.builtin.file:
       +    path: /etc/efingerd
       +    state: directory
       +    mode: '0755'
       +
       +- name: Copy efingerd scripts
       +  ansible.builtin.copy:
       +    src: "{{ item }}"
       +    dest: "/etc/efingerd/{{ item }}"
       +    owner: root
       +    group: root
       +    mode: '0755'
       +  loop:
       +    - list
       +    - logo.txt
       +    - log
       +    - luser
       +    - nouser
       +
       +- name: Enable inetd
       +  ansible.builtin.systemd:
       +    name: inetd
       +    state: started
       +    daemon_reload: true
 (DIR) diff --git a/ansible/roles/finger/vars/Debian.yml b/ansible/roles/finger/vars/Debian.yml
       @@ -0,0 +1,3 @@
       +common_packages:
       +  - openbsd-inetd
       +  - efingerd
 (DIR) diff --git a/ansible/roles/git/handlers/main.yml b/ansible/roles/git/handlers/main.yml
       @@ -0,0 +1,6 @@
       +---
       +- name: Restart git-daemon
       +  ansible.builtin.systemd:
       +    name: git-daemon
       +    state: started
       +    daemon_reload: true
 (DIR) diff --git a/ansible/roles/git/tasks/main.yml b/ansible/roles/git/tasks/main.yml
       @@ -0,0 +1,31 @@
       +---
       +- name: Include OS-specific variables
       +  ansible.builtin.include_vars: "{{ ansible_os_family }}.yml"
       +
       +- name: Install required packages
       +  ansible.builtin.package:
       +    name: "{{ common_packages }}"
       +    state: present
       +
       +- name: Added git service account
       +  ansible.builtin.user:
       +    name: "{{ git.user }}"
       +    comment: "Git Service Account"
       +    home: "{{ git.base_path }}"
       +    shell: /usr/bin/git-shell
       +    group: "{{ git.group }}"
       +
       +- name: Set initial authorized key
       +  ansible.posix.authorized_key:
       +    user: git
       +    state: present
       +    key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"
       +
       +- name: Create systemd service file
       +  ansible.builtin.template:
       +    src: templates/git-daemon.service.j2
       +    dest: /lib/systemd/system/git-daemon.service
       +    owner: root
       +    group: root
       +    mode: "0644"
       +  notify: Restart git-daemon
 (DIR) diff --git a/ansible/roles/git/templates/git-daemon.service.j2 b/ansible/roles/git/templates/git-daemon.service.j2
       @@ -0,0 +1,18 @@
       +[Unit]
       +Description=Start Git Daemon
       +
       +[Service]
       +ExecStart=/usr/bin/git daemon --reuseaddr --base-path={{ git.base_path }} {{ git.base_path }}
       +
       +Restart=always
       +RestartSec=500ms
       +
       +StandardOutput=syslog
       +StandardError=syslog
       +SyslogIdentifier=git-daemon
       +
       +User={{ git.user }}
       +Group={{ git.group }}
       +
       +[Install]
       +WantedBy=multi-user.target
 (DIR) diff --git a/ansible/roles/git/vars/Debian.yml b/ansible/roles/git/vars/Debian.yml
       @@ -0,0 +1,2 @@
       +common_packages:
       +  - git
 (DIR) diff --git a/ansible/roles/gopher/handlers/main.yml b/ansible/roles/gopher/handlers/main.yml
       @@ -0,0 +1,11 @@
       +---
       +- name: Restart geomyidae
       +  ansible.builtin.systemd:
       +    name: geomyidae
       +    state: started
       +    daemon_reload: true
       +
       +- name: Install geomyidae
       +  community.general.system.make:
       +    chdir: "{{ build_path }}"
       +    target: install
 (DIR) diff --git a/ansible/roles/gopher/tasks/main.yml b/ansible/roles/gopher/tasks/main.yml
       @@ -0,0 +1,58 @@
       +---
       +- name: Include OS-specific variables.
       +  ansible.builtin.include_vars: "{{ ansible_os_family }}.yml"
       +
       +- name: Install required packages
       +  ansible.builtin.package:
       +    name: "{{ common_packages }}"
       +    state: present
       +
       +- name: Git checkout
       +  ansible.builtin.git:
       +    repo: "{{ source_repo }}"
       +    dest: "{{ build_path }}"
       +    force: false
       +    version: "{{ geomyidae.git_branch }}"
       +  register: repo_clone
       +  failed_when:
       +    - repo_clone.failed
       +    - not 'Local modifications exist in the destination' in repo_clone.msg
       +
       +- name: Disable TLS options
       +  ansible.builtin.replace:
       +    path: "{{ build_path }}/Makefile"
       +    regexp: '^TLS_CFLAGS = -DENABLE_TLS'
       +    replace: '#TLS_CFLAGS = -DENABLE_TLS'
       +  when: disable_tls
       +
       +- name: Disable TLS flags
       +  ansible.builtin.replace:
       +    path: "{{ build_path }}/Makefile"
       +    regexp: '^TLS_LDFLAGS = -ltls'
       +    replace: '#TLS_LDFLAGS = -ltls'
       +  when: disable_tls
       +
       +- name: Build geomyidae
       +  community.general.system.make:
       +    chdir: "{{ build_path }}"
       +  notify: Install geomyidae
       +
       +- name: Flush handlers
       +  ansible.builtin.meta: flush_handlers
       +
       +- name: Create root directory
       +  ansible.builtin.file:
       +    path: "{{ geomyidae.root_path }}"
       +    owner: "{{ geomyidae.user }}"
       +    group: "{{ geomyidae.group }}"
       +    mode: 0755
       +    state: directory
       +
       +- name: Create systemd service file
       +  ansible.builtin.template:
       +    src: templates/geomyidae.service.j2
       +    dest: /lib/systemd/system/geomyidae.service
       +    owner: root
       +    group: root
       +    mode: '0644'
       +  notify: Restart geomyidae
 (DIR) diff --git a/ansible/roles/gopher/templates/geomyidae.service.j2 b/ansible/roles/gopher/templates/geomyidae.service.j2
       @@ -0,0 +1,16 @@
       +[Unit]
       +Description=Geomyidae Gopher Server
       +After=network.target
       +Wants=network.target
       +StartLimitBurst=5
       +StartLimitIntervalSec=1
       +
       +[Service]
       +Type=forking
       +Restart=on-abnormal
       +RestartSec=1
       +User=root
       +ExecStart=/usr/local/bin/geomyidae -v 0 -b {{ geomyidae.root_path }} -p 70 -e -n -u {{ geomyidae.user }} -g {{ geomyidae.group }}
       +
       +[Install]
       +WantedBy=multi-user.target
 (DIR) diff --git a/ansible/roles/gopher/vars/Debian.yml b/ansible/roles/gopher/vars/Debian.yml
       @@ -0,0 +1,4 @@
       +common_packages:
       +  - git
       +  - build-essential
       +  - libssl-dev
 (DIR) diff --git a/ansible/roles/gopher/vars/main.yml b/ansible/roles/gopher/vars/main.yml
       @@ -0,0 +1,5 @@
       +---
       +
       +build_path: /tmp/src/geomyidae
       +source_repo: git://r-36.net/geomyidae
       +disable_tls: true
 (DIR) diff --git a/ansible/roles/stagit/handlers/main.yml b/ansible/roles/stagit/handlers/main.yml
       @@ -0,0 +1,5 @@
       +---
       +- name: Install stagit
       +  community.general.system.make:
       +    chdir: "{{ build_path }}"
       +    target: install
 (DIR) diff --git a/ansible/roles/stagit/tasks/main.yml b/ansible/roles/stagit/tasks/main.yml
       @@ -0,0 +1,46 @@
       +---
       +- name: Include OS-specific variables.
       +  ansible.builtin.include_vars: "{{ ansible_os_family }}.yml"
       +
       +- name: Install required packages
       +  ansible.builtin.package:
       +    name: "{{ common_packages }}"
       +    state: present
       +
       +- name: Git checkout
       +  ansible.builtin.git:
       +    repo: "{{ source_repo }}"
       +    dest: "{{ build_path }}"
       +    force: false
       +    version: "{{ stagit_gopher.git_branch }}"
       +  register: repo_clone
       +  failed_when:
       +    - repo_clone.failed
       +    - not 'Local modifications exist in the destination' in repo_clone.msg
       +
       +- name: Enable old libgit2 workaround
       +  ansible.builtin.replace:
       +    path: "{{ build_path }}/Makefile"
       +    regexp: '^#STAGIT_CFLAGS'
       +    replace: 'STAGIT_CFLAGS'
       +  when: enable_old_libgit2
       +
       +- name: Build from source
       +  community.general.system.make:
       +    chdir: "{{ build_path }}"
       +  notify: Install stagit
       +
       +- name: Create stagit run script
       +  ansible.builtin.template:
       +    src: templates/stagit_create.sh.j2
       +    dest: "/home/{{ stagit_gopher.cron_user }}/stagit_create.sh"
       +    owner: "{{ stagit_gopher.cron_user }}"
       +    group: "{{ stagit_gopher.cron_group }}"
       +    mode: "755"
       +
       +- name: Adding script to cron
       +  ansible.builtin.cron:
       +    name: "run stagit script"
       +    user: "{{ stagit_gopher.cron_user }}"
       +    minute: "0"
       +    job: "/home/{{ stagit_gopher.cron_user }}/stagit_create.sh"
 (DIR) diff --git a/ansible/roles/stagit/templates/stagit_create.sh.j2 b/ansible/roles/stagit/templates/stagit_create.sh.j2
       @@ -0,0 +1,32 @@
       +#!/bin/sh
       +
       +reposdir="{{ stagit_gopher.repo_path }}"
       +gopherdir="{{ stagit_gopher.output_path }}"
       +stagitdir="git/"
       +destdir="${gopherdir}/${stagitdir}"
       +
       +# remove /'s at the end.
       +stagitdir=$(printf "%s" "${stagitdir}" | sed 's@[/]*$@@g')
       +
       +rm -rf "{{ stagit_gopher.output_path }}/git/*"
       +
       +# make index.
       +/usr/local/bin/stagit-gopher-index -b "${stagitdir}" "${reposdir}/"*/ >"${destdir}/index.gph"
       +
       +# make files per repo.
       +for dir in "${reposdir}/"*/; do
       +        # strip .git suffix.
       +        r=$(basename "${dir}")
       +        d=$(basename "${dir}" ".git")
       +        printf "%s... " "${d}"
       +
       +        mkdir -p "${destdir}/${d}"
       +        cd "${destdir}/${d}" || continue
       +        /usr/local/bin/stagit-gopher -b "${stagitdir}/${d}" -c ".cache" \
       +                -u "gopher://jay.scot/1/git/$d/" "${reposdir}/${r}"
       +
       +        # symlinks
       +        ln -sf log.gph index.gph
       +
       +        echo "done"
       +done
 (DIR) diff --git a/ansible/roles/stagit/vars/Debian.yml b/ansible/roles/stagit/vars/Debian.yml
       @@ -0,0 +1,4 @@
       +common_packages:
       +  - git
       +  - build-essential
       +  - libgit2-dev
 (DIR) diff --git a/ansible/roles/stagit/vars/main.yml b/ansible/roles/stagit/vars/main.yml
       @@ -0,0 +1,5 @@
       +---
       +
       +build_path: /tmp/src/stagit-gopher
       +source_repo: git://git.codemadness.org/stagit-gopher
       +enable_old_libgit2: true
 (DIR) diff --git a/main.tf b/main.tf
       @@ -1,54 +0,0 @@
       -terraform {
       -  required_providers {
       -    hcloud = {
       -      source  = "hetznercloud/hcloud"
       -      version = "1.36.2"
       -    }
       -  }
       -}
       -
       -provider "hcloud" {
       -  token = var.hcloud_token
       -}
       -
       -
       -resource "hcloud_ssh_key" "this" {
       -  name       = "main_key"
       -  public_key = file("~/.ssh/id_rsa.pub")
       -}
       -
       -
       -resource "hcloud_firewall" "this" {
       -  name = "firewallrules"
       -
       -  dynamic "rule" {
       -    for_each = var.firewall_rules
       -
       -    content {
       -      description = rule.key
       -      direction   = rule.value.direction
       -      protocol    = rule.value.protocol
       -      source_ips  = rule.value.source_ips
       -      port        = rule.value.port
       -    }
       -  }
       -}
       -
       -
       -resource "hcloud_server" "nodes" {
       -  for_each = var.nodes
       -
       -  name         = each.key
       -  image        = each.value.image
       -  server_type  = each.value.server_type
       -  location     = each.value.location
       -  labels       = each.value.labels
       -  ssh_keys     = [hcloud_ssh_key.this.id]
       -  user_data    = file("user_data.yml")
       -  firewall_ids = [hcloud_firewall.this.id]
       -
       -  public_net {
       -    ipv4_enabled = each.value.ipv4
       -    ipv6_enabled = each.value.ipv6
       -  }
       -}
 (DIR) diff --git a/terraform.tfvars b/terraform.tfvars
       @@ -1,41 +0,0 @@
       -nodes = {
       -  node1 = {
       -    image       = "debian-11"
       -    location    = "hel1",
       -    server_type = "cx11",
       -    ipv4        = true
       -    ipv6        = true
       -    labels = {
       -      services = "git"
       -    }
       -  }
       -}
       -
       -firewall_rules = {
       -  gopher = {
       -    direction  = "in"
       -    protocol   = "tcp"
       -    source_ips = ["0.0.0.0/0", "::/0"]
       -    port       = "70"
       -  }
       -  ssh = {
       -    direction  = "in"
       -    protocol   = "tcp"
       -    source_ips = ["0.0.0.0/0", "::/0"]
       -    port       = "22"
       -  }
       -  git = {
       -    direction  = "in"
       -    protocol   = "tcp"
       -    source_ips = ["0.0.0.0/0", "::/0"]
       -    port       = "9418"
       -  }
       -  fingerd = {
       -    direction  = "in"
       -    protocol   = "tcp"
       -    source_ips = ["0.0.0.0/0", "::/0"]
       -    port       = "79"
       -  }
       -
       -
       -}
 (DIR) diff --git a/.terraform.lock.hcl b/terraform/.terraform.lock.hcl
 (DIR) diff --git a/terraform/main.tf b/terraform/main.tf
       @@ -0,0 +1,67 @@
       +terraform {
       +  required_providers {
       +    hcloud = {
       +      source  = "hetznercloud/hcloud"
       +      version = "1.36.2"
       +    }
       +  }
       +
       +  backend "local" {
       +    path = "/home/jay/.config/infra/terraform.tfstate"
       +  }
       +
       +}
       +
       +resource "hcloud_ssh_key" "this" {
       +  for_each = var.public_ssh_keys
       +
       +  name       = each.key
       +  public_key = file(each.value)
       +}
       +
       +
       +resource "hcloud_firewall" "this" {
       +  for_each = var.nodes
       +
       +  name = each.key
       +
       +  dynamic "rule" {
       +    for_each = each.value.firewall_rules
       +
       +    content {
       +      description = rule.key
       +      direction   = rule.value.direction
       +      protocol    = rule.value.protocol
       +      source_ips  = rule.value.source_ips
       +      port        = rule.value.port
       +    }
       +  }
       +}
       +
       +
       +resource "hcloud_server" "this" {
       +  for_each = var.nodes
       +
       +  name         = each.key
       +  image        = each.value.image
       +  server_type  = each.value.server_type
       +  location     = each.value.location
       +  labels       = each.value.labels
       +  ssh_keys     = [hcloud_ssh_key.this[each.value.public_key].id]
       +  user_data    = file(each.value.user_data)
       +  firewall_ids = [hcloud_firewall.this[each.key].id]
       +
       +  public_net {
       +    ipv4_enabled = each.value.ipv4
       +    ipv6_enabled = each.value.ipv6
       +  }
       +}
       +
       +resource "hcloud_rdns" "this" {
       +  for_each = hcloud_server.this
       +
       +  server_id  = each.value.id
       +  ip_address = each.value.ipv4_address
       +  dns_ptr    = var.nodes[each.key].reverse_dns
       +}
       +
 (DIR) diff --git a/terraform/outputs.tf b/terraform/outputs.tf
       @@ -0,0 +1,3 @@
       +output "public_ip_address" {
       +  value = {for name, server in hcloud_server.this: name => server.ipv4_address}
       +}
 (DIR) diff --git a/terraform/terraform.tfvars b/terraform/terraform.tfvars
       @@ -0,0 +1,45 @@
       +public_ssh_keys = {
       +  main_key = "~/.ssh/id_rsa.pub"
       +}
       +
       +nodes = {
       +  "jay.scot" = {
       +    image       = "debian-11"
       +    location    = "hel1",
       +    server_type = "cx11",
       +    reverse_dns = "jay.scot"
       +    user_data   = "user_data/boot.yml"
       +    public_key  = "main_key"
       +    firewall_rules = {
       +      gopher = {
       +        direction  = "in"
       +        protocol   = "tcp"
       +        source_ips = ["0.0.0.0/0", "::/0"]
       +        port       = "70"
       +      }
       +      ssh = {
       +        direction  = "in"
       +        protocol   = "tcp"
       +        source_ips = ["0.0.0.0/0", "::/0"]
       +        port       = "22"
       +      }
       +      git = {
       +        direction  = "in"
       +        protocol   = "tcp"
       +        source_ips = ["0.0.0.0/0", "::/0"]
       +        port       = "9418"
       +      }
       +      fingerd = {
       +        direction  = "in"
       +        protocol   = "tcp"
       +        source_ips = ["0.0.0.0/0", "::/0"]
       +        port       = "79"
       +      }
       +    }
       +    ipv4 = true
       +    ipv6 = true
       +    labels = {
       +      git = "true"
       +    }
       +  }
       +}
 (DIR) diff --git a/terraform/user_data/boot.yml b/terraform/user_data/boot.yml
       @@ -0,0 +1,16 @@
       +#cloud-config
       +
       +# disable ssh password authentication
       +ssh_pwauth: false
       +
       +# TODO: add in a ansible pull on boot at somepoint.
       +# add an ansible user
       +users:
       +  - name: ansible
       +    gecos: Ansible User
       +    groups: users,wheel
       +    sudo: ALL=(ALL) NOPASSWD:ALL
       +    shell: /bin/bash
       +    lock_passwd: true
       +    ssh_authorized_keys:
       +    - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCRWnkYAChsjuT/T/IoENtm8OT18tPereaw6OOqmZ5Kvx2W8wCLL8zaBK1ieYRTeDfNU6cnAEkZdn0B2/twWvDLwyTihkWKa6FxdZ8Pv+4BEDhUS5jpxUhpBbLMOKu1SRTu9cr3jv7CcK90ouMes4d9Mnm76C0yskCBTiXdNKZ0LEYf+7hbRN1UnF9tG+RNHpnqx/3uKSWEjAEwu0lXLzOsJhNZMUXaruoKVohvRS1h9C3CT5SKWjhVX7f0oVWtSt4BhExO9B4lOgfPFZ46Aj+AsFffk2TluQq9ChdJXmSxd6OBRUae4KuX4QykHty9cU+63O45PZp92Ay8Gk5tlSqlFn2DUc4gU68CKcAwQSM018ASQiWou4Gw9Dq8sKa6R1HIi7X3marVJW/wKLu7xFyIiWYddyUGNhuINpj+vx0fk5ET+dE+5i43kM6YVWSAyazyGRhholPFFh7y4+FbdG+lkMnU9ScvnB8j0nTMOptu9HwIAVhVqHK1s+aJgRp4QU= jay@elma.jay.scot
 (DIR) diff --git a/terraform/variables.tf b/terraform/variables.tf
       @@ -0,0 +1,21 @@
       +
       +variable "public_ssh_keys" {
       +  description = "Public SSH key location to attach to instance."
       +  type        = map(any)
       +}
       +
       +variable "nodes" {
       +  description = "Configuration settings for each required node."
       +  type = map(object({
       +    image          = string
       +    location       = string
       +    server_type    = string
       +    reverse_dns    = string
       +    user_data      = string
       +    public_key     = string
       +    labels         = map(any)
       +    firewall_rules = map(any)
       +    ipv4           = bool
       +    ipv6           = bool
       +  }))
       +}
 (DIR) diff --git a/user_data.yml b/user_data.yml
       @@ -1,58 +0,0 @@
       -#cloud-config
       -users:
       -  - name: jay
       -    groups: users
       -    sudo: ALL=(ALL) NOPASSWD:ALL
       -    shell: /bin/bash
       -    ssh_authorized_keys:
       -      - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCRWnkYAChsjuT/T/IoENtm8OT18tPereaw6OOqmZ5Kvx2W8wCLL8zaBK1ieYRTeDfNU6cnAEkZdn0B2/twWvDLwyTihkWKa6FxdZ8Pv+4BEDhUS5jpxUhpBbLMOKu1SRTu9cr3jv7CcK90ouMes4d9Mnm76C0yskCBTiXdNKZ0LEYf+7hbRN1UnF9tG+RNHpnqx/3uKSWEjAEwu0lXLzOsJhNZMUXaruoKVohvRS1h9C3CT5SKWjhVX7f0oVWtSt4BhExO9B4lOgfPFZ46Aj+AsFffk2TluQq9ChdJXmSxd6OBRUae4KuX4QykHty9cU+63O45PZp92Ay8Gk5tlSqlFn2DUc4gU68CKcAwQSM018ASQiWou4Gw9Dq8sKa6R1HIi7X3marVJW/wKLu7xFyIiWYddyUGNhuINpj+vx0fk5ET+dE+5i43kM6YVWSAyazyGRhholPFFh7y4+FbdG+lkMnU9ScvnB8j0nTMOptu9HwIAVhVqHK1s+aJgRp4QU= jay@elma.jay.scot
       -
       -package_update: true
       -package_upgrade: true
       -
       -packages:
       -  - openbsd-inetd
       -  - efingerd
       -  - libgit2-dev
       -  - vim
       -  - htop
       -  - git
       -
       -runcmd:
       -  # SSH config
       -  - sed -ie '/^PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config
       -  - sed -ie '/^PasswordAuthentication/s/^.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
       -  - sed -ie '/^X11Forwarding/s/^.*$/X11Forwarding no/' /etc/ssh/sshd_config
       -  - sed -ie '/^#MaxAuthTries/s/^.*$/MaxAuthTries 2/' /etc/ssh/sshd_config
       -  - sed -ie '/^#AllowTcpForwarding/s/^.*$/AllowTcpForwarding no/' /etc/ssh/sshd_config
       -  - sed -ie '/^#AllowAgentForwarding/s/^.*$/AllowAgentForwarding no/' /etc/ssh/sshd_config
       -  - sed -ie '/^#AuthorizedKeysFile/s/^.*$/AuthorizedKeysFile .ssh/authorized_keys/' /etc/ssh/sshd_config
       -  - systemctl restart ssh
       -  # Git setup
       -  - mkdir -p /srv/git
       -  - chown -R git:git /srv/git
       -  - systemctl enable git-daemon
       -  - systemctl start git-daemon
       -
       -write_files:
       -  - content: |
       -      [Unit]
       -      Description=Start Git Daemon
       -
       -      [Service]
       -      ExecStart=/usr/bin/git daemon --reuseaddr --base-path=/srv/git/ /srv/git/
       -
       -      Restart=always
       -      RestartSec=500ms
       -
       -      StandardOutput=syslog
       -      StandardError=syslog
       -      SyslogIdentifier=git-daemon
       -
       -      User=git
       -      Group=git
       -
       -      [Install]
       -      WantedBy=multi-user.target
       -    path: /etc/systemd/system/git-daemon.service
       -    permissions: '0644'
 (DIR) diff --git a/variables.tf b/variables.tf
       @@ -1,25 +0,0 @@
       -variable "hcloud_token" {
       -  description = "Hetzner cloud personal API token."
       -  type        = string
       -  sensitive   = true
       -}
       -
       -variable "nodes" {
       -  type = map(object({
       -    image       = string
       -    location    = string
       -    server_type = string
       -    labels      = map(any)
       -    ipv4        = bool
       -    ipv6        = bool
       -  }))
       -}
       -
       -variable "firewall_rules" {
       -  type = map(object({
       -    direction  = string
       -    protocol   = string
       -    source_ips = list(any)
       -    port       = string
       -  }))
       -}