init
This commit is contained in:
commit
642869ce9b
27 changed files with 1414 additions and 0 deletions
318
flake.nix
Normal file
318
flake.nix
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
{
|
||||
description = "Basic MediaWiki primary + replica deployment";
|
||||
|
||||
nixConfig = {
|
||||
max-jobs = "auto";
|
||||
cores = 0;
|
||||
};
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
agenix = {
|
||||
url = "github:ryantm/agenix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
deploy-rs = {
|
||||
url = "github:serokell/deploy-rs";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
disko = {
|
||||
url = "github:nix-community/disko";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
nixos-anywhere = {
|
||||
url = "github:nix-community/nixos-anywhere";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
agenix,
|
||||
deploy-rs,
|
||||
disko,
|
||||
nixos-anywhere,
|
||||
...
|
||||
}:
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
lib = nixpkgs.lib;
|
||||
|
||||
siteConfig = rec {
|
||||
wikiName = "Noisebridge";
|
||||
baseDomain = "noisebridge.net";
|
||||
replicaSubdomain = "replica";
|
||||
sshUser = "root";
|
||||
primaryHostName = "main-wiki";
|
||||
replicaHostName = "replica-wiki";
|
||||
|
||||
database = {
|
||||
name = "noisebridge_mediawiki";
|
||||
mediawikiUser = "wiki";
|
||||
replicationUser = "repl";
|
||||
};
|
||||
|
||||
hosts = {
|
||||
primary = {
|
||||
nixosName = primaryHostName;
|
||||
tailscaleName = primaryHostName;
|
||||
};
|
||||
replica = {
|
||||
nixosName = replicaHostName;
|
||||
tailscaleName = replicaHostName;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkPublicDomain =
|
||||
role:
|
||||
if role == "primary" then
|
||||
siteConfig.baseDomain
|
||||
else
|
||||
"${siteConfig.replicaSubdomain}.${siteConfig.baseDomain}";
|
||||
|
||||
mkHostMeta =
|
||||
role:
|
||||
siteConfig.hosts.${role}
|
||||
// {
|
||||
inherit role;
|
||||
publicDomain = mkPublicDomain role;
|
||||
};
|
||||
|
||||
mkHost =
|
||||
{
|
||||
hostMeta,
|
||||
hostModule,
|
||||
roleModules,
|
||||
}:
|
||||
lib.nixosSystem {
|
||||
inherit system;
|
||||
specialArgs = {
|
||||
inherit agenix siteConfig hostMeta;
|
||||
};
|
||||
modules = [
|
||||
agenix.nixosModules.default
|
||||
disko.nixosModules.disko
|
||||
hostModule
|
||||
./disk-config.nix
|
||||
./modules/common.nix
|
||||
./modules/security.nix
|
||||
./modules/tailscale.nix
|
||||
./modules/caddy.nix
|
||||
./modules/mediawiki-base.nix
|
||||
]
|
||||
++ roleModules;
|
||||
};
|
||||
|
||||
primaryMeta = mkHostMeta "primary";
|
||||
replicaMeta = mkHostMeta "replica";
|
||||
in
|
||||
{
|
||||
nixosConfigurations = {
|
||||
main-wiki = mkHost {
|
||||
hostMeta = primaryMeta;
|
||||
hostModule = ./hosts/main-wiki;
|
||||
roleModules = [
|
||||
./modules/wiki-primary/mysql.nix
|
||||
./modules/wiki-primary/mediawiki.nix
|
||||
];
|
||||
};
|
||||
|
||||
replica-wiki = mkHost {
|
||||
hostMeta = replicaMeta;
|
||||
hostModule = ./hosts/replica-wiki;
|
||||
roleModules = [
|
||||
./modules/wiki-replica/mysql.nix
|
||||
./modules/wiki-replica/mediawiki.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
deploy.nodes = {
|
||||
main-wiki = {
|
||||
hostname = primaryMeta.tailscaleName;
|
||||
profiles.system = {
|
||||
user = siteConfig.sshUser;
|
||||
sshUser = siteConfig.sshUser;
|
||||
path = deploy-rs.lib.${system}.activate.nixos self.nixosConfigurations.main-wiki;
|
||||
};
|
||||
};
|
||||
|
||||
replica-wiki = {
|
||||
hostname = replicaMeta.tailscaleName;
|
||||
profiles.system = {
|
||||
user = siteConfig.sshUser;
|
||||
sshUser = siteConfig.sshUser;
|
||||
path = deploy-rs.lib.${system}.activate.nixos self.nixosConfigurations.replica-wiki;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
checks = builtins.mapAttrs (_: deployLib: deployLib.deployChecks self.deploy) deploy-rs.lib;
|
||||
|
||||
apps.${system} = {
|
||||
deploy = {
|
||||
type = "app";
|
||||
program = "${pkgs.writeShellScript "deploy-noisebridge" ''
|
||||
if [ "$#" -eq 0 ] || [ "''${1#-}" != "$1" ]; then
|
||||
exec ${deploy-rs.packages.${system}.default}/bin/deploy \
|
||||
--auto-rollback true \
|
||||
--magic-rollback true \
|
||||
path:.# \
|
||||
"$@"
|
||||
fi
|
||||
|
||||
exec ${deploy-rs.packages.${system}.default}/bin/deploy \
|
||||
--auto-rollback true \
|
||||
--magic-rollback true \
|
||||
"$@"
|
||||
''}";
|
||||
meta.description = "Deploy all Noisebridge wiki hosts by default";
|
||||
};
|
||||
|
||||
bootstrap-host = {
|
||||
type = "app";
|
||||
program = "${pkgs.writeShellScript "bootstrap-host" ''
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
nix run .#bootstrap-host -- <main-wiki|replica-wiki> <target-host> [ssh-identity-file]
|
||||
nix run .#bootstrap-host -- <main-target-host> <replica-target-host> [ssh-identity-file]
|
||||
|
||||
Examples:
|
||||
nix run .#bootstrap-host -- main-wiki root@203.0.113.10 ~/.ssh/do-bootstrap
|
||||
nix run .#bootstrap-host -- root@203.0.113.10 root@203.0.113.11 ~/.ssh/do-bootstrap
|
||||
EOF
|
||||
}
|
||||
|
||||
if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
repo_root="$(pwd)"
|
||||
if [ ! -f "$repo_root/flake.nix" ]; then
|
||||
printf 'Run bootstrap-host from the repo root\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ssh_identity_file=""
|
||||
main_target=""
|
||||
replica_target=""
|
||||
selected_host=""
|
||||
|
||||
case "$1" in
|
||||
main-wiki|replica-wiki)
|
||||
selected_host="$1"
|
||||
if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
if [ "$selected_host" = "main-wiki" ]; then
|
||||
main_target="$2"
|
||||
else
|
||||
replica_target="$2"
|
||||
fi
|
||||
ssh_identity_file="''${3:-}"
|
||||
;;
|
||||
*)
|
||||
main_target="$1"
|
||||
replica_target="$2"
|
||||
ssh_identity_file="''${3:-}"
|
||||
;;
|
||||
esac
|
||||
|
||||
install_root="$(mktemp -d)"
|
||||
cleanup() {
|
||||
rm -rf "$install_root"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
ensure_host_key() {
|
||||
local host_name="$1"
|
||||
local private_key_file="$repo_root/.bootstrap/$host_name/host.age"
|
||||
local public_key_file="$repo_root/secrets/hosts/$host_name.age.pub"
|
||||
local public_key
|
||||
|
||||
mkdir -p "$(dirname "$private_key_file")" "$(dirname "$public_key_file")"
|
||||
|
||||
if [ ! -s "$private_key_file" ]; then
|
||||
public_key="$(${pkgs.age}/bin/age-keygen -o "$private_key_file" | sed 's/^Public key: //')"
|
||||
chmod 600 "$private_key_file"
|
||||
printf 'Generated host age key for %s\n' "$host_name"
|
||||
else
|
||||
public_key="$(${pkgs.age}/bin/age-keygen -y "$private_key_file")"
|
||||
printf 'Reused existing host age key for %s\n' "$host_name"
|
||||
fi
|
||||
|
||||
printf '%s\n' "$public_key" > "$public_key_file"
|
||||
}
|
||||
|
||||
run_bootstrap() {
|
||||
local host_name="$1"
|
||||
local target_host="$2"
|
||||
local private_key_file="$repo_root/.bootstrap/$host_name/host.age"
|
||||
local -a nixos_anywhere_args
|
||||
|
||||
mkdir -p "$install_root/var/lib/agenix"
|
||||
${pkgs.coreutils}/bin/install -m 0400 "$private_key_file" "$install_root/var/lib/agenix/host.age"
|
||||
|
||||
nixos_anywhere_args=(
|
||||
--extra-files "$install_root"
|
||||
--flake "path:$repo_root#$host_name"
|
||||
)
|
||||
|
||||
if [ -n "$ssh_identity_file" ]; then
|
||||
nixos_anywhere_args+=( -i "$ssh_identity_file" )
|
||||
fi
|
||||
|
||||
printf 'Bootstrapping %s onto %s\n' "$host_name" "$target_host"
|
||||
${
|
||||
nixos-anywhere.packages.${system}.default
|
||||
}/bin/nixos-anywhere "''${nixos_anywhere_args[@]}" "$target_host"
|
||||
rm -f "$install_root/var/lib/agenix/host.age"
|
||||
}
|
||||
|
||||
if [ -n "$main_target" ]; then
|
||||
ensure_host_key main-wiki
|
||||
fi
|
||||
if [ -n "$replica_target" ]; then
|
||||
ensure_host_key replica-wiki
|
||||
fi
|
||||
|
||||
printf 'Rekeying agenix secrets\n'
|
||||
${agenix.packages.${system}.default}/bin/agenix -r
|
||||
|
||||
if [ -n "$main_target" ]; then
|
||||
run_bootstrap main-wiki "$main_target"
|
||||
fi
|
||||
if [ -n "$replica_target" ]; then
|
||||
run_bootstrap replica-wiki "$replica_target"
|
||||
fi
|
||||
|
||||
printf '\nBootstrap complete. The hosts should now join Tailscale using their configured hostnames.\n'
|
||||
''}";
|
||||
meta.description = "Install NixOS on one or both raw hosts and seed agenix identities";
|
||||
};
|
||||
};
|
||||
|
||||
devShells.${system}.default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
agenix.packages.${system}.default
|
||||
deploy-rs.packages.${system}.default
|
||||
nixos-anywhere.packages.${system}.default
|
||||
mariadb.client
|
||||
rsync
|
||||
curl
|
||||
jq
|
||||
age
|
||||
openssl
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue