Skip to content

Repository files navigation

monolock

CI latest release license

monolock is a lightweight TCP server for named locks — a distributed mutex without the distributed system.

Documentation: monolock-dev.github.io — concepts, operations, wire protocol reference, clients.

Features

  • raw TCP, one connection per lock
  • single server, no database, no dependencies outside the Go standard library
  • named locks, FIFO waiters
  • connection-scoped ownership: closing the connection is the release
  • client-chosen lease and RTT-aware heartbeats
  • instant graceful handover
  • fencing tokens: every grant carries a monotonically growing number
  • TLS and mTLS with certificate rotation on SIGHUP
  • ACL authorization: mTLS identity → lock name glob rules
  • JSON audit log of every ownership change
  • admin HTTP API: introspection, force-release, kicking waiters
  • Prometheus metrics and health endpoints
  • connections and waiters limited only by system resources
  • simple by design: a single point of coordination — no replication, no quorum, no consensus guarantees

Quick start

docker run -p 7070:7070 ghcr.io/monolock-dev/monolock

How it works

One client owns a named lock and does the work; the others queue up in FIFO order. On graceful shutdown the next client takes over immediately. If a client hangs or the network drops, the lock moves on once the session stays silent for a full lease.

The lease is not a fixed term — it is a sliding window of silence. The server remembers when it last heard from a session, and every heartbeat resets that countdown to the full lease. As long as heartbeats keep arriving, a lock can be held forever; the lease only decides how quickly a dead holder is detected. Clients heartbeat at lease / 4 (shrunk further on slow links) and give up on their own at 0.8 × lease — before the server does — so a holder never believes in a lock the server has already moved on from.

sequenceDiagram
    participant A as worker A
    participant S as monolock
    participant B as worker B
    A->>S: ACQUIRE "deploy" lease=2s
    S-->>A: ACQUIRED token=41
    B->>S: ACQUIRE "deploy" lease=2s
    S-->>B: WAITING (queued, FIFO)
    par holder works
        loop every lease/4
            A->>S: HEARTBEAT
            S-->>A: ACQUIRED token=41
        end
    and waiter keeps its place
        loop every lease/4
            B->>S: HEARTBEAT
            S-->>B: WAITING
        end
    end
    A--xS: connection closed
    S-->>B: ACQUIRED token=42
Loading

Configuration

There is no config file. Every knob is a flag, and every flag has a matching environment variable; a flag wins over the environment, which wins over the default. monolock -h prints the same table.

Flag Environment variable Default Meaning
-listen MONOLOCK_LISTEN_ADDRESS 0.0.0.0:7070 address to listen on
-ops-listen MONOLOCK_OPS_LISTEN_ADDRESS (empty) address of the ops HTTP server: /metrics, /healthz, /readyz; empty disables it
-admin-listen MONOLOCK_ADMIN_LISTEN_ADDRESS (empty) address of the admin HTTP API; empty disables it
-tls-cert MONOLOCK_TLS_CERT (empty) PEM server certificate; with -tls-key enables TLS on the protocol port
-tls-key MONOLOCK_TLS_KEY (empty) PEM private key for -tls-cert
-tls-client-ca MONOLOCK_TLS_CLIENT_CA (empty) PEM CA pool for client certificates; enables mTLS
-acl-file MONOLOCK_ACL_FILE (empty) JSON file with identity → lock name glob rules; requires -tls-client-ca, empty disables authorization
-audit-log MONOLOCK_AUDIT_LOG (empty) audit log destination: a file path or - for stdout; empty disables audit
-io-timeout MONOLOCK_IO_TIMEOUT 5s deadline for a single read or write on a connection
-log-level MONOLOCK_LOG_LEVEL info debug, info, warn or error
-log-format MONOLOCK_LOG_FORMAT text text or json

Durations are Go duration strings, e.g. 5s or 250ms. There is no lease knob and no heartbeat knob: each client picks its own lease in ACQUIRE, and the server's only I/O policy is io-timeout.

SIGHUP re-reads every external file — the TLS certificate, key and client CA, the ACL file — and reopens the audit log for logrotate. A failed reload keeps the previous state.

About

Monolock is a lightweight TCP server for named locks — a distributed mutex without the distributed system

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages