-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement user-machines for member-only VPS
This commit adds a NixVirt (libvirt-based) orchestration infrastructure that gives each ACM member (defined in user-machines/secrets/user-vms.json) their own persistent virtual machine.
- Loading branch information
1 parent
a5a6f71
commit 363d91a
Showing
15 changed files
with
771 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,5 @@ result | |
results | ||
/servers/exp* | ||
.envrc | ||
.venv | ||
.nixos-test-history |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
disable=SC2016 |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
{ config, lib, pkgs, ... }: | ||
|
||
let | ||
inherit (import <acm-aws/user-machines/vm/config.nix> { inherit pkgs; }) | ||
ips; | ||
in | ||
|
||
{ | ||
imports = [ | ||
<acm-aws/user-machines/vm> | ||
]; | ||
|
||
acm.user-vms = { | ||
enable = true; | ||
users = builtins.fromJSON (builtins.readFile <acm-aws/user-machines/secrets/user-vms.json>); | ||
# Pin all CPU usages to the 4 host cores. | ||
cpuPinning = [4 5 6 7]; | ||
poolDirectory = "/var/lib/acm-vm"; | ||
}; | ||
|
||
services.diamondburned.caddy.sites."https://vps.acmcsuf.com" = '' | ||
root * ${pkgs.writeTextDir "vps.json" (builtins.toJSON config.acm.user-vms.usersData)} | ||
rewrite * /vps.json | ||
file_server | ||
''; | ||
|
||
services.sshwifty = { | ||
enable = true; | ||
config = { | ||
Servers = [ | ||
{ | ||
ListenInterface = "127.0.0.1"; | ||
ListenPort = 38274; | ||
} | ||
]; | ||
Presets = map | ||
(offset: | ||
let | ||
ip = ips.ipFromOffset offset; | ||
in | ||
{ | ||
Title = "SSH to ${ip}"; | ||
Type = "SSH"; | ||
Host = "${ip}:22"; | ||
} | ||
) | ||
(ips.range); | ||
OnlyAllowPresetRemotes = true; | ||
}; | ||
}; | ||
|
||
services.diamondburned.caddy.sites."http://ssh.acmcsuf.com" = '' | ||
reverse_proxy * localhost:38274 | ||
''; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#!/usr/bin/env bash | ||
. "$(dirname "$0")/../scripts/lib/init" | ||
|
||
USERS_FILE="$(dirname "$0")/secrets/user-vms.json" | ||
USERS_ID_REGEX='^[a-zA-Z0-9\-_.]{1,32}$' | ||
|
||
main() { | ||
lib::require_installed uuidgen jq | ||
|
||
# Format the JSON file. | ||
users_jq '.' | lib::write_file "$USERS_FILE" | ||
|
||
# Guarantee that there are no null IDs. | ||
readarray -t nullUsers < <(users_jq -c '.[] | select(.id == null)') | ||
if (( ${#nullUsers[@]} > 0 )); then | ||
lib::log "Null IDs found in $USERS_FILE for the following users:" | ||
for user in "${nullUsers[@]}"; do | ||
lib::log " $user" | ||
done | ||
return 1 | ||
fi | ||
|
||
# Guarantee that all user IDs are unique. | ||
readarray -t duplicateIDs < <(users_jq -r '.[].id' | sort | uniq -d) | ||
if (( ${#duplicateIDs[@]} > 0 )); then | ||
lib::log "Duplicate user IDs found in $USERS_FILE for the following users:" | ||
for user in "${duplicateIDs[@]}"; do | ||
lib::log " - $user" | ||
done | ||
return 1 | ||
fi | ||
|
||
# Validate all user IDs. We ask jq to return one JSON string per line in | ||
# case the IDs have a new line. Ideally this should be never, but... | ||
readarray -t userIDs < <(users_jq '.[].id') | ||
for id in "${userIDs[@]}"; do | ||
# Trim the quotes manually then compare that result with the parsed JSON | ||
# string. None of our characters should require special escaping, so | ||
# manually trimming should just work. | ||
id="${id%\"}" | ||
id="${id#\"}" | ||
if [[ $id != $(jq -r -n --arg id "$id" '$id') ]]; then | ||
lib::logf "Invalid user ID %q found in %s." "$id" "$USERS_FILE" | ||
return 1 | ||
fi | ||
|
||
# Actually pass the ID through regex. | ||
if [[ ! $id =~ $USERS_ID_REGEX ]]; then | ||
lib::logf "Invalid user ID %q found in %s." "$id" "$USERS_FILE" | ||
return 1 | ||
fi | ||
done | ||
|
||
# Guarantee that all users have a unique UUID. | ||
readarray -t idsWithNoUUID < <(users_jq -r '.[] | select(.uuid == null) | .id') | ||
for id in "${idsWithNoUUID[@]}"; do | ||
uuid=$(uuidgen) | ||
dupe=$(users_jq --arg uuid "$uuid" -r '.[] | select(.uuid == $uuid) | .id') | ||
if [[ $dupe != "" ]]; then | ||
lib::fatal "uuidgen returned colliding UUID $uuid, please retry." | ||
fi | ||
|
||
lib::logf "Assigning user with ID %q UUID %s." "$id" "$uuid" | ||
users_jq \ | ||
--arg id "$id" \ | ||
--arg uuid "$uuid" \ | ||
'(.[] | select(.id == $id)).uuid = $uuid' | lib::write_file "$USERS_FILE" | ||
done | ||
} | ||
|
||
users_jq() { | ||
jq "$@" "$USERS_FILE" | ||
} | ||
|
||
if lib::is_main; then | ||
main "$@" | ||
fi |
Oops, something went wrong.