• Stars
    star
    931
  • Rank 49,076 (Top 1.0 %)
  • Language
    Shell
  • Created over 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A configuration manager for Arch Linux

aconfmgr: A configuration manager for Arch Linux
testCoverage StatusDiscussions

aconfmgr is a package to track, manage, and restore the configuration of an Arch Linux system. Its goals are:

  • Quickly configure a new system, or restore an existing system according to a saved configuration
  • Track temporary/undesired changes to the system's configuration
  • Identify obsolete packages and maintain a lean system

aconfmgr tracks the list of installed packages (both native and external), as well as changes to configuration files (/etc/). Since the system configuration is described as shell scripts, it is trivially extensible.

screenshot

Table of Contents

Usage

Installation

Simply clone (or download+unzip) the GitHub repository. aconfmgr will install dependencies as needed during execution. An AUR package is also available.

First run

Run aconfmgr save to transcribe the system's configuration to the configuration directory. This will create the file 99-unsorted.sh in the configuration directory, as well as other files describing the system configuration. (The configuration directory will usually be ~/.config/aconfmgr, or ./config if running directly from git, or it can be overridden with -c.)

On the first run, aconfmgr will likely include some files which you may not want to include in your system configuration. These can be temporary or auto-generated files which are not directly owned by a package. To prevent aconfmgr from including these files in the configuration, create e.g. 10-ignores.sh in the configuration directory, with the lines e.g. IgnorePath '/path/to/file.ext' or IgnorePath '/path/to/dir/*'. (See ignoring files for details.) Delete everything from the configuration directory except that file and re-run aconfmgr save to regenerate a configuration minding these ignore rules.

Once aconfmgr save finishes, you should review the contents of 99-unsorted.sh, and sort it into one or more new files (e.g.: 10-base.sh, 20-drivers.sh, 30-gui.sh, 50-misc.sh ...). The files should have a .sh extension, and use bash syntax. I suggest adding a comment for each package describing why installing the package was needed, so it is clear when the package is no longer needed and can be removed.

During this process, you may identify packages or system changes which are no longer needed. Do not sort them into your configuration files - instead, delete the file 99-unsorted.sh, and run aconfmgr apply. This will synchronize the system state against your configuration, thus removing the omitted packages. (You will be given a chance to confirm all changes before they are applied.)

Note: you don't need to run aconfmgr via sudo. It will elevate as necessary by invoking sudo itself.

Maintenance

The configuration directory should be versioned using a version control system (e.g. Git). Ideally, the file 99-unsorted.sh should not be versioned - it will only be created when the current configuration does not reflect the current system state, therefore indicating that there are system changes that have not been accounted for.

Periodic maintenance consists of running aconfmgr save; if this results in uncommitted changes to the configuration directory, then there are unaccounted system changes. The changes should be reviewed, sorted, documented, committed and pushed.

Restoring

To restore a system to its earlier state, or to set up a new system, simply make sure the correct configuration is in the configuration directory and run aconfmgr apply. You will be able to preview and confirm any actual system changes.

Modus operandi

The aconfmgr script has two subcommands:

  • aconfmgr save calculates the difference between the current system's configuration and the configuration described by the configuration directory, and writes it back to the configuration directory.
  • aconfmgr apply applies the difference between the configuration described by the configuration directory and the current system's configuration, installing/removing packages and creating/editing configuration files.

The configuration directory contains shell scripts, initially generated by the save subcommand, and then usually edited by the user. Evaluating these scripts will compile a system configuration description in the output directory. The difference between that directory's contents, and the actual current system configuration, dictates the actions ultimately taken by aconfmgr.

aconfmgr save will write the difference to the file 99-unsorted.sh (under the configuration directory) as a series of shell commands which attempt to bring the configuration up to date with the current system. When starting with an empty configuration, this difference will consist of the entire system description. Since the script only appends to that file, it may end up undoing configuration changes done earlier in the scripts (e.g. removing packages from the package list). It is up to the user to refactor the configuration to remove redundancies, document changes, and improve maintainability.

aconfmgr apply will apply the differences to the actual system.

The contracts of both commands are that they are mutually idempotent: after a successful invocation of either, invoking either command immediately after will be a no-op.

Packages

Background: On Arch Linux, every installed package is installed either explicitly, or as a dependency for another package. Packages can also have mandatory (hard) or optional dependencies. You can view this information using pacman -Qi <package> ("Install Reason", "Depends On", "Optional Deps").

aconfmgr only tracks explicitly-installed packages, ignoring their hard dependencies. Therefore:

  • aconfmgr save will only save installed packages that are marked as explicitly installed.
  • Installed packages that are neither explicitly installed, nor are hard dependencies of other installed packages, are considered prunable orphans and will be removed.
  • Packages that are only optional dependencies of other packages must be listed explicitly, otherwise they will be pruned.
  • aconfmgr apply removes unlisted packages by unpinning them (setting their install reason as "installed as a dependency"), after which it prunes all orphan packages. If the package is still required by another package, it will remain on the system (until it is no longer required); otherwise, it is removed.
  • Packages that are installed and explicitly listed in the configuration will have their install reason set to "explicitly installed".

Advanced Usage

Configuration syntax

The configuration files use bash syntax. The easiest way to learn the syntax is to run aconfmgr save and examine its output (99-unsorted.sh).

Some simple helper functions are defined in src/helpers.bash (sourced automatically). You are encouraged to examine their implementation - their main goal is not so much to provide an API as simply to make the generated configuration terser and more readable. As such, their use is in no way required, and they can be substituted with their underlying implementations.

The list of provided helper functions:

  • AddPackage [--foreign] PACKAGE... - Adds a package to the list of packages to be installed.
  • RemovePackage [--foreign] PACKAGE... - Removes an earlier-added package to the list of packages to be installed.
  • IgnorePackage [--foreign] PACKAGE... - Adds a package to the list of packages to be ignored.
  • AddPackageGroup GROUP - Adds all packages currently in the given group to the list of packages to be installed.
  • CopyFile PATH [MODE [OWNER [GROUP]]] - Copies a file from the files subdirectory to the output.
  • CopyFileTo SRC-PATH DST-PATH [MODE [OWNER [GROUP]]] - As above, but allows source and output paths to vary.
  • CreateFile [--no-clobber] PATH [MODE [OWNER [GROUP]]] - Creates an empty file, to be included in the output. Prints its absolute path to standard output.
  • GetPackageOriginalFile [--no-clobber] PACKAGE PATH - Extracts the original file from a package's archive for inclusion in the output. Prints its absolute path to standard output.
  • CreateLink PATH TARGET [OWNER [GROUP]] - Creates a symbolic link with the specified target.
  • RemoveFile PATH - Removes an earlier-added file.
  • SetFileProperty PATH TYPE VALUE - Sets a file property.
  • IgnorePath PATTERN - Adds the specified pattern to the list of ignored paths.
  • AddFileContentFilter PATTERN FUNCTION - Adds the specified rule to the list of file content filters.

You are free to define your own custom helper functions as part of your configuration, e.g. by placing them in a 00-helpers.sh file.

Some examples can be found on the project wiki.

Ignoring some changes

Ignoring files

Some files will inevitably neither belong to or match any installed packages, nor can be considered part of the system configuration. This can include:

  • Temporary / cache / auto-generated / lock / pipe / pid / timestamp / database / backup / log files
  • Files managed by third-party package managers, esp. programming languages' package managers (pip, gem, npm)
  • Virtual machine disk images

Other files may not be desirable to include in the managed system configuration because they are security-sensitive (e.g. sshd private keys).

To declare a group of files to be ignored by aconfmgr, you can use the provided IgnorePath function, e.g.:

IgnorePath '/var/lib/pacman/local/*' # package metadata
IgnorePath '/var/lib/pacman/sync/*.db' # repos
IgnorePath '/var/lib/pacman/sync/*.db.sig' # repo sigs

