PCeS (Persistent Certificate Store) is a certificate lifecycle management system written in Go.
- Automatic certificate renewal and issuance
- SSH and x.509 certificate support
- SSH agent integration
- Windows keychain integration
The repo also provides a CLI and daemon components for flexible deployment.
- Integration with SKS for leveraging hardware security modules (e.g TPM, SecureEnclave)
- gRPC-based client-server architecture as an example usage
Requires Go 1.25+ and is distributed as github.com/facebookincubator/pces module.
PCeS is a certificate management tool designed to simplify the lifecycle management of SSH and X.509 certificates. Originally developed as part of Meta's internal certificate infrastructure, PCeS has been extracted into a standalone, open-source module that can be deployed in any environment.
PCeS addresses common certificate management challenges including expiration monitoring, automatic renewal, and secure storage, making it suitable for development environments, CI/CD systems, and production deployments where certificate lifecycle automation is critical.
The best place to start is example folder. You can also expore the man pages for more details.
The system consists of a certificate agent daemon that handles automatic certificate issuance and renewal, and a command-line client for manual operations and status monitoring. Communication between components uses gRPC over Unix sockets.
You can explore an example of running and creating a PCeS daemon server in the root.go file.
- Create SSH and X.509 Certificates
- Generate SSH and TLS certificate issuers with appropriate keys and configurations.
sshIssuer := issuers.NewSSHIssuer(cfg) tlsIssuer := issuers.NewTLSIssuer(cfg)
- Create certificate objects that handle issuance and renewal.
sshCert := cert.NewSSH(sshSigner, sshIssuer) tlsCert := cert.NewTLS(tlsSigner, tlsIssuer)
- Create Updaters for Automatic Renewal
- For each certificate type, create an updater that periodically checks if renewal is needed and triggers issuance.
needsUpdateFunc := storage.NeedsRenewWithFactor(certificate, defaultRenewalFactor) updater := storage.NewUpdater( label, func(ctx context.Context, cb storage.OnUpdate) { err := certificate.Issue(ctx) cb(err) }, needsUpdateFunc, storage.UpdaterFrequency(20*time.Second), storage.UpdaterMinRetry(5*time.Second), storage.UpdaterMaxRetry(1*time.Minute), )
- Configure Storage
- Initialize a storage object that holds certificates and their updaters, managing lifecycle and updates.
storage := storage.NewStorage( storage.WithCertificate(cert.TypeSSH, sshCert, sshUpdater), storage.WithCertificate(cert.TypeTLS, tlsCert, tlsUpdater), )
- Create SSH Agent
- Instantiate an SSH agent that integrates with the storage to provide SSH certificate access.
agent := sshagent.New(st, sshagent.WithLogger(logger))
- Setup Unix Socket Listeners
- Prepare Unix domain sockets for the SSH agent and server, ensuring proper permissions and cleanup of existing sockets.
sshListener := net.Listen("unix", sshSocketPath) grpcListener := net.Listen("unix", grpcSocketPath)
Prerequisites:
- Go 1.25 or later
Install dependencies:
Follow the Protobuf installation instructions in the protobuf.dev website.
# Install GO Protobuf compiler
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# Install mockgen
go install go.uber.org/mock/mockgen@latest
# Generate code, install plugins and build
go generate ./api/if/...
go build -v ./...
# Run server binaries
go run ./example/server --help # w/o sks backend
go run -tags sks_backend ./example/server --help # with sks backendNote for the SKS usage: To use SecureEnclave on Mac, your app must have a registered App ID (com.apple.application-identifier entitlement). For more information, see this thread.
Project structure:
├── cert # Certificate types and interfaces for SSH and TLS
├── example # Example implementations and usage
│ ├── api # API definitions and gRPC server/client code
│ ├── cli # Command-line interface client implementation
│ ├── issuers # Certificate issuer implementations
│ ├── man # Manual pages and documentation
│ └── server # Certificate agent server implementation
├── oscert # OS certificate integration utilities
├── sshagent # SSH agent implementation and integration
└── storage # Certificate storage and updater logicExamples of the tests run can be found in the GitHub Actions workflows for CI/CD.
go generate ./generate_mocks.go # Generate test mocks
go test ./...# Generate protobuf code
go generate ./api/if/...# Run a server w/o SKS
go run ./example/server
--ssh-socket-path=<ssh socket path>
--grpc-socket-path=<grpc socket path>
--cert-dir=<cert directory>
# Run a server with SKS
go run -tags sks_backend ./example/server
--ssh-socket-path=<ssh socket path>
--grpc-socket-path=<grpc socket path>
--cert-dir=<cert directory>
# Run a server with OS keychain integration (works for Windows only)
go run ./example/server
--ssh-socket-path=<ssh socket path>
--grpc-socket-path=<grpc socket path>
--cert-dir=<cert directory>
--os-keychain# Run e2e tests from the client
go run ./example/server e2e
--ssh-socket-path=<ssh socket path>
--grpc-socket-path=<grpc socket path>
--cert-dir=<cert directory>PCeS is published under the Apache v2.0 License.
