Security
Envoryx is a development tool for your own network, and it runs containers for you through the Docker socket. That’s a lot of power, so it’s worth knowing where the boundaries are and what you should keep an eye on.
The Docker socket
Section titled “The Docker socket”Envoryx starts with /var/run/docker.sock mounted, and access to that socket is effectively root
on the host. There’s no way around that for a tool that creates containers, so Envoryx puts its
own limits in place.
It builds container specifications only from a fixed catalogue, and that catalogue simply can’t
express the dangerous things: no privileged mode, no extra capabilities, no host networking, no
device access, no arbitrary bind mounts. Containers run with no-new-privileges and without
NET_RAW. Before it changes anything, Envoryx checks the target’s envoryx.managed=true label,
so containers, networks and volumes it didn’t create are never touched - they only show up,
read-only, on the Docker page. The same goes for what another Envoryx on the host created: its
envoryx.instance label names the other instance, and this one keeps its hands off
(several instances on one host). And the API never takes container ids at all; it talks about
project + service and looks up the container on the server side, so nobody can point it at a
container of their choosing.
If you want to narrow things down further, put a socket proxy such as
tecnativa/docker-socket-proxy in between and set DOCKER_HOST=tcp://docker-socket-proxy:2375.
Envoryx needs the CONTAINERS, IMAGES, NETWORKS, VOLUMES, EXEC, EVENTS, INFO,
VERSION and POST groups, plus BUILD if you build custom images from a project Dockerfile
and SYSTEM for the volume sizes in the resource history. SWARM, NODES, SECRETS,
CONFIGS, PLUGINS and COMMIT can stay off.
A socket proxy filters by endpoint, not by what a request asks for. With CONTAINERS and
POST open, whoever controls Envoryx can still create a privileged container, so the proxy
narrows what a bug can reach but doesn’t make a taken-over Envoryx any less than root on the
host. The real protection is keeping Envoryx out of reach: HTTPS, not open to the internet,
and accounts only for people you’d trust with the projects’ containers.
Sign-in and sessions
Section titled “Sign-in and sessions”Passwords are hashed with argon2id and have to be at least 10 characters long. A session ends
after 12 hours without activity and after 7 days at the latest (ENVORYX_SESSION_IDLE_TIMEOUT,
ENVORYX_SESSION_ABSOLUTE_TIMEOUT). When you serve Envoryx over HTTPS, set
ENVORYX_SECURE_COOKIES=true so the session cookie never travels unencrypted.
Envoryx slows down failed sign-ins per address and user name, so guessing passwords gets tedious quickly. Changing your password signs out all your other sessions - useful if you suspect a browser somewhere is still logged in.
Locked yourself out? See Troubleshooting → Lost access.
API tokens
Section titled “API tokens”A token (they start with stq_) is shown once and then stored only as a hash. Give every client
its own token with the smallest scope it needs, and limit
it to projects where you can - then a leaked CI token can only do so much. Tokens can’t create
other tokens, change the password, manage users or show the secret key, and the MCP endpoint only
accepts tokens, never a session cookie.
SSH server
Section titled “SSH server”The SSH server on port 2222 never lets anyone into the Envoryx container or onto the host. Every
session is a docker exec into a project container, as the project owner. SFTP shows exactly two
folders: the project and its persistent home. Wrong or unknown API tokens are counted: ten within
ten minutes lock that address out of the project for five minutes, 30 over all projects lock out
the whole address. Offered keys and the empty password OpenSSH sends without a prompt don’t count,
so a team behind one NAT doesn’t lock itself out by accident. The details are under
Locked out?.
Debug ports
Section titled “Debug ports”Delve (Go), rdbg (Ruby) and JDWP (Java) have no authentication at all: whoever reaches the port can run any code in the container. Xdebug, the Node inspector and debugpy aren’t much different. So switch a debug port on while you’re debugging, switch it off afterwards, and don’t use them on a Docker host that’s reachable from networks you don’t trust.
Keep /config private
Section titled “Keep /config private”/config holds the database (with project credentials and secret variables), the SSH keys and
the local CA. The CA key deserves special care: it can sign certificates for any name, so whoever
has it can impersonate websites on every device that trusts your CA. Keep the folder private and
only install the CA on machines you control. If you ever think the key got out, delete
/config/ca/; Envoryx creates a new CA, which you then install on your devices again.
Backups contain credentials and tokens too. Treat a downloaded backup like a password file, and use the encryption of offsite backups.
The secret key
Section titled “The secret key”The secrets Envoryx stores are encrypted: Git tokens, secret variables, the service credentials,
the single sign-on client secret, registry logins, and the notification, offsite and ACME settings.
The key for that comes from ENVORYX_SECRET_KEY on the container, or, without it, from
/config/secret.key, which Envoryx creates at the first start. The variable is the better place,
because then a copy of /config (an appdata backup, a stolen disk image) holds only encrypted
secrets. openssl rand -base64 32 makes a good key, and switching from the file to the variable
needs nothing else: at that start Envoryx re-encrypts everything with the new key and deletes the
file.
Settings → Secret key shows the key’s ID and where it comes from. Show key reveals the key
itself, and the audit log notes that you did. Keep a copy somewhere outside Envoryx. Instance
backups never contain the key, so without that copy you can’t restore one on another host. With
the key file, Replace the key creates a new one and re-encrypts everything; with the variable,
you set the new key there and the current one as ENVORYX_SECRET_KEY_OLD for one start. Your
local project backups are re-encrypted along with everything else, but instance backups made
before and the copies of project backups already on offsite targets keep
needing the old key, so keep it as long as you might restore one of them. A restore that lacks the
key names the ID of the one it needs. Either way of replacing the key ends up in the audit log
(settings.secret_key_rotated).
Showing and replacing the key need an admin’s browser session. API tokens are refused, even with
admin scope, so a leaked token can’t walk off with the key to every stored secret.
Shares
Section titled “Shares”A share makes a project reachable from the internet without any sign-in. If there’s anything in it that isn’t meant for everyone, put a password on it in the project’s rules - or share a staging copy instead of the real thing.
Code in your projects
Section titled “Code in your projects”Project containers can reach Envoryx’s ports on the project network, just like any other device on your LAN. Code you run in a project is trusted about as much as code you run on your own workstation, so treat unfamiliar repositories with the same care.