diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..520a490 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +skz-opack/ diff --git a/.sloptrap b/.sloptrap new file mode 100644 index 0000000..d1a905a --- /dev/null +++ b/.sloptrap @@ -0,0 +1,4 @@ +name=skz-void +packages_extra=vagrant make jq python3 ripgrep curl git openssh-client +agent=codex +allow_host_network=true diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..0dc78f8 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,76 @@ +# Agent Guide + +This repository builds and deploys OpenBSD VPN servers on Google Cloud. The goal is to make it easy to create multiple VPN VMs in two flavors: + +- WireGuard, matching the existing historical deployment in `server/`. +- IPsec, using OpenBSD `iked`/`ipsecctl`. + +Keep this repository focused on VPN server definitions, provisioning glue, firewall rules, and run commands. The local `skz-opack/` directory is an ignored dependency that provides the OpenBSD image/build/deploy Makefile interface. Read it when you need to understand `OPACK_*` variables or targets, but do not modify it unless the user explicitly asks for dependency work. + +## Repository Shape + +- `server/` is the current WireGuard deployment. It includes the OpenBSD install disklabel, provisioning script, GCP firewall overlay, and Makefile using `../skz-opack/src/opack.mk`. +- `src/` is early IPsec/iked work and should stay separate from WireGuard-specific provisioning. +- Future VPN servers should live in separate directories or separate Makefiles. Do not merge WireGuard and IPsec into one opaque shared Makefile until real duplication justifies it. +- Each server definition should declare its own `OPACK_TARGET`, hostname, GCP project/key settings, provision script, firewall rules, client list, and generated-state ignore patterns. + +## Tools And Installation + +Before build or deployment work, verify the required host tools: + +```sh +for x in make jq python3 rg curl git ssh scp nc vagrant packer terraform gcloud qemu-system-x86_64; do command -v "$x" || echo "missing: $x"; done +``` + +In sloptrap/Codex containers, install missing third-party tools under `/sloptrap-tools` and expose executables through `/sloptrap-tools/bin`, which is already on `PATH`. Do not install toolchains into this repo, `$HOME`, or one-off directories. + +Use `/sloptrap-tools` for SDKs, plugins, and caches when configurable. For example, a Google Cloud SDK install may live under `/sloptrap-tools/google-cloud-sdk` with `/sloptrap-tools/bin/gcloud` symlinked to the real executable. Keep Packer plugin caches and similar generated tool state under `/sloptrap-tools` when possible. + +## Secrets And Live State + +`server/` may contain ignored live credentials and generated deployment state: + +- `id_ed25519` +- `skz-void-bbb88f038188.json` +- `opack-cloud` +- `opack_deploy_*` +- `opack_installer_*` + +Never commit, print, copy into tracked files, rotate, delete, or regenerate these files unless the user explicitly asks. Treat them as live operational material. + +Agents may SSH for read-only diagnostics when useful, using the ignored key and current deployed IP: + +```sh +ssh -i server/id_ed25519 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@$(cat server/opack-cloud) 'uname -a; sysctl kern.version' +``` + +Do not change services, firewall rules, VPN keys, GCP resources, package state, or deployed configuration on the live VM without explicit user approval. + +## Workflows + +For existing WireGuard deployment work, the main entrypoint is: + +```sh +make -C server void +``` + +This is not a harmless check. It may build an OpenBSD image, run Terraform, apply firewall rules, copy the external `skz-wg` tree to the live VM, and run remote provisioning. Use it only when the user wants deployment or provisioning work. + +For read-only live inspection, prefer direct SSH commands and report exactly what was inspected. Avoid broad commands that dump secrets or large config files. + +For future IPsec work, use OpenBSD-native `iked`/`ipsecctl` conventions. Keep IPsec provisioning, firewall rules, client/certificate generation, and run targets separate from WireGuard. Make IPsec firewall allowances explicit instead of reusing the WireGuard UDP rule. + +For future multi-server work, prefer adding a new isolated server directory or Makefile that includes `../skz-opack/src/opack.mk` and overrides `OPACK_*` values before the include. Keep generated files ignored next to the server that creates them. + +## Validation + +For documentation-only changes, validate with: + +```sh +sed -n '1,240p' AGENTS.md +git diff -- AGENTS.md +``` + +Do not run deployment targets as documentation validation. + +For Makefile/provisioning changes, use the narrowest non-destructive validation first, such as reading expanded Make variables, shell syntax checks, or targeted dry-run inspection. Treat `make ... opack-cloud`, `make -C server void`, Terraform apply/destroy, and remote provisioning commands as live infrastructure changes. diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..1215c2a --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,5 @@ +skz-void-bbb88f038188.json +opack-cloud +opack_deploy_* +opack_installer_* +id_ed25519 diff --git a/server/Makefile b/server/Makefile new file mode 100644 index 0000000..8520ae4 --- /dev/null +++ b/server/Makefile @@ -0,0 +1,51 @@ +OPACK_TARGET= skz-void-server +OPACK_SYS_VERSION= snapshots +OPACK_SYS_CPU= 2 +OPACK_SYS_MEMORY= 1024 +OPACK_SYS_DISK_SIZE= 10000 +OPACK_SYS_SETS= +* -x* +xbase* -game* -comp* +bsd.rd +OPACK_SYS_HOSTNAME= void.sk4.nz +OPACK_SYS_USER= sk4nz +#OPACK_SYS_SSH_PRIVATE_KEY= $(HOME)/.ssh/id_ed25519 +OPACK_GCE_MACHINE= e2-micro +OPACK_AUTODISKLABEL_FILE= $(shell realpath ./autodisklabel) +OPACK_PROVISION_FILE= $(shell realpath void-provision.sh) +OPACK_GCE_PROJECT= skz-void +OPACK_GCE_JSON_KEY= skz-void-bbb88f038188.json +OPACK_DEBUG=y + +include ../skz-opack/src/opack.mk + +SSH_OPTS= -i $(OPACK_SYS_SSH_PRIVATE_KEY) -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null +FW_TF= $(OPACK_TERRAFORM_DIR)/opack-module/firewall.tf + +IN_TCP= ssh +VPN_TCP= ssh domain http https 1024:65535 +VPN_UDP= domain ntp 1024:65535 + +VOID_CLIENTS= psychopomp skzphone miri + +.DEFAULT_GOAL := all + +all: void + +$(FW_TF): | opack-cloud + cp firewall.tf $@ + cd $(OPACK_TERRAFORM_DIR) && terraform apply \ + -target=module.opack-module.google_compute_firewall.icmp \ + -target=module.opack-module.google_compute_firewall.wireguard \ + -target=module.opack-module.google_compute_firewall.ssh \ + -auto-approve > /dev/null + echo ▒ GCP Firewall configured + #-target=module.opack-module.google_compute_firewall.deny \ + +void: | $(FW_TF) + ssh $(SSH_OPTS) root@$(shell cat opack-cloud) \ + "uname -a; sysctl kern.version;" 2> /dev/null + scp -q -r $(SSH_OPTS) \ + ../../skz-wg root@$(shell cat opack-cloud):/root/skz-wg + #vagrant ssh -c "make -C run bootstrap" + ssh $(SSH_OPTS) root@$(shell cat opack-cloud) \ + "sh -c 'IN_TCP=\"$(IN_TCP)\" VPN_TCP=\"$(VPN_TCP)\" VPN_UDP=\"$(VPN_UDP)\" CLIENTS=\"$(VOID_CLIENTS)\" make -C /root/skz-wg'" 2> /dev/null + +clean: opack-clean diff --git a/server/autodisklabel b/server/autodisklabel new file mode 100644 index 0000000..2baf99c --- /dev/null +++ b/server/autodisklabel @@ -0,0 +1,5 @@ +/ 1G-* 60% +swap 1G-2G 2% +/tmp 1G-4G 4% +/usr 3G-* 24% +/usr/local 2G-* 10% diff --git a/server/firewall.tf b/server/firewall.tf new file mode 100644 index 0000000..ee43a54 --- /dev/null +++ b/server/firewall.tf @@ -0,0 +1,46 @@ +#resource "google_compute_firewall" "deny" { +# name = "deny-all" +# network = "default" +# direction = "INGRESS" +# deny { +# protocol = "all" +# } +# target_tags = ["skz-opack"] +# source_ranges = ["0.0.0.0/0"] +# priority = 1001 +#} + +resource "google_compute_firewall" "icmp" { + name = "allow-icmp" + network = "default" + direction = "INGRESS" + allow { + protocol = "icmp" + } + target_tags = ["skz-opack"] + source_ranges = ["0.0.0.0/0"] +} + +resource "google_compute_firewall" "wireguard" { + name = "allow-wireguard" + network = "default" + direction = "INGRESS" + allow { + protocol = "udp" + ports = ["5353"] + } + target_tags = ["skz-opack"] + source_ranges = ["0.0.0.0/0"] +} + +resource "google_compute_firewall" "ssh" { + name = "allow-ssh" + network = "default" + direction = "INGRESS" + allow { + protocol = "tcp" + ports = ["22"] + } + target_tags = ["skz-opack"] + source_ranges = ["0.0.0.0/0"] +} diff --git a/server/id_ed25519.pub b/server/id_ed25519.pub new file mode 100644 index 0000000..3d2fc13 --- /dev/null +++ b/server/id_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHG+eIJBRWgko97xcSbp9EWI/LT82WKubSfYUvR7cErb sk4nz@psychopomp diff --git a/server/void-provision.sh b/server/void-provision.sh new file mode 100644 index 0000000..1f8be5f --- /dev/null +++ b/server/void-provision.sh @@ -0,0 +1,22 @@ +#!/bin/sh +set -e +set +x +packages="htop vim--no_x11 nload" +( + echo VOID: Starting provisioning. + sysctl -n kern.version + printf 'hw.smt=1\n' >> /etc/sysctl.conf + printf 'permit nopass :wheel\n' > /etc/doas.conf + pkg_add -u 2> /dev/null || pkg_add -u -D snap 2> /dev/null + pkg_add -Iv $packages 2> /dev/null || pkg_add -Iv -D snap $packages 2> /dev/null + while(pgrep -f reorder_kernel > /dev/null) do echo Waiting for reorder_kernel to finish...; sleep 10; done + syspatch 2> /dev/null || (echo "No syspatch, continuing..."; true) + rm -f /etc/ssh/ssh_host* + find /var/log -type f | while read f; do echo -ne '' > $f; done + find /tmp -type f | while read f; do echo -ne '' > $f; done + for part in $(df | tail -n+2 | awk '{print $6}'); do dd if=/dev/zero of=$part/EMPTY bs=1M 2> /dev/null || true; rm -f $part/EMPTY || true; done + sync + sync + echo OPACK: provisionning done. +) +exit 0 diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..e259253 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,26 @@ +DATE= $$(date "+%H:%M:%S") +CLIENTS= sk4nz test +HOSTNAME!= cat /etc/myname +CA_PASSWORD= yolo + +all: void + +void: /etc/iked.conf $(CLIENTS) + @echo ▒ $(DATE) Void complete + +$(CLIENTS): ca + ikectl ca void certificate $@.$(HOSTNAME) create + cp /etc/ssl/vpn/$@.$(HOSTNAME).crt /etc/iked/certs/ + ikectl ca void certificate $@.$(HOSTNAME) export + tar -C /tmp -xzf $@.$(HOSTNAME).tgz *pfx + ls + #cp /tmp/export/client1.domain.pfx /var/www/htdocs/client1.domain.pfx + ls -lah + ls -lah /tmp + @echo ░ $(DATE) Client $@ configured + +ca: + ikectl ca void create password $(CA_PASSWORD) + +/etc/iked.conf: + @echo ░ $(DATE) IKED configured