KLYRN
KLYRN Web
All documentation
  1. Home
  2. Docs
  3. Applications

Applications

An application is one or more container images, a private network, storage with a fixed size, and a domain with a certificate. It gets no Docker socket, no privileged mode and no host network.

What an application is

A site is a domain served by nginx from a directory. An application is a domain served by nginx from a container. Accounts, certificates, backups, jobs, resource limits and the reseller model work the same way on both.

Service
One image, running. An application may have several. They see each other by name on a network only they share.
Route
A domain, a service and a port inside that service. nginx and the certificate are KLYRN's, as for a site.
Volume
Storage that survives redeployment. Its own filesystem with its own fixed size.
Release
One deployment, recorded with the image digest it ran, so a rollback is exact.

Node.js applications have a different lifecycle and are documented under Node.js. They are klyrn app. These are klyrn container.

Creating and deploying

klyrn container list
klyrn container show shop
klyrn container deploy shop --image ghcr.io/you/shop:2.1
klyrn container route add shop shop.example.com --port 8080
klyrn container logs shop --tail 200 --search error

A deployment pulls the image, starts the new container and waits for it to answer. If it never answers, the deployment fails and the previous release is put back.

A service a domain reaches is checked before anyone can reach it. Its new container comes up on a private port beside the one that is serving. The health check is aimed at that port, and nginx moves to it only after the check passes. A database or worker, which nothing outside the server reaches, is replaced in place. A routed service that mounts a volume has two containers on it while the check runs. The full entry.

Every release records the digest it ran. A tag can move and a digest cannot, so a rollback puts back what was serving:

klyrn container releases shop
klyrn container rollback shop 7

A Docker Compose file can be imported from the panel. Unsafe fields are refused by name, with the reason. See what is refused.

What is enforced, and by what

A control the kernel applies is different from one a daemon reports. This table names what enforces each property.

PropertyEnforced by
A volume cannot exceed its sizeext4 on its own loop device. The write fails with ENOSPC. The server's free space does not move.
A container cannot write to its root filesystemReadonlyRootfs, in the kernel. The write is refused.
Scratch space is boundedA tmpfs with a size, charged to the memory cgroup.
An account's memory and CPUIts cgroup slice.
A container cannot regain dropped privilegesno-new-privileges, plus every capability dropped.
A container's writable layerNothing. See below.

Why the root filesystem is read-only

Docker accepts a per-container storage limit. With the overlay driver it installs by default, it applies that limit to nothing. The limit is accepted at creation, as a daemon default and by the update endpoint. Each returns success and enforces nothing, so a container can fill the server's disk.

KLYRN therefore offers no writable-layer quota. It removes the writable layer: the root filesystem is read-only by default, scratch space is a tmpfs with a size, and anything that must survive goes in a volume. The kernel applies all three.

A service can be given a writable root deliberately. KLYRN then states that what it writes outside its volumes is limited only by the server's free disk. The machine's disk reserve is not a limit on that application.

Volumes

A KLYRN volume is a sparse ext4 image on its own loop device: a real filesystem with a real size.

Default size
1 GiB. The largest is 1 TiB.
Filling it
Stops that application and nothing else. The write fails, the server's free space does not move, and no other customer notices.
Growing it
Online, from the panel. It never shrinks.
Backups
Included unless the volume is marked excluded.
Occupancy
Measured from the filesystem and shown as used-of-capacity, with a warning before it fills.

An application will not start against an empty directory where its data should be. If a volume cannot be mounted, the deployment is refused and no container is created. A database that starts on an empty disk would initialise a new one.

The server's own reserve

KLYRN keeps headroom on the host that applications may not allocate into. It is 10% of the disk, never less than 2 GiB and never more than 20 GiB. A volume that would eat into it is refused when it is asked for.

Isolation

Every application gets a private network. Its services reach each other by name on it, and nothing else is on it.

