# Milestone: Running an Offline Kemal App with DNF on Fedora Linux! 🎉

**URL:** <https://forum.crystal-lang.org/t/milestone-running-an-offline-kemal-app-with-dnf-on-fedora-linux/9181>\
**Category:** Community\
**Created:** [October 1, 2026, 11:25pm UTC](https://forum.crystal-lang.org/t/milestone-running-an-offline-kemal-app-with-dnf-on-fedora-linux/9181 "2026-10-01T23:25:31Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![renich](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/renich/32/2137_2.png) [@renich](https://forum.crystal-lang.org/u/renich)\
**Post date:** [October 1, 2026, 11:25pm UTC](https://forum.crystal-lang.org/t/milestone-running-an-offline-kemal-app-with-dnf-on-fedora-linux/9181/1 "2026-10-01T23:25:31Z")

</div>

Hey everyone!

We wanted to share an exciting milestone from our work on the **Fedora Crystal SIG** (`crystal-in-fedora`):

Today, we successfully ran a Kemal web application **entirely offline** inside a network-isolated container (`--net=none`), after installing Kemal directly as a system library with `dnf`!

No `git clone`, no network calls, no `shard.yml`, no `shard.lock`, no local `lib/` directory, and no vendored tarballs. Just:

```bash
# dnf install crystal crystal-kemal

```

And in a single script (`app.cr`):

```crystal
require "kemal"

get "/" do
  "Hello from Fedora Crystal (100% offline)!"
end

Kemal.run

```

Running `crystal run app.cr` immediately compiled, resolved all transitive dependencies (`radix`, `exception_page`, `backtracer`), and served HTTP requests completely offline.

* * *

### How Did We Do It?

While Fedora’s packaging guidelines permit standalone leaf applications to vendor dependencies (similar to Go and Rust using a `vendor.tar.xz`), distributing reusable shard libraries as unbundled system packages has historically been a challenge. Distributing compiled `.so` binaries doesn’t work for Crystal because of compile-time macros, generics monomorphization, and whole-program optimizations.

We solved this through three simple mechanisms:

1. **Native System Shard Path** : When building the Fedora `crystal` compiler RPM, we injected `/usr/share/crystal/shards` into `CRYSTAL_CONFIG_PATH`:

```plaintext
CRYSTAL_PATH="lib:/usr/share/crystal/shards:/usr/share/crystal/src"

```

2. **Shard-as-RPM** : We package reusable shard libraries as uncompiled source trees into versioned directories (e.g. `/usr/share/crystal/shards/kemal-1.14.0/`). This leaves the full AST available to the compiler so macros, generics, and LLVM inlining work natively at build time.
3. **The LLVM Primary Symlink Model** : To allow single scripts to do `require "kemal"` while still letting multiple library versions coexist on the system without RPM package collisions:
  - The primary `crystal-kemal` package provides an unversioned symlink:  
`/usr/share/crystal/shards/kemal -> kemal-1.14.0`
  - Compatibility packages (like `crystal-kemal1.13`) live in their own versioned directory without the unversioned symlink.
  - For complex projects with a `shard.lock`, our companion tool `shards-link` reads the lockfile and creates local symlinks in `./lib/` pointing directly to system packages—again, completely offline, reproducible, and without touching Git state.

* * *

### Multithreading & Fibers

As a bonus during our verification, Crystal 1.21.1’s new **Execution Contexts** concurrency model and multi-threaded fibers ran effortlessly in the same offline container. Resizing the default execution context or creating worker pools scaled smoothly across system threads:

```plaintext
Observed threads: DEFAULT-0, DEFAULT-1, DEFAULT-2, DEFAULT-3

```

Concurrent compute fibers executed in parallel across all worker threads with zero hitches.

* * *

### What Does This Mean for the Ecosystem?

1. **True Air-Gapped Development** : You can now develop Crystal applications in high-security, offline environments (finance, telecom, defense, offline laptops) using standard system packages without needing internet access or manual vendoring.
2. **First-Class Distro Shards** : Reusable Crystal shard libraries can be installed and managed cleanly via distribution packages, receiving system security updates and CVE tracking.
3. **Frictionless Scripting** : Anyone can install a library with `dnf` and immediately write a one-off script using `require "<shard>"` without initializing a whole shard workspace.

* * *

### Come Join the Fedora Crystal SIG!

We are actively building out the Crystal packaging ecosystem in Fedora and EPEL, testing compiler builds on Rawhide and Fedora 44+, and packaging key community shards.

If you love Crystal and want to help with packaging, testing, or shaping how Crystal integrates with Linux distributions, we would love to have you with us!

- **Fedora Crystal SIG Wiki** : [SIGs/Crystal - Fedora Project Wiki](https://fedoraproject.org/wiki/SIGs/Crystal)
- **Packaging & Tooling on Codeberg** : [Fedora Crystal - Codeberg.org](https://codeberg.org/fedora-crystal)
- **Copr Repositories (F44/Rawhide x86\_64 & aarch64)**: [Making sure you're not a bot!](https://copr.fedorainfracloud.org/coprs/renich/crystal/)
- **Matrix Chat** : `#crystal:fedoraproject.org`

Cheers,  
**Rénich Bon Ćirić** & **Gemini** (_AI pair programmer collaborating with Rénich_)
