- Light theme uses Papirus-Light: the panel icons of Papirus are #dfdfdf, made for dark panels (xsettings, theme index, login screen). - das-panel-icon help/-h/--help print usage instead of setting an icon; unknown options are rejected. - New packages publisher (publish) and deployer (deploy) on the desktop image: config in ~/.config/<name>/ (neutral example copied on first run), history in ~/.local/state/<name>/. - das-theme 0.3.0, das-settings 0.6.0. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
30 KiB
Das OS
A light, friendly Void Linux–based desktop with Xfce and a Ukrainian touch, plus a console server edition
💡 Purpose
Void Linux is fast, simple and independent: runit instead of systemd, and its own xbps package manager. Out of the box, though, it is a bare system, and getting it ready for daily use takes hours of setup. Das OS builds a live ISO that boots straight into a configured Xfce desktop and installs it with a graphical installer. It has its own look, a Ukrainian interface and keyboard layout, the usual desktop apps and Btrfs snapshots that let a broken update be undone. Everything Das OS adds comes from its own xbps packages, so the setup can be reproduced and updated like any other package. A second, console-only ISO installs a server with SSH, a firewall, fail2ban and Docker set up, on the same Btrfs layout with snapshots.
📃 Features
- Live ISO that boots on UEFI and BIOS straight into the desktop
- Graphical installer (Calamares) set up for Void and runit
- Snapshots and rollback: hourly Btrfs snapshots, bootable from the GRUB menu
- System update with a snapshot taken before it: a window, a tray icon and a terminal mode
- Welcome window at the first login: language, home folders, updates, the developer profile and help
- Server image: a console live ISO with a text installer, SSH, firewall, fail2ban and Docker
- Command-line helpers for everyday admin tasks: services (
dsv), users (duser), firewall (dfw) and system settings (dsys) - Terminal prompt and SSH login banner: the Das prompt by default, the
dpromptprompt builder and thedbannerbanner editor with the Das OS logo and the tryzub - Aliases and functions for every terminal:
extract,mkcd,netinfo,pkgowner, Docker shortcuts and more, withlsfuncto list them - Developer profile in one command: Go, Python, Node.js, Docker, rootless Podman, VS Code and IDEs from Flathub
- Das OS look: light and dark themes, generated window frames, wallpapers and logo
- Desktop defaults for Xfce that don't overwrite stock files
- Own package repository built by xbps-src from in-tree templates
- Containerised build that runs on any Linux host with Docker, and QEMU scripts for testing
- CI build of the packages and both ISOs on every push, on a self-hosted Gitea Actions runner
⭐ Advantages
- Void underneath – a fast runit boot, the xbps package manager and fresh software, with none of the manual setup.
- Safe updates –
das-updatetakes a snapshot before every update, the system can return to any snapshot, and personal files in/homeare never part of a rollback. - Light – no systemd, plus Xfce, LightDM and PipeWire, so it runs well on older laptops too.
- Nothing hidden – all customisations ship as ordinary xbps packages, so
xbps-query -f das-settingsshows exactly what changed. - Users keep control – defaults live in
/etc/xdg/das, so a user's own settings always take precedence and upgrades never reset them. - One base for desktop and server – both images share the packages, the disk layout, snapshots and
das-update, so a server is updated and rolled back the same way as a laptop. - Builds anywhere – the build runs in a Void container, so the host can be Mint, Ubuntu or Fedora.
📱 Screenshots
📌 Using
Live ISO
The live system logs in to the desktop on its own, with no installation needed.
- Boots on UEFI (GRUB) and on legacy BIOS (isolinux), both with a Das OS splash screen.
- The graphics disabled entry boots with
nomodesetfor machines whose screen stays black, and the RAM entry copies the whole system to memory. - User
live, passwordlive, withsudothat needs no password. The user is created at boot and exists only in the live session. - Ukrainian interface (
uk_UA.UTF-8) and the Kyiv time zone by default. Keyboard layouts areus,ua, switched with Alt+Shift. - Includes NetworkManager, Bluetooth, PipeWire sound and Firefox with the Ukrainian language pack. Services run under runit:
dbus,elogind,polkitd,NetworkManager,bluetoothd,lightdm. - Includes guest tools for QEMU/SPICE and VirtualBox.
- The Install Das OS icon on the desktop and in the menu starts the installer.
Graphical installer
Calamares installs Das OS in a few steps: language and time zone, keyboard, disk, user.
- The interface is in Ukrainian by default, with the Kyiv time zone and Das OS branding and slides.
- The disk can be erased automatically or partitioned by hand. Btrfs is the default, ext4 and XFS are also available. On UEFI machines it creates a 512 MiB EFI partition.
- It copies the clean live image (
/dev/mapper/live-base), without the live user and its boot-time settings. - After copying, it builds locales for the chosen language, keeps only the guest tools of the hypervisor it runs in (none on real hardware), sets up snapshots, builds the initramfs and installs GRUB.
- When it finishes, it removes itself and the packages that only it needed.
- Disk encryption is not offered yet.
Snapshots and rollback
Btrfs snapshots keep the system recoverable after a bad update.
- The installer creates the subvolumes
@(root),@home,@snapshots,@var_logand@var_cache_xbps. Root snapshots don't include personal files, logs or the package cache. - snapper makes a Fresh install snapshot right after installation and an hourly snapshot (cron). It keeps the last 5 hourly, 7 daily and 2 weekly ones.
- grub-btrfs adds every snapshot to the Das OS snapshots submenu in GRUB and updates it as snapshots appear.
- A snapshot is read-only. When it boots, the
das-snapshot-overlaydracut module puts a writable overlay in RAM on top, so the full desktop works. Changes made there are lost at shutdown. sudo snapper-rollback <number>makes the snapshot the new root (the old one is kept as@<date>). The change takes effect after a reboot. It works both from the running system and from a booted snapshot.- Members of
wheelcan list snapshots without sudo:snapper list.
System update
das-update installs updates between a pair of snapshots, so a bad update can be undone from the boot menu.
- Before updating, it creates a snapper pre snapshot, then runs
xbps-install -Su(updating xbps itself first when needed), then creates the paired post snapshot, also when the update failed. - If the pre snapshot cannot be created, nothing is installed. Without Btrfs (ext4, XFS) it updates without a snapshot and says so.
- When it finishes, it shows the snapshot number and how to roll back to it, and asks for a reboot when the kernel, glibc, runit or other core packages were updated.
- The System update window lists the packages with the installed and new versions and shows the xbps output. The privileged part runs through pkexec (polkit action
ua.org.das.update). - In the background it checks for updates 2 minutes after login and then every 6 hours, without root. The tray icon and a notification appear only when updates are available. A click opens the window, and a right click opens a menu with Check now. The check is off in the live session.
das-update --clidoes the same in a terminal (servers, ssh). It asks before installing (-yskips the question) and runs itself again through sudo. Without a display it works in the terminal even without--cli.- The command itself is the
das-updatepackage without GTK, the window and the tray icon are/usr/libexec/das/das-update-guifromdas-tools.
Welcome window
das-welcome opens at the first login and gathers the first steps in one place.
- In the live session it offers to install Das OS.
- The interface language can be chosen when the system has more than one locale built. It is stored in AccountsService and
~/.dmrcand takes effect at the next login. - If the home folders still have English names (
Documents,Downloads…), it offers to rename them to the system language, together withuser-dirs.dirsand the file manager bookmarks. Folders the user moved, and those whose new name is already taken, are left alone. - It installs the developer profile in a terminal window, where the IDEs and the password are asked for, and once the profile is installed, adds IDEs from Flathub.
- It links to the system update, Xfce settings and help.
- It opens by itself only once. The Show at login check box keeps it opening at every login.
Server image
A console-only live ISO that installs a Das OS server with SSH, a firewall and Docker ready to use.
dasos-server-<version>-x86_64.isoboots on UEFI and BIOS with a login on the screen and on the serial console (ttyS0, 115200), so it also works through IPMI, VPS consoles andqemu -nographic. Log in aslivewith the passwordlive, then runsudo das-server-install.- The installer asks in Ukrainian or English: the disk, server name, administrator and password, an SSH key (and whether password logins stay allowed), time zone, console layout, language and network (dhcpcd or NetworkManager).
das-server-install --config FILEinstalls without questions, see/usr/share/examples/das-server-installer/install.conf. - It uses the same GPT and Btrfs layout as the desktop installer, so snapshots, the Das OS snapshots boot menu and
snapper-rollbackwork the same way. GRUB is installed for UEFI (also at the fallback path) or BIOS, on the serial console too when the installer was started there. - The administrator gets sudo through
wheeland is in thedockerandsockloggroups. root has no password. - The installed system runs
sshd,chronyd,nftables,fail2ban,docker,socklogand the chosen network service. - nftables lets in only SSH, ICMP and DHCPv6 (
/etc/nftables.conf), more ports are opened withdfw. The rules live in their own tableinet das, so reloading them keeps the Docker and fail2ban rules. Ports that containers publish pass through Docker's own rules. - fail2ban bans addresses that keep failing SSH logins, reading the socklog log. sshd doesn't accept root password logins.
- Tools: Docker with Compose, lazydocker, lazygit, Midnight Commander, tmux, htop, ncdu, Python 3, curl,
das-update --cli, the helpers,dpromptanddbanner, aliases and functions and xtools (xi,xq,xrs). There are no graphical libraries, and no firmware for NVIDIA graphics or sound cards (/etc/xbps.d/das-server.confkeeps updates from bringing it back).
Command-line helpers
Short commands for tasks that systemd distributions handle with systemctl, hostnamectl and the like, and that Void leaves to manual editing.
- They answer in Ukrainian or English, run themselves again through sudo when they need root and have bash completion. In a terminal they ask for whatever is missing, and with all arguments given they work in scripts.
dsvmanages runit services:list(enabled or not, state, PID, uptime),enableanddisable(at boot and right now),start,stop,restart,statusandlogs [-f](the service's own svlogd log or its lines in socklog).dsv newcreates a service for your own program: the command, user, working directory and environment variables go to/etc/sv/NAME, with a log in/var/log/NAME. It then starts the service and checks that it stays up.dsv rmdeletes such a service and refuses to touch services from packages.dusermanages accounts:addwith the same groups as the desktop installer (--adminaddswheel,dockerandsocklog), a password and an SSH key;passwd,lockandunlock(a locked account can't log in with a key either),key add|list|rmforauthorized_keys,groups NAME +GROUP -GROUPanddel. It won't delete or lock out the current user, and it won't delete the only administrator.dfwopens ports in the server firewall:dfw allow 80/tcp,dfw allow https 8000-8010/tcp,dfw deny 80/tcp. The ports are kept in/etc/nftables.d/dfw.nftand checked withnft -cbefore loading, and only theinet dastable is reloaded.dfw statusalso lists the ports Docker containers publish and the addresses fail2ban has banned. SSH always stays open.dsysreplaces hostnamectl, timedatectl and localectl:info(time sync, language, console, addresses),hostname,timezone(part of the name will do:dsys timezone Kyiv),locale(builds the glibc locale if needed) andkeymap(with a Cyrillic console font for Cyrillic layouts).- They come in the
das-helperspackage and are on the desktop too. Both images also includextools-minimalfrom Void for package work:xiinstalls,xrssearches,xqshows package details andxcheckrestartfinds programs to restart after an update.
Terminal prompt and SSH login banner
A two-line bash prompt out of the box, and two terminal editors to change it and to draw the banner shown at SSH login.
- The stock prompt:
┌─[✗]─[user@host]─[2026-10-21]─[08:12]─[~/dir]and└─╼ $on the second line.[✗]appears only after a failed command, root's name is red, and without colours or on the Linux console the shape stays the same. - It comes from
/etc/bash/bashrc.d/das-prompt.sh: the user's~/.config/das/prompt.sh, else/etc/das/prompt.sh, else the stock one. Void's/etc/skel/.bashrcsets its own PS1 afterwards, so that one is replaced once, but a user's own PS1 is never touched. dpromptis a prompt builder: ready-made prompts (das,das-gitwith the git branch, venv and background jobs,server,minimal,classic), segments to add, move and colour, and a live preview as a normal user, after an error and as root. Ctrl+S applies it for yourself, Ctrl+G for every user through sudo. Without the editor:dprompt list,dprompt show NAME,dprompt apply NAME [--system],dprompt reset.- Conditional parts (exit status, git, venv, jobs, SSH, a command's output) are computed by a
PROMPT_COMMANDhook and only read by PS1, so a branch name is never run as code. dbanneredits the banner shown at SSH login. It starts with a list of ready-made banners with a live preview:das-classic(a#frame with the name, IP and link),double(the host name in big figlet letters),blocks(the Das OS logo with system facts),ukraine(the lesser coat of arms of Ukraine),tryzub,dashboardandminimal.- The editor draws with the mouse or the keyboard: pen, eraser, line, boxes (single, double, rounded, heavy, ASCII,
#, blocks), fill, text, big letters, select with copy and paste, undo. A palette offers box and block symbols, 16 colours for text and background and bold. Ready pictures go in with one click: the Das OS logo and the tryzub, plain or on a shield, in two sizes. - Fields show live values in a fixed width, so a frame never shifts:
{hostname},{ip},{uptime},{mem},{os},{kernel}and others, plus your own variables like{url};[[Ukrainian|English]]labels follow the user's language. - Widgets add blocks under or beside the picture: disks with usage bars, memory, load, network, Docker containers, available updates, weather from wttr.in, SMART disk health, runit services that are down, fail2ban bans, snapper snapshots, the previous login, or any command or file with a script's output.
- Quick widgets run at login with a short timeout. Slow or root-only ones (updates, weather, SMART, fail2ban) are refreshed by the
das-bannerrunit service into/var/cache/das/banner, anddbanner applyenables it when a banner needs it. No cron is needed. - Drafts are kept in
~/.config/das/banner; Ctrl+A ordbanner apply NAMEwrites/etc/das/banner.jsonthrough sudo.dbanner offandonturn the banner off for everyone,~/.hushloginfor one user;"local": trueshows it on console logins too.
Aliases and functions
Ready shortcuts for everyday terminal work in every interactive bash, rewritten for Void: xbps, nftables, runit and Docker.
- They come from
/etc/bash/bashrc.d/das-aliases.sh(packagedas-shell):/usr/share/das/shell/aliases.shandfunctions.sh, then your own~/.bash_aliasesand~/.bash_functions, which win.touch ~/.config/das/no-aliasesturns the Das OS ones off for one user.lsfunclists the functions with a description in the user's language,aliaslists the aliases. ls:ll,la,l,sl,lsl(inless),lsz(by size),lst(by time),lsd(directories only);grep,diffandipin colour.- Directories:
..,...,....,cd..,up [N](N levels up),mkcd DIR(create and enter),cl DIR(enter and list),path(onePATHentry per line);mkdirmakes parents. - Files:
f PATTERN [DIR](find by name, any case),fhere NAME,cnt(number of files),bigfiles [DIR] [N],dirsize [DIR](sizes of everything in a directory),whatsize [DIR](subdirectory sizes,/by default),bu FILE...(copy with the date in the name),ednt FILE(edit keeping the modification time). - Archives:
extract ARCHIVE...unpacks tar of any compression,.xbps, zip, rar, 7z, gz, bz2, xz, zst, lz4 and Z;compress NAME.tar.gz|tar.xz|tar.zst|zip|7z FILE...packs by the name's extension. A missing tool is named together with the package to install. - Disks and memory:
df,dft(with types and a total),dftl,mnt(mounted devices),mounts,devid(lsblk, blkid and lsusb),snaps(root snapshots),free,meminfo,cpuinfo,gpumeminfo. - Processes and history:
psa TEXT,pst TEXT(as a tree),psg,psmem/psmem10,pscpu/pscpu10,j,hgrep TEXT,histat [N]andhistop10(most used commands),EC(the previous exit code),please(the previous command again with sudo). - Packages:
updandupdy(das-update --cliwith snapshots,updywithout questions),pkgshow [TEXT](installed),pkgfind TEXT(in the repositories),pkgowner FILE|COMMAND,pkgclean(package cache and orphans). - Network:
myip,netinfo(addresses, gateway, DNS, public IP),oportsandgport TEXT(listening ports),ping5,fastping,header URLandheaderc URL(HTTP headers, with compression),listen PORT,serve [PORT](the current directory over HTTP),rmhost HOST|LINE(cleanknown_hosts),nftlist,firewall(dfw status),weather [CITY],cheat COMMAND(cheat.sh). - Docker:
dps,dlog CONTAINER,dcu,dcd,dcl,dcp(compose up, down, logs, pull),lzd,lzg. - Small tools:
calc EXPR,epoch [SECONDS],genpass [LENGTH],now,nowdate,note [-c] [TEXT](~/.notes),todo [-l|-r N|-c] [TEXT](~/.todo),csrc FILE.c(compile and run C),manwith coloured headings.
Developer profile
dprofile install dev turns a desktop or a server into a development machine, with a snapshot taken before it.
- Packages from the Void repository:
base-devel, gdb, strace, Git with LFS, GitHub CLI, lazygit, Go with gopls, delve and golangci-lint, Python with pip, virtualenv and uv, Node.js, Docker with Compose and Buildx, lazydocker, Podman with podman-compose, jq, ripgrep, fd, fzf, direnv, shellcheck and SQLite. - On a desktop also VS Code (Void's open-source build
code-oss, extensions come from Open VSX), Meld, Flatpak with the Flathub remote and the desktop portals. - It enables Docker and adds the user who runs it to the
dockergroup, gives them subordinate IDs for rootless Podman and makes/a shared mount at every boot (/etc/runit/core-services/60-das-shared-root.sh), which rootless containers need. - Before installing, it asks which IDEs to add from Flathub: Android Studio, IntelliJ IDEA Open and Ultimate, PyCharm, GoLand, WebStorm or Microsoft's Visual Studio Code. Later they are added with
dprofile app add GoLandand removed withdprofile app rm, which also removes the Flatpak runtimes nothing else uses. - The packages are installed between a snapper pre/post snapshot pair, like with
das-update, and the command prints how to roll back.dprofile listanddprofile show devshow what is installed already;--yesand--apps ID,...|all|nonemake it work without questions. - The profile is a plain list in
/usr/share/das/profiles/dev.conf. The desktop installer doesn't offer it because the installation copies the live image without a network, and the profile downloads about 550 MB of packages (an IDE from Flathub takes 1–4 GB more with its runtimes).
Das OS look
A modern minimal style with a blue and yellow eight-petal star from Ukrainian embroidery.
- The GTK themes
DasOSandDasOS-Darkbuild on adw-gtk3 and add the Das OS accent colours. They also style the Xfce panel, which adw-gtk3 leaves black. - The xfwm4 window frames (rounded corners, round buttons, a red close button on hover) are generated as PNG files by
xfwm4gen(Go) from a single palette. - Light and dark wallpapers show the star over a rushnyk-style embroidered ribbon. The same star is the Das OS logo and the menu button.
- Fonts are Inter for the interface and JetBrains Mono in the terminal. Icons are Papirus (the Papirus-Light variant, so the panel icons are dark) and the cursor theme is Adwaita.
Desktop defaults
The das-settings package configures Xfce without touching files owned by other packages.
/etc/profile.d/das-xdg.shputs/etc/xdg/dasbefore/etc/xdg, and xfconf reads the Das OS defaults from there.- One bottom panel holds the Whisker menu, window buttons, tray, keyboard layout, volume, notifications, clock and a show-desktop button.
- At the first login,
das-session-initsets the wallpaper on every connected monitor, because Xfce stores wallpapers per monitor name. - LightDM uses the GTK greeter with the Das OS theme and wallpaper.
- Home folders get names in the session language. xdg-user-dirs 0.20 looks for its translations only in the first
XDG_DATA_DIRSentry that has alocaledirectory, the empty/usr/local/share/locale, so it created English folders./etc/X11/xinit/xinitrc.d/50-das-user-dirscreates them before the Xfce session with a lookup path that finds the translations.
Own package repository
Every Das OS file is installed and updated by xbps.
srcpkgs/das-themecontains the themes, xfwm4 frames, wallpapers and logo.srcpkgs/das-settingscontains the Xfce, LightDM and session defaults.srcpkgs/das-toolscontainsdas-welcomeand the update window and tray icon (Go, GTK 3 through gotk3) with their menu and autostart entries. Its subpackagedas-updateis the update command and polkit action, without GTK.srcpkgs/das-snapshotscontains the snapper configuration,das-snapper-setupand the dracut module for booting snapshots.srcpkgs/das-installercontains the Calamares settings and branding,srcpkgs/das-server-installerthe console installer. The steps both share (mount-source,postinstall) are insrcpkgs/das-install-common. They exist only on the live ISOs.srcpkgs/das-serveris the server metapackage with the nftables, fail2ban, sshd and Docker defaults.srcpkgs/das-helperscontainsdsv,duser,dfw,dsys,dprofileand the profiles.srcpkgs/publisher(publish) andsrcpkgs/deployer(deploy) are the developer's TUI/CLI tools that publish builds and deploy projects to a server over ssh + rsync. Each one keeps its config in~/.config/<name>/(an example is copied there on the first run) and its history in~/.local/state/<name>/.srcpkgs/calamares,srcpkgs/adw-gtk3andsrcpkgs/font-jetbrains-monopackage upstream releases that Void does not have.make packageslays the templates over a shallow clone of void-packages and builds them withxbps-srcintoout/hostdir/binpkgs. The ISO build installs them from there.- A package is rebuilt only when its directory in
srcpkgs/changed, its binary package is missing, or Void no longer provides a shared library it links to (checked with a dry-run install).DASOS_REBUILD=1 make packagesrebuilds everything.
Containerised build
The whole build runs in a Docker container, so only Docker and QEMU are needed on the host.
make packagesbuilds the local xbps repository.make isobuilds the packages and then the ISO withvoid-mklive, using the profile inlive/(package list, services, root file system overlay).make iso-serverdoes the same for the server profile inserver/.make qemuboots the newest ISO with UEFI.make qemu-biosuses legacy BIOS, andmake qemu-diskalso attaches a 20 GB virtual disk to install on.make qemu-serverboots the server ISO with the disk on a serial console in the terminal (Ctrl-A X quits). The guest's SSH is forwarded tolocalhost:2222(DASOS_SSH_PORTchanges it).
CI build
Every push to main or dev and every v* tag builds the packages and both ISOs on git.das.org.ua.
- The workflow
.gitea/workflows/build.ymlrunsmake iso iso-serveron a self-hosted runner with thedascilabel. - The runner is a WSL2 distro on a Windows machine: Ubuntu 24.04 with Docker Engine and
gitea-runneras a systemd service. A scheduled task starts it when Windows boots, no login needed. ci/runner/setup.shinstalls Docker, the runner and itsconfig.yaml;setup.sh register <token>registers it,autostart.ps1creates the scheduled task.DASOS_OUTmovesout/out of the checkout, so void-packages, the bootstrapped masterdir and the download cache survive between builds.- A
v*tag that matchesVERSIONalso publishes both ISOs andSHA256SUMSas a release (ci/release.sh, with the job's own token):git tag v0.8.0 && git push origin v0.8.0. Other builds keep the ISOs on the CI host in/var/lib/dasos-ci/out/iso.
🚀 Building the application
Requirements: Linux with Docker (the user must be in the docker group), QEMU and OVMF for testing, and Go 1.24+ with the GTK 3 development files plus Python 3 for make test. About 10 GB of free disk space.
make iso # build packages and the live ISO (the first run downloads ~2 GB)
make qemu # boot it in QEMU with UEFI
make iso-server # build packages and the server ISO
make qemu-server # boot it on a serial console with a disk to install on
make test # run Go and Python tests
make clean # remove build output, keep the download cache
The ISOs appear in out/iso/dasos-<version>-x86_64.iso and out/iso/dasos-server-<version>-x86_64.iso. Write them to a USB stick with dd or Ventoy. For a Ventoy theme there is a 48×48 menu icon live/branding/ventoy/dasos.png: copy it to the theme's icons/ folder and add { "key": "dasos", "class": "dasos" } to menu_class in ventoy.json.
Note: Das OS is an early version (0.9.3). Packages and ISOs are built in CI; signed repository hosting is planned for an upcoming stage. Until the repository is hosted, an installed system gets updates from Void only. Das OS is based on Void Linux but is not affiliated with it.











