Compare commits

..

No commits in common. "main" and "main" have entirely different histories.
main ... main

15 changed files with 95 additions and 183 deletions

View file

@ -38,41 +38,6 @@ There's already a `.vscode` directory which should direct VSCode to enable the D
# Infrastructure # Infrastructure
## Setting up SSH access
You'll need to trust the SSH certificate authority that generates SSH keys for Epesooj's hosts.
The CA's public key is in `./host_config/ssh_certs/host_ca.pub`.
This is the template for the SSH `known_hosts` entry:
```
@cert-authority <dns name or ip address> <CONTENTS OF host_ca.pub>
```
For example:
```
@cert-authority code.akols.com ssh-ed25519 AAAA...
```
## Signing a user's public SSH key to give them host access
Run `just sign_user_key <username> <user_pub_key_path>`.
This will by default give them `root` access.
Check the definition of this `just` command to see how to give them access to different user(s).
Once this is done, give them the signed public key (it'll be a file in the same directory as `<user_pub_key_path>` with the `-cert.pub` suffix) and tell them to add the `CertificateFile` option to their SSH config to make sure it'll also present the signed public key.
For example:
```
Host epesooj
User root
HostName code.akols.com
IdentityFile ~/.ssh/epesooj_personal.pub
CertificateFile ~/.ssh/epesooj_personal-cert.pub
IdentitiesOnly yes
```
## Nixifying a new host ## Nixifying a new host
If you have a bunch of SSH keys in your SSH agent and get errors when trying to SSH into a fresh host, you may need to temporarily add the following config to your SSH config (obviously change the details for your case). If you have a bunch of SSH keys in your SSH agent and get errors when trying to SSH into a fresh host, you may need to temporarily add the following config to your SSH config (obviously change the details for your case).
@ -85,15 +50,7 @@ Host 188.245.194.78
IdentitiesOnly yes IdentitiesOnly yes
``` ```
Once you can SSH into the host normally, run `just nixify_host <hostname> "code" "<dns name>,<ip address>"`.
For example: `just nixify_host epesooj-code-0001 code "code.akols.com,188.245.194.78"`.
This command requires you to have the key for the Epesooj Host SSH certificate authority.
If you don't have it, contact someone who does.
## Deploying the webring ## Deploying the webring
You should have a `.env` file with the id and deploy key for each script in the webring, as well as a key to deploy the index page to bunny. You should have a `.env` file with the id and deploy key for each script in the webring, as well as a key to deploy the index page to bunny.
When you have this, run `deno task deploy`. When you have this, run `deno task deploy`.
You'll need the API keys required to deploy these.
If you don't have them, contact someone who does.

View file

@ -96,10 +96,6 @@
settings = { settings = {
PasswordAuthentication = false; PasswordAuthentication = false;
}; };
extraConfig = ''
HostCertificate /persisted/etc/ssh/ssh_host_ed25519_key-cert.pub
TrustedUserCAKeys /persisted/etc/ssh/user_cas.pub
'';
}; };
users.users.root = { users.users.root = {

103
flake.lock generated
View file

@ -7,11 +7,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1750903843, "lastModified": 1739841949,
"narHash": "sha256-Ng9+f0H5/dW+mq/XOKvB9uwvGbsuiiO6HrPdAcVglCs=", "narHash": "sha256-lSOXdgW/1zi/SSu7xp71v+55D5Egz8ACv0STkj7fhbs=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "83c4da299c1d7d300f8c6fd3a72ac46cb0d59aae", "rev": "15dbf8cebd8e2655a883b74547108e089f051bf0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -25,11 +25,11 @@
"nixpkgs-lib": "nixpkgs-lib" "nixpkgs-lib": "nixpkgs-lib"
}, },
"locked": { "locked": {
"lastModified": 1749398372, "lastModified": 1738453229,
"narHash": "sha256-tYBdgS56eXYaWVW3fsnPQ/nFlgWi/Z2Ymhyu21zVM98=", "narHash": "sha256-7H9XgNiGLKN1G1CgRh0vUL4AheZSYzPm+zmZ7vxbJdo=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "9305fe4e5c2a6fcf5ba6a3ff155720fbe4076569", "rev": "32ea77a06711b758da0ad9bd6a844c5740a87abd",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -38,18 +38,38 @@
"type": "github" "type": "github"
} }
}, },
"nil": { "flake-utils": {
"inputs": { "inputs": {
"nixpkgs": [ "systems": "systems"
"nixpkgs"
]
}, },
"locked": { "locked": {
"lastModified": 1751341694, "lastModified": 1731533236,
"narHash": "sha256-zXag1+8iZC3H5yVFP7KhIi4ps9z8xKrFIkyaeXlZ7Uo=", "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nil": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
],
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1732053863,
"narHash": "sha256-DCIVdlb81Fct2uwzbtnawLBC/U03U2hqx8trqTJB7WA=",
"owner": "oxalica", "owner": "oxalica",
"repo": "nil", "repo": "nil",
"rev": "b043bfe1f3f4c4be4b688e24c5ae96e81f525805", "rev": "2e24c9834e3bb5aa2a3701d3713b43a6fb106362",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -60,11 +80,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1751271578, "lastModified": 1740126099,
"narHash": "sha256-P/SQmKDu06x8yv7i0s8bvnnuJYkxVGBWLWHaU+tt4YY=", "narHash": "sha256-ozoOtE2hGsqh4XkTJFsrTkNxkRgShxpQxDynaPZUGxk=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "3016b4b15d13f3089db8a41ef937b13a9e33a8df", "rev": "32fb99ba93fea2798be0e997ea331dd78167f814",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -76,17 +96,14 @@
}, },
"nixpkgs-lib": { "nixpkgs-lib": {
"locked": { "locked": {
"lastModified": 1748740939, "lastModified": 1738452942,
"narHash": "sha256-rQaysilft1aVMwF14xIdGS3sj1yHlI6oKQNBRTF40cc=", "narHash": "sha256-vJzFZGaCpnmo7I6i416HaBLpC+hvcURh/BQwROcGIp8=",
"owner": "nix-community", "type": "tarball",
"repo": "nixpkgs.lib", "url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
"rev": "656a64127e9d791a334452c6b6606d17539476e2",
"type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "type": "tarball",
"repo": "nixpkgs.lib", "url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
"type": "github"
} }
}, },
"root": { "root": {
@ -96,6 +113,42 @@
"nil": "nil", "nil": "nil",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
} }
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"nil",
"nixpkgs"
]
},
"locked": {
"lastModified": 1731983527,
"narHash": "sha256-JECaBgC0pQ91Hq3W4unH6K9to8s2Zl2sPNu7bLOv4ek=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "71287228d96e9568e1e70c6bbfa3f992d145947b",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -21,7 +21,7 @@
systems = [ "x86_64-linux" ]; systems = [ "x86_64-linux" ];
imports = [ imports = [
./host_config ./code_server.nix
]; ];
flake = flake =

View file

@ -1,47 +0,0 @@
#!/usr/bin/env bash
set -euxo pipefail
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
host_ca_key="${SCRIPT_DIR}/ssh_certs/host_ca"
user_ca_pub="${SCRIPT_DIR}/ssh_certs/user_ca.pub"
if [ ! -f "${host_ca_key}" ]
then
echo "Host CA key not found."
exit 1
fi
if [ ! -f "${user_ca_pub}" ]
then
echo "Public User CA key not found."
exit 1
fi
temp=$(mktemp -d)
cleanup() {
rm -rf "${temp}"
}
# trap cleanup EXIT
host_type=$1
hostname=$2
extra_names=${3:-}
principal_names="${hostname}"
if [ ! -z "${extra_names}" ]
then
principal_names="${principal_names},${extra_names}"
fi
install -d -m755 "${temp}/persisted/etc/ssh"
ssh-keygen -t ed25519 -f "${temp}/persisted/etc/ssh/ssh_host_ed25519_key" -C '' -N ''
ssh-keygen -s ${host_ca_key} -I ${hostname} -h -n "${principal_names}" -V +52w "${temp}/persisted/etc/ssh/ssh_host_ed25519_key.pub"
cp "${user_ca_pub}" "${temp}/persisted/etc/ssh/user_cas.pub"
echo "${temp}"
#nix run github:nix-community/nixos-anywhere -- --extra-files "${temp}" --flake .#${host_type} --target-host root@${hostname}

View file

@ -1,25 +0,0 @@
#!/usr/bin/env bash
set -euxo pipefail
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
user_ca_key="${SCRIPT_DIR}/ssh_certs/user_ca"
if [ ! -f "${user_ca_key}" ]
then
echo "User CA key not found."
exit 1
fi
username=$1
principals=$2
user_pub=$3
if [ ! -f "${user_pub}" ]
then
echo "User public key not found."
exit 1
fi
ssh-keygen -s "${user_ca_key}" -I "${username}" -n "${principals}" -V +52w "${user_pub}"
echo "Done!"

View file

@ -1,2 +0,0 @@
host_ca
user_ca

View file

@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJygYxMUdGgApUE3KirRQVgG2X5zWurIBPbwEc10FxDi epesooj host ca

View file

@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINdiqYdA3pm9yKgR5hFlL7ZeSV3xeKH9HwyNwaxY6yZZ epesooj user ca

View file

@ -4,8 +4,5 @@ default:
build_nixos_config host_type="code": build_nixos_config host_type="code":
nix build .#nixosConfigurations.{{host_type}}.config.system.build.toplevel nix build .#nixosConfigurations.{{host_type}}.config.system.build.toplevel
nixify_host hostname host_type="code" extra_names="": nixify_host hostname host_type="code":
./host_config/bootstrap_host.sh {{host_type}} {{hostname}} {{extra_names}} nix run github:nix-community/nixos-anywhere -- --flake .#{{host_type}} --target-host root@{{hostname}}
sign_user_key username user_pub_key principals="root":
./host_config/sign_user_pub.sh {{username}} {{principals}} {{user_pub_key}}

View file

@ -90,21 +90,21 @@ export async function uploadFile(filepath: string, contents: Uint8Array) {
} }
} }
export async function purgeCDNCache() { export async function purgePath(filepath: string) {
const pullZoneIdEnvName = 'BUNNY_PULL_ZONE_ID'; const cdnBaseUrlEnvName = 'BUNNY_CDN_BASE_URL';
const pullZoneId = Deno.env.get(pullZoneIdEnvName); const cdnBaseUrl = Deno.env.get(cdnBaseUrlEnvName);
const accessKeyEnvName = 'BUNNY_ACCESS_KEY'; const accessKeyEnvName = 'BUNNY_ACCESS_KEY';
const accessKey = Deno.env.get(accessKeyEnvName); const accessKey = Deno.env.get(accessKeyEnvName);
if (pullZoneId === undefined) { if (cdnBaseUrl === undefined) {
throw new Error( throw new Error(
`Can't purge CDN cache for because we don't know the pull zone ID. Please set it by setting the environment variable '${pullZoneIdEnvName}'.` `Can't purge cache for '${filepath}' because we don't know the CDN base URL. Please set it by setting the environment variable '${cdnBaseUrlEnvName}'.`
); );
} }
if (accessKey === undefined) { if (accessKey === undefined) {
throw new Error( throw new Error(
`Can't purge CDN cache because we don't have an API key. Please set it by setting the environment variable '${accessKeyEnvName}'.` `Can't purge cache for '${filepath}' because we don't have an API key. Please set it by setting the environment variable '${accessKeyEnvName}'.`
); );
} }
@ -114,7 +114,9 @@ export async function purgeCDNCache() {
accesskey: accessKey, accesskey: accessKey,
}; };
const fetchUrl = `https://api.bunny.net/pullzone/${pullZoneId}/purgeCache`; const fetchUrl = new URL(`https://api.bunny.net/purge`);
fetchUrl.searchParams.append('async', 'false');
fetchUrl.searchParams.append('url', `${cdnBaseUrl}/${filepath}`);
const res = await fetch(fetchUrl.toString(), { const res = await fetch(fetchUrl.toString(), {
method: 'POST', method: 'POST',
@ -123,6 +125,6 @@ export async function purgeCDNCache() {
if (!res.ok) { if (!res.ok) {
console.error(await res.text()); console.error(await res.text());
throw new Error(`Failed to purge CDN cache: ${res.statusText}`); throw new Error(`Failed to purge cache: ${res.statusText}`);
} }
} }

View file

@ -1,5 +1,5 @@
import { join } from '@std/path'; import { join } from '@std/path';
import { deployScript, purgeCDNCache, uploadFile } from './bunny_api/main.ts'; import { deployScript, purgePath, uploadFile } from './bunny_api/main.ts';
if (import.meta.main) { if (import.meta.main) {
console.log(`Attempting to upload index.html`); console.log(`Attempting to upload index.html`);
@ -8,8 +8,8 @@ if (import.meta.main) {
await uploadFile('index.html', indexContents); await uploadFile('index.html', indexContents);
console.log(`Done!`); console.log(`Done!`);
console.log(`Attempting to purge the CDN cache.`); console.log(`Attempting to purge the cache for index.html`);
await purgeCDNCache(); await purgePath('index.html');
console.log(`Done!`); console.log(`Done!`);
for (const dirEntry of Deno.readDirSync( for (const dirEntry of Deno.readDirSync(

View file

@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<style> <style>
body { body {
overflow: hidden;
padding: 0; padding: 0;
margin: 0; margin: 0;
height: 100vh; height: 100vh;

View file

@ -52,23 +52,5 @@
"title": "Data Collection", "title": "Data Collection",
"author": "graphdev", "author": "graphdev",
"url": "https://blog.graphicalmethods.com" "url": "https://blog.graphicalmethods.com"
},
{
"id": "scottsmitelli",
"title": "Scott Smitelli - Articles",
"author": "Scott Smitelli",
"url": "https://www.scottsmitelli.com/articles/"
},
{
"id": "srxl",
"title": "ruby's site",
"author": "ruby iris juric",
"url": "https://foxgirl.engineering"
},
{
"id": "entropic",
"title": "Entropic",
"author": "Entropic",
"url": "https://entropic.mataroa.blog/"
} }
] ]