Troubleshooting and FAQ
Certificates, Firefox and mobile requirements, the Docker socket, GPUs, storage, and other things that go wrong.
Connecting
The dashboard says "Server unreachable" right after I imported my configuration.
With a self-signed certificate the browser refuses the served UI until you
have accepted the certificate once. Click Open server, accept it in the
tab that opens, then Retry. Browsers forget an accepted self-signed
certificate after a while; when that happens to a server the extension has
reached over HTTPS, it shows Secure connection failed instead of quietly
loading the interface over plain HTTP. Accept the certificate again, or
choose Continue without TLS. If the address or ports are wrong, Change
connection takes you back to the connection page. Check that the session
port is reachable from where you are (curl -k https://<server>:8443/).
Login fails with "Failed to fetch".
Either nothing answers on the ports in your configuration, or the TLS certificate is expired. The server logs an error at start-up when the proxy certificate has expired and warns two weeks ahead; the dashboard shows the same warning. Renew the certificate (the docker-sealskin installer can renew a Duck DNS one) and restart the container.
Firefox never connects, Chrome works.
Firefox does not allow extensions to talk to a server with an untrusted certificate and has no HTTP fallback. Use a trusted certificate, for example the Let's Encrypt one the installer obtains through Duck DNS, and make sure the extension's server address is that hostname, not an IP.
The mobile app shows a blank page or "Server unreachable".
The Android and iOS WebViews reject self-signed certificates and block mixed content, so the served UI only loads over HTTPS from a certificate the device trusts. There is no fallback. Once the certificate is trusted, the app behaves like the extension.
The server says "HOST_URL" in admin.json.
HOST_URL was not set when the container was first started. Open the file
and replace the string with your server's hostname or IP before importing
it, or set HOST_URL and delete the keys/admins/admin file and
admin.json to have them generated again (that also generates a new key).
I lost admin.json.
The server only keeps the public key. Remove /config/.config/sealskin/keys/admins/admin
and restart: a new key pair and admin.json for admin are created, and
the account keeps its desktops and its root key. Any other administrator can
also create a new administrator from the dashboard.
The client says "Update required".
The extension or app speaks a different bridge protocol version than the UI your server serves. Update whichever is older; the served UI is updated by updating the server image.
Sessions
A launch fails with a Docker error.
The server needs the Docker socket and the right to use it. If the error is
a permission denied on /var/run/docker.sock, make the socket group-writable
on the host (sudo chmod g+rw /var/run/docker.sock) and restart the
container. docker logs sealskin shows the exact error from Docker.
A launch times out waiting for the container.
The container started but did not answer HTTP within a minute. Usually the image is still being pulled for the first time (pull it from Installed Apps ahead of time), the host is out of memory, or the server cannot reach the container's IP. The server and its sessions must share a Docker network; the server uses the network it finds itself attached to.
"Nvidia runtime error on host."
Install the nvidia-container-toolkit, v1.20.1 or higher, and register it
with Docker. NVIDIA support needs the proprietary driver 580 or newer with
nvidia-drm.modeset=1; the toolkit's refresh service creates
/dev/nvidia-modeset at boot, so a headless host needs nothing more.
No GPU is offered in the launcher.
Three things have to line up: the server detected the GPU at start-up (the
dashboard lists detected GPUs), the user's settings allow GPU access, and
the application declares support for that GPU type (nvidia_support or
dri3_support in the store entry). Restart the container after installing
drivers so detection runs again.
Files I put in the session are gone after it stops.
Cleanroom sessions are deleted with the session. Use a home directory (or
Auto) and put files in Desktop/files, which is your shared files
directory and survives every session. Sending a file to a running session
from the launcher also places it there.
The session opens but the clock is wrong.
The client sends your browser's time zone with every launch and the
container's TZ follows it; failing that, the server's own TZ applies. Set
TZ on the sealskin container for a sensible default.
Server
Can I run SealSkin behind my existing reverse proxy?
Yes. The proxy terminates TLS for the web app's name and passes WebSockets;
SealSkin's own Caddy stays behind it and keeps routing and authenticating
every session request. With session isolation it also serves the session
names, <session id>.<domain>, which takes a wildcard certificate. The
proxy can also sign users in.
Behind a reverse proxy has configurations for
SWAG, Traefik, Nginx Proxy Manager, and Caddy, with Authelia and Authentik.
Why must the container be named sealskin?
The server inspects its own container to translate the paths it sees
(/config, /storage) into the host paths Docker needs for session
volumes, to learn the externally mapped ports it writes into configuration
files, and to attach sessions to its network. It looks itself up by that
name, falling back to its hostname.
I edited a YAML file by hand and nothing happened.
The watcher reloads a file when it changes on disk, with a short debounce.
Check the log for a parse error: a broken file is skipped with a message and
the previous state kept. Files whose name starts with . are ignored, and
SEALSKIN_WATCH_CONFIG_FILES=false disables the watcher altogether, in
which case a restart picks up the edit.
How do I move to a new server key or a new certificate?
Replace ssl/proxy_cert.pem and ssl/proxy_key.pem and restart for a new
certificate; clients need nothing. Replacing ssl/server_key.pem changes
the server public key every client has stored, so every user has to import
a new configuration file (the Export Config of an already-updated client
or a new file from the Users panel).
Where are the logs?
docker logs -f sealskin. SEALSKIN_LOG_LEVEL=DEBUG makes the server
considerably more talkative. Caddy logs errors only.
Getting help
Search the issues and ask on the LinuxServer.io Discord. Problems with a specific application image belong with that image's repository; problems with the container packaging belong with docker-sealskin.