lfsb

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 5, 2024 License: MIT Imports: 7 Imported by: 0

README ¶

📦 litefs-backup (lfsb)

A drop-in, self-hosted replacement for LiteFS Cloud, which was deprecated in July 2024.

Litefs-backup is a standalone backup process that streams backups of your LiteFS cluster to any s3-compatible storage provider, with 5 minute point-in-time restore granularity. It supports both static and dynamic LiteFS lease modes.

This project is sponsored by Tender - a private, productive personal finance tool.

This codebase is a simplified fork of LiteFS Cloud, originally authored and graciously donated by @benbjohnson and co at fly.io.

Limitations & differences with LiteFS Cloud

  • Lfsb does not do any authentication and assumes access across a private network.
  • Lfsb is API-compatible with LiteFS, but its control plane API slightly differs from LiteFS Cloud. Calls from packages like lfsc-go may not work or have expected results.
  • Lfsb expects to be run as a singleton service. Running multiple instances could cause corruption or inconsistencies.

Quickstart: switching from LiteFS Cloud

Lfsb is intended to be a mostly drop-in replacement for LiteFS Cloud. For system requirements, lfsb needs a single-node machine with a persistent disk and s3-compatible object storage.

Deployment on fly.io

Prerequisite: set up a fly.io account and install flyctl.

  1. Launch the app from this repository.
mkdir litefs-backup
cd litefs-backup
fly launch --from git@github.com:stephen/litefs-backup.git --build-only --generate-name --copy-config

When prompted to tweak settings, choose no.

  1. Add tigris object storage and sentry (optional)

If you want to use S3 or another S3-compatible provider, skip this step and use fly secrets set to set the necessary environment variables.

fly ext storage create
fly ext sentry create # optional

These commands should automatically configure the necessary environment variables.

  1. Deploy privately with a single instance
fly deploy --ha=false --no-public-ips --flycast
  1. Finish
fly logs

# Expected output:
# INFO running litefs-backup
# INFO server listening addr=:2200
# INFO waiting for signal or subprocess to exit
# INFO monitoring compaction level=1 interval=10s retention=1h0m0s
# INFO monitoring compaction level=2 interval=5m0s retention=720h0m0s
# INFO monitoring compaction level=3 interval=1h0m0s retention=720h0m0s

This configuration gives the same 5-minute granularity point-in-time restore as LiteFS Cloud.

Configure LiteFS to use lfsb

Use litefs from commit 2e78724973211ba426c224e89d99c256fd6722be or later. If you pull litefs from docker, this looks like:

COPY --from=flyio/litefs:sha-2e78724 /usr/local/bin/litefs /usr/local/bin/litefs

Configure your service running litefs with two environment variables:

  • Set LITEFS_CLOUD_ENDPOINT to the location of your newly deployed lfsb. On fly, this might look like http://someones-litefs-backup.internal:2200.
  • Set LITEFS_CLOUD_TOKEN to cluster [cluster name], e.g. cluster canary. Clusters do not need to be pre-registered.

Using the control plane

Install and configure the cli

Install the release for your system and place it in your $PATH.

curl "https://github.com/stephen/litefs-backup/releases/latest/download/litefs-backup_$(uname -s)_$(uname -m).tar.gz" 2>/dev/null | tar -xz run 2>/dev/null

You can optionally set LFSB_CLUSTER and LFSB_ENDPOINT to your expected cluster and endpoint url, e.g.

export LFSB_CLUSTER="prod" # or --cluster
export LFSB_ENDPOINT="http://someones-litefs-backup.internal:2200" # or --endpoint

If you are using fly.io, setup a wireguard vpn to connect into your private network:

fly wireguard create
Basic operation

List known databases:

lfsb list

List restore points for a database:

lfsb info data.db

Download the current snapshot of a database:

lfsb export data.db

Restore a database to a timestamp or txid:

# first, do a dry run to check that the restore point is available:
lfsb restore data.db --check --txid=[txid] # or --timestamp=[timestamp, e.g. 2024-06-08T12:22:39]

# now, actually run the restore
lfsb restore data.db --txid=[txid]

System overview

Lfsb is organized into clusters. A cluster can contain multiple sqlite databases. For instance, you might have a prod cluster with users.db and datapoints.db and another cluster beta with separate users.db and jobs.db.

Authentication

Lfsb does not support any authentication scheme. To keep API-compatibility with LiteFS, the Authorization header is still used to identify which cluster LiteFS is connecting to.

The authorization header is in the format cluster [cluster name], instead of the LiteFS Cloud format FlyV1 [token].

Storage subsystem

Lfsb stores data in two places:

  • a sqlite metadata db on disk
  • s3-compatible remote storage

Both are expected to be available and durable for the system to function.

Development

Setup

go install github.com/amonks/run/cmd/run@latest
run install

Test

run test
run test-integration

Migrations

dbmate [up, down, new]

Configuration

Configuration is done through environment variables.

LFSB_DATA_PATH (required)

The directory where lfsb will keep its local data store. This should be a persistent, durable location.

LFSB_BIND (optional)

The address to bind to. The default is :2200.

Note that the .envrc sets this to 127.0.0.1:2200 to help with macOS security prompting.

BUCKET_NAME (required)

The AWS S3 bucket name to use.

AWS_ENDPOINT_URL_S3 (optional)

The AWS S3 endpoint to use. The default is AWS S3.

This option is useful for using S3-compatible storage providers.

AWS_REGION (required)

The AWS S3 region to use.

AWS_ACCESS_KEY (required)

The AWS S3 access key to use.

AWS_SECRET_KEY (required)

The AWS S3 secret key to use.

SENTRY_DSN (optional)

The Sentry DSN to use. Sentry reporting will be disabled if unset.

Documentation ¶

Index ¶

Constants ¶

View Source
const (
	EPOSMISMATCH       = "EPOSMISMATCH"
	ENOCLUSTER         = "ENOCLUSTER"
	ENOCOMPACTION      = "ENOCOMPACTION"
	EPARTIALCOMPACTION = "EPARTIALCOMPACTION"
)

Common error codes. Used for compile-time checks.

View Source
const (
	// CompactionLevelMax is the highest compaction level allowed.
	CompactionLevelMax = 8

	// CompactionLevelSnapshot is a reserved level for full snapshots only.
	CompactionLevelSnapshot = 9
)
View Source
const (
	MaxClusterLen  = 32
	MaxDatabaseLen = 256
)

Maximum identifier lengths.

View Source
const LTXFilenameLen = 16 + 1 + 16 + 4 // min,dash,max,ext

LTXFilenameLen is the length of LTX base filenames.

Variables ¶

View Source
var (
	ErrInvalidLTXFilename = Errorf(ErrorTypeValidation, "EBADPATH", "invalid ltx filename")

	ErrClusterRequired = Errorf(ErrorTypeValidation, "EBADCLUSTER", "cluster required")
	ErrClusterInvalid  = Errorf(ErrorTypeValidation, "EBADCLUSTER", "cluster invalid")

	ErrDatabaseRequired = Errorf(ErrorTypeValidation, "EBADDB", "database required")
	ErrDatabaseNotFound = Errorf(ErrorTypeNotFound, "ENODB", "database not found")

	ErrMinTXIDRequired = Errorf(ErrorTypeValidation, "EBADTXID", "minimum transaction id required")
	ErrMaxTXIDRequired = Errorf(ErrorTypeValidation, "EBADTXID", "maximum transaction id required")

	ErrCannotCompactToLevelZero = Errorf(ErrorTypeValidation, "EBADLEVEL", "cannot compact to level zero")
	ErrCompactionLevelTooHigh   = Errorf(ErrorTypeValidation, "EBADLEVEL", "compaction level too high")

	ErrTxNotAvailable = Errorf(ErrorTypeNotFound, "ENOTXID", "tx not available")
	// ErrPgnoOutOfBounds = Errorf(ErrorTypeNotFound, "EPGNOOOB", "page number out of bounds")
	ErrPageNotFound = Errorf(ErrorTypeNotFound, "ENOPAGE", "page not found")

	ErrTimestampNotAvailable = Errorf(ErrorTypeNotFound, "ENOTIMESTAMP", "timestamp not available")

	ErrPageSizeMismatch = Errorf(ErrorTypeUnprocessable, "EBADHEADER", "page size mismatch")
)

Functions ¶

func ErrorCode ¶

func ErrorCode(err error) string

ErrorCode returns the error code from an error. Returns blank if err is nil. Returns EINTERNAL if no lfsc.Error is found.

func FormatLTXFilename ¶

func FormatLTXFilename(min, max ltx.TXID) string

FormatLTXFilename returns a filename based on the min & max TXID.

func IsApplicationError ¶

func IsApplicationError(err error) bool

IsApplicationError returns true if err is an lfsc.Error or ltx.PositionMismatchError.

func ParseLTXFilename ¶

func ParseLTXFilename(name string) (min, max ltx.TXID, err error)

ParseLTXFilename parses a base filename into min & max TXID. Returns ErrInvalidLTXFilename if it is invalid.

func ValidateClusterName ¶

func ValidateClusterName(s string) error

ValidateClusterName returns nil if s is a valid cluster.

func ValidateDatabase ¶

func ValidateDatabase(s string) error

ValidateDatabase returns nil if s is a valid database name.

Types ¶

type Config ¶

type Config struct {
	// Path is the directory where litefs-backup should store its
	// local data.
	Path string

	// Address is the address to bind to.
	Address string

	// S3Bucket is the bucket to use for long term storage.
	S3Bucket string

	// S3Endpoint is the S3 api endpoint to use. Useful for using S3-compatible alternatives.
	S3Endpoint string

	// SentryDSN is the sentry DSN to use.
	// See: https://docs.sentry.io/concepts/key-terms/dsn-explainer/
	SentryDSN string
}

func ConfigFromEnv ¶

func ConfigFromEnv() (*Config, error)

type Error ¶

type Error struct {
	Type              ErrorType
	Code              string
	Message           string
	TXID              ltx.TXID
	PostApplyChecksum ltx.Pos
}

func Errorf ¶

func Errorf(typ ErrorType, code, format string, a ...any) *Error

Errorf is a helper function for returning Error values.

func (*Error) Error ¶

func (e *Error) Error() string

Error implements Error interace

func (*Error) Is ¶

func (e *Error) Is(err error) bool

type ErrorType ¶

type ErrorType string
const (
	ErrorTypeAuth          ErrorType = "auth"
	ErrorTypeConflict      ErrorType = "conflict"
	ErrorTypeNotFound      ErrorType = "notfound"
	ErrorTypeValidation    ErrorType = "validation"
	ErrorTypeUnprocessable ErrorType = "unprocessable"

	ErrorTypeUnknown = "unknown"
)

Directories ¶

Path Synopsis
cmd
lfsb/cmd
* From https://github.com/superfly/flyctl/blob/19481dfa110c8a6274500321b3214c5d2abbfc71/internal/render/render.go * Copyright 2023 https://github.com/superfly * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.
* From https://github.com/superfly/flyctl/blob/19481dfa110c8a6274500321b3214c5d2abbfc71/internal/render/render.go * Copyright 2023 https://github.com/superfly * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.
lfsb/cmd/client
* Copyright 2023 https://github.com/superfly * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.
* Copyright 2023 https://github.com/superfly * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.
db
s3

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL