🛠️
Stacks Documentation
  • Start Here
  • 🧠Concepts
    • Stacks 101
      • What Is Stacks?
      • Bitcoin Connection
      • Proof of Transfer
      • Stacks Among Other Layers
      • Financial Incentive and Security Budget
    • Network Fundamentals
      • Network Basics
      • Mainnet and Testnets
      • Accounts
      • Authentication
      • Bitcoin Name System
      • SIPs
      • Technical Specifications
    • Block Production
      • Mining
      • Signing
      • Bitcoin Finality
      • Bitcoin Reorgs
      • Stacking
    • Transactions
      • How Transactions Work
      • Post Conditions
    • Clarity
      • Overview
      • Decidability
    • sBTC
      • Core Features
      • sBTC Operations
        • Deposit
        • Withdrawal
        • Deposit vs Withdrawal Times
      • Emily API
      • Peg Wallet UTXO
      • Clarity Contracts
        • sBTC Registry
        • sBTC Token
        • sBTC Deposit
        • sBTC Withdrawal
      • Auxiliary Features
        • Transaction Fee Sponsorship
        • Signer Wallet Rotation
      • Walkthroughs
        • Signer Process Walkthrough
        • sBTC Transaction Walkthrough
      • sBTC FAQ
    • Gaia
      • Configuration
      • Deploy Gaia Hub
      • Amazon EC2
      • Linux
      • Mac OS
  • 🛠️Guides & Tutorials
    • Developer Quickstart
    • Clarity Crash Course
    • Build a Borrowing & Lending Protocol
    • Bitcoin Integration
      • Sending Bitcoin with Leather Wallet
      • Verifying a Bitcoin Transaction
      • Parsing a Bitcoin Transaction
    • Create Tokens
      • Creating a NFT
      • Creating a Fungible Token
    • Build a Frontend
      • Post Conditions with Stacks.js
      • Authentication with Stacks.js
      • Sending Transactions with Stacks.js
    • Testing Smart Contracts
      • Fuzz Testing
    • Run a Node
      • Run a Node with Docker
      • Run a Node with Digital Ocean
      • Run a Node with a Hosted Provider
      • Run a Node with Quicknode
      • Run a Bitcoin Node
      • Run a Pruned Bitcoin Node
    • Run a Miner
      • Miner Prerequisites
      • Miner Costs and Fees
      • Mine Testnet Stacks Tokens
      • Mine Mainnet Stacks Tokens
      • Verify Miner
    • Run a Signer
      • Signer Quickstart
      • How to Read Signer Logs
      • How to Monitor a Signer
      • Best practices for running a Signer
      • OpSec Best Practices
    • sBTC
      • How to Run an sBTC Signer
      • Best practices for running an sBTC Signer
      • How to Use the sBTC Bridge
      • Earn sBTC Rewards
    • Stack STX
      • Solo Stack
      • Operate a Pool
      • Stack with a Pool
      • Increase Stacked Position
      • Stop Stacking
    • Oracles
    • Community Tutorials
  • 📚Reference
    • API
    • Clarity Types
    • Clarity Functions
    • Clarity Keywords
    • Stacks Node Configuration
    • Signer Configuration
    • Stacks Tooling
  • 🏗️Example Contracts
    • Audited Starter Contracts
    • Stacking
    • BNS
    • Multi Send
  • 🧡Press & Top Links
    • 🔶2024
      • 🔸January 2024
      • 🔸February 2024
      • 🔸March 2024
      • 🔸April 2024
      • 🔸May 2024
      • 🔸June 2024
      • 🔸July 2024
      • 🔸August 2024
      • 🔸September 2024
      • 🔸October 2024
      • 🔸November 2024
      • 🔸December 2024
    • 🔶2025
      • 🔸January 2025
      • 🔸February 2025
      • 🔸March 2025
      • 🔸April 2025
      • 🔸May 2025
  • 🧡Bitcoin Theses and Reports
    • 🟠Bitcoin Theses
    • 📙Bitcoin Reports
  • Contribute
Powered by GitBook
On this page

Was this helpful?

  1. Guides & Tutorials
  2. Run a Signer

OpSec Best Practices

PreviousBest practices for running a SignerNextsBTC

Last updated 3 months ago

Was this helpful?

Threat Modeling

A threat actor that is able to compromise > 70% of Signers (by stake weight) would be able to successfully propose Stacks blocks that would otherwise be considered invalid.

Some potential vectors for signer key compromise are as follows:

  1. stacks-signer node is compromised and key is exfiltrated from the filesystem

  2. Signer key is compromised during generation or deployment

  3. Signer key is accidentally checked into SCM (eg Github or Gitlab)

  4. Social engineering attack against Signer community: eg a malicious link is posted to social media that harvests key material

  5. An undisclosed backdoor is discovered in the Signer binary.

  6. Supply chain attack against stacks-signer source code: threat actor compromises upstream dependencies of stacks-signer

Countermeasures

What can Signers do to mitigate the threat vectors identified above? Let's identify countermeasures in response to each of the threats identified above, starting with #1.

1. Stacks-signer node is compromised and key is exfiltrated from the filesystem

An obvious attack vector is a direct attack on the system running the stacks-signer software. Presently, the stacks-signer depends on a signing key that is both loaded into memory, and resident on the filesystem in cleartext. Thus a system or process level intrusion on the stacks-signer node will likely lead to compromise of the signing key.

Some countermeasures that can help mitigate this vector include:

  1. Run the stacks-signer on a separate system from the stacks-node. This is important, as the IP addresses of systems running the stacks-signer cannot be trivially enumerated, but the same is not true for systems running stacks-node, due to the fact that stacks-node systems participate in the peer to peer network. If an attacker can't find your stacks-signer, they can't attack it (directly). It’s best practice to ensure that the stacks-node and stacks-signer communicate only over trusted networks, ideally using localhost (127.0.0.1) or a secure private subnet. While running the stacks-signer on a separate system is an option, it’s not necessary for security. Instead, running both on the same virtual machine within a private network, with traffic firewalled to allow only incoming peer-to-peer (P2P) connections (port 20444), provides a secure and easier setup. This minimizes the risk of exposure to attacks while avoiding the complexity of managing multiple systems.

  2. Run the stacks-signer as a separate user from the stacks-node. This is helpful in situations where due to resource constraints, it's not possible to separate the stacks-signer and stacks-node deployments onto separate workloads. Run the stacks-signer as a separate user from the stacks-node to enhance security, especially when resource constraints prevent deploying them on separate systems. The key here is ensuring that each user has exclusive ownership and access to its respective configuration files. For example, the user running the signer binary (e.g., signer) should own the signer’s config file, with permissions set restrictively to prevent other users from reading it. The same principle applies to the stacks-node user. This setup ensures that only the appropriate processes can access sensitive configuration details.

  3. Harden the systemd configuration for the stacks-signer. Hardening systemd can help mitigate the blast radius from an attack that successfully gets control of the stacks-signer process. An example stacks-signer.service systemd unit is below. Specifically, this systemd unit prevents certain filesystem writes (which can prevent an attacker from gaining persistence). Read more about .

[Unit]
Description=Stacks Signer
After=network.target
StartLimitBurst=3
StartLimitIntervalSec=300
ConditionFileIsExecutable=/usr/local/bin/stacks-signer
ConditionPathExists=/etc/stacks/signer
ConditionFileNotEmpty=/etc/stacks/signer/signer-config.toml

[Service]
ExecStart=/usr/local/bin/stacks-signer run --config /home/etc/stacks/signer/signer-config.toml
User={{ svc_user }}
Group={{ svc_user }}
Type=simple
Restart=on-failure
TimeoutStopSec=600
KillSignal=SIGTERM
#KillSignal=SIGINT
# Provide a private /tmp and /var/tmp.
PrivateTmp=true
# Mount /usr, /boot/ and /etc read-only for the process.
ProtectSystem=full
# Deny access to /home, /root and /run/user
ProtectHome=true
# Disallow the process and all of its children to gain
# new privileges through execve().
NoNewPrivileges=true
# Use a new /dev namespace only populated with API pseudo devices
# such as /dev/null, /dev/zero and /dev/random.
PrivateDevices=true

[Install]
WantedBy=multi-user.target
  1. Restrict access to unnecessary ports and protocols. The stacks-signer requires outbound TCP access to the stacks-node, but no other communications (except for what may be necessary to update the underlying OS).

  2. Harden the operating system. This is a broad topic, but the basics are:

    1. Run stacks-signer as an unprivileged user (not root)

    2. Set permissions on the stacks-signer key to be readable only by the user running the stacks-signer process, eg sudo chmod 600 signer/signer-config.toml

    3. Require public-key authentication for remote SSH to the system running the stacks-signer and disable ssh root login.

    4. Run sshd on a non-standard port to reduce noise from port scanners and credential stuffing attacks

This post outlines essential operational security best practices for Stacks Signers, key actors in the Nakamoto architecture.

By implementing these strategies, signer operators can effectively mitigate risks and maintain the security and reliability of the Stacks network.

🛠️
systemd hardening