Make sure to quote the pattern argument to prevent globbing at configuration parse time.

Ignoring parts of files

If only some parts of a file are relevant to the system configuration, and the rest can be safely omitted or normalized to some default value, a filter rule can be configured to normalize how the contents of a file appears to aconfmgr. For example, this is applicable if a file contains a timestamp or some randomly-generated or frequently-changing value, which can be safely discarded.

To configure a file content rule, first define a function which specifies how to filter the file. The function is called with the file name as the only parameter, the file contents on its stdin, and is expected to provide the filtered contents on its stdout:

function NetworkManagerConnectionFilter() {
	grep -v '^timestamp='
}

Then, register the rule by calling the AddFileContentFilter helper function:

AddFileContentFilter '/etc/NetworkManager/system-connections/*.nmconnection' NetworkManagerConnectionFilter

Only one function may be configured per unique pattern. The most recently added rule takes precedence over any rules with matching patterns preceding it.

Ignoring packages

To ignore the presence of some packages on the system, you can use the IgnorePackage function:

IgnorePackage linux-git

aconfmgr save will not update the configuration based on ignored packages' presence or absence, and aconfmgr apply will not install or uninstall them. The packages should also not be present in the configuration's package list, of course. To ignore a foreign package (e.g. a non-AUR foreign package), use the --foreign switch (e.g. IgnorePackage --foreign my-flobulator).

Inlining files

In the output generated by aconfmgr save, non-empty new or modified files are copied in their entirety to the configuration directory, under the /files/ subdirectory, accompanied by a Copyfile invocation. However, this can sometimes be wasteful or unwieldy if the file consists of a single line, or has one line changed out of a thousand. This section describes some techniques to move the edits into the configuration files entirely.

Inlining file content entirely

Instead of copying, the file's can be inlined using a bash heredoc, or even an echo:

# Enable Magic SysRq
echo "kernel.sysrq = 1" > "$(CreateFile /etc/sysctl.d/99-sysrq.conf)"

# https://wiki.archlinux.org/index.php/Getty#Have_boot_messages_stay_on_tty1
cat > "$(CreateFile /etc/systemd/system/[email protected]/noclear.conf)" <<EOF
[Service]
TTYVTDisallocate=no
EOF

Inlining file edits

It is also possible to generate an output file that is a modification of the original. For this purpose, the helper function GetPackageOriginalFile is provided. The function will extract the indicated file from the archive in pacman's package cache, downloading it first if necessary.

# Append some options to systemd's system.conf
cat >> "$(GetPackageOriginalFile systemd /etc/systemd/system.conf)" <<EOF
RuntimeWatchdogSec=10min
ShutdownWatchdogSec=10min
DefaultTimeoutStartSec=30s
DefaultTimeoutStopSec=30s
EOF

# Specify locales
f="$(GetPackageOriginalFile glibc /etc/locale.gen)"
sed -i 's/^#\(en_US.UTF-8\)/\1/g' "$f"
sed -i 's/^#\(en_DK.UTF-8\)/\1/g' "$f" # for ISO timestamps

The Augeas package can assist in editing configuration files:

AconfNeedProgram augtool augeas n # Install augeas now, if needed
aug() { augtool --root="$output_dir/files" "$@" ; }

# DNS
GetPackageOriginalFile filesystem /etc/resolv.conf > /dev/null
aug set '/files/etc/resolv.conf/nameserver[101]' 127.0.0.1 # dnsmasq
aug set '/files/etc/resolv.conf/nameserver[102]' 8.8.8.8 # Google
aug set '/files/etc/resolv.conf/nameserver[103]' 8.8.4.4 # Google

Comparing differences

When files are automatically generated by the configuration, or inlined therein, it can be onerous to obtain the differences between the configuration-generated version and the current system version. For this purpose, aconfmgr provides the diff action, which can be used to display a comparison between the two.

$ aconfmgr --skip-config --skip-inspection diff /etc/resolv.conf
: Compiling user configuration...
:: Skipped.
: Inspecting system state...
:: Skipped.
--- ./tmp/system/files/etc/resolv.conf	2020-10-12 07:36:00.095597318 +0000
+++ ./tmp/output/files/etc/resolv.conf	2020-10-12 07:35:39.087903266 +0000
...

The diff direction is from system to configuration, i.e., it displays changes that would be applied by aconfmgr apply. If the file belongs to a package and is unmodified on the system, aconfmgr will display the comparison between the original package version and the configuration version; likewise, if the file is absent from the configuration, the comparison will be between the filesystem version and the original package version.

Managing multiple systems

You can use the same configuration repository to manage multiple sufficiently-similar systems. One way of doing so is e.g. Git branches (having one main branch plus one branch per machine, and periodically merge in changes from the main branch into the machine-specific branches); however, it is simpler to use shell scripting:

AddPackage coreutils
# ... more common packages ...

if [[ "$HOSTNAME" == "home.example.com" ]]
then
	AddPackage nvidia
	AddPackage nvidia-utils
	# ... more packages only for the home system ...
fi

To manage different versions of a file for different systems, you can inline the file, or copy a different version depending on the hostname.

An example for inlining /etc/hosts:

f="$(GetPackageOriginalFile filesystem /etc/hosts)"
echo '1.2.3.4 home.example.net' >> "$f"
if [[ "$HOSTNAME" == laptop.example.net ]]
then
	echo '127.0.1.1 laptop.example.net laptop' >> "$f"
fi

If the file is binary, or too large to make inlining practical, CopyFileTo can be used:

CopyFileTo "/etc/hosts-$HOSTNAME" "/etc/hosts"

This will use files/etc/hosts-home.example.net for the home.example.net machine, and so on.

Comparisons

aconfmgr vs. Puppet/Ansible

Although aconfmgr calls itself a configuration manager, it has a number of core distinctions from the more well-known ones. One big distinction is that aconfmgr manages only one system - the one it is running on. It does not depend on any background services or network agents to work.

Another big distinction is the scope, and the direction of the flow of information. To clarify:

  • Puppet and Ansible have limited discovery abilities, whereas aconfmgr attempts to discover and save the system configuration in its entirety. There is no Puppet/Ansible command that can be run to save a running system's configuration to a file which, when executed, will produce a similarly-configured system; however, this is the goal of aconfmgr save.

  • Puppet and Ansible manage the system's configuration insofar as it is defined by the configuration file, whereas aconfmgr manages the entire system; as such, the absence of an item in the configuration file indicates its absence on the system. This is not true for Puppet or Ansible, where, to remove a package, one must first push a configuration file that explicitly indicates that the package is to be removed, only after which can all mentions of the package be removed from the configuration file.

aconfmgr vs. NixOS

There are some similarities between the NixOS configuration file and aconfmgr: they both attempt to describe the entire system configuration from a text file, with any changes in the configuration reflecting on the system. However, while NixOS forbids directly editing files under its control, aconfmgr doesn't. As with Puppet/Ansible, aconfmgr differs in that it provides a mechanism to transcribe changes in system state back to the configuration, making it idempotent.

Another difference is that NixOS provides a specialized syntax for many common configuration settings of managed software (e.g. allowing syntax such as boot.loader.grub.device = "/dev/sda";). aconfmgr doesn't provide this directly, though this can be achieved to some extent using tools such as Augeas, without also sacrificing the extent of possible configuration to only the predefined set of available options.

aconfmgr vs. lostfiles

lostfiles is a "simple script that identifies files not owned and not created by any Arch Linux package". aconfmgr provides a superset of its functionality, not least the ability to save exclusions to a configuration file.

aconfmgr vs. etckeeper

etckeeper allows storing /etc in a version control system. aconfmgr allows this as well, although it does not directly provide a way to automatically merge configuration files with upstream package versions. This can be done manually, by inlining file changes.

