Skip to navigation

Your first configuration

This walkthrough manages a directory and a file on one host. Run it on a disposable Ubuntu 24.04 machine or VM, because it makes real changes. To drive the host from a Mac or another machine instead, follow the same steps with --target in place of --local; see SSH from a controller.

Describe the desired state

Create configuration/main.hcl. The same file is in the repository at examples/file/main.hcl.

file "directory" {
path = "/var/lib/rivet-example"
ensure = "directory"
mode = "0755"
}
file "message" {
path = "/var/lib/rivet-example/message.txt"
content = "managed by rivet\n"
mode = "0644"
meta {
depends_on = [file.directory]
}
}

Each block is a resource: a type (file), a label you choose ("message"), and the properties you want. The label identifies the declaration; path identifies the object on the host. depends_on orders the directory first. Rivet would also infer that ordering here, because the directory is the file’s parent.

Collect facts and compile

umask 077
rivet facts --local > facts.json
rivet compile ./configuration --facts facts.json --out first.bundle
rivet graph first.bundle
Compiled 2 resources, digest c076537d80561d9902e1ed74009f714988266267f22fa3d63f6550ef615a9eba
file.directory
file.message
file.directory -> file.message (DependsOn)
file.directory -> file.message (Expression)

facts.json describes this host. Compiling against it produces a bundle bound to this machine. graph lists resources in the order they will run and explains each edge. Compilation never overwrites an existing file, so use a new bundle name each time you compile.

Preview and apply

rivet plan first.bundle --local
WouldChange file.directory [ensure]
Deferred file.message [] Prerequisite changes have not been observed

The plan predicts that the directory will be created. It can’t predict the file yet, because the directory it lives in doesn’t exist, so the file is Deferred. Planning writes nothing.

sudo rivet apply first.bundle --local
Changed file.directory [ensure]
Changed file.message [ensure]

Apply it again and nothing changes:

Unchanged file.directory []
Unchanged file.message []

Repair drift

Edit the file by hand, then apply the same bundle again:

echo drift | sudo tee /var/lib/rivet-example/message.txt
sudo rivet apply first.bundle --local
Unchanged file.directory []
Changed file.message [content]

Rivet inspects each resource before acting, so it notices the edit and restores the content. Only declared properties are managed: if you removed mode from the file declaration, Rivet would stop managing the mode and leave whatever is there.

Add --format json to any of these commands for a full report. Run sudo rivet journal --local to see unresolved work, which is [] after a clean run.

Clean up

To remove what you created, set ensure = "absent" on both resources, remove content, mode, and the meta block, then compile a new bundle and apply it. Rivet removes the file before the directory. See file for removal rules.

Next, manage an application with a validated config file and a service that restarts when it changes.