SealSkin

Administration

Users, groups, administrators, app stores, installed applications, templates, the App Laboratory, sessions, and GPUs.

Administrators manage the server from the same options page every user sees, which grows the panels below. All of it is also plain YAML and text under /config (see Configuration); the panels and the files are two views of the same data, and hand edits are picked up live.

There are two roles. Administrators can do everything, have no per-user settings (they always get the defaults, with storage and GPU enabled) and cannot be limited. Users launch and manage their own sessions and files within the permissions set for them. The built-in administrator admin, who signs in with the root key on the web and with the first start's key file in the apps, cannot be deleted.

Dashboard

The landing panel shows who you are, the server address, CPU model, storage use, the GPUs the server detected, and a warning when the proxy certificate expires within 14 days or has expired. Export Config produces the same JSON file you imported, for setting up another device; Logout & Clear Config wipes the client.

Users

Create New User takes a username (letters, digits, _, and -). In the web app, and wherever key files are off, that is all: the user signs in through the identity provider or proxy, and one who signs in before being created is created then, with the default settings; creating the name first is for a provider that is not to create accounts (SEALSKIN_SSO_CREATE_USERS=false). With key files on, in the extension and the mobile app the form also takes a public key: leave it blank and the server generates an RSA key pair, shows the resulting configuration file once, and forgets the private key; paste a key when the user generated their own pair on the connection page and sent you the public half. The Admins tab, which makes key-file administrators, is there while key files are on; otherwise administrators come from the provider's group or a group's Administrator switch.

Each user carries these settings, editable later:

SettingEffect
Active AccountAn inactive user is refused.
GroupsThe groups the user is in, beside those the identity provider puts them in, which the form lists. In none, the user is in default (see Groups).
AdministratorThe user administers the server.
Allow Persistent StorageWithout it every session is a cleanroom, the file manager is unavailable, and files cannot be sent to sessions.
Allow Public File SharingEnables share links from the file manager. Requires persistent storage.
Allow GPU AccessWhether the launcher offers GPUs to this user.
Share GPUsOff gives each of the user's GPU sessions a GPU no other session is on.
Move Home DirectoriesThe user may move their own home directories between the nodes of a cluster, from the launcher. On by default: a user who has home directories can take them where they launch.
Allow Editing App TemplatesOpens the App Templates editor to a user who is not an administrator. They create, change, and delete templates, except for the DOCKER_* and KUBERNETES_* settings, which grant authority over the Docker host or the namespace: those keep the values an administrator gave them, and only an administrator deletes a template that carries any.
Harden Container, Harden Window ManagerForce the base image presets HARDEN_DESKTOP and HARDEN_OPENBOX on every session the user starts, including apps a collaboration room swaps to. They are applied after the app template and the app's own environment overrides, so neither can switch them back off. Leave them off to let the template decide.
LimitsSessions at once, storage, CPUs and memory per session, session length, and a time allowance per day, week, or month; see the limits. Blank or negative is no limit.
Application keysWhether the user may sign the extension and the mobile app in with application keys, which apps may use them, how long a key lives, and the dormancy rules that send the user back to the web to sign in. These bind administrators too.
PoolsRestricted pools open to the user, and pools closed to them.
PRoot Apps catalogThe catalog the user's sessions install PRoot Apps from. Left at None, the first of the user's groups to choose one decides.

Deleting a user also deletes their storage on the node the dashboard is served from. A user with no key shows Single sign-on only in place of a public key.

Manage Home Directories in a user's row lists, creates, deletes, and, on a cluster, moves home directories on their behalf. Keys lists the user's application keys, with the app each was last used from, and revokes one or all of them; the user makes new ones under Application Keys in Settings.

Groups

A group sets some of the same switches and limits for its members and leaves the rest alone: each switch is Not set, Allow, or Deny, and a blank limit is not set. A user in one group gets the group's value for everything the group sets. A user in several gets, for each setting, the restricting value if any of the groups gives it, and the smallest limit; the edit dialog shows the result as Effective Settings. The PRoot Apps catalog is a choice rather than a limit: a member's own choice wins, then the first of their groups that makes one. Identity provider groups names the provider's groups whose members are in this group without being listed. Groups are also a permission target for applications, VPN profiles, and pools. Deleting a group leaves its members with what their other groups and their own settings give.

The table opens with default, marked Built in: the group of every user in no other group, with no file behind it. View shows its settings, which are the server's defaults; they cannot be changed here, and no group may take the name. To change what a user in default gets, place them in a group or edit the user. Naming default in the users and groups of an application, a VPN profile, or a pool opens it to exactly those users, where all opens it to everyone.

Cluster

Shown to administrators; Clusters explains each part.

  • Nodes: every node with its roles, pool, load, and sessions, whether it is answering, and the controls to approve, suspend, move to a pool, or remove it. Add a node issues a join code.
  • Pools: who may use each pool and what an hour in it costs.
  • Store: where the shared records are kept and whether it answers.
  • Usage: the weighted hours each user spent this day, week, or month.

Branding

The web app can wear your organization's name instead of SealSkin's. The panel is a form beside a mock of the home page, which repaints as you type; nothing changes until Save branding, and Back to defaults removes it all.

  • Product name: stands wherever the interface would say SealSkin, in every language: the page title, the sidebar, the sign-in page, the installed web app, and the browser's search engine entry.
  • Logo: a square PNG, JPEG, or WebP up to 1 MB. It is the sidebar logo, the favicon, the icon of the installed web app, and the picture of an application that has none. The logo links to an address of your own, opened in a new tab; empty, the logo links nowhere. By default it leads to the SealSkin project on GitHub.
  • Accent color: one color, from which the buttons, highlights, focus rings, and the wordmark take their shades. Clear it for the default violet.
  • Companion apps: where users get the Chrome extension, the Firefox add-on, the Android app, and the iOS app, linked from the sign-in page and beside the application keys in the profile. Each link can point at a build of your own, or be hidden, as when an organization ships one of them only.
  • Wallpaper: a picture behind the home page, up to 8 MB (a larger one is scaled down in the browser before it is uploaded), with the same position, blur, and dim controls users have. Users start from it and may still pick their own background, unless Force this wallpaper on every user is on, which also takes the Customize button off the home page.
  • Home page links: tiles the home page shows above the applications, for your own sites and tools, in the order given. Each has a name, an address, an icon (a Font Awesome class such as fa-book or fab fa-github, or an https address of a picture, which the server fetches and serves itself), and opens either in a new tab or, marked In isolation, in a session of an application the user picks, as a pasted link does.

The brand is kept in branding/ beside the other shared records, as branding.yml with the logo and wallpaper files next to it, so every node of a cluster serves it and a deployment can seed it from a volume (see Configuration). The browser extension and the mobile app show their own name until they connect; what they frame then is the branded web app. With auto sign-in on, the sign-in page is the identity provider's own, so there is nothing of SealSkin's to brand there.

Sign In

One card for each way of signing in, written for the whole cluster: OpenID Connect and SAML with the addresses to register at the provider and a Test that asks the provider for its metadata and shows what came back; the reverse proxy headers; Landing, which sends a signed-out browser straight to a provider; and who a sign-in is (the username and groups claims, the administrator group, and how long a sign-in lasts). A field left empty is taken from each node's environment. The Root Token card says whether this node still takes the token, and warns when it does not and no identity provider group names administrators.

Audit Log

What was done on every node, by whom, newest first: sign-ins, launches and stops, and administrative changes. Search it, choose a day or a range, page through it, and export everything that matches as CSV or JSON.

Admins

Creates and deletes administrators, with the same key handling as users. The panel also shows the server public key that every configuration file carries; a user who configures the client by hand needs it.

A user an identity provider or a proxy signs in as an administrator, through SEALSKIN_SSO_ADMIN_GROUP or a group with the Administrator switch, is not listed here: they stay under Users, marked Administrator, since the rights come from the provider at each sign-in.

App Stores

An app store is a YAML catalogue at a URL. The default store is linuxserver/sealskin-apps, which covers the LinuxServer.io desktop images. Add New App Store takes a name and a URL; the server fetches and caches the file and refreshes it on the auto-update interval or on demand with Refresh. The format is described in Configuration, and a host that asks for a sign-in is served by the node's netrc file.

Available Apps shows the selected store. Installing opens the app's settings:

  • Custom Name and Container Image: override what the store says. An image you change here is kept even when the store entry is updated.
  • Allowed Users and Allowed Groups: comma-separated names, or all. An app is visible to a user when they are listed, their group is listed, or either list says all.
  • Features: GPU support, home directory mounting, URL opening, and file opening as declared by the store, which you can turn off for this install.
  • Auto Update Image: include this image in the hourly pull.
  • Application Template: the template whose environment is applied to every launch.
  • Environment variables: extra NAME=value pairs passed to the container.

Add Manual App installs an image that is in no store. It must be built on a Selkies-compatible base (the LinuxServer.io baseimage-selkies), listen on the port you enter, and honour the same environment variables.

Installed Apps

Every installed application with its source, image, and image status. Check compares the local image digest with the registry; Pull fetches the newest image and refreshes the app's cached autostart script. On Kubernetes, where nodes pull images themselves, Pull pins the registry's current digest for new sessions instead (see Kubernetes). Edit reopens the install dialog. Deleting an app does not stop its running sessions. A private registry, and a mirror every image is pulled through, are set up on the node (Registries and proxies).

With SEALSKIN_AUTO_UPDATE_APPS enabled (the default) a background job pulls every auto-updating app's image once an hour, refreshes the store caches, and prunes dangling images. Running sessions keep their container; the new image is used by the next launch.

Installed apps are stored as a reference to the store entry plus your overrides, so when the store changes an image tag or an extension list, the change applies at the next cache refresh without reinstalling. Only the fields you changed stay pinned.

PRoot Apps

PRoot Apps is the package manager inside every LinuxServer.io desktop image: proot-apps install firefox unpacks an application into the home directory, and its graphical installer (gui) offers the same list with icons. A catalog is a folder of those packages that SealSkin keeps on every node and mounts read-only into sessions, so the users assigned to it install and update from the folder and their sessions reach no registry: PRoot Apps finds the catalog through PA_REPO_FOLDER, which the session's environment points at the mount.

New Catalog opens the editor. Give the catalog a name, then pick its apps from the grid, which lists what the remote publishes. A remote is the GitHub owner/repo of a proot-apps repository, or the base URL of one served elsewhere and the registry of its images, one space apart (Registries and proxies); the editor opens on SEALSKIN_PROOT_APPS_REMOTE (linuxserver/proot-apps) and takes any repository built the same way. The apps of SEALSKIN_PROOT_APPS_REMOTE keep their short names: a session on a catalog gets PA_DEFAULT_REPO, the registry of that remote, which tells PRoot Apps what install <app> means. Apps of any other remote are installed by their full image name (registry.example/it/proot-apps:<app>). A catalog can mix apps from several remotes. A PRoot Apps older than PA_DEFAULT_REPO takes short names for apps of linuxserver/proot-apps whatever the setting says, so with such a desktop image only that remote may be the setting. Apps the remote marks disabled are not listed.

The table shows the state of this node's copy of each catalog. Every node with sessions fetches the apps itself, for its own architecture, as soon as a catalog is saved; Update fetches again, on every node, the apps whose package changed, which Auto update also does on the auto-update interval. Apps a remote does not build for the node's architecture are skipped there and hidden by the installer. Deleting a catalog removes every node's copy; users assigned to it keep the setting, which then does nothing.

Assign a catalog to a user or a group in their settings. A session mounts its catalog at /mnt/proot-apps, and a user with no catalog has PRoot Apps as the image ships it, fetching from the registry. The catalogs live under SEALSKIN_PROOT_APPS_PATH (/storage/sealskin_proot_apps), one folder per catalog, in the layout the proot-apps README describes for a local repository: metadata/ for the installer and one folder per package, named after its image (ghcr.io_<owner>_<repo>_<app>/).

VPN Profiles

A profile is a provider's WireGuard or OpenVPN configuration, imported from one config file or a zip of thousands, reduced to a template and a list of endpoints. A session that picks a profile leaves through a gateway container the node runs for that profile and endpoint, shared by every session that picked them, and the application image needs nothing for it. Import a profile, publish the endpoints users may pick, cap the connections it may spend, and say who may use it; VPN profiles describes the import, what the providers hand out, and how the routing works.

App Templates

A template is a named set of environment variables applied to every session of the apps that use it. The Application Template Editor shows the variables as collapsible cards, each with a count of the values that differ from the default; a box above filters them by name, and Changed only leaves just the values a template sets. The cards:

  • Appearance: the page title, logo, sidebar title, and dashboard style, then whether the Selkies sidebar shows and which of its sections and buttons it offers, with a preview that follows the toggles.
  • Display: manual resolution, dynamic resize, aligned resolution, scaling and DPI, second screen, fullscreen, window decorations, and the Wayland backend.
  • Input: keyboard shortcuts, cursors, pointer options, published input devices, and gamepads with their kernel devices.
  • Audio and Webcam: enabling each, what starts at connect, and the encoding of each.
  • Performance: encoders, frame rate, CRF and bitrate ranges, rate control, keyframes, JPEG and paint-over quality, backpressure, and the watermark on the stream.
  • GPU: GPU selection, render nodes, DRI3, and CPU encoding.
  • Clipboard and Files: clipboard policy and seamless sync, file transfers and their directory, printing, and the command websocket.
  • Sharing: sharing links, view-only, collaboration, and players.
  • Hardening: the presets behind the user-level hardening switches and their individual components.
  • Lifecycle: connect and disconnect hooks, the application ready file, Docker-in-Docker, the Steam shim, and IPv6.
  • Integrations: the audit webhook, the Computer-Use server, recording, metrics, and debugging.
  • WebRTC: a block of its own, since its values are one decision: the base image streams over WebSockets until the mode says WebRTC or a STUN, TURN, Cloudflare, or public IP value is set, and then streams over WebRTC with dual mode on. The card's badge names which the template amounts to. Inside it: mode and dual mode, transport (pacing, congestion control, ICE-lite, ports), STUN, TURN credentials, the TURN REST API, Cloudflare TURN, and diagnostics.
  • Container: DOCKER_* settings that become container run options rather than environment variables: privileged mode, capabilities, devices, extra bind mounts, memory and CPU limits, network, IPC and PID modes, DNS, sysctls, ulimits, tmpfs, and extra groups; and on Kubernetes KUBERNETES_POD_TEMPLATE, a PodTemplate laid over the session pod. Only an administrator edits these.

The list of variables comes from template_schema.yml on the server, so a new image option is a server change and never needs a client update. The per-app environment overrides from the install dialog are applied after the template, so the more specific setting wins; the user-level hardening switches are applied after both.

Templates written before the Selkies variables were renamed keep working: SELKIES_H264_* keys, SELKIES_IS_MANUAL_RESOLUTION_MODE, the three SELKIES_CLIPBOARD_* booleans, and the x264enc encoder spellings are translated to their current names when the template is loaded, and saving the template from the editor writes the current names.

A blank Default template is created on first start. Templates shipped in the default templates directory cannot be deleted from the UI.

App Laboratory

The laboratory builds a meta-app: a variant of an installed app with its own name, icon, autostart script, and, most usefully, a pre-populated home directory. Choose the base app, name the new one, upload an icon, optionally paste an autostart script (the Wayland and X11 variants are separate), and pick who may use it, then Save & Launch Customization Session.

That session runs the base app with the meta-app's home template mounted read-write. Configure the application, sign in to services, place files, adjust settings; when you are done, Close Session & Finalize stops it and keeps the directory as the template. Reopening the laboratory on an existing meta-app launches it the same way for further changes.

In the web app the customization session opens in a tab of its own, and the laboratory keeps track of it: while one is open the page shows it first, with Re-open session and Close & save template, wherever you have been in between. An administrator has one open at a time. It is not a session in the ordinary sense: it appears in no session list, only here, and counts toward no limit. It runs on the node the dashboard is served from, where the template is kept.

For users, a meta-app behaves like any other app, except that the first launch copies the template into their auto-<name> home directory, and a cleanroom launch copies it into the ephemeral one. Deleting a meta-app removes its icon and template.

Sessions

Active Sessions lists every user's sessions with the application, start time, and launch context, and can stop any of them. Users see only their own.

GPUs

At start-up the server detects GPUs on the host:

  • NVIDIA cards through the NVIDIA driver. Sessions get the NVIDIA container runtime with all capabilities and, when it exists, /dev/nvidia-modeset. This needs the proprietary driver 580 or newer, the nvidia-container-toolkit v1.20.1 or higher, whose refresh service creates that node at boot, and the kernel parameter nvidia-drm.modeset=1.
  • DRI3 devices (Intel, AMD, and others) through /dev/dri. The render node is passed into the container and exported as DRI_NODE.

A launch may use a GPU when the user's settings allow it and the app declares support for that GPU type. On Wayland, NVIDIA sessions also receive the DRI node so the compositor can use the card directly. On Kubernetes the GPUs are the requests sessions can make, detected or defined as PodTemplates, as Kubernetes describes.

Keys and certificates

The dashboard warns about a proxy certificate that is expired or about to expire. Replacing ssl/proxy_cert.pem and ssl/proxy_key.pem under /config and restarting the container installs a new one; the installer script from docker-sealskin can renew a Duck DNS certificate and do the restart for you.

The server key ssl/server_key.pem is what every client's stored server public key verifies. Replacing it invalidates every client configuration, so treat it like the CA of your installation. Rotating a user's key means creating a new user file or editing the public key in it; see Configuration.