# quickcfg [github](https://github.com/udoprog/quickcfg) [crates.io](https://crates.io/crates/quickcfg) [docs.rs](https://docs.rs/quickcfg) [build status](https://github.com/udoprog/quickcfg/actions?query=branch%3Amain) Apply a base configuration to a system, quickly! It reads a configuration and template structure from a [dotfiles] directory and tries to normalize the machine that it is run base on this configuration. **WARNING**: This project is currently in development. I've tried my best to make all operations non-destructive, but beware of bugs! [dotfiles]: https://github.com/udoprog/dotfiles ![Example](gfx/example1.gif)
## Getting started To get started, you can have quickcfg clone the configuration for you in the default location: ```bash qc --init ``` This will put the checked out configuration in the default config location for you platform. For example: * Windows - `%APPDATA%\quickcfg` * Linux - `$HOME/.config/quickcfg` To find out where the various quickcfg directories are, use: ```bash qc --paths ```
## Features **Zero dependencies**, All you need is the `quickcfg` binary and your configuration repo. **Blazingly fast**, multi-threaded and uses a simple dependency graph to determine when things can run in parallel. **Flexible but opinionated manifests**, There are a couple of powerful primitives available (e.g. `copy-dir`), which does _a lot_ of work with very little configuration. **Uses fast checksumming**, to reduce the amount of unnecessary work. Only applies changes when it has to.
## Automatically applying updates If you want quickcfg to periodically check your git repositories for updates, you can add the following to your `.zshrc` or `.bashrc`: ```bash if command -v qc > /dev/null 2>&1; then qc --updates-only alias upd="qc" fi ``` Every time you open a shell quickcfg will not check if your dotfiles are up-to-date. You control how frequently by setting the `git_refresh` option in `quickcfg.yml`: ```no_test git_refresh: 3d ```
## Configuration Create a repository with a `quickcfg.yml` in its root: ```no_test git_refresh: 1d hierarchy: - secrets.yml - db/common.yml - db/{distro}.yml systems: # System to ensure that a set of packages are installed. - type: install ``` You also want to add a `.gitignore` file that looks like this: ```gitignore /secrets.yml /.state.yml /.state ``` Then populate `secrets.yml` with your secret information - this you **DO NOT** check into git. Any variables you put in here can be used in future templates since they are part of the hierarchy. The [`hierarchy`] specifies a set of files that should be looked for. These can use variables like `{distro}`, which will be expanded based on the facts known of the system you are running on. You can use my [dotfiles](https://github.com/udoprog/dotfiles) repository as inspiration. The following section will detail all the systems which are available. [`hierarchy`]: #hierarchy
## Hierarchy The hierarchy is a collection of files which contain data. Some systems query the hierarchy for information, like the `key` setting in [`install`]. This then determines which packages should be installed. Hierarchy variables can also be made available in [`templates`] by adding a `quickcfg:` tag at the top of the template. [`install`]: #install [`templates`]: #templating
## Systems
#### `copy-dir` Copies a directory recursively. ```yaml type: copy-dir from: ./some/dir to: home://some/dir templates: false ``` Will copy a directory recursively.
#### `link-dir` Links a directory recursively. ```yaml type: link-dir # Directory to link from. from: ./some/dir # Directory to link towards. to: home://some/dir ``` Will create the corresponding directory structure, but all files will be symbolic links.
#### `git-sync` System that syncs a single git repository to some path. ```yaml type: git-sync # Where to clone. path: home://.oh-my-zsh # Remote to clone. remote: https://github.com/robbyrussell/oh-my-zsh.git # Refresh once per day. refresh: 1d ```
#### `install` Compares the set of installed packages, with a set of packages from the hierarchy to install and installs any that are missing. Will use `sudo` if needed to install packages. ```yaml type: install # The provider of the package manager to use. provider: pip3 # Hierarchy key to lookup for packages to install. key: pip3::packages ``` The simplest example of this system is the one that uses the primary provider: ```yaml systems: - type: install ``` This will look up packages under the `packages` key and install it using the primary provider for the system that you are currently running. These are the supported providers: * `debian`: For Debian-based systems. This is a _primary_ provider. * `pip`: The Python 2 package manager. * `pip3`: The Python 3 package manager. * `gem`: The Ruby package manager. * `cargo`: Install packages using `cargo`. * `rust components`: Rust components using `rustup`. * Key: `rust::components` * `rust toolchains`: Rust toolchains using `rustup`. * Key: `rust::toolchains` By default, any _primary_ provider will be the default provider of the system if it can be detected. Explicitly configured providers look up packages based on the hierarchy key `::packages`. Default providers use the key `packages`.
#### `download` Downloads a single file into the given target path. ```yaml type: download id: plug-vim # Url to download the command from. url: https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim # Path to download to. path: home://.config/nvim/autoload/plug.vim ``` The `id` is to uniquely identify that this system has only been run once.
#### `download-and-run` Downloads a script of the internet and runs it once. ```yaml type: download-and-run id: install-oh-my-zsh # Url to download the command from. url: https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh # Set to `true` if the downloaded command requires interaction. (default: false) interactive: true # Set to `true` if the command must be run through a shell (`/bin/sh`). (default: false). shell: true ``` The `id` is to uniquely identify that this system has only been run once.
#### `link` Creates a symlink. ```yaml type: link path: home://.vimrc link: .vim/vimrc ``` This creates a symbolic link at `path` which contains whatever is specified in `link`.
#### `only-for` Limit a set of systems based on a condition. ```yaml type: only-for os: windows systems: # Download and install Rust - type: download-and-run name: rustup-init.exe id: install-rust url: https://win.rustup.rs/x86_64 args: ["-y"] ```
## Templating Some systems treats files as templates, like [`copy-dir`] when the `templating` option is enabled. Any file being copied is then treated as a [`handlebars`] template. Any template file can make use of hierarchy data, by specifying their dependencies using a `quickcfg:` tag at the top of the file, like this: ```no_test # quickcfg: name, hobbies:array Hi, my name is {{name}} My hobbies are: {{#each hobbies}} - {{this}} {{/#each}} ``` This will load the `name` and `hobbies` variables out of the [`hierarchy`]. `hobbies` will be loaded as an array, causing all values in the hierarchy for that value to be loaded. [`copy-dir`]: #copy-dir [`handlebars`]: https://handlebarsjs.com/