mirror of
https://github.com/Smaug123/PulumiConfig
synced 2025-10-08 10:08:40 +00:00
Use Pulumi to provision and Nix to configure (#12)
This commit is contained in:
@@ -1,47 +1,18 @@
|
||||
namespace PulumiWebServer
|
||||
|
||||
open System
|
||||
open System.Diagnostics
|
||||
open System.IO
|
||||
open System.Reflection
|
||||
open Pulumi
|
||||
open Pulumi.Command.Remote
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Server =
|
||||
|
||||
let createUser (PrivateKey privateKey) (address : Address) (name : BashString) =
|
||||
let args = CommandArgs ()
|
||||
args.Connection <- Command.connection privateKey address
|
||||
|
||||
args.Create <- $"useradd --no-create-home --no-user-group {name} 2>/dev/null 1>/dev/null || echo {name}"
|
||||
|
||||
Command ($"create-user-{name}", args)
|
||||
|
||||
let rec waitForReady (PrivateKey privateKey as pk) (address : Address) : Output<unit> =
|
||||
output {
|
||||
let psi = ProcessStartInfo "/usr/bin/ssh"
|
||||
|
||||
psi.Arguments <-
|
||||
$"root@{address.Get ()} -o ConnectTimeout=5 -o IdentityFile={privateKey.FullName} -o StrictHostKeyChecking=off echo hello"
|
||||
|
||||
psi.RedirectStandardError <- true
|
||||
psi.RedirectStandardOutput <- true
|
||||
psi.UseShellExecute <- false
|
||||
let proc = psi |> Process.Start
|
||||
proc.WaitForExit ()
|
||||
let output = proc.StandardOutput.ReadToEnd ()
|
||||
let error = proc.StandardOutput.ReadToEnd ()
|
||||
// We don't expect to have configured SSH yet, so this is fine.
|
||||
if proc.ExitCode = 0 && output.StartsWith "hello" then
|
||||
// For some reason /usr/bin/ssh can get in at this point even though Pulumi cannot :(
|
||||
// error: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain
|
||||
|
||||
System.Threading.Thread.Sleep (TimeSpan.FromSeconds 10.0)
|
||||
return ()
|
||||
else
|
||||
printfn $"Sleeping due to: {proc.ExitCode} {error}"
|
||||
System.Threading.Thread.Sleep (TimeSpan.FromSeconds 5.0)
|
||||
return! waitForReady pk address
|
||||
}
|
||||
let waitForReady (id : int) (PrivateKey privateKey) (address : Address) : Pulumi.Command.Local.Command =
|
||||
let args = Pulumi.Command.Local.CommandArgs ()
|
||||
args.Create <- Input.lift $"/bin/sh waitforready.sh {address.Get ()} {privateKey.FullName}"
|
||||
args.Dir <- Input.lift (FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName)
|
||||
Pulumi.Command.Local.Command ($"wait-for-ready-{id}", args)
|
||||
|
||||
let infectNix (PrivateKey privateKey) (address : Address) =
|
||||
let args = CommandArgs ()
|
||||
@@ -60,102 +31,6 @@ fi && mkdir -p /preserve/nixos && cp /etc/nixos/* /preserve/nixos && touch /pres
|
||||
|
||||
Command ("nix-infect", args)
|
||||
|
||||
let writeFlake (trigger : Output<'a>) (privateKey : PrivateKey) (address : Address) =
|
||||
let flakeFile = Utils.getEmbeddedResource typeof<PrivateKey>.Assembly "flake.nix"
|
||||
let flakeLock = Utils.getEmbeddedResource typeof<PrivateKey>.Assembly "flake.lock"
|
||||
|
||||
[
|
||||
{
|
||||
WriteConfigFile =
|
||||
Command.contentAddressedCopy
|
||||
privateKey
|
||||
address
|
||||
"write-flake"
|
||||
trigger
|
||||
"/preserve/nixos/flake.nix"
|
||||
flakeFile
|
||||
EnableConfig = []
|
||||
}
|
||||
{
|
||||
WriteConfigFile =
|
||||
Command.contentAddressedCopy
|
||||
privateKey
|
||||
address
|
||||
"write-flake-lock"
|
||||
trigger
|
||||
"/preserve/nixos/flake.lock"
|
||||
flakeLock
|
||||
EnableConfig = []
|
||||
}
|
||||
]
|
||||
|
||||
let private writeUserConfig
|
||||
(trigger : Output<'a>)
|
||||
(keys : SshKey seq)
|
||||
(Username username)
|
||||
(privateKey : PrivateKey)
|
||||
(address : Address)
|
||||
: Command
|
||||
=
|
||||
let keys =
|
||||
keys
|
||||
|> Seq.collect (fun k -> k.PublicKeyContents.Split '\n')
|
||||
|> Seq.filter (not << String.IsNullOrEmpty)
|
||||
|
||||
let userConfig =
|
||||
Utils.getEmbeddedResource typeof<PrivateKey>.Assembly "userconfig.nix"
|
||||
|> fun s ->
|
||||
s
|
||||
.Replace("@@AUTHORIZED_KEYS@@", keys |> String.concat "\" \"")
|
||||
.Replace ("@@USER@@", username)
|
||||
|
||||
Command.contentAddressedCopy
|
||||
privateKey
|
||||
address
|
||||
"write-user-config"
|
||||
trigger
|
||||
"/preserve/nixos/userconfig.nix"
|
||||
userConfig
|
||||
|
||||
let private loadUserConfig (onChange : Output<'a>) (PrivateKey privateKey) (address : Address) =
|
||||
let args = CommandArgs ()
|
||||
|
||||
args.Triggers <- onChange |> Output.map (unbox<obj> >> Seq.singleton) |> InputList.ofOutput
|
||||
|
||||
args.Connection <- Command.connection privateKey address
|
||||
|
||||
Command.addToNixFileCommand args "userconfig.nix"
|
||||
|
||||
Command ("configure-users", args, Command.deleteBeforeReplace)
|
||||
|
||||
let configureUser<'a>
|
||||
(infectNixTrigger : Output<'a>)
|
||||
(remoteUser : Username)
|
||||
(keys : SshKey seq)
|
||||
(privateKey : PrivateKey)
|
||||
(address : Address)
|
||||
: Module
|
||||
=
|
||||
let writeConfig =
|
||||
writeUserConfig infectNixTrigger keys remoteUser privateKey address
|
||||
|
||||
{
|
||||
WriteConfigFile = writeConfig
|
||||
EnableConfig = loadUserConfig writeConfig.Stdout privateKey address |> List.singleton
|
||||
}
|
||||
|
||||
let nixRebuild (counter : int) (onChange : Output<'a>) (PrivateKey privateKey) (address : Address) =
|
||||
let args = CommandArgs ()
|
||||
args.Connection <- Command.connection privateKey address
|
||||
// The rebuild fails with exit code 1, indicating that we need to restart. This is fine.
|
||||
args.Create <-
|
||||
// TODO /nix/var/nix/profiles/system/sw/bin/nixos-rebuild might do it
|
||||
"$(find /nix/store -type f -name nixos-rebuild | head -1) switch --flake /preserve/nixos#nixos-server || exit 0"
|
||||
|
||||
args.Triggers <- onChange |> Output.map (unbox<obj> >> Seq.singleton) |> InputList.ofOutput
|
||||
|
||||
Command ($"nixos-rebuild-{counter}", args)
|
||||
|
||||
let reboot (stage : string) (onChange : Output<'a>) (PrivateKey privateKey) (address : Address) =
|
||||
let args = CommandArgs ()
|
||||
args.Connection <- Command.connection privateKey address
|
||||
@@ -166,11 +41,3 @@ fi && mkdir -p /preserve/nixos && cp /etc/nixos/* /preserve/nixos && touch /pres
|
||||
"while ! ls /preserve/ready.txt ; do sleep 10; done && rm -f /preserve/ready.txt && shutdown -r now"
|
||||
|
||||
Command ($"reboot-{stage}", args)
|
||||
|
||||
let copyPreserve (PrivateKey privateKey) (address : Address) =
|
||||
let args = CommandArgs ()
|
||||
args.Connection <- Command.connection privateKey address
|
||||
|
||||
args.Create <- "mkdir /preserve && cp -ar /old-root/preserve/nixos /preserve/nixos"
|
||||
|
||||
Command ("copy-preserve", args)
|
||||
|
Reference in New Issue
Block a user