Limitations

  • Dependencies where more than one package provides something (e.g. fcron and cronie provide cron) are not tracked, and the desired dependency must be pinned or added to the configuration manually.
  • Installing AUR packages that depend on virtual packages (such as java-environment) is not currently implemented. The desired dependency can be manually specified in the configuration, or a supported AUR helper can be used instead.

License

Copyright (c) 2016-2018 aconfmgr authors.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

More Repositories

1

btdu

sampling disk usage profiler for btrfs
D
414
star
2

RABCDAsm

Robust ABC (ActionScript Bytecode) [Dis-]Assembler
D
411
star
3

DFeed

D news aggregator, newsgroup client, web newsreader and IRC bot
D
368
star
4

dhcptest

Cross-platform DHCP test client
D
315
star
5

trimcheck

SSD TRIM check tool for Windows
D
236
star
6

ae

An auxiliary general-purpose D library
D
168
star
7

DustMite

General-purpose data reduction tool
D
112
star
8

hax11

Hackbrary to Hook and Augment X11 protocol calls
C
98
star
9

term-keys

Lossless keyboard input for Emacs
Emacs Lisp
90
star
10

Digger

A tool to build D and bisect old D versions
D
56
star
11

AutoMouseLock

Multi-monitor gaming helper
C++
34
star
12

WormKit

W:A Extension Framework
Pascal
30
star
13

wp2git

Downloads and imports Wikipedia page histories to a git repository
D
27
star
14

DuolingoMoreKeys

JavaScript
24
star
15

SlimD

Bare-bones D on Win32
D
20
star
16

swfutilsex

Some classes that use or extend the Adobe Flex 4 SDK that may be useful for reverse engineering.
Java
20
star
17

dmdprof

DMD compilation time profiler
Python
19
star
18

DBuildStat

Tools to measure and visualize performance of building D programs
D
17
star
19

tree-sitter-d

JavaScript
17
star
20

Ditto

Fork of Ditto Clipboard Manager
C++
14
star
21

TrenD

D stats/benchmarks and historic results
JavaScript
13
star
22

MMTool-Extract-All

D
12
star
23

csfo4

Fallout 4 native mods
D
11
star
24

MyWormNET2

WormNET server written in D
D
11
star
25

dscripten-tools

Alternative build toolchain for Dscripten
D
11
star
26

LiteUnits

Lightweight Delphi units to replace heavy system units like SysUtils. I did not write these, I only maintain them for personal projects.
Pascal
11
star
27

dlint

D
10
star
28

thincow

Create a deduplicated, COW view of block devices as a FUSE filesystem
D
9
star
29

DMapTreeMap

Visualizes D map files in a treemap
D
9
star
30

EnvMan

FAR plugin for comfortable management of environment variables
Pascal
9
star
31

steamkeyactivator

Cross-platform Steam bulk key activator
D
9
star
32

dcaptcha

CAPTCHA for D programming websites
D
8
star
33

keygen.js

<keygen> polyfill for modern browsers
JavaScript
8
star
34

Diamond

D memory debugger and profiler
D
8
star
35

DDD

