Documentation
¶
Overview ¶
Package rqlitestorage implements a CertMagic/Caddy storage backend on top of rqlite (https://rqlite.io) — distributed, Raft-replicated SQLite.
It lets a fleet of Caddy instances share one certificate store: certificates and keys are shared, and ACME challenge tokens live in rqlite, so whichever instance a challenge lands on can answer it, and a cert issued by one instance is immediately usable by the others. rqlite's Raft consensus provides the linearizable distributed locking an ACME cluster needs — two instances must never solve or issue the same certificate concurrently — without standing up a separate datastore for it.
This file is the transport-agnostic core: all storage and locking logic, exercised in full by the unit tests against an in-memory SQLite. The production rqlite HTTP transport is in httpconn.go; the Caddy module / certmagic.Storage adapter lives in the ./caddymodule subpackage so this core stays dependency-light.
Index ¶
- Variables
- type CaddyLocks
- type CaddyStorage
- type KeyInfo
- type Statement
- type Store
- func (s *Store) Del(ctx context.Context, key string) error
- func (s *Store) EnsureSchema(ctx context.Context) error
- func (s *Store) Get(ctx context.Context, key string) ([]byte, error)
- func (s *Store) Has(ctx context.Context, key string) bool
- func (s *Store) List(ctx context.Context, prefix string, recursive bool) ([]string, error)
- func (s *Store) Lock(ctx context.Context, name string) error
- func (s *Store) Put(ctx context.Context, key string, value []byte) error
- func (s *Store) SetLockTTL(d time.Duration)
- func (s *Store) SetReadLevel(level string) error
- func (s *Store) Stat(ctx context.Context, key string) (KeyInfo, error)
- func (s *Store) Unlock(ctx context.Context, name string) error
Constants ¶
This section is empty.
Variables ¶
var ErrNotExist = errors.New("rqlitestorage: does not exist")
ErrNotExist is returned by Get/Stat/Del when the key is absent. The certmagic adapter maps it to fs.ErrNotExist so CertMagic's errors.Is checks succeed.
Functions ¶
This section is empty.
Types ¶
type CaddyLocks ¶
type CaddyLocks struct {
Name string `db:"name" json:"name"`
Token string `db:"token" json:"token"`
Expires int64 `db:"expires" json:"expires"`
}
func (CaddyLocks) Table ¶
func (c CaddyLocks) Table() string
type CaddyStorage ¶
type CaddyStorage struct {
Key string `db:"key" json:"key"`
Value string `db:"value" json:"value"`
Size int64 `db:"size" json:"size"`
Modified int64 `db:"modified" json:"modified"`
}
func (CaddyStorage) Table ¶
func (c CaddyStorage) Table() string
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store holds the storage + locking logic over a conn.
func NewHTTPStore ¶
NewHTTPStore builds a Store backed by the rqlite node reachable at baseURL (e.g. "http://127.0.0.1:4001"). username/password may be empty when rqlite has no HTTP basic auth. This is the constructor the Caddy module uses.
func NewStore ¶
func NewStore(c conn) *Store
NewStore builds a Store over c with default lock TTL/poll.
func (*Store) EnsureSchema ¶
EnsureSchema creates the storage and lock tables if absent. Idempotent.
func (*Store) List ¶
List returns the keys under prefix. With recursive=false only immediate children (one path segment beyond prefix, '/'-separated) are returned, deduplicated. An empty prefix lists the whole store.
func (*Store) Lock ¶
Lock blocks until the named lock is acquired or ctx is done. Acquisition is a single atomic upsert (insert-if-absent, else steal-if-expired) serialized by rqlite's Raft, so at most one caller across the fleet holds the lock.
func (*Store) Put ¶
Put stores value under key (upsert). Values are base64-encoded so arbitrary binary survives rqlite's JSON transport untouched.
func (*Store) SetLockTTL ¶
SetLockTTL overrides how long an acquired lock is held before it may be stolen by another instance (and how often a held lock is refreshed: TTL/3). No-op for d <= 0.
func (*Store) SetReadLevel ¶
SetReadLevel sets the rqlite read-consistency level used for key lookups: "weak" (default), "none", "linearizable", or "strong". "weak" routes reads through the Raft leader, so the store always sees its own writes. "none" reads the local node's FSM — faster, but on a multi-node cluster a non-leader node can lag right after a write forwarded from it, which fails CertMagic's write-then-read storage preflight and aborts certificate obtains; only use "none" on single-node deployments. No-op (returns nil) when the Store is not backed by the rqlite HTTP transport.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package caddymodule registers the rqlite CertMagic storage backend as a Caddy module (`caddy.storage.rqlite`) and adapts the transport-agnostic core in the parent package to certmagic.Storage.
|
Package caddymodule registers the rqlite CertMagic storage backend as a Caddy module (`caddy.storage.rqlite`) and adapts the transport-agnostic core in the parent package to certmagic.Storage. |