StackPanel
Networking

Certificates

Local HTTPS with automatic TLS certificates via Step CA

Stackpanel integrates with Step CA to provide automatic TLS certificate provisioning for local development. This lets you run your dev services over HTTPS with real certificates—issued by a private certificate authority that your team controls.

Why Local HTTPS?

Some features only work over HTTPS—secure cookies, service workers, WebAuthn, and many browser APIs require a secure context. Using self-signed certificates leads to browser warnings and trust issues. Step CA gives you a proper certificate chain that your machine trusts, with automatic renewal.

Combined with Caddy as a reverse proxy, you get HTTPS for every local service with zero manual certificate management.

Enable Step CA

stackpanel.step-ca = {
  enable = true;
  ca-url = "https://ca.internal:443";
  ca-fingerprint = "e4b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
};
OptionDescription
enableActivate Step CA integration
ca-urlURL of your team's Step CA server
ca-fingerprintSHA256 fingerprint of the CA root certificate (used to bootstrap trust)

The CA fingerprint is used on first connection to verify you're talking to the right certificate authority. You can get it from your CA administrator or by running step certificate fingerprint root_ca.crt on the CA server.

How It Works

When Step CA is enabled, Stackpanel:

  1. Bootstraps trust — On first shell entry, the Step CA root certificate is downloaded and installed into your local trust store using the provided URL and fingerprint.
  2. Requests certificates — When a service needs HTTPS (e.g., through Caddy), Stackpanel requests a certificate from the CA for the appropriate domain.
  3. Handles renewal — Certificates are short-lived by default (24 hours). The agent handles automatic renewal before expiration, so you never see an expired certificate.
Developer machine
  → stackpanel enters devshell
    → Step CA client bootstraps trust (first time only)
    → Caddy requests certificate for myapp.local
    → Step CA issues a short-lived TLS certificate
    → Caddy serves HTTPS on myapp.local
    → Certificate auto-renews before expiration

Using with Caddy

The most common pattern is combining Step CA with Caddy for automatic HTTPS on local domains:

{
  stackpanel.step-ca = {
    enable = true;
    ca-url = "https://ca.internal:443";
    ca-fingerprint = "e4b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
  };

  stackpanel.caddy = {
    enable = true;
    routes = {
      "myapp.local" = {
        upstream = "localhost:${toString config.stackpanel.ports.computed.web}";
      };
      "api.myapp.local" = {
        upstream = "localhost:${toString config.stackpanel.ports.computed.api}";
      };
    };
  };
}

With this configuration, https://myapp.local and https://api.myapp.local resolve to your local dev servers, with valid TLS certificates issued by your team's CA.

You'll also need DNS configured to resolve .local domains to 127.0.0.1. Stackpanel can manage this for you—see the DNS docs.

Team Setup

Step CA is a team-wide resource. One person sets up the CA server, and everyone else connects to it.

Setting Up the CA Server

If your team doesn't have a Step CA instance yet, you can run one:

# Install step-ca
step ca init --name "My Team CA" --provisioner admin --address ":443"

# Start the CA
step-ca $(step path)/config/ca.json

Share the CA URL and root fingerprint with your team. The fingerprint is printed during step ca init, or you can retrieve it later:

step certificate fingerprint $(step path)/certs/root_ca.crt

Connecting Team Members

Each team member adds the same Step CA configuration to the shared Stackpanel config:

stackpanel.step-ca = {
  enable = true;
  ca-url = "https://ca.yourteam.internal:443";
  ca-fingerprint = "your-ca-fingerprint-here";
};

On first shell entry, Stackpanel bootstraps trust with the CA. After that, certificate operations are automatic.

Token-Based Authentication

Step CA supports several authentication methods for certificate requests. Stackpanel uses token-based authentication by default—when a service needs a certificate, the agent requests a one-time token from the CA and uses it to obtain the certificate.

This means:

  • No long-lived credentials stored on developer machines
  • Each certificate request is individually authenticated
  • Tokens are short-lived and single-use
  • The CA maintains an audit trail of every issued certificate

Certificate Storage

Certificates and keys are stored in the Stackpanel state directory:

.stack/state/certs/
├── root_ca.crt          # CA root certificate (trusted)
├── myapp.local.crt      # Issued certificate
└── myapp.local.key      # Private key

These files are gitignored by default since they contain machine-specific certificates and private keys.

Certificate private keys never leave your machine. They're generated locally and only the certificate signing request (CSR) is sent to the CA.

Security Model

The Step CA integration follows a security model designed for development teams:

PropertyDetail
Short-lived certificates24-hour default lifetime, auto-renewed
Private CANot publicly trusted—only machines that have bootstrapped trust can verify certificates
Per-machine keysPrivate keys are generated and stay on each developer's machine
Token authEach certificate request uses a fresh, single-use token
Audit trailThe CA logs every certificate issuance

This is significantly more secure than the common alternatives (self-signed certificates, disabling TLS verification, or sharing a wildcard certificate).

Troubleshooting

"Certificate not trusted" in browser

The CA root certificate may not be in your system trust store. Re-bootstrap trust:

step ca bootstrap --ca-url https://ca.internal:443 --fingerprint <fingerprint> --install

The --install flag adds the root certificate to your system trust store so that browsers recognize it.

"Connection refused" to CA

Verify the CA server is running and reachable:

curl -k https://ca.internal:443/health

If you're on a VPN or private network, ensure the CA URL is accessible from your current network.

Certificate renewal failing

Check the agent logs for renewal errors:

stackpanel logs

Common causes:

  • The CA server is temporarily unreachable
  • Your authentication token has been revoked
  • The CA's provisioner configuration has changed

Certificates have a renewal window (typically starting at 2/3 of the lifetime), so a brief CA outage won't immediately cause issues.

Reference

On this page