Generic External-Memory Delayed-Duplicate-Detection Search Engine for Implicit Graphs. Based on Kwirk DDD solver ( http://github.com/CyberShadow/kwirk ).
C++
7
star
36

D-dot-git

Git repository generator for all D components
D
7
star
37

graphstudio

Fork of MONOGRAM GraphStudio
C++
7
star
38

misc

Miscellaneous (non-script) utilities to complement my dotfiles
D
7
star
39

FiddlerAutoCapture

Fiddler extension to automatically save all content hierarchically
C#
7
star
40

DAppenderResearch

Benchmarks and experiments in writing appenders in D
D
6
star
41

turbotuber

relentless external youtube-dl downloader for YouTube
D
6
star
42

cacheset64

64-bit CacheSet
C++
6
star
43

squelch

D
6
star
44

dbt-mode

Emacs Lisp
5
star
45

rtf2any

D
5
star
46

putty-terminfo

Attempt at a better terminfo for PuTTY
5
star
47

steamguides

Steam Guide Uploader
D
5
star
48

MyWormNET

Personal WormNET server software
PHP
5
star
49

data.d

D wrapper for raw data located in unmanaged memory.
D
5
star
50

SimpleIndent

C++
5
star
51

term-title

Emacs Lisp
5
star
52

ProcMonTools

Process Monitor stuff
D
5
star
53

ripfs

Simple deduplicating userspace filesystem for recordings of Internet radio stations.
D
5
star
54

ProSnooper

ProSnooper is an application that lets you connect to WormNET, chat on the channels, join and host games.
Pascal
5
star
55

KeyboardEmperor

Kernel-mode hack to speed up USB keyboards [I have no idea what I'm doing]
C
5
star
56

DBugTests

Curated D issue test case database
D
4
star
57

FAR

Obsolete, see https://github.com/CyberShadow/farmanager
C++
4
star
58

UniUpload

CyberShadow's file uploader
Pascal
4
star
59

TextNavigate

Obsolete. See:
C++
4
star
60

DDD-Kwirk

Kwirk module for generic DDD solver ( http://github.com/CyberShadow/DDD )
C++
4
star
61

xmacro

Fork of the xmacro program with some essential fixes
C
4
star
62

GHDaemon

Caching GitHub API proxy for Digger
D
4
star
63

ForumAntiSpam

Client-side forum spam filter
D
4
star
64

localcmdhistory

C++
4
star
65

colorout

Colorize your compiler’s output
D
3
star
66

cyberzshadow

My zsh theme
Shell
3
star
67

d-btrfs

D
3
star
68

win32

Shell
3
star
69

TimeTracker

Minimalistic time-tracking program for Windows
D
3
star
70

json2colorer

Utility to convert DMD .json output to Colorer wordlists
D
3
star
71

cirun

[WORK IN PROGRESS] Stand-alone CI test runner
D
3
star
72

ColorCalc

Command-line calculator for hex RGB colors.
D
3
star
73

image-quality

Quantifying generation loss using machine learning
Python
3
star
74

kwirk

Kwirk C++ solver. Obsolete, this project was split up into a generic DDD engine ( http://github.com/CyberShadow/DDD ) and the Kwirk module for it ( http://github.com/CyberShadow/DDD-Kwirk ).
C++
3
star
75

DDraw

Deprecated project, merged into ae:
D
2
star
76

monocre

D
2
star
77

DomainManager

D
2
star
78

pas2d

Simplistic text processor for doing part of grungework of Pascal->D conversion.
D
2
star
79

DvorakLayouts

Dvorak keyboard layouts
Shell
2
star
80

ShellUtils

Some stuff that goes into /usr/local/bin on my machines
Shell
2
star
81

Drain

D
2
star
82

metahumble

HumbleBundle Metalink generator
Python
2
star
83

multishellcheck

Lint multi-file scripts with ShellCheck
Shell
2
star
84

reduce

General-purpose data reduction tool
D
2
star
85

Team15

D1/Phobos library with various (mostly network) code
D
2
star
86

photosensitivity

Makefile
2
star
87

rwm

Remote Window Manager - list and manipulate windows remotely
D
2
star
88

SteamKeyAdder

Easily add bundle/retail keys to your Steam account
D
2
star
89

function_factory

D
2
star
90

ColorerVCLog

Combine Visual C++ build logs with colorer HTML output
D
2
star
91

DAutoTest

My D autotester (currently for just the documentation)
D
2
star
92

git-splice

Programs to splice histories of git repositories
D
2
star
93

ddoc2ghmd

Extremely simple filter to convert DMD Ddoc output to github Markdown
D
2
star
94

CpuUsageMon

D
2
star
95

AutoFix

D
2
star
96

PuttySessionsToSSH

Convert PuTTY sessions to OpenSSH config
D
2
star
97

SeatD

SeatD SVN mirror
D
2
star
98

dbot-server

D
1
star
99

dbot-client

D
1
star
100

dchmgen

D CHM generator
D
1
star