This directory contains an example of a minimal decman configuration. This also functions as a tutorial for starting out with decman. I recommend looking at the docs after this.
I will first install git and base-devel. Then I'll clone the PKGBUILD and install decman.
sudo pacman -S git base-devel
git clone https://aur.archlinux.org/decman.git
cd decman/
makepkg -sicI will create a source directory for the system's configuration.
mkdir ~/source
cd ~/sourceDecman will remove all explicitly installed packages not found in the source. Let's find all explicitly installed packages.
$ pacman -Qeq
base
base-devel
btrfs-progs
decman
dosfstools
efibootmgr
git
grub
linux
openssh
qemu-guest-agent
sudo
vimFirst thing to note: decman is not a native package. I remember this, but if you don't, you can find only native packages with pacman -Qeqn and foreign packages with pacman -Qeqm. Since decman is not a native package, the pacman plugin cannot handle it. I'll add decman to AUR packages.
Instead of adding all of these packages to decman.pacman.packages, I will first create a module for base system packages in ~/source/base.py.
import decman
from decman.plugins import pacman, aur
class BaseModule(decman.Module):
def __init__(self):
# I'll intend this module to be a singleton (only one instance ever),
# so I'll inline the module name
super().__init__("base")
@pacman.packages
def pkgs(self) -> set[str]:
return {
"base",
"btrfs-progs",
"dosfstools",
"efibootmgr",
"grub",
"linux",
# I'll also include git and base-devel here, they are essential to this system
"git",
"base-devel",
}
@aur.packages
def aurpkgs(self) -> set[str]:
return {"decman"}Then I'll create the main source file with the rest of the packages. I'll import BaseModule and add it to decman.modules. The main file is ~/source/source.py.
import decman
from base import BaseModule
decman.pacman.packages |= {"openssh", "qemu-guest-agent", "sudo", "vim"}
decman.modules += [BaseModule()]This config is already enough to run decman for the first time.
sudo decman --source /home/arch/source/source.pyThis will run a system upgrade, but otherwise nothing else happens, since my system already matches the desired configuration.
Now I'll want to gradually add more stuff to my config. As an example, I'll add my custom mkinitcpio.conf. I'll create the file ~/source/files/mkinitcpio.conf with the desired content. Then I'll add the file to my BaseModule. Since I want to run the command mkinitcpio -P every time I update my config, I'll add a on change hook as well. I'll update the file ~/source/base.py.
class BaseModule(decman.Module):
...
def files(self) -> dict[str, decman.File]:
return {"/etc/mkinitcpio.conf": decman.File(source_file="./files/mkinitcpio.conf")}
def on_change(self, store):
decman.prg(["mkinitcpio", "-P"])I'll also add my vim config to decman. I could now create a Vim module, but since my config is simple, I feel that is not needed. I'll update the main source file ~/source/source.py.
import decman
...
decman.files["/home/arch/.vimrc"] = decman.File(source_file="./files/vimrc", owner="arch", permissions=0o600)Then I'll apply my changes. Decman will remember my source, so no need to give it as an argument anymore. I don't want to waste time checking for aur updates, so I'll skip them.
sudo decman --skip aurI want add a desktop environment. I'll create a module for that in the file ~/source/kde.py. I'll use SDDM as the login manager. SDDM service needs to be enabled, so I'll use the systemd plugin for that.
import decman
from decman.plugins import pacman, systemd
class KDE(decman.Module):
def __init__(self):
super().__init__("kde")
@pacman.packages
def pkgs(self) -> set[str]:
return {
"plasma-desktop",
"konsole",
"sddm",
}
@systemd.units
def units(self) -> set[str]:
return {"sddm.service"}I'll add the module to enabled modules in ~/source/source.py.
import decman
from base import BaseModule
from kde import KDE
...
decman.modules += [BaseModule(), KDE()]I'll run decman once again. I'll also start SDDM manually, since decman can't autostart it.
sudo decman
sudo systemctl start sddmLastly I want to install some packages with flatpak. I'll first have to install flatpak to make the plugin available. I'll do it manually since it's quicker.
sudo pacman -S flatpakThen I'll modify ~/source/source.py. I must add flatpak to execution steps to run the plugin.
import decman
...
decman.execution_order = [
"files",
"pacman",
"aur",
"flatpak",
"systemd",
]
decman.pacman.packages.add("flatpak")
decman.flatpak.packages |= {"org.mozilla.firefox", "org.signal.Signal"}Then run decman.
sudo decmanDecman is intended to replace your upgrade procedures. Instead of running yay -Syu for example, you would run sudo decman. With after_update hooks you can chain other update commands such as rustup update. This way you'll only have to remember to run decman. All other update steps are defined in your source.
It is possible to create your own plugins for decman. However, you probably won't need to do that, as modules are already very capable. This example directory also contains a very minimal plugin. To learn more about plugins, look at the docs.