Describe your workflow

I’ve been using Linux personally for around 6 years now and professionally as a PHP developer for around two years.

I’m the most junior dev at our software shop and it has been very interesting learning how some of the more senior devs use Linux. On one hand, there’s never time to discuss using Linux because everyone’s busy, but on the other all you have to do is ask and they will probably drop whatever they’re doing to nerd out over some part of their workflow that they recently overhauled.

The main constant is that everyone has their own set of shell toys (everyone loves fzf), but everything else (DE, wacky keyboards, window manager, text editors, git wrapper, tmux or no tmux, how to install programming languages, etc…) is usually quite individual.

So let’s have that discussion in this thread. Go ahead, nerd out about whatever parts of your workflow feel the best to you! I’ll start:

OS: Fedora Silverblue, with my own downstream image built weekly
GNOME extensions: Caffeine, Brightness control using ddcutil, Legacy GTK3 theme auto switcher, Run or raise, Auto power profile, Hide cursor
Keyboard & Mouse: Happy Hacking Keyboard Pro Hybrid Type-S (so smooth! :drooling_face:) + Logitech MX Master 3
Terminal emulator: Ptyxis (shame that it’s unmaintained at the moment but so far I haven’t needed to replace it)
Text editor: Emacs (long story, very worth it, especially now with widespread LSP and TUI AI agents)
Shell: Mostly distrobox, if it needs to be part of the host for some reason I usually just add it to my downstream image
Web browser: Firefox
Entertainment: Books (zathura or Foliate), interesting articles (hacker news, wikipedia), youtube (restorations, engines, that kind of thing. I don’t spend a lot of time here because the algorithm constantly pushes AI slop brainrot stuff)


How do all these pieces fit together? My day usually starts by plugging in a laptop to an external display and connecting the peripherals. I keep the laptop in clamshell mode when plugged in, maybe I would change that if I got one of those laptop stands. Next, I open up a web browser, any comms tools I need, and start hacking on some code base (writing code, running shell commands, talking to customer support about bugs, feature design with org mode, that kind of thing). I basically do that until it’s time to go home.

In general I follow the “GNOME way” with fullscreen windows or two side-by-side, augmented with the Run or raise extension for windows I switch between frequently instead of trying to guess what alt-tab will give me next. I adopted this back when I started working with Linux professionally; before that I ran Void Linux with AwesomeWM. The problem with that setup is that there were so many paper cuts and I can’t afford to mess around with debugging my workflow instead of doing my job, so I needed a solution that would Just Work :trade_mark:. Enter Fedora Silverblue. The learning curve where everything is in a container was fairly steep but I’ll tell you right now it paid off immensely.

Here’s an example of how I use distrobox for work:

$ cat ~/dotfiles/distrobox-assemble/web-dev-toolbox.ini 
[web-dev]
image=fedora:43
replace=true
additional_packages="composer inotify-tools make php php-cli php-common php-xml php-gd php-bcmath php-pdo php-mysqlnd php-mbstring php-pecl-xdebug pnpm nodejs"
exported_bins="/usr/bin/inotifywait /usr/sbin/node /usr/sbin/npm /usr/sbin/php /usr/sbin/pnpm /usr/sbin/pnpx /usr/sbin/composer"
volume="~/.config/php/conf.d/99-memory-limit.ini:/etc/php.d/99-memory-limit.ini"
$ distrobox assemble create --file ~/dotfiles/distrobox-assemble/web-dev-toolbox.ini 
... output elided ...
... this step included for demonstration only, these containers are persistent ...
$ which php
~/.local/bin/php
$ cat $(which php)
#!/bin/sh
# distrobox_binary
# name: web-dev
if [ -z "${CONTAINER_ID}" ]; then
    exec "/usr/bin/distrobox-enter"  -n web-dev  --  '/usr/sbin/php'  "$@"
elif [ -n "${CONTAINER_ID}" ] && [ "${CONTAINER_ID}" != "web-dev" ]; then
    exec distrobox-host-exec '/var/home/silver/.local/bin/php' "$@"
else
    exec  '/usr/sbin/php' "$@"
fi
$ php -a
Interactive shell

php > echo 'Hello world!';
Hello world!

That’s about it. Happy to answer any questions about this and interested to hear how you use Linux! :v:

2 Likes

My setup is almost default Fedora Silverblue. The only things I changed were:

  • Install Dash2Dock
  • Clean my laptop from Fedora Flatpaks (I replaced it mostly with GNOME Nightly and Flathub)
  • change 4 keyboard shortcuts.
  • I also installed Firefox from Flathub
2 Likes

How do you use Dash2Dock?

My workflow is largely a vanilla GNOME workflow, I make use of the workspaces and at time of writing I have 5 open (not including the empty ready-to-use one) . I find the keyboard shortcuts to zip around very productive.

As for the setup, It’s Fedora Silverblue and my customisations (if you can call it that) can be found on my Gitlab: Christopher Boni / Fedora Silverblue Setup · GitLab

My applications are mostly Flatpaks but I do presently have quite a few layered packages for the Kernel Test Day that’s currently ongoing (great thing is I can just rpm-ostree reset when I’m done, the beauty of Atomic Desktop). I have two Toolbox containers, one for WebDev and one of Fedora QA stuff. Recently I have also been experimenting with systemd-sysext recently.

1 Like

Let’s start with configuration:

  • OS: Fedora 44 i3 Spin
  • Keyboard & Mouse: Microsoft Wireless Keyboard 850 + HyperX Pulsefire Core
  • Display: LG UltraGear 27G610A-B
  • Terminal emulator: Kitty
  • Text editor: vim and neovim
  • Shell: zsh with oh-my-zsh
  • Web browser: Firefox
  • Entertainment: Books (calibre), interesting articles (hacker news, wikipedia), youtube (mostly tutorial)

My workflow is usually just to sit in front of my laptop and click or tap the spacebar to bringing it to life and start working. Mostly terminal commands to clone repos, vim as IDE with airline theme and some plugins for syntax highlighting. A lot of terraform and pipelines (mostly jenkins), git and the cloud console depending on the client (it could be GCP or AWS). For the Fedora project, specifically for the i3 Spin, I use Boxes to test stuff in virtual machines and ansible to keep my configuration consistent between installations.

1 Like

I also have a KVM, very generic but it does the work, to switch my keyboard between my personal laptop and my work laptop (usually running windows).

Fedora Silverblue, distroboxes for every supported Java version project I need to support, one for flutter dev. Use shell extensions to split 4k screen vertically, then left side horizontally, then bottom left vertically again, where the right side is the main task, top left is for whatever else I need to do the main task, bottom left for comms or terminal. Live in some version of IntelliJ. As much as it’s gnome, I add extra shortcuts to anything I jump to or need to do, as well as extra shortcuts in IntelliJ, to avoid the mouse. The goal is supposed to be at most 3’ish things on the screen to draw attention, with priority in order of size. Telling myself that has helped me focus, in this world of stuff constantly vying for attention. Also always keep work on one workspace, make sure alt tab only includes apps open on the current workspace.

the setup … can be found on my Gitlab: …

Nice! I’ll definitely be adding that step for removing the extra repositories to my build scripts. Although on the other hand, what effect does that actually have for Silverblue? Is it just removing them as possible upstreams for when you run rpm-ostree install some-package?

How is the 200Hz refresh rate? I have the 4k version of the Dell S2725QC but nothing with a powerful enough graphics card to run games on it so it’s work only. I sometimes wish it were brighter but other than that I’m pretty satisfied with it.

I like the sound of this window placement strategy; what scaling settings are you using on the 4k display? I have one as well and at 166% it’s comfortable for two windows side-by-side but I don’t use any tiling extensions so maybe I’m missing out on some screen real estate

Fedora Silverblue here too, and I’ve landed on a “the host doesn’t really exist” setup — everything real lives one layer down.

The base

Host stays close to stock, almost nothing layered with rpm-ostree. All dev tooling lives inside one Fedora toolbox container (fedora-toolbox:44, named development). $HOME and XDG_RUNTIME_DIR are shared between host and container, so a single host-run gpg-agent/ssh-agent covers both sides no per-container auth setup. Podman itself only runs on the host, by the way tried running it inside the toolbox once for spinning up dev databases and it fails outright (cannot re-exec process to join the existing user namespace, real nested-rootless limitation). So any project database is a container on the host, reached from inside the toolbox over localhost since the network namespace is shared.

Runtime management the dnf/mise split

This is the part I’m most opinionated about. mise owns two things only: per-project language runtimes (via each project’s own mise.toml) and a fixed set of CLI tools, global, currently: pipx, neovim, lazygit, ripgrep, fd, tree-sitter, starship, fastfetch, gh, glab, fzf, bat, eza, zoxide, delta, yq, btop, dust, atuin, cmake, zellij, jq, xh, glow, hyperfine, watchexec, lazydocker, yazi, plus pgcli/mycli via pipx.

Everything else on the toolbox’s dnf layer is there for exactly one reason: it’s a system dependency Neovim’s Mason installer needs to build something, not a runtime I actually develop against. nodejs/npm so Mason can install npm-based LSP servers (tailwind, dockerfile, yaml, json, vtsls, pyright). golang because gopls/goimports/gofumpt build from source via go install. dotnet-sdk-9.0 because csharpier/fantomas pull from nuget. php-cli/php-common because mise’s own PHP plugin compiles PHP from source (confirmed by actually hitting that build failure) completely impractical, so PHP comes from dnf instead. Plus gcc/make/gdb for treesitter parser compilation, wl-clipboard for Neovim<->host clipboard, chafa/poppler-utils/unar/ffmpeg (full, RPM Fusion enabled toolbox-only) for yazi’s image/PDF/video/archive previews, git-crypt, libpq, and stow. The rule that’s kept me sane: if a new language extra needs its Mason tooling to install via a real compiler/toolchain, that goes on dnf it never goes on mise’s global list, because that would defeat mise’s whole per-project-isolation point.

Editor

Neovim on LazyVim. It ships with zero language support turned on by default every language is an opt-in extra, so nothing attaches until you import it. I’ve got 14 enabled: php, typescript, tailwind, docker, terraform, yaml, json, markdown, sql, go, python, rust, clangd, dotnet. Actual verified-live LSP list behind those: intelephense/phpactor (phpactor’s the default), vtsls, tailwindcss-language-server, terraform-ls, marksman, yaml-language-server, json-lsp, dockerfile-language-server, docker-compose-language-service, gopls, pyright+ruff together, rust-analyzer, clangd+codelldb, omnisharp+csharpier+netcoredbg. I actually opened real files and checked vim.lsp.get_clients() for each rather than trusting “installed” a couple need project root markers to attach at all (phpactor wants composer.json, gopls wants go.mod, omnisharp wants a .csproj), which is correct LSP behavior, not a bug.

Shell + terminal

zsh inside the toolbox only (host stays bash, they don’t even share /etc/passwd). Plugins cloned manually, no framework, in a specific order that actually matters: completions path added before compinit, fzf-tab loaded right after compinit, then fzf keybindings, autosuggestions, history-substring-search, and zsh-syntax-highlighting last get that order wrong and things misbehave silently instead of erroring. A tiny check in .bashrc detects /run/.containerenv and auto-execs into zsh, so it doesn’t matter how I entered the container.

Terminal is Ptyxis, kept deliberately boring one profile, no forced container binding, no custom command. Tried getting clever with profile-level container binding twice; both times it eventually leaked the toolbox binding into the actual host terminal itself. The built-in per-tab container picker does the job with zero hacks.

Dotfiles

One GNU Stow repo (silverblue.dots) covering zsh, bash, ssh config, starship, git, mise, lazygit, bat, the full nvim/LazyVim config including lazy-lock.json, and gnupg config (conf files only, never the live state dir). Editing through the repo path is instantly live. A bootstrap.sh rebuilds the whole toolbox from nothing on a new machine dnf layer, mise tools, zsh plugins, Neovim LSPs, stow restow, all of it. Secrets (SSH/GPG private keys, the nwgroup git-crypt key) live in a separate git-crypt-encrypted repo, deliberately kept apart from the dotfiles repo so a “just browse my config” clone never touches actual key material.

One hard rule I’ll flag because it saved me a redo: no tool in this whole stack gets a hardcoded color theme (no Catppuccin, no Gruvbox, nothing). Ptyxis stays on its stock gnome palette and every other tool starship, bat, delta, eza, lazygit just reads terminal ANSI colors. Tried a real theme once, hated maintaining it across eight configs, reverted everything. Now there’s exactly one place to change if I ever do pick something.

Beyond the laptop self-hosted GitLab CE

This is the part that ties it together for me: I run my own GitLab instance (Hetzner CX33) for every repo, all groups (infra/work/personal/security/dotfiles). A shared infra/ci-templates project holds every pipeline building block base.yml, laravel.yml, node.yml, sast.yml (Semgrep), secret-detection.yml (Gitleaks), dependency-scan.yml (Trivy SCA), dast.yml (OWASP ZAP), sbom.yml (CycloneDX), container-scan.yml (Trivy image scan), oci-build.yml/iso-build.yml (Buildah/bootc), and a full-scan-bundle.yml that nests every self-gating scan template behind one include line. Five runners split by trust level: a shell-executor fallback that picks up anything untagged, a dedicated deploy runner, an OCI/privileged builder, a docker-based scan runner, and an isolated security runner for CTF/pentest work. Renovate runs group-wide from its own project rather than per-repo config, error tracking is GitLab’s own integrated Sentry-compatible tracker (no third-party SaaS), and backups + uptime checks are systemd timers (no cron on this box) that email me on failure. Keeping that whole side self-hosted and boring is as much “the workflow” for me as the editor config is the laptop and the server are the same philosophy applied twice.

I’m officially retired but still do development work pretty much every day (for fun instead of money). I use a basic Fedora 44, dual monitors, ancient IBM SK-8815 keyboard (I like the feel) and vim as my main editor under bash.

I do many varied things, such as embedded systems, helping to maintain a Linux distro that runs on smartwatches (AsteroidOS.org if you’re interested) and writing scripts and software for my own purposes in C++, Python, shell scripts, or whatever else seems like it might be most useful.

My latest project has been setting up ramalama as the basis for a local-only LLM assistant to work on Yocto and bitbake issues. The project before that was to use a custom circuit based on a STM8S processor (a cheap and tiny 8-bit micro) to connect a microSD card to my 50-year-old Commodore PET for use as a disk emulator.

Launch and switch between apps. I customised it to be a little more vanilla-like tho.

125% scaling. 150% is nice to look at, but I feel like I’m wasting too much screen real estate.

I guess when you put it like that it’s pretty obvious :sweat_smile: I was just curious because the dash is part of GNOME that I almost never interact with :person_shrugging:

Yeah fair. One tip though, on recent GNOME versions you can set scaling to things that will result in an even number of pixels in both directions, which if I recall correctly was introduced to fix blurriness in xwayland windows. The closest one for you would then be 133%.

Sounds like you’ve spent a lot of time and energy carefully crafting this setup :v: Thanks for sharing! are you a devops engineer?

for fun instead of money

The mark of true passion! I hope to keep this approach over time as well.

ancient IBM SK-8815 keyboard

I love the way it looks! Like a station in a battleship or something!

a Linux distro that runs on smartwatches

Will definitely be keeping an eye on this. I have a smartwatch that I only put on when I go for a run and I kind of hate everything about it, other than how easy it makes it to record distance, pace, and overall duration. I would consider getting another one only if it were either completely focused on just recording those three values that I care about or were otherwise actually useful enough in day-to-day life to justify the amount of software it needs to run.

Appreciate that! To your question not by title, no. I graduated this year as a Software Engineer/Developer and I’m heading into a Cyber Security degree next, with DevOps/DevSecOps as a genuine standing interest running alongside both rather than a job description of its own. I’ve also freelanced across a fairly broad range of work. Put those three together and this setup stops looking like scope creep and starts looking like the natural intersection of all of them:

The security side is why so much of this is built around reproducibility and provenance rather than convenience the immutable Silverblue host, a bootstrap script that rebuilds the entire toolbox from nothing rather than hand-tuned state I’d have to trust blindly, GPG-signed commits, secrets kept git-crypt-encrypted in a repo deliberately separated from anything I’d casually clone or share. None of that is theoretical for me it’s the same instinct that’s pulling me toward the Cyber Security degree, just applied to my own daily environment instead of someone else’s system.

The DevOps/DevSecOps interest is why the self-hosted GitLab side exists at all rather than just using GitHub running my own CI template library with SAST, dependency scanning, secret detection, and DAST as composable, reusable pipeline pieces isn’t something a solo dev setup strictly needs, but it’s exactly the kind of thing I wanted hands-on experience designing and maintaining rather than just reading about.

And the freelance breadth explains the rest why the editor setup covers PHP, TypeScript, Go, Rust, Python, .NET, and Docker/Terraform tooling all at once instead of one language stack. Different clients, different stacks, and the tooling had to flex across all of it rather than assume one specialization.

So I’d say it’s less “I’m a DevOps engineer” and more that DevOps practices are the connective tissue between a dev background, freelance breadth, and where I’m headed with security and this setup is what that looks like applied to my own machine.

1 Like

If you don’t mind it also recording heartrate and then creating an industry-standard GPX file containing all of this data, you might like this exercise recording project. One nice thing I bet your watch doesn’t have: this one respects your privacy and does not put your data into a cloud service.

1 Like