No Docker socket
Mounting /var/run/docker.sock (or containerd's, or CRI-O's, or Podman's) is refused. A container that can talk to the daemon can start a privileged one, which makes it root on the server.
No privileged mode
Refused. A privileged container holds every capability and every host device. It is a root process with a different filesystem.
No host networking
Refused. It would put the container on the server's own network stack. There it could bind the server's ports and reach anything listening on 127.0.0.1, including the database and the panel, unfiltered by the firewall.
No host paths
A container mounts KLYRN volumes, and nothing else off the host.
Capabilities
All dropped, always, with only a small reviewed set addable.
Registries
An allow-list: klyrn container registry list | allow | deny. Allowing one is an administrator's decision.

The validated type KLYRN deploys from has no field for privileged, network mode, devices, host ports or host mounts. A future code path that forgets to check still cannot ask the daemon for one. The request type carries them only so they can be refused by name.

When something is refused

A refusal names the field, the value it held, and the reason, and explains what the field does.

The fix is almost always to delete the line. A container that wanted the Docker socket wanted to deploy things. A container that wanted host networking wanted a port. KLYRN gives it a route and a domain.

Environment and secrets

klyrn container env shop APP_ENV=production
klyrn container env shop --secret DATABASE_URL
klyrn container env shop --remove OLD_KEY

A secret's value is read from standard input, never from an argument. An argument is visible in ps to every user on the machine, and it lands in the shell history of whoever typed it.

Sealed values are stored sealed and unsealed at the last moment, by the deploy engine alone. They do not appear in the job log, a backup manifest, the panel or a support bundle.

Backups

klyrn container backup create shop
klyrn container backup list shop
klyrn container backup restore 128
klyrn container backup restore-as-new 128 --name shop-copy --domain copy.example.com
klyrn container backup schedule shop daily --keep 7

A backup holds the application's definition, the image digest each service ran, its routes, its limits, its environment including sealed secrets, and its volumes. It does not hold the image's layers. A restore pulls the recorded digest back from the registry.

A backup is enough to rebuild the application after it has been deleted, and it outlives the application on purpose.

Crash-consistent

A volume backup is crash-consistent. The filesystem is frozen and copied, and nothing asks the application to flush first. A database restored from one recovers the way it recovers from a power cut. That is reliable, and it is not identical to a clean shutdown.

restore-as-new builds a second application beside the original from the same backup. It needs a domain of its own, because the original is still serving its name.

Restarts and reboots

KLYRN remounts volumes and brings services back itself, in an order where nothing starts against storage that is not there yet. This is tested by rebooting a server with a volume 99% full and a WordPress site running beside the application.

A service that has died is shown as dead, whatever the page showed when it last loaded.

What this server can run

klyrn container capabilities
klyrn containers status
klyrn containers preflight

capabilities answers whether this server can run an application at all and what it has left. preflight is the check the installer runs before enabling the runtime, and it can be run by hand at any time.

The container runtime is optional. A KLYRN server that hosts only websites never installs it, and enabling it later is one operation.

Building from a git repository

An application can start from a repository with a Dockerfile. KLYRN clones it, builds the image on this server, and deploys it by the digest it built, never by a tag. After the image, it is the same engine as every other application: network, volumes, environment, health check, domain, certificate, backups, Move and rollback.

Applications → New application → Git repository

klyrn container source <name> [--repo URL] [--branch NAME] [--dockerfile PATH] [--context DIR]
klyrn container deploy <name>             # clone, build, deploy, health-check, keep or roll back
klyrn container releases <name>           # commit, branch, digest, how long the build took, what happened
klyrn container rollback <name> <release> # the image that release ran, started again; nothing is rebuilt

A build is treated as hostile code. It runs with no Docker socket, no host network and no privileges. It has a hard memory limit with no swap behind it, a CPU quota and a time limit. It is held to the same storage reserve every website on the server depends on, so it cannot fill the disk. The build context is confined to the repository. ../, absolute paths, symlinks that point out, devices and FIFOs are refused before a byte reaches the daemon.

Failures are named. A build that fails says Build failed and production is unchanged. It never says a deployment failed when none started. A build that succeeds and then fails its health check leaves the previous release serving, and the message says which of the two happened.

Private repositories use a deploy key KLYRN generates per application. The panel shows the public half to paste into the repository as a read-only key. The private half never leaves the server. A push can deploy automatically through a signed webhook whose secret is shown exactly once. Auto-deploy is off until you turn it on, so a repository never deploys before its environment is set.

Discord WhatsApp