Tidy up TF scripts and first run of Ansible configuration. - infrastructure - U… | |
Log | |
Files | |
Refs | |
README | |
--- | |
commit 88aea3aa647f7a1b1e7c69ae731b6e846ba9cf3e | |
parent 1689e2eba4bdb38eac00a4dc51d5f98335431252 | |
Author: Jay Scott <[email protected]> | |
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(-) | |
--- | |
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> | |
diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml | |
@@ -0,0 +1,3 @@ | |
+default: | |
+ username: jay | |
+ comment: Jay Scott | |
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 | |
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 | |
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 | |
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 | |
diff --git a/ansible/roles/common/files/sshd_config b/ansible/roles/common/file… | |
@@ -0,0 +1,6 @@ | |
+PasswordAuthentication no | |
+ChallengeResponseAuthentication no | |
+UsePAM yes | |
+X11Forwarding no | |
+Subsystem sftp /usr/lib/openssh/sftp-server | |
+PermitRootLogin no | |
diff --git a/ansible/roles/common/handlers/main.yml b/ansible/roles/common/hand… | |
@@ -0,0 +1,4 @@ | |
+- name: Restart sshd | |
+ ansible.builtin.service: | |
+ name: sshd | |
+ state: restart | |
diff --git a/ansible/roles/common/tasks/main.yml b/ansible/roles/common/tasks/m… | |
@@ -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 | |
diff --git a/ansible/roles/common/tasks/setup-Debian.yml b/ansible/roles/common… | |
@@ -0,0 +1,5 @@ | |
+- name: Update apt cache. | |
+ ansible.builtin.apt: | |
+ update_cache: true | |
+ upgrade: true | |
+ cache_valid_time: 3600 | |
diff --git a/ansible/roles/common/vars/Debian.yml b/ansible/roles/common/vars/D… | |
@@ -0,0 +1,5 @@ | |
+common_packages: | |
+ - htop | |
+ - vim | |
+ - finger | |
+ - lynx | |
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)" | |
diff --git a/ansible/roles/finger/files/log b/ansible/roles/finger/files/log | |
@@ -0,0 +1 @@ | |
+# nope, no logs | |
diff --git a/ansible/roles/finger/files/logo.txt b/ansible/roles/finger/files/l… | |
@@ -0,0 +1,7 @@ | |
+ ___ _______ __ __ _______ _______ _______ _______ | |
+ | || _ || | | | | || || || | | |
+ | || |_| || |_| | | _____|| || _ ||_ _| | |
+ | || || | | |_____ | || | | | | | | |
+ ___| || ||_ _| ___ |_____ || _|| |_| | | | | |
+| || _ | | | | | _____| || |_ | | | | | |
+|_______||__| |__| |___| |___| |_______||_______||_______| |___| | |
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 | |
diff --git a/ansible/roles/finger/files/nouser b/ansible/roles/finger/files/nou… | |
@@ -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 | |
diff --git a/ansible/roles/finger/tasks/main.yml b/ansible/roles/finger/tasks/m… | |
@@ -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 | |
diff --git a/ansible/roles/finger/vars/Debian.yml b/ansible/roles/finger/vars/D… | |
@@ -0,0 +1,3 @@ | |
+common_packages: | |
+ - openbsd-inetd | |
+ - efingerd | |
diff --git a/ansible/roles/git/handlers/main.yml b/ansible/roles/git/handlers/m… | |
@@ -0,0 +1,6 @@ | |
+--- | |
+- name: Restart git-daemon | |
+ ansible.builtin.systemd: | |
+ name: git-daemon | |
+ state: started | |
+ daemon_reload: true | |
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 | |
diff --git a/ansible/roles/git/templates/git-daemon.service.j2 b/ansible/roles/… | |
@@ -0,0 +1,18 @@ | |
+[Unit] | |
+Description=Start Git Daemon | |
+ | |
+[Service] | |
+ExecStart=/usr/bin/git daemon --reuseaddr --base-path={{ git.base_path }} {{ g… | |
+ | |
+Restart=always | |
+RestartSec=500ms | |
+ | |
+StandardOutput=syslog | |
+StandardError=syslog | |
+SyslogIdentifier=git-daemon | |
+ | |
+User={{ git.user }} | |
+Group={{ git.group }} | |
+ | |
+[Install] | |
+WantedBy=multi-user.target | |
diff --git a/ansible/roles/git/vars/Debian.yml b/ansible/roles/git/vars/Debian.… | |
@@ -0,0 +1,2 @@ | |
+common_packages: | |
+ - git | |
diff --git a/ansible/roles/gopher/handlers/main.yml b/ansible/roles/gopher/hand… | |
@@ -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 | |
diff --git a/ansible/roles/gopher/tasks/main.yml b/ansible/roles/gopher/tasks/m… | |
@@ -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 | |
diff --git a/ansible/roles/gopher/templates/geomyidae.service.j2 b/ansible/role… | |
@@ -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 … | |
+ | |
+[Install] | |
+WantedBy=multi-user.target | |
diff --git a/ansible/roles/gopher/vars/Debian.yml b/ansible/roles/gopher/vars/D… | |
@@ -0,0 +1,4 @@ | |
+common_packages: | |
+ - git | |
+ - build-essential | |
+ - libssl-dev | |
diff --git a/ansible/roles/gopher/vars/main.yml b/ansible/roles/gopher/vars/mai… | |
@@ -0,0 +1,5 @@ | |
+--- | |
+ | |
+build_path: /tmp/src/geomyidae | |
+source_repo: git://r-36.net/geomyidae | |
+disable_tls: true | |
diff --git a/ansible/roles/stagit/handlers/main.yml b/ansible/roles/stagit/hand… | |
@@ -0,0 +1,5 @@ | |
+--- | |
+- name: Install stagit | |
+ community.general.system.make: | |
+ chdir: "{{ build_path }}" | |
+ target: install | |
diff --git a/ansible/roles/stagit/tasks/main.yml b/ansible/roles/stagit/tasks/m… | |
@@ -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" | |
diff --git a/ansible/roles/stagit/templates/stagit_create.sh.j2 b/ansible/roles… | |
@@ -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}/"*/ >"${dest… | |
+ | |
+# 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 | |
diff --git a/ansible/roles/stagit/vars/Debian.yml b/ansible/roles/stagit/vars/D… | |
@@ -0,0 +1,4 @@ | |
+common_packages: | |
+ - git | |
+ - build-essential | |
+ - libgit2-dev | |
diff --git a/ansible/roles/stagit/vars/main.yml b/ansible/roles/stagit/vars/mai… | |
@@ -0,0 +1,5 @@ | |
+--- | |
+ | |
+build_path: /tmp/src/stagit-gopher | |
+source_repo: git://git.codemadness.org/stagit-gopher | |
+enable_old_libgit2: true | |
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 | |
- } | |
-} | |
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" | |
- } | |
- | |
- | |
-} | |
diff --git a/.terraform.lock.hcl b/terraform/.terraform.lock.hcl | |
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 | |
+} | |
+ | |
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} | |
+} | |
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" | |
+ } | |
+ } | |
+} | |
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/IoENtm8OT18tPerea… | |
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 | |
+ })) | |
+} | |
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/IoENtm8OT18tPer… | |
- | |
-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/… | |
- - 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/ssh… | |
- - sed -ie '/^#AllowAgentForwarding/s/^.*$/AllowAgentForwarding no/' /etc/ssh… | |
- - sed -ie '/^#AuthorizedKeysFile/s/^.*$/AuthorizedKeysFile .ssh/authorized_k… | |
- - 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' | |
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 | |
- })) | |
-} |