Continuous Profiling
    eBPF Agent

    Deploy Parca on a VPS

    Self-host Parca, an eBPF-based continuous profiling server and agent, on a RamNode VPS with systemd services and Caddy TLS.

    Target stack: Ubuntu 24.04 LTS, parca server + parca-agent (eBPF-based whole-system profiler), both as systemd services, fronted by Caddy for TLS.

    Parca (by Polar Signals) has two parts:

    • parca — the server: stores profiles and serves the web UI/API.
    • parca-agent — an eBPF-based agent that profiles every process on the host with (near) zero code changes required in your applications.

    You typically run one parca server and one parca-agent per node you want profiled. On a single VPS, both run locally.


    1. Prerequisites

    shell
    sudo apt update && sudo apt upgrade -y
    sudo apt install -y curl wget tar ufw linux-headers-$(uname -r)

    parca-agent needs a kernel with BTF (BPF Type Format) support and the matching headers — Ubuntu 24.04's default kernel has this built in, so the headers package above is mostly a safety net.

    shell
    sudo ufw allow OpenSSH
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw enable

    2. Install the Parca server

    shell
    cd /tmp
    PARCA_VERSION="0.22.1"   # check https://github.com/parca-dev/parca/releases for latest
    wget "https://github.com/parca-dev/parca/releases/download/v${PARCA_VERSION}/parca_${PARCA_VERSION}_Linux_x86_64.tar.gz"
    tar -xzf "parca_${PARCA_VERSION}_Linux_x86_64.tar.gz"
    sudo mv parca /usr/local/bin/parca
    sudo chmod +x /usr/local/bin/parca
    parca --version

    Create a system user and data directory:

    shell
    sudo groupadd --system parca
    sudo useradd --system --gid parca --no-create-home \
      --shell /usr/sbin/nologin parca
    
    sudo mkdir -p /etc/parca /var/lib/parca
    sudo chown -R parca:parca /var/lib/parca

    Config file:

    shell
    sudo tee /etc/parca/parca.yaml > /dev/null <<'EOF'
    object_storage:
      bucket:
        type: "FILESYSTEM"
        config:
          directory: "/var/lib/parca"
    EOF
    sudo chown -R parca:parca /etc/parca

    Systemd unit:

    shell
    sudo tee /etc/systemd/system/parca.service > /dev/null <<'EOF'
    [Unit]
    Description=Parca continuous profiling server
    After=network.target
    
    [Service]
    Type=simple
    User=parca
    Group=parca
    ExecStart=/usr/local/bin/parca \
      --config-path=/etc/parca/parca.yaml \
      --http-address=127.0.0.1:7070 \
      --storage-active-memory=536870912
    Restart=on-failure
    RestartSec=5
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    sudo systemctl daemon-reload
    sudo systemctl enable --now parca
    sudo systemctl status parca

    --storage-active-memory (bytes) caps the in-memory buffer before flushing to disk — 512 MiB above is a reasonable starting point for a small VPS; tune based on available RAM.

    3. Install parca-agent (eBPF profiler)

    parca-agent needs CAP_SYS_ADMIN/CAP_BPF privileges, so it runs as root (unlike the server).

    shell
    cd /tmp
    AGENT_VERSION="0.36.1"   # check https://github.com/parca-dev/parca-agent/releases for latest
    wget "https://github.com/parca-dev/parca-agent/releases/download/v${AGENT_VERSION}/parca-agent_${AGENT_VERSION}_Linux_x86_64.tar.gz"
    tar -xzf "parca-agent_${AGENT_VERSION}_Linux_x86_64.tar.gz"
    sudo mv parca-agent /usr/local/bin/parca-agent
    sudo chmod +x /usr/local/bin/parca-agent
    parca-agent --version

    Systemd unit:

    shell
    sudo tee /etc/systemd/system/parca-agent.service > /dev/null <<'EOF'
    [Unit]
    Description=Parca Agent (eBPF continuous profiler)
    After=network.target parca.service
    Requires=parca.service
    
    [Service]
    Type=simple
    ExecStart=/usr/local/bin/parca-agent \
      --node=$(hostname) \
      --remote-store-address=127.0.0.1:7070 \
      --remote-store-insecure \
      --http-address=127.0.0.1:7071
    Restart=on-failure
    RestartSec=5
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    sudo systemctl daemon-reload
    sudo systemctl enable --now parca-agent
    sudo systemctl status parca-agent

    Check that it's picking up processes:

    shell
    sudo journalctl -u parca-agent -f

    You should see log lines about discovered processes/cgroups being profiled.

    4. Front the server UI with Caddy (TLS + auth)

    Install Caddy if not already present:

    shell
    sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
    sudo apt update && sudo apt install -y caddy

    /etc/caddy/Caddyfile:

    shell
    parca.example.com {
        basicauth {
            admin $2a$14$hashedpasswordhere
        }
        reverse_proxy 127.0.0.1:7070
    }

    Generate the password hash first:

    shell
    caddy hash-password

    Reload:

    shell
    sudo systemctl reload caddy

    Parca has no built-in auth, and the eBPF agent means this box is already profiling every process on the host — treat the /etc/parca and /var/lib/parca data as sensitive, since profiles can reveal function/symbol names and call paths from your applications. Keep the UI behind auth as shown above.

    5. Verify

    shell
    curl -s http://127.0.0.1:7070/metrics | head

    Open https://parca.example.com in a browser. Under Targets, you should see your host, and the Profiles view will let you query CPU flame graphs for any process the agent discovered — no code changes needed.

    6. Profiling remote/other nodes (optional)

    If you later add more VPS instances, install just parca-agent on each, pointing --remote-store-address at this server's public address (put it behind TLS via Caddy and use --remote-store-address=parca.example.com:443 without --remote-store-insecure, adding --remote-store-bearer-token if you gate ingestion with a token/reverse-proxy auth rule).

    7. Updates and maintenance

    • Data lives in /var/lib/parca — back this up if you need historical profiles preserved (Parca's local retention defaults are relatively short-lived by design; it's meant for continuous/recent profiling rather than long-term archival).
    • To upgrade either binary: download the new release, stop the relevant service, replace the binary, restart:
      shell
      sudo systemctl stop parca-agent
      sudo mv /tmp/parca-agent /usr/local/bin/parca-agent
      sudo systemctl start parca-agent