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
- }))
-}