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.conf

This 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.crt

This 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-tools

2. 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 status

Look 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.roxy

If this works but resolvectl query doesn’t, the drop-in config may need a restart:

sudo systemctl restart systemd-resolved

3. Verify the drop-in file exists:

cat /etc/systemd/resolved.conf.d/roxy.conf

If 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.service

The 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 start

For system-level diagnostics, inspect the generated units:

sudo systemctl status roxy
sudo systemctl status roxy-http.socket roxy-https.socket
Edit this documentation on GitHub