Compare commits
No commits in common. "main" and "main" have entirely different histories.
14 changed files with 17 additions and 146 deletions
43
README.md
43
README.md
|
@ -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.
|
|
||||||
|
|
|
@ -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 = {
|
|
@ -21,7 +21,7 @@
|
||||||
systems = [ "x86_64-linux" ];
|
systems = [ "x86_64-linux" ];
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
./host_config
|
./code_server.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
flake =
|
flake =
|
||||||
|
|
|
@ -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}
|
|
|
@ -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!"
|
|
2
host_config/ssh_certs/.gitignore
vendored
2
host_config/ssh_certs/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
host_ca
|
|
||||||
user_ca
|
|
|
@ -1 +0,0 @@
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJygYxMUdGgApUE3KirRQVgG2X5zWurIBPbwEc10FxDi epesooj host ca
|
|
|
@ -1 +0,0 @@
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINdiqYdA3pm9yKgR5hFlL7ZeSV3xeKH9HwyNwaxY6yZZ epesooj user ca
|
|
7
justfile
7
justfile
|
@ -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}}
|
|
||||||
|
|
|
@ -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}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -52,11 +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/"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Add table
Reference in a new issue