| Removing old Anisble, updating hetzner Terraform. - infra - Terraform IoC for m… | |
| Log | |
| Files | |
| Refs | |
| README | |
| --- | |
| commit d5730ddfc770cf4d3daaec8224f90d10eb986d4c | |
| parent 635e9945ef2e0d2def7301381daec2115377891e | |
| Author: Jay Scott <[email protected]> | |
| Date: Wed, 17 Jul 2024 19:34:12 +0100 | |
| Removing old Anisble, updating hetzner Terraform. | |
| Diffstat: | |
| M README | 45 +++++++----------------------… | |
| D ansible/group_vars/all.yml | 4 ---- | |
| D ansible/group_vars/git.yml | 4 ---- | |
| D ansible/group_vars/gopher.yml | 12 ------------ | |
| D ansible/inventory.yml | 10 ---------- | |
| D ansible/main.yml | 21 --------------------- | |
| D ansible/roles/common/files/sshd_co… | 6 ------ | |
| D ansible/roles/common/handlers/main… | 4 ---- | |
| D ansible/roles/common/tasks/main.yml | 47 -----------------------------… | |
| D ansible/roles/common/tasks/setup-D… | 5 ----- | |
| D ansible/roles/common/vars/Debian.y… | 5 ----- | |
| D ansible/roles/finger/files/list | 16 ---------------- | |
| D ansible/roles/finger/files/log | 1 - | |
| D ansible/roles/finger/files/logo.txt | 7 ------- | |
| D ansible/roles/finger/files/luser | 29 ----------------------------- | |
| D ansible/roles/finger/files/mcrae.t… | 222 ---------------------------… | |
| D ansible/roles/finger/files/morris.… | 125 ---------------------------… | |
| D ansible/roles/finger/files/nouser | 19 ------------------- | |
| D ansible/roles/finger/tasks/main.yml | 36 -----------------------------… | |
| D ansible/roles/finger/vars/Debian.y… | 3 --- | |
| D ansible/roles/git/handlers/main.yml | 6 ------ | |
| D ansible/roles/git/tasks/main.yml | 31 -----------------------------… | |
| D ansible/roles/git/templates/git-da… | 18 ------------------ | |
| D ansible/roles/git/vars/Debian.yml | 2 -- | |
| D ansible/roles/gopher/handlers/main… | 12 ------------ | |
| D ansible/roles/gopher/tasks/main.yml | 58 ------------------------------ | |
| D ansible/roles/gopher/templates/geo… | 16 ---------------- | |
| D ansible/roles/gopher/vars/Debian.y… | 4 ---- | |
| D ansible/roles/gopher/vars/main.yml | 5 ----- | |
| D ansible/roles/stagit/handlers/main… | 5 ----- | |
| D ansible/roles/stagit/tasks/main.yml | 46 -----------------------------… | |
| D ansible/roles/stagit/templates/sta… | 38 ---------------------------… | |
| D ansible/roles/stagit/vars/Debian.y… | 4 ---- | |
| D ansible/roles/stagit/vars/main.yml | 5 ----- | |
| A remote/.terraform.lock.hcl | 24 ++++++++++++++++++++++++ | |
| A remote/checks.tf | 8 ++++++++ | |
| A remote/cloudinit/main.yml | 47 +++++++++++++++++++++++++++++… | |
| A remote/main.tf | 69 ++++++++++++++++++++++++++++++ | |
| A remote/outputs.tf | 3 +++ | |
| A remote/terraform.tfvars | 53 ++++++++++++++++++++++++++++++ | |
| A remote/variables.tf | 25 +++++++++++++++++++++++++ | |
| 41 files changed, 239 insertions(+), 861 deletions(-) | |
| --- | |
| diff --git a/README b/README | |
| @@ -1,42 +1,17 @@ | |
| -|> Terraform | |
| + ___ __ | |
| +| |\ | |__ |__) /\ | |
| +| | \| | | \ /~~\ | |
| -Bootstrap Hetzner Cloud servers. | |
| - Add public ssh key to account | |
| - Provision X servers with desired configuration | |
| - Create custom firewall rules | |
| - Add reverse dns entry | |
| - Userdata bootscript adding an Ansible user account | |
| - | |
| -If you actually want to use this for yourself then you might need to do | |
| -the following depending on your requirements. | |
| +--- | |
| +The remote servers are hosted Hetzner Cloud servers and selfhosted are running | |
| +on Incus. If you actually want to use this for yourself then you might need to | |
| +do the following depending on your requirements. | |
| export HCLOUD_TOKEN='thisismylongasstoken' | |
| - | |
| -The user_data script is a standard cloud-init yaml config that creates | |
| -an Ansible user for further configuration 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> | |
| + tofu init | |
| + tofu plan | |
| + tofu apply | |
| diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml | |
| @@ -1,4 +0,0 @@ | |
| -default: | |
| - username: jay | |
| - comment: Jay Scott | |
| - hostname: jay.scot | |
| diff --git a/ansible/group_vars/git.yml b/ansible/group_vars/git.yml | |
| @@ -1,4 +0,0 @@ | |
| -git: | |
| - user: git | |
| - group: users | |
| - base_path: /srv/git | |
| diff --git a/ansible/group_vars/gopher.yml b/ansible/group_vars/gopher.yml | |
| @@ -1,12 +0,0 @@ | |
| -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 | |
| @@ -1,10 +0,0 @@ | |
| -all: | |
| - vars: | |
| - ansible_user: jay | |
| - children: | |
| - git: | |
| - hosts: | |
| - jay.scot | |
| - gopher: | |
| - hosts: | |
| - jay.scot | |
| diff --git a/ansible/main.yml b/ansible/main.yml | |
| @@ -1,21 +0,0 @@ | |
| -- hosts: all | |
| - become: true | |
| - roles: | |
| - - role: common | |
| - tags: | |
| - - common | |
| - | |
| -- hosts: git | |
| - become: true | |
| - roles: | |
| - - role: git | |
| - - role: stagit | |
| - tags: | |
| - - git | |
| - | |
| -- hosts: gopher | |
| - become: true | |
| - roles: | |
| - - role: gopher | |
| - tags: | |
| - - gopher | |
| diff --git a/ansible/roles/common/files/sshd_config b/ansible/roles/common/file… | |
| @@ -1,6 +0,0 @@ | |
| -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… | |
| @@ -1,4 +0,0 @@ | |
| -- name: Restart sshd | |
| - ansible.builtin.service: | |
| - name: sshd | |
| - state: restarted | |
| diff --git a/ansible/roles/common/tasks/main.yml b/ansible/roles/common/tasks/m… | |
| @@ -1,47 +0,0 @@ | |
| ---- | |
| - | |
| -- 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 | |
| - | |
| -- name: Set the hostname | |
| - ansible.builtin.hostname: | |
| - name: "{{ default.hostname }}" | |
| - use: systemd | |
| diff --git a/ansible/roles/common/tasks/setup-Debian.yml b/ansible/roles/common… | |
| @@ -1,5 +0,0 @@ | |
| -- 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… | |
| @@ -1,5 +0,0 @@ | |
| -common_packages: | |
| - - htop | |
| - - vim | |
| - - finger | |
| - - lynx | |
| diff --git a/ansible/roles/finger/files/list b/ansible/roles/finger/files/list | |
| @@ -1,16 +0,0 @@ | |
| -#!/bin/sh | |
| - | |
| -cat "/etc/efingerd/logo.txt" | |
| - | |
| -printf "\n\n" | |
| -printf "Welcome to jay.scot!\n" | |
| -printf "Uptime : %s\n\n" "$(uptime)" | |
| - | |
| -printf "Available Fingers:\n\n" | |
| -printf "\tusername ... get user info\n" | |
| - | |
| -printf "\n\n" | |
| -printf "Current Users:\n\n" | |
| -printf "\tJay Scott\t\t%s\n" "$(last jay -n1 -R --time-format full | head -n1)" | |
| -printf "\tRobert Morris\t\tmorris\t pts/0\t Wed Nov 2 08:23:03 1988\t st… | |
| -printf "\tWilliam McRae\t\tmcrae \t pts/1\t Sun Apr 7 15:35:49 1985\t st… | |
| diff --git a/ansible/roles/finger/files/log b/ansible/roles/finger/files/log | |
| @@ -1 +0,0 @@ | |
| -# nope, no logs | |
| diff --git a/ansible/roles/finger/files/logo.txt b/ansible/roles/finger/files/l… | |
| @@ -1,7 +0,0 @@ | |
| - ___ _______ __ __ _______ _______ _______ _______ | |
| - | || _ || | | | | || || || | | |
| - | || |_| || |_| | | _____|| || _ ||_ _| | |
| - | || || | | |_____ | || | | | | | | |
| - ___| || ||_ _| ___ |_____ || _|| |_| | | | | |
| -| || _ | | | | | _____| || |_ | | | | | |
| -|_______||__| |__| |___| |___| |_______||_______||_______| |___| | |
| diff --git a/ansible/roles/finger/files/luser b/ansible/roles/finger/files/luser | |
| @@ -1,29 +0,0 @@ | |
| -#!/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}/.header" ]; then | |
| - cat "${user_folder}/.header" | |
| - printf "\n" | |
| - fi | |
| - | |
| - if [ -f "${user_folder}/.plan" ]; then | |
| - printf "Plan:\n" | |
| - cat "${user_folder}/.plan" | |
| - printf "\n" | |
| - fi | |
| - | |
| - if [ -f "${user_folder}/.project" ]; then | |
| - printf "Project:\n" | |
| - cat "${user_folder}/.project" | |
| - printf "\n" | |
| - fi | |
| - | |
| -fi | |
| - | |
| -exit 0 | |
| diff --git a/ansible/roles/finger/files/mcrae.txt b/ansible/roles/finger/files/… | |
| @@ -1,222 +0,0 @@ | |
| - | |
| -T H E M Y S T E R Y O F | |
| - | |
| - __ __ ___ | |
| -| | | | | | /\ |\/| |\/| / ` |__) /\ |__ | |
| -|/\| | |___ |___ | /~~\ | | | | \__, | \ /~~\ |___ | |
| - | |
| - | |
| - | |
| -Willie McRae (18 May 1923 – 7 April 1985) was a Scottish lawyer, orator, | |
| -naval officer, politician and anti-nuclear campaigner. In the Second | |
| -World War he served in the British Army and then the Royal Indian Navy. | |
| -He supported the Indian independence movement and for much of his life | |
| -was active in the Scottish National Party (SNP). | |
| - | |
| -McRae is remembered for his mysterious death, in which his car crashed | |
| -in a remote part of the Scottish Highlands and he was found shot in the | |
| -head with a revolver. The official verdict was undetermined. | |
| - | |
| - | |
| -|> Life | |
| - | |
| - | |
| -McRae was born in Carron, Falkirk, where his father was an electrician. | |
| -McRae edited a local newspaper in Grangemouth at the same time as | |
| -reading history at the University of Glasgow, from which he gained | |
| -a first-class degree. In the Second World War he was commissioned into | |
| -the Seaforth Highlanders but transferred to the Royal Indian Navy, in | |
| -which he became a lieutenant commander and aide-de-camp to Admiral Lord | |
| -Mountbatten. He supported the Indian independence movement. | |
| - | |
| -After the war McRae returned to the University of Glasgow and graduated | |
| -again, this time in law.[1] He authored the maritime law of Israel and | |
| -was an emeritus professor of the University of Haifa. | |
| -After his death a forest of 3,000 trees was planted in Israel in his | |
| -memory. | |
| - | |
| -McRae became a solicitor and an SNP activist. In both of the 1974 | |
| -General Elections and in the 1979 General Election he stood for | |
| -Parliament as the SNP candidate for Ross and Cromarty. In October 1974 | |
| -he only lost to the Conservative Hamish Gray by 633 votes, but in 1979 | |
| -Gray's majority increased to 4,735. In the latter year he also contested | |
| -the SNP leadership, coming third in a three-way contest with 52 votes to | |
| -Stephen Maxwell's 117 votes and winner Gordon Wilson's 530 votes. | |
| - | |
| -McRae was a vocal critic of the British nuclear lobby. Early in the | |
| -1980s he was a key figure in a campaign against the United Kingdom | |
| -Atomic Energy Authority plans to dispose of nuclear waste in the | |
| -Mullwharchar area of the Galloway Hills. Representing the SNP in | |
| -a public inquiry, McRae asked difficult questions of the UKAEA and | |
| -famously declared at one meeting that "nuclear waste should be stored | |
| -where Guy Fawkes put his gunpowder." The authority's plans were | |
| -rejected, and McRae was credited with "single-handedly" preventing the | |
| -area from becoming a nuclear waste dump. | |
| - | |
| - | |
| -|> Death | |
| - | |
| - | |
| -On 5 April 1985 McRae left his Glasgow flat at 18:30 to spend the | |
| -weekend at his cottage at Ardelve near Dornie, Ross-shire. He was not | |
| -seen again until the next morning around 10:00, when two Australian | |
| -tourists saw his maroon Volvo saloon car on a moor a short distance from | |
| -the junction of the A887 and A87 roads Bun Loyne, Glenmoriston, | |
| -Inverness-shire. The car was straddling a burn about 90 feet (27 m) from | |
| -the road. The tourists flagged down the next car to pass, whose driver | |
| -turned out to be a doctor, Dorothy Messer, accompanied by her fiancé as | |
| -well as David Coutts, an SNP Dundee councillor who knew McRae. | |
| - | |
| -It was discovered that McRae was in the car. His hands were "folded on | |
| -his lap", his head was "slumped on his right shoulder", and there was | |
| -a "considerable amount of blood on his temple". He was not wearing | |
| -a seat belt. | |
| - | |
| -Another car was sent to call the emergency services. Dr Messer examined | |
| -McRae and found that he was still alive and breathing. She noted that | |
| -one of his pupils was dilated, indicating the possibility of brain | |
| -damage, and estimated that he had been in that state for 10 hours. | |
| - | |
| -McRae was removed by ambulance to Raigmore Hospital, Inverness, | |
| -accompanied by Dr Messer. After admission it was decided to transfer him | |
| -to Aberdeen Royal Infirmary. At Aberdeen it was realised that the | |
| -incident was more than a road accident; six hours after he had been | |
| -found, a nurse washing his head discovered what appeared to be the entry | |
| -wound of a gunshot. An X-ray confirmed that McRae had been shot above | |
| -his right ear and a bullet was detected in his head. His brain was | |
| -severely damaged and his vital functions very weak. The next day, Sunday | |
| -7 April, after consultation with his next of kin, McRae's life-support | |
| -machine was switched off. | |
| - | |
| - | |
| -|>Investigation | |
| - | |
| - | |
| -The investigation was headed by Chief Superintendent Andrew Lister of | |
| -Northern Constabulary CID. Despite no weapon having yet been found, | |
| -McRae's car was moved at 12:00 on 7 April. It later transpired that the | |
| -police had kept no record of the precise location where the car had been | |
| -found, and the position stated by them was later found to be 1 mile (1.6 | |
| -km) in error, and was corrected by a witness who had been present at the | |
| -scene. | |
| - | |
| -A weapon was found the next day, in the burn over which the car had been | |
| -discovered, 60 feet (18 m) from the vehicle. It was a Smith & Wesson .22 | |
| -calibre revolver containing two spent cartridges and five remaining | |
| -rounds. | |
| - | |
| - | |
| -|> Controversy | |
| - | |
| - | |
| -Although it was ruled at the time by authorities that McRae's death was | |
| -undetermined, aspects of the investigation remain disputed, some | |
| -claiming that the distance from McRae's car at which the gun was found | |
| -and the lack of fingerprints on it rendered a suicide not credible. | |
| - | |
| -At the time of his death, McRae had been working to counter plans to | |
| -dump nuclear waste from the Dounreay Nuclear Power Development | |
| -Establishment into the sea. Due to his house being burgled on repeated | |
| -occasions prior to his death, he had taken to carrying a copy of the | |
| -documents relating to his Dounreay work with him at all times. They were | |
| -not found following his death, and the sole other copy which was kept in | |
| -his office was stolen when it was burgled, no other items being | |
| -taken. | |
| - | |
| -Neither McRae's medical reports nor the post-mortem data have been | |
| -released to the public and there was no fatal accident inquiry. | |
| - | |
| - | |
| -|> Aftermath | |
| - | |
| - | |
| -Winnie Ewing – then President of the SNP and herself an accomplished | |
| -lawyer – was directed by the SNP's National Executive Committee (NEC) to | |
| -conduct an internal investigation for the party to come to a conclusion | |
| -as to whether Ewing "was satisfied or dissatisfied with the official | |
| -version that he committed suicide". Having been refused access to police | |
| -records of the investigation and rebuffed by both the Lord Advocate and | |
| -the Procurator Fiscal in her attempts to conduct private, confidential | |
| -meetings with them, Ewing, as she later wrote, came "up against a brick | |
| -wall".[10] Ewing reported to the SNP NEC that she was not satisfied with | |
| -the official account of suicide: "I do not know what happened, but | |
| -I think it is important that the truth emerges, despite the time that | |
| -has passed. Why the State refuses to let the truth be known is | |
| -a pertinent question." | |
| - | |
| -In 1991 Channel 4 broadcast a "Scottish Eye" documentary investigating | |
| -the mysterious circumstances of McRae's death. It found evidence to | |
| -suggest that McRae had been under surveillance by UK intelligence | |
| -services and that his death had likely involved foul play. | |
| - | |
| -In 2005 Winnie Ewing's son Fergus, by then an MSP, requested a meeting | |
| -with Elish Angiolini, Solicitor General for Scotland, to discuss | |
| -allegations that have persisted that McRae was under surveillance at the | |
| -time of his death. The request was rebuffed, with Angiolini claiming | |
| -that he had not been under surveillance and that she was satisfied that | |
| -a thorough investigation into the case had been carried out. | |
| - | |
| -In July 2006 a retired police officer, Iain Fraser, who was working as | |
| -a private investigator at the time of McRae's death, claimed that he had | |
| -been anonymously employed to keep McRae under surveillance only weeks | |
| -before he died. In November 2006 an episode of the Scottish Television | |
| -show Unsolved examined the circumstances of McRae's death. | |
| - | |
| -In November 2010 John Finnie, then SNP group leader on Highland Council | |
| -and a former police officer, wrote to the Lord Advocate urging her to | |
| -reinvestigate McRae's death and release any details so far withheld. | |
| -Finnie's request was prompted by the release the previous month of | |
| -further details concerning the death of David Kelly.[14] In January 2011 | |
| -the Crown Office requested the files on the case from Northern | |
| -Constabulary. | |
| - | |
| -Also in November 2010 Donald Morrison, a former Strathclyde Police | |
| -officer, alleged that McRae had been "under surveillance" by both | |
| -Special Branch and MI5. Morrison had collaborated with former colleague | |
| -Iain Fraser to discover more about McRae's death. Morrison called for an | |
| -enquiry into McRae's death and promised that he would give it a sworn | |
| -affidavit that MI5 was involved. | |
| - | |
| -In July 2014 two unconnected plays by George Gunn and Andy Paterson | |
| -about McRae's life and death, both coincidentally titled 3,000 Trees, | |
| -were staged at the Edinburgh Festival Fringe. One of the plays explored | |
| -his anti-nuclear campaigning, links with nationalist radicals and | |
| -allegations that Special Branch and MI5 were surveilling him. | |
| - | |
| -In November 2014 a Scottish Sunday Express front-page article alleged | |
| -that McRae had uncovered evidence of the alleged paedophile ring in | |
| -Westminster during the 1980s. The article suggests he may have been | |
| -murdered and that the evidence he possessed was stolen at the time of | |
| -his death. | |
| - | |
| -In April 2015 there was a campaign to have a Fatal Accident Inquiry | |
| -(FAI) on McRae's death. It attracted 6,500 signatures in 5 days. | |
| - | |
| -The petition eventually collected over 13,000 signatures and was handed | |
| -in, in June 2015. The Crown Office rejected the proposal to hold a Fatal | |
| -Accident Inquiry. | |
| - | |
| -On the Easter weekend of April 2015, the 30th anniversary of McRae's | |
| -death, Scotland on Sunday ran a story claiming that McRae's Volvo was | |
| -moved back to the crash site by Northern Constabulary in an attempt to | |
| -hide that the car had been moved before the bullet had been found | |
| -– accounting for the discrepancies relating to the gun's distance from | |
| -the car. | |
| - | |
| -On the same day, one of the journalists involved started crowdfunding | |
| -for a book on the case titled '30 Years of Silence'. | |
| - | |
| -Following the rejection of the petition for a Fatal Accident Inquiry by | |
| -the Crown Office, a "Justice For Willie" Campaign group was set up by | |
| -Mark MacNicol. The campaign decided to launch their own investigation | |
| -since no official inquiry was forthcoming. They hired two private | |
| -investigators to re-interview original witnesses from the time of Willie | |
| -McRae's death. The results were published in November 2016, and the | |
| -campaign were unable to find any new evidence to undermine the official | |
| -suicide verdict. | |
| - | |
| -In October 2018, fresh doubt on the official verdict was raised again by | |
| -a nurse who claims to have treated Willie McRae at Foresterhill Hospital | |
| -in Aberdeen. Katharine Mcgonigal disputed that the bullet wound was to | |
| -the right temple, as the post-mortem claimed, and said it was instead to | |
| -the back of the neck. | |
| diff --git a/ansible/roles/finger/files/morris.txt b/ansible/roles/finger/files… | |
| @@ -1,125 +0,0 @@ | |
| - | |
| -T H E | |
| - ___ ___ ___ ____ ____ ____ _____ __ __ ___ ____ ___ ___ | |
| - | | |/ \| \| \| / ___/ | |__| |/ \| \| | | | |
| - | _ _ | | D ) D )| ( \_ | | | | | D ) _ _ | | |
| - | \_/ | O | /| / | |\__ | | | | | O | /| \_/ | | |
| - | | | | \| \ | |/ \ | | ` ' | | \| | | | |
| - | | | | . \ . \| |\ | \ /| | . \ | | | |
| - |___|___|\___/|__|\_|__|\_|____|\___| \_/\_/ \___/|__|\_|___|___| | |
| - | |
| - | |
| - | |
| -The Morris worm or Internet worm of November 2, 1988, is one of the oldest | |
| -computer worms distributed via the Internet, and the first to gain significant | |
| -mainstream media attention. It resulted in the first felony conviction in the | |
| -US under the 1986 Computer Fraud and Abuse Act. It was written by a graduate | |
| -student at Cornell University, Robert Tappan Morris, and launched on November | |
| -2, 1988, from the Massachusetts Institute of Technology network. | |
| - | |
| - | |
| -|> Architecture | |
| - | |
| - | |
| -The worm was created by Morris simply to see if it could be done, | |
| -and was released from the Massachusetts Institute of Technology (MIT) in the | |
| -hope of suggesting that its creator studied there, instead of Cornell. Morris | |
| -later became a tenured professor at MIT in 2006. The worm's creator Robert | |
| -Tappan Morris is the son of cryptographer Robert Morris, who worked at the NSA | |
| -at the time. | |
| - | |
| -The worm exploited several vulnerabilities of targeted systems, including: | |
| - | |
| - A hole in the debug mode of the Unix sendmail program | |
| - | |
| - A buffer overflow or overrun hole in the finger network service | |
| - | |
| - The transitive trust enabled by people setting up network logins with no | |
| - password requirements via remote execution (rexec) with Remote Shell (rsh), | |
| - termed rexec/rsh | |
| - | |
| - The worm exploited weak passwords. Morris's exploits became generally | |
| - obsolete due to decommissioning rsh (normally disabled on untrusted networks… | |
| - fixes to sendmail and finger, widespread network filtering, and improved | |
| - awareness of weak passwords. | |
| - | |
| -Though Morris did not intend for the worm to be actively destructive, instead | |
| -seeking to merely highlight the weaknesses present in many networks of the | |
| -time, an unintentional consequence of Morris's coding resulted in the worm | |
| -being more damaging and spreadable than originally planned. It was initially | |
| -programmed to check each computer to determine if the infection was already | |
| -present, but Morris believed that some system administrators might counter this | |
| -by instructing the computer to report a false positive. Instead, he programmed | |
| -the worm to copy itself 14% of the time, regardless of the status of infection | |
| -on the computer. This resulted in a computer potentially being infected | |
| -multiple times, with each additional infection slowing the machine down to | |
| -unusability. This had the same effect as a fork bomb, and crashed the computer | |
| -several times. | |
| - | |
| -The main body of the worm can only infect DEC VAX machines running 4BSD, | |
| -alongside Sun-3 systems. A portable C "grappling hook" component of the worm | |
| -was used to download the main body parts, and the grappling hook runs on other | |
| -systems, loading them down and making them peripheral victims. | |
| - | |
| - | |
| -|> Coding mistake | |
| - | |
| - | |
| -Morris's coding mistake, in instructing the worm to replicate itself regardless | |
| -of a computer's reported infection status, transformed the worm from a | |
| -potentially harmless intellectual and computing exercise into a viral | |
| -denial-of-service attack. Morris's inclusion of the rate of copy within the | |
| -worm was inspired by Michael Rabin's mantra of randomization. | |
| - | |
| -The resulting level of replication proved excessive, with the worm spreading | |
| -rapidly, infecting some computers several times. Rabin would eventually comment | |
| -that Morris "should have tried it on a simulator first". | |
| - | |
| - | |
| -|> Effects | |
| - | |
| - | |
| -During the Morris appeal process, the US court of appeals estimated the cost of | |
| -removing the virus from each installation was in the range of $200–53,000. | |
| -Possibly based on these numbers, Clifford Stoll of Harvard estimated for the US | |
| -Government Accountability Office that the total economic impact was between | |
| -$100,000 and $10,000,000. Stoll, a systems administrator known for discovering | |
| -and subsequently tracking the hacker Markus Hess three years earlier, helped | |
| -fight the worm, writing in 1989 that "I surveyed the network, and found that | |
| -two thousand computers were infected within fifteen hours. These machines were | |
| -dead in the water—useless until disinfected. And removing the virus often to… | |
| -two days." Stoll commented that the worm showed the danger of monoculture, | |
| -because "If all the systems on the ARPANET ran Berkeley Unix, the virus would | |
| -have disabled all fifty thousand of them." | |
| - | |
| -It is usually reported that around 6,000 major UNIX machines were infected by | |
| -the Morris worm. However, Morris's colleague Paul Graham claimed, "I was there | |
| -when this statistic was cooked up, and this was the recipe: someone guessed | |
| -that there were about 60,000 computers attached to the Internet, and that the | |
| -worm might have infected ten percent of them." Stoll estimated that "only a | |
| -couple thousand" computers were affected, writing that "Rumors have it that | |
| -[Morris] worked with a friend or two at Harvard's computing department (Harvard | |
| -student Paul Graham sent him mail asking for 'Any news on the brilliant | |
| -project')." | |
| - | |
| -The Internet was partitioned for several days, as regional networks | |
| -disconnected from the NSFNet backbone and from each other to prevent | |
| -recontamination while cleaning their own networks. | |
| - | |
| -The Morris worm prompted DARPA to fund the establishment of the CERT/CC at | |
| -Carnegie Mellon University, giving experts a central point for coordinating | |
| -responses to network emergencies. Gene Spafford also created the Phage mailing | |
| -list to coordinate a response to the emergency. | |
| - | |
| -Morris was tried and convicted of violating United States Code Title 18 (18 | |
| -U.S.C. § 1030), the Computer Fraud and Abuse Act, in United States v. Morris. | |
| -After appeals, he was sentenced to three years' probation, 400 hours of | |
| -community service, and a fine of US$10,050 (equivalent to $20,000 in 2021) plus | |
| -the costs of his supervision. The total fine ran to $13,326, which included a | |
| -$10,000 fine, $50 special assessment, and $3,276 cost of probation oversight. | |
| - | |
| -The Morris worm has sometimes been referred to as the "Great Worm", due to the | |
| -devastating effect it had on the Internet at that time, both in overall system | |
| -downtime and in psychological impact on the perception of security and | |
| -reliability of the Internet. The name was derived from the "Great Worms" of | |
| -Tolkien: Scatha and Glaurung. | |
| diff --git a/ansible/roles/finger/files/nouser b/ansible/roles/finger/files/nou… | |
| @@ -1,19 +0,0 @@ | |
| -#!/bin/sh | |
| - | |
| -if [ "$3" = "morris" ]; then | |
| - cat "/etc/efingerd/morris.txt" | |
| -elif [ "$3" = "mcrae" ]; then | |
| - cat "/etc/efingerd/mcrae.txt" | |
| -else | |
| - | |
| - cat <<EOF | |
| - | |
| - 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 | |
| -EOF | |
| - | |
| -fi | |
| diff --git a/ansible/roles/finger/tasks/main.yml b/ansible/roles/finger/tasks/m… | |
| @@ -1,36 +0,0 @@ | |
| ---- | |
| -- 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 | |
| - - morris.txt | |
| - - mcrae.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… | |
| @@ -1,3 +0,0 @@ | |
| -common_packages: | |
| - - openbsd-inetd | |
| - - efingerd | |
| diff --git a/ansible/roles/git/handlers/main.yml b/ansible/roles/git/handlers/m… | |
| @@ -1,6 +0,0 @@ | |
| ---- | |
| -- 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 | |
| @@ -1,31 +0,0 @@ | |
| ---- | |
| -- 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/… | |
| @@ -1,18 +0,0 @@ | |
| -[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.… | |
| @@ -1,2 +0,0 @@ | |
| -common_packages: | |
| - - git | |
| diff --git a/ansible/roles/gopher/handlers/main.yml b/ansible/roles/gopher/hand… | |
| @@ -1,12 +0,0 @@ | |
| ---- | |
| -- name: Restart geomyidae | |
| - ansible.builtin.systemd: | |
| - name: geomyidae | |
| - state: started | |
| - enabled: true | |
| - 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… | |
| @@ -1,58 +0,0 @@ | |
| ---- | |
| -- 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… | |
| @@ -1,16 +0,0 @@ | |
| -[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 -n … | |
| - | |
| -[Install] | |
| -WantedBy=multi-user.target | |
| diff --git a/ansible/roles/gopher/vars/Debian.yml b/ansible/roles/gopher/vars/D… | |
| @@ -1,4 +0,0 @@ | |
| -common_packages: | |
| - - git | |
| - - build-essential | |
| - - libssl-dev | |
| diff --git a/ansible/roles/gopher/vars/main.yml b/ansible/roles/gopher/vars/mai… | |
| @@ -1,5 +0,0 @@ | |
| ---- | |
| - | |
| -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… | |
| @@ -1,5 +0,0 @@ | |
| ---- | |
| -- 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… | |
| @@ -1,46 +0,0 @@ | |
| ---- | |
| -- 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: "*/5" | |
| - job: "/home/{{ stagit_gopher.cron_user }}/stagit_create.sh" | |
| diff --git a/ansible/roles/stagit/templates/stagit_create.sh.j2 b/ansible/roles… | |
| @@ -1,38 +0,0 @@ | |
| -#!/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/*" | |
| - | |
| -/usr/local/bin/stagit-gopher-index -b "${stagitdir}" "${reposdir}/"*.git/ >"${… | |
| - | |
| -# 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 | |
| - | |
| - if [ "$d" != "pass" ]; then | |
| - /usr/local/bin/stagit-gopher -b "${stagitdir}/${d}" \ | |
| - -u "gopher://jay.scot/1/git/$d/" "${reposdir}/${r}" | |
| - | |
| - # symlinks | |
| - ln -sf log.gph index.gph | |
| - | |
| - echo "done" | |
| - else | |
| - echo "skipping" | |
| - fi | |
| -done | |
| - | |
| - | |
| diff --git a/ansible/roles/stagit/vars/Debian.yml b/ansible/roles/stagit/vars/D… | |
| @@ -1,4 +0,0 @@ | |
| -common_packages: | |
| - - git | |
| - - build-essential | |
| - - libgit2-dev | |
| diff --git a/ansible/roles/stagit/vars/main.yml b/ansible/roles/stagit/vars/mai… | |
| @@ -1,5 +0,0 @@ | |
| ---- | |
| - | |
| -build_path: /tmp/src/stagit-gopher | |
| -source_repo: git://git.codemadness.org/stagit-gopher | |
| -enable_old_libgit2: false | |
| diff --git a/remote/.terraform.lock.hcl b/remote/.terraform.lock.hcl | |
| @@ -0,0 +1,24 @@ | |
| +# This file is maintained automatically by "tofu init". | |
| +# Manual edits may be lost in future updates. | |
| + | |
| +provider "registry.opentofu.org/hetznercloud/hcloud" { | |
| + version = "1.47.0" | |
| + constraints = "1.47.0" | |
| + hashes = [ | |
| + "h1:aqEPcSpaWhKqbMs7c7Pf5ot6Tye7ntRitWsuNGPRPfk=", | |
| + "zh:0759f0c23d0e59baab3382320eef4eb314e0c5967b6ef67ff07135da07a97b34", | |
| + "zh:0e9ca84c4059d6d7e2c9f13d3c2b1cd91f7d9a47bedcb4b80c7c77d536eff887", | |
| + "zh:17a033ac4650a39ddacf3265a449edabaea528f81542c4e63e254272d5aac340", | |
| + "zh:2997c76a500e42b7519b24fa1f8646d9baab70c68277f80394560d3e1fd06e6d", | |
| + "zh:37f3fe7bb34cac63c69123e43e5426bab75816b3665dbe7125276a8d2ee6b2d8", | |
| + "zh:45d4b04dc470f24ad96c1c0b6636ea5422c659004f3e472c863bc50130fabf25", | |
| + "zh:46df99d972a78af6875565e53a73df66d870c474a20cd90e9e0a3092aa25197f", | |
| + "zh:4b5bb8d49366ad895c6c767efe16a1b8143802414abfe3fdb1184cbbecf424eb", | |
| + "zh:55c6199eb401c4b0a6c948ceac8b50f352e252e1c985903ed173bf26ad0f109e", | |
| + "zh:7b6efe897bffa37248064155a699e67953350b5b9a5476456c0160ce59254557", | |
| + "zh:7bc004bcb649ce1ec70e2cf848392e10a1edbcbf11b3292a4cc5c5d49bd769e4", | |
| + "zh:e1b17b7595f158fbb3021afa8869b541b5c10bdd2d8d2b2b3eaa82200b104ddd", | |
| + "zh:f741ca40e8e99a3e4114ad108ea2b5a5bccbedb008326c7f647f250580e69c0e", | |
| + "zh:fae9c7f8d08a447bb0972529f6db06999c35391046320206041a988aeca6b54c", | |
| + ] | |
| +} | |
| diff --git a/remote/checks.tf b/remote/checks.tf | |
| @@ -0,0 +1,8 @@ | |
| +check "server_status" { | |
| + assert { | |
| + condition = alltrue([ | |
| + for k, v in var.nodes : hcloud_server.this[k].status == "running" | |
| + ]) | |
| + error_message = "Server status check failed." | |
| + } | |
| +} | |
| diff --git a/remote/cloudinit/main.yml b/remote/cloudinit/main.yml | |
| @@ -0,0 +1,47 @@ | |
| +#cloud-config | |
| + | |
| +ssh_pwauth: false | |
| +hostname: jay.scot | |
| +timezone: Europe/London | |
| +package_update: true | |
| + | |
| +packages: | |
| + - caddy | |
| + - git | |
| + - git-daemon-sysvinit | |
| + - unattended-upgrades | |
| + | |
| +users: | |
| + - name: jay | |
| + groups: users,wheel | |
| + sudo: ALL=(ALL) NOPASSWD:ALL | |
| + shell: /bin/bash | |
| + lock_passwd: true | |
| + ssh_authorized_keys: | |
| + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDLmKYxwXTbyRWLG0S24RTpyfyBO6AL8Dc… | |
| + | |
| + - name: git | |
| + shell: /usr/bin/git-shell | |
| + homedir: /srv/git | |
| + ssh_authorized_keys: | |
| + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDLmKYxwXTbyRWLG0S24RTpyfyBO6AL8Dc… | |
| + | |
| +write_files: | |
| + - path: /etc/default/git-daemon | |
| + permissions: '0644' | |
| + content: | | |
| + GIT_DAEMON_ENABLE=true | |
| + GIT_DAEMON_USER=git | |
| + GIT_DAEMON_BASE_PATH=/srv/git | |
| + GIT_DAEMON_DIRECTORY=/srv/git | |
| + GIT_DAEMON_OPTIONS="--export-all" | |
| + | |
| + - path: /etc/caddy/Caddyfile | |
| + permissions: '0644' | |
| + content: | | |
| + jay.scot { | |
| + tls [email protected] | |
| + root * /srv/www | |
| + encode gzip | |
| + file_server | |
| + } | |
| diff --git a/remote/main.tf b/remote/main.tf | |
| @@ -0,0 +1,69 @@ | |
| +terraform { | |
| + required_version = ">=1.7.0" | |
| + required_providers { | |
| + hcloud = { | |
| + source = "hetznercloud/hcloud" | |
| + version = "1.47.0" | |
| + } | |
| + } | |
| +} | |
| + | |
| +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.firewall_rules | |
| + | |
| + name = each.key | |
| + | |
| + dynamic "rule" { | |
| + for_each = each.value.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 | |
| + } | |
| + | |
| + lifecycle { | |
| + postcondition { | |
| + condition = self.status == "running" | |
| + error_message = "Instance must be running." | |
| + } | |
| + } | |
| +} | |
| + | |
| +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/remote/outputs.tf b/remote/outputs.tf | |
| @@ -0,0 +1,3 @@ | |
| +output "public_ip_address" { | |
| + value = { for name, server in hcloud_server.this : name => server.ipv4_addre… | |
| +} | |
| diff --git a/remote/terraform.tfvars b/remote/terraform.tfvars | |
| @@ -0,0 +1,53 @@ | |
| +public_ssh_keys = { | |
| + main = "~/.ssh/id_ed25519.pub" | |
| +} | |
| + | |
| +firewall_rules = { | |
| + "main" = { | |
| + rules = { | |
| + 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" | |
| + } | |
| + http = { | |
| + direction = "in" | |
| + protocol = "tcp" | |
| + source_ips = ["0.0.0.0/0", "::/0"] | |
| + port = "80" | |
| + } | |
| + https = { | |
| + direction = "in" | |
| + protocol = "tcp" | |
| + source_ips = ["0.0.0.0/0", "::/0"] | |
| + port = "443" | |
| + } | |
| + | |
| + } | |
| + } | |
| + | |
| +} | |
| + | |
| +nodes = { | |
| + "main" = { | |
| + image = "debian-12" | |
| + location = "hel1", | |
| + server_type = "cx22", | |
| + reverse_dns = "jay.scot" | |
| + user_data = "cloudinit/main.yml" | |
| + public_key = "main" | |
| + ipv4 = true | |
| + ipv6 = true | |
| + labels = { | |
| + git = "true" | |
| + gemini = "true" | |
| + } | |
| + } | |
| +} | |
| diff --git a/remote/variables.tf b/remote/variables.tf | |
| @@ -0,0 +1,25 @@ | |
| + | |
| +variable "public_ssh_keys" { | |
| + description = "Public SSH key location to attach to instance." | |
| + type = map(any) | |
| +} | |
| + | |
| +variable "firewall_rules" { | |
| + description = "Firewall configuration settings." | |
| + 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) | |
| + ipv4 = bool | |
| + ipv6 = bool | |
| + })) | |
| +} |