Sign inSign up

heywoodlh/attic

By heywoodlh

•Updated 2 days ago

Unofficial Attic server build

Image
1

4.6K

heywoodlh/attic repository overview

Unofficial build of the Nix binary cache Attic⁠

Here is the GitHub Action used to build this image: https://github.com/heywoodlh/actions/blob/master/.github/workflows/attic-buildx.yml⁠

⁠Quickstart

Generate a token:

openssl rand 64 | base64 -w0

Run the container, setting the ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64 environment variable to the output of the last command:

docker run -it --rm --name=attic -e ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64="openssl-token-value" -p 8080:8080 -v attic_config:/var/empty/.config/attic -v attic_data:/var/empty/.local/share/attic docker.io/heywoodlh/attic

Get a shell in the container with docker exec -it --rm attic ash and the run the following command to issue a token to manage caches with the attic client:

atticadm make-token \
  --validity "10y" \
  --sub "*" \
  --pull "*" \
  --push "*" \
  --create-cache "*" \
  --configure-cache "*" \
  --configure-cache-retention "*" \
  --destroy-cache "*"

Then, from a machine with the attic client installed, run the following (replacing $URL with the URL of your attic server):

attic login my-attic-instance http://$URL:8080 <token-from-last-command>

Then create a public cache:

attic cache create testing --public

Get the Public Key and Binary Cache Endpoint of your cache and URL using this command:

attic cache info testing

In NixOS or Nix-Darwin, use the following configuration to use the cache:

  nix.settings = {
    substituters = [
      "$ENDPOINT_URL"
    ];
    trusted-public-keys = [
      "$PUBLIC_KEY"
    ];
  };

⁠Advanced usage

I would recommend creating an atticd configuration file, mounting it and then referencing the mounted file in the container. Here's an example command:

docker run -it --rm  -v /tmp/server.toml:/server.toml -p 8080:8080 docker.io/heywoodlh/attic -f /server.toml

See below for reference server.toml as of April 28, 2024:

# Socket address to listen on
listen = "[::]:8080"

# Allowed `Host` headers
#
# This _must_ be configured for production use. If unconfigured or the
# list is empty, all `Host` headers are allowed.
allowed-hosts = []

# The canonical API endpoint of this server
#
# This is the endpoint exposed to clients in `cache-config` responses.
#
# This _must_ be configured for production use. If not configured, the
# API endpoint is synthesized from the client's `Host` header which may
# be insecure.
#
# The API endpoint _must_ end with a slash (e.g., `https://domain.tld/attic/`
# not `https://domain.tld/attic`).
#api-endpoint = "https://your.domain.tld/"

# Whether to soft-delete caches
#
# If this is enabled, caches are soft-deleted instead of actually
# removed from the database. Note that soft-deleted caches cannot
# have their names reused as long as the original database records
# are there.
#soft-delete-caches = false

# Whether to require fully uploading a NAR if it exists in the global cache.
#
# If set to false, simply knowing the NAR hash is enough for
# an uploader to gain access to an existing NAR in the global
# cache.
#require-proof-of-possession = true

# JWT signing token
#
# Set this to the Base64 encoding of some random data.
# You can also set it via the `ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64` environment
# variable.
#token-hs256-secret-base64 = "somevalue"

# Database connection
[database]
# Connection URL
#
# For production use it's recommended to use PostgreSQL.
url = "sqlite:///var/empty/.local/share/attic/server.db"

# Whether to enable sending on periodic heartbeat queries
#
# If enabled, a heartbeat query will be sent every minute
#heartbeat = false

# File storage configuration
[storage]
# Storage type
#
# Can be "local" or "s3".
type = "local"

# ## Local storage

# The directory to store all files under
path = "/var/empty/.local/share/attic/storage"

# ## S3 Storage (set type to "s3" and uncomment below)

# The AWS region
#region = "us-east-1"

# The name of the bucket
#bucket = "some-bucket"

# Custom S3 endpoint
#
# Set this if you are using an S3-compatible object storage (e.g., Minio).
#endpoint = "https://xxx.r2.cloudflarestorage.com"

# Credentials
#
# If unset, the credentials are read from the `AWS_ACCESS_KEY_ID` and
# `AWS_SECRET_ACCESS_KEY` environment variables.
#[storage.credentials]
#  access_key_id = ""
#  secret_access_key = ""

# Data chunking
#
# Warning: If you change any of the values here, it will be
# difficult to reuse existing chunks for newly-uploaded NARs
# since the cutpoints will be different. As a result, the
# deduplication ratio will suffer for a while after the change.
[chunking]
# The minimum NAR size to trigger chunking
#
# If 0, chunking is disabled entirely for newly-uploaded NARs.
# If 1, all NARs are chunked.
nar-size-threshold = 65536 # chunk files that are 64 KiB or larger

# The preferred minimum size of a chunk, in bytes
min-size = 16384            # 16 KiB

# The preferred average size of a chunk, in bytes
avg-size = 65536            # 64 KiB

# The preferred maximum size of a chunk, in bytes
max-size = 262144           # 256 KiB

# Compression
[compression]
# Compression type
#
# Can be "none", "brotli", "zstd", or "xz"
type = "zstd"

# Compression level
#level = 8

# Garbage collection
[garbage-collection]
# The frequency to run garbage collection at
#
# By default it's 12 hours. You can use natural language
# to specify the interval, like "1 day".
#
# If zero, automatic garbage collection is disabled, but
# it can still be run manually with `atticd --mode garbage-collector-once`.
interval = "12 hours"

# Default retention period
#
# Zero (default) means time-based garbage-collection is
# disabled by default. You can enable it on a per-cache basis.
#default-retention-period = "6 months"
⁠Kubernetes

Below is an example Kubernetes deployment to reference

---
apiVersion: v1
data:
  token: sometoken
kind: Secret
metadata:
  name: attic-server-token
  namespace: default
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: server-toml
  namespace: default
data:
  server.toml: |-
    listen = "[::]:8080"
    allowed-hosts = []
    [database]
    url = "sqlite:///data/db/server.db"
    [storage]
    type = "local"
    path = "/data/attic/storage"
    [chunking]
    nar-size-threshold = 65536
    min-size = 16384
    avg-size = 65536
    max-size = 262144
    [compression]
    type = "zstd"
    [garbage-collection]
    interval = "12 hours"
    default-retention-period = "3 months"
---
apiVersion: v1
kind: Service
metadata:
  name: attic
  namespace: default
  labels:
    app.kubernetes.io/name: attic
    app.kubernetes.io/instance: attic
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: attic
      protocol: TCP
      name: attic
  selector:
    app.kubernetes.io/name: attic
    app.kubernetes.io/instance: attic
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: attic
  namespace: default
  labels:
    app.kubernetes.io/name: attic
    app.kubernetes.io/instance: attic
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: attic
      app.kubernetes.io/instance: attic
  template:
    metadata:
      labels:
        app.kubernetes.io/name: attic
        app.kubernetes.io/instance: attic
    spec:
      securityContext:
        {}
      containers:
        - name: attic
          securityContext:
            runAsNonRoot: true
            runAsUser: 1000
          image: "docker.io/heywoodlh/attic:latest"
          command:
            - "/bin/ash"
            - "-c"
          args:
            - /bin/atticd -f /server.toml
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          resources:
            {}
          volumeMounts:
            - name: server-toml
              mountPath: /server.toml
              subPath: server.toml
            - name: dbdir
              mountPath: /data/db
            - name: storagedir
              mountPath: /data/attic/storage
          env:
            - name: ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64
              valueFrom:
                secretKeyRef:
                  name: attic-server-token
                  key: token
      volumes:
        - name: server-toml
          configMap:
            name: server-toml
        - hostPath:
            path: /opt/attic/db
            type: Directory
          name: dbdir
        - hostPath:
            path: /opt/attic/storage
            type: Directory
          name: storagedir

Tag summary

Content type

Image

Digest

sha256:7a6e8765d…

Size

33.6 MB

Last updated

2 days ago

docker pull heywoodlh/attic