- Shell 100%
| bin | ||
| lib | ||
| fig.png | ||
| README.md | ||
Fig
Fig is configuration management for small infrastructure. It's written in Bash and aims to provide just enough structure to make it pleasant to configure a system with shell scripts.
The central concept in Fig is a module. Fig modules can specify a list of packages to install, and can provide an apply function which is called on every configured module during a fig apply. Fig provides several idempotent helper functions allowing placing of files, template generation, and more.
A module is a directory under modules/ which contains a module.sh file. Module names can contain slashes for namespacing, and in this case they appear as subdirectories somewhere under modules/. An example module.sh might look like:
packages=(
nginx
)
apply() {
ensure-file /etc/nginx/nginx.conf
ensure-service nginx
}
When applied, this example module will install the nginx package, copy the file files/etc/nginx/nginx.conf relative to the module root to /etc/nginx/nginx.conf in the filesystem, and then enable and start the nginx systemd service.
The collection of modules to be applied to a system is defined in index.sh in the root of your configuration repository. index.sh defines a modules array, and can populate this array however makes sense. For example, you might use a system's hostname to determine which modules are applied:
# apply the base module to all nodes
modules=(
base
)
# apply node-specific modules based on hostname
case "$(hostname -s)" in
web-server)
modules+=(nginx)
;;
dns-server)
modules+=(bind)
;;
esac
Getting started
-
Create a new Git repository for your configuration and
cdinto it:$ git init my-infra $ cd my-infra -
Add the Fig repository as a submodule at
figin the root of the repository:$ git submodule add https://github.com/haileys/fig fig -
Create the necessary file structure:
$ touch index.sh # the entrypoint to your fig configuration $ mkdir modules # fig modules go here
You're good to go! Use fig apply to apply your Fig config to the local machine, or fig apply-ssh to apply to a remote machine over SSH.
Lifecycle of fig apply
-
Load
index.shto determine modules to apply on this system -
Collect all
bootstrap_packagesfrom each configured module and install using system package manager -
Call
before-packagesfunction for each configured module -
Collect all
packagesfrom each configured module and install using system package manager -
Call
applyfunction for each configured module
Repository layout
/ # repo root
index.sh # fig entrypoint, defines `modules` array
modules/
foo/
module.sh # module definition for "foo"
files/
etc/
foo.txt # placed in /etc/foo.txt by `ensure-file`
gen/
etc/
magic.txt # executable script which generates /etc/magic.txt called by `ensure-gen`
bar/
module.sh # nested module definition for "foo/bar"
# NOTE: has no implicit relationship to "foo" module
Full module structure
# Packages listed in the `packages` array are installed using the system package manager.
packages=()
# The `apply` function is called after installing packages.
#
# Example use case: place config files and enable systemd services.
apply() {
true
}
# The `before-packages` function is called before installing packages.
#
# Example use case: setup third-party apt sources.
before-packages() {
true
}
# Packages listed in `bootstrap_packages` are installed before calling `before-packages`.
# Use sparingly, because there's no hook that comes before this one.
#
# Example use case: install gnupg for verifying third-party apt signatures, or install
# `ca-certificates` for accessing apt repos over https.
bootstrap_packages=()
Ensure helpers
ensure-service
usage: ensure-service service
Enables and starts systemd unit service.
ensure-file
usage: ensure-file path [source=source] [chown=chown] [chmod=chmod]
Places a file at path in the filesystem, sourcing from files/path by default.
-
source - path to source file, relative to module root
-
chown - arguments to chown(1), eg.
user,user:group,:group -
chmod - arguments to chmod(1), eg.
+w,u+wa+x,0755
ensure-dir
usage: ensure-dir path [chown=chown] [chmod=chmod]
Ensures path in the filesystem is a directory.
-
chown - arguments to chown(1), eg.
user,user:group,:group -
chmod - arguments to chmod(1), eg.
+w,u+wa+x,0755
ensure-gen
usage: ensure-gen path [template=template] [chown=chown] [chmod=chmod]
Executes a script to generate the contents of path in the filesystem, executing gen/path by default.
-
template - path to executable template file, relative to module root
-
chown - arguments to chown(1), eg.
user,user:group,:group -
chmod - arguments to chmod(1), eg.
+w,u+wa+x,0755
ensure-url
usage: ensure-url path url sha256=sha256 [chown=chown] [chmod=chmod]
Downloads file from url, validates checksum according to sha256, and places in filesystem at path.
-
sha256 - sha256 checksum for validation. mandatory
-
chown - arguments to chown(1), eg.
user,user:group,:group -
chmod - arguments to chmod(1), eg.
+w,u+wa+x,0755
ensure-user
usage: ensure-user user [groups=groups] [usergroup=1] [homedir=homedir] [createhome=1] [shell=shell] [uid=uid] [gid=gid]
Creates user with name user if user does not already exist.
⚠️ Does not make any changes if user with name user already exists.
-
groups - comma separated list of supplementary groups for new user, eg.
sudo,sudo,wheel -
usergroup - create group with same name as user
-
homedir - home directory of the new user
-
createhome - create the user's home directory
-
shell - login shell for new user
-
uid - uid for new user
-
gid - gid for new user
ensure-group
usage: ensure-group group [gid=gid]
Creates group with name group if group does not already exist.
⚠️ Does not make any changes if group with name group already exists.
- gid - gid for new group
ensure-ssh-keygen
usage: ensure-ssh-keygen user [type=type] [file=file]
Ensures SSH key exists for user at file.
-
type -
-tparameter to ssh-keygen(1), defaults toed25519 -
file - file path for SSH key, defaults to
~user/.ssh/id_type
Fig icon in fig.png designed by Freepik, sourced from https://www.freepik.com/icon/fig_13324385