Environment Variables
Configuration for a self-hosted server. For the agent’s variables, see Agent Configuration.
Where to put them
Files are read in order, and the last one wins:
.env— the defaults. Do not edit this; an upgrade overwrites it..env.enterprise— Enterprise defaults, when the edition is not community.../cloud/.env— when present, for Cloud deployments..env.override— yours, and it wins over everything above.
Put every change in .env.override.
# .env.override
SHELLHUB_DOMAIN=shellhub.example.com
SHELLHUB_AUTO_SSL=true
SHELLHUB_POSTGRES_PASSWORD=<not-admin>
Network
| Variable | Default | Meaning |
|---|---|---|
SHELLHUB_BIND_ADDRESS |
0.0.0.0 |
Address the gateway binds |
SHELLHUB_HTTP_PORT |
80 |
HTTP port |
SHELLHUB_HTTPS_PORT |
443 |
HTTPS port. Only bound when SHELLHUB_AUTO_SSL=true |
SHELLHUB_SSH_PORT |
22 |
SSH port. Published by the server, not the gateway |
SHELLHUB_DOMAIN |
localhost |
Public domain. Required for auto-SSL |
SHELLHUB_NETWORK |
shellhub_network |
Docker network name. Change to run several instances on one host |
SHELLHUB_NETWORK_EXTERNAL |
false |
Join SHELLHUB_NETWORK as an existing network instead of creating it. It must exist before the stack starts, and down leaves it in place |
TLS
| Variable | Default | Meaning |
|---|---|---|
SHELLHUB_AUTO_SSL |
false |
Obtain certificates from Let’s Encrypt |
SHELLHUB_TLS_CERT_FILE |
(empty) | Path to your own certificate, inside the gateway container |
SHELLHUB_TLS_KEY_FILE |
(empty) | Its key. Set both or the gateway will not start |
SHELLHUB_ACME_CA_SERVER |
(empty) | Alternative ACME directory. Empty means Let’s Encrypt production |
Behind a proxy
| Variable | Default | Meaning |
|---|---|---|
SHELLHUB_PROXY |
false |
Accept the PROXY protocol from a Layer 4 balancer |
SHELLHUB_PROXY_TRUSTED_IPS |
0.0.0.0/0 ::/0 |
Space-separated CIDRs allowed to declare a client address |
SHELLHUB_SSH_PROXY_TRUSTED_IPS |
(empty) | Space-separated CIDRs allowed to send a PROXY protocol header to the SSH port, besides loopback |
SHELLHUB_PUBLIC_URL |
built from SHELLHUB_DOMAIN and SHELLHUB_AUTO_SSL |
URL users reach ShellHub at, such as https://shellhub.example.com. An http or https origin with no path |
SHELLHUB_TUNNEL_PING_INTERVAL |
(empty) | How often the server pings each device’s tunnel, as a duration such as 15s. Empty keeps each transport’s default, 30s on v1 tunnels and 35s on v2 tunnels |
ShellHub builds the links it hands out, such as the SSH approval links in the terminal and the SAML
URLs it sends an identity provider, from SHELLHUB_DOMAIN, with https:// only when
SHELLHUB_AUTO_SSL=true. When TLS ends at an ingress or load balancer in front of the gateway, set
SHELLHUB_PUBLIC_URL so those links use https:// without the gateway requesting certificates.
SHELLHUB_PROXY and SHELLHUB_PROXY_TRUSTED_IPS apply to the gateway, which serves HTTP and
HTTPS. SHELLHUB_PROXY_TRUSTED_IPS decides the client address of web sign-in and of web terminal
sessions, so their lockout, firewall rules and access policy source IPs depend on it. The default
trusts everyone, which is fine only if nothing but your balancer can reach the port.
The SSH port reads only SHELLHUB_SSH_PROXY_TRUSTED_IPS, which decides the client address of SSH
clients that connect to it. It closes a connection whose PROXY header comes from a peer outside
those ranges and loopback, and logs a warning with that peer’s
address. List your balancer’s range. Under Docker Compose, do not list the Docker bridge range:
the userland proxy makes every external client appear to come from it, so any client could forge
its address.
A NAT, load balancer or proxy that drops idle connections in under 30 seconds closes device tunnels
between two pings. Set SHELLHUB_TUNNEL_PING_INTERVAL below its idle timeout. Each answered ping
also marks the device as seen, and a device reads offline two minutes after the last one, so an
interval above 40 seconds tolerates fewer than three missed pings. The server refuses to start on a
value that is not a positive duration under one minute.
Database
| Variable | Default | Meaning |
|---|---|---|
SHELLHUB_DATABASE |
postgres |
Anything else warns and falls back to postgres |
SHELLHUB_POSTGRES_HOST |
postgres |
|
SHELLHUB_POSTGRES_EXTERNAL |
false |
Use a PostgreSQL outside this Compose project, at SHELLHUB_POSTGRES_HOST. The bundled postgres service does not start |
SHELLHUB_POSTGRES_PORT |
5432 |
|
SHELLHUB_POSTGRES_EXTRA_ARGS |
(empty) | Extra flags appended to the postgres command, for sizing the database to the host |
SHELLHUB_POSTGRES_USERNAME |
admin |
Note: _USERNAME, not _USER |
SHELLHUB_POSTGRES_PASSWORD |
admin |
Change this |
SHELLHUB_POSTGRES_DATABASE |
main |
Note: _DATABASE, not _DB |
SHELLHUB_POSTGRES_LOG_LEVEL |
INFO |
|
SHELLHUB_POSTGRES_LOG_VERBOSE |
false |
Logging
| Variable | Default | Meaning |
|---|---|---|
SHELLHUB_LOG_LEVEL |
info |
trace, debug, info, warn, error, fatal |
SHELLHUB_LOG_FORMAT |
text |
text or json |
SHELLHUB_GATEWAY_ACCESS_LOGS |
true |
|
SHELLHUB_SENTRY_DSN |
(empty) |
Features and behavior
| Variable | Default | Meaning |
|---|---|---|
SHELLHUB_EDITION |
community |
community, enterprise, or cloud |
SHELLHUB_VERSION |
the release you checked out | Which image tag to run |
SHELLHUB_METRICS |
false |
Metrics endpoint |
SHELLHUB_PAYWALL |
true |
Show Cloud/Enterprise features to Community users |
SHELLHUB_MAXIMUM_ACCOUNT_LOCKOUT |
60 |
Maximum lockout minutes after repeated failed sign-ins, 0 disables |
SHELLHUB_ACCOUNT_LOCKOUT_BASE |
1m |
First lockout’s length as a Go duration, at least 1s; each later one is four times longer |
SHELLHUB_PERMIT_EMPTY_PASSWORDS |
false |
Agent-side |
SHELLHUB_REDIS_CACHE_POOL_SIZE |
0 |
0 means the driver default |
SHELLHUB_WORKER_SCHEDULE |
@daily |
Cron format |
SHELLHUB_ASYNQ_UNIQUENESS_TIMEOUT |
24 |
Hours; 0 or less disables uniqueness |
SHELLHUB_ONBOARDING_URL |
the ShellHub survey workspace | Client API root of the survey workspace (https://<host>/api/v1/client/<workspaceId>); empty disables the survey |
SHELLHUB_PROVISIONING_KEY_WEBHOOK_ALLOWED_CIDRS |
(empty) | Empty blocks all private, loopback and metadata addresses |
SHELLHUB_ALLOW_PUBLIC_KEY_ACCESS_BELLOW_0_6_0 |
false |
Permit public-key auth from agents older than 0.6.0 |
SHELLHUB_NAMESPACE_REQUIRE_VERIFIED_DEVICE_KEY |
true |
Whether a namespace created from now on starts with Device signature enforcement on. Namespaces that already exist keep their own setting |
Enterprise
From .env.enterprise, and only meaningful when the edition is not community.
| Variable | Default | Meaning |
|---|---|---|
SHELLHUB_ENTERPRISE_ADMIN_USERNAME |
(empty) | Enterprise Admin Console |
SHELLHUB_ENTERPRISE_ADMIN_PASSWORD |
(empty) | |
SHELLHUB_SAML_SECRET |
(empty) | Encrypts the SP’s X.509 private key |
SHELLHUB_WEB_ENDPOINTS |
false |
Enable web endpoints |
SHELLHUB_WEB_ENDPOINTS_DOMAIN |
falls back to SHELLHUB_DOMAIN |
Domain endpoints are published under |
SHELLHUB_WEB_ENDPOINTS_DNS_PROVIDER |
digitalocean |
DigitalOcean, Cloudflare, or acme-dns |
SHELLHUB_WEB_ENDPOINTS_DNS_PROVIDER_TOKEN |
(empty) | Required with auto-SSL |
SHELLHUB_OBJECT_STORAGE_ENDPOINT |
http://minio:9000 |
Session recording storage |
SHELLHUB_OBJECT_STORAGE_REGION |
default |
|
SHELLHUB_OBJECT_STORAGE_BUCKET |
shellhub |
|
SHELLHUB_OBJECT_STORAGE_ACCESS_KEY |
username |
Change this |
SHELLHUB_OBJECT_STORAGE_SECRET_KEY |
password |
Change this |
SHELLHUB_MAXMIND_MIRROR |
(empty) | GeoIP source |
SHELLHUB_MAXMIND_LICENSE |
(empty) |
Applying changes
$ make restart
Where to go next
- Ports and Connectivity — What the network variables mean in practice.
- Backup — Using the database credentials above.