Roxy documentation
Linux guide
Linux installation details, certificate trust, and troubleshooting.
This guide covers Linux-specific setup details and troubleshooting. For general usage, see the main documentation.
Supported Distributions
Roxy is tested on Ubuntu 22.04+ and Debian 12+. It should work on any distribution that uses:
- systemd-resolved for DNS
- update-ca-certificates for the system trust store
Other distributions (Fedora, Arch, etc.) may work but are not yet officially supported.
How It Works on Linux
DNS Resolution
On macOS, Roxy uses /etc/resolver/roxy to route .roxy DNS queries. On Linux, it uses systemd-resolved with a drop-in configuration file:
/etc/systemd/resolved.conf.d/roxy.confThis file tells systemd-resolved to forward all .roxy queries to Roxy’s built-in DNS server on port 1053. Other DNS queries are unaffected.
The file is created automatically by sudo roxy install and removed by sudo roxy uninstall.
Certificate Trust
On macOS, the Root CA is added to the system Keychain. On Linux, Roxy copies the Root CA to the system certificate store and runs update-ca-certificates:
/usr/local/share/ca-certificates/roxy-ca.crtThis makes the CA trusted by curl, wget, git, Electron apps, and non-sandboxed browsers.
Snap Browsers and Certificate Trust
This is the most common issue on Linux.
Snap-packaged browsers (Firefox, Chromium) run in a sandbox and cannot access the system’s certificate trust store. Even with proper system CA installation, these browsers will show certificate warnings for .roxy domains.
This does not affect:
curl,wget,git, and other CLI tools- Non-snap browsers (installed via apt/deb)
- Electron apps (VS Code, Slack, etc.)
Fix: Import the CA with certutil
This is a one-time step per browser. Once the Root CA is imported, all .roxy domains (including newly registered ones) are automatically trusted.
1. Install certutil:
sudo apt install libnss3-tools2. Import the Roxy CA into your browser:
Snap Firefox:
certutil -A -n "Roxy Local Development CA" -t "CT,C,C" \
-i "$HOME/.local/share/roxy/ca.crt" \
-d sql:$(find ~/snap/firefox/common/.mozilla/firefox \
-name '*.default*' -type d | head -1)/Snap Chromium:
certutil -A -n "Roxy Local Development CA" -t "CT,C,C" \
-i "$HOME/.local/share/roxy/ca.crt" \
-d sql:$(find ~/snap/chromium -name 'nssdb' \
-type d | head -1)/No browser restart is needed after import.
Why Does This Happen?
Snap applications are sandboxed using AppArmor and seccomp. They cannot load the host system’s p11-kit trust modules, which is how most Linux applications discover trusted CAs. The certutil command writes directly into the browser’s own NSS certificate database, bypassing the sandbox limitation.
Removing the CA
To remove the Roxy CA from a snap browser:
Firefox:
certutil -D -n "Roxy Local Development CA" \
-d sql:$(find ~/snap/firefox/common/.mozilla/firefox \
-name '*.default*' -type d | head -1)/Chromium:
certutil -D -n "Roxy Local Development CA" \
-d sql:$(find ~/snap/chromium -name 'nssdb' \
-type d | head -1)/Troubleshooting
DNS Not Resolving
If curl https://myapp.roxy fails with “Could not resolve host”:
1. Check if systemd-resolved has the config:
resolvectl statusLook for DNS Servers: 127.0.0.1:1053 and DNS Domain: ~roxy in the global section.
2. Check if the Roxy DNS server responds:
dig @127.0.0.1 -p 1053 myapp.roxyIf this works but resolvectl query doesn’t, the drop-in config may need a restart:
sudo systemctl restart systemd-resolved3. Verify the drop-in file exists:
cat /etc/systemd/resolved.conf.d/roxy.confIf missing, re-run sudo roxy install.
Port Already in Use
On Linux, check which process is using a port with ss:
sudo ss -tlnp | grep ':80\b'
sudo ss -tlnp | grep ':443\b'
sudo ss -tlnp | grep ':1053\b'Common culprits: Apache (apache2), nginx, or another Roxy instance. Stop the conflicting service or change Roxy’s ports in $HOME/.config/roxy/config.toml, then rerun sudo roxy install to update the socket units.
Service and Socket Activation
sudo roxy install creates and enables these system units:
roxy-http.socket
roxy-https.socket
roxy.serviceThe socket units own ports 80 and 443 and pass their file descriptors to roxy.service. The service has User= set to the developer who ran the installer, so configuration, logs, Docker access, and the daemon process do not use root.
Use Roxy for normal lifecycle management:
roxy status
roxy stop
roxy startFor system-level diagnostics, inspect the generated units:
sudo systemctl status roxy
sudo systemctl status roxy-http.socket roxy-https.socketEdit this documentation on GitHub