feat: Replace ncps with attic

This commit is contained in:
2025-08-26 21:02:04 +02:00
parent 12c1f0f060
commit 6eca17a487
13 changed files with 284 additions and 95 deletions
@@ -1,2 +1,2 @@
ncps:
attic:
enabled: true
@@ -1,3 +1,3 @@
ncps:
attic:
enabled: false
autosync: false
@@ -1,7 +1,7 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: ncps
name: attic
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
@@ -12,12 +12,12 @@ spec:
sources:
- repoURL: https://gitlab.com/oceanbox/manifests.git
targetRevision: HEAD
path: values/ncps/manifests
project: sys
path: values/attic/manifests
project: aux
syncPolicy:
managedNamespaceMetadata:
labels:
component: sys
component: aux
syncOptions:
- CreateNamespace=true
- ApplyOutOfSyncOnly=true
+16
View File
@@ -0,0 +1,16 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: attic-db
namespace: attic
labels:
app: attic-db
spec:
instances: 1
initdb:
database: attic
primaryUpdateStrategy: unsupervised
backup:
retentionPolicy: "7d"
storage:
size: "20Gi"
+167
View File
@@ -0,0 +1,167 @@
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/name: attic
name: attic-config
namespace: attic
data:
config.toml: |
# src: https://github.com/zhaofengli/attic/blob/main/server/src/config-template.toml
# 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://attic.srv.oceanbox.io"
# 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
# Database connection
[database]
# Connection URL
#
# For production use it's recommended to use PostgreSQL.
url = ""
# 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 = "/attic"
# ## 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 = "1 week"
# 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"
[jwt]
# WARNING: Changing _anything_ in this section will break any existing
# tokens. If you need to regenerate them, ensure that you use the the
# correct secret and include the `iss` and `aud` claims.
# JWT `iss` claim
#
# Set this to the JWT issuer that you want to validate.
# If this is set, all received JWTs will validate that the `iss` claim
# matches this value.
#token-bound-issuer = "some-issuer"
# JWT `aud` claim
#
# Set this to the JWT audience(s) that you want to validate.
# If this is set, all received JWTs will validate that the `aud` claim
# contains at least one of these values.
#token-bound-audiences = ["some-audience1", "some-audience2"]
[jwt.signing]
# JWT RS256 secret key
#
# Set this to the base64-encoded private half of an RSA PEM PKCS1 key.
# You can also set it via the `ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64`
# environment variable.
token-rs256-secret-base64 = "r0To/djPCwwXRtFcHakhiEHLkEuOQQJtPPeRsfyg8XAkp0A8Tu+AwGz12RFR65JvyhWXSPg7RUIwXzbg6YLcmA=="
+63
View File
@@ -0,0 +1,63 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: attic
spec:
selector:
matchLabels:
app: attic
strategy:
type: Recreate
template:
metadata:
labels:
app: attic
spec:
nodeName: atlas
containers:
- name: attic
image: ghcr.io/zhaofengli/attic:latest
args:
- -f
- /config.toml
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
env:
- name: ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64
value: "r0To/djPCwwXRtFcHakhiEHLkEuOQQJtPPeRsfyg8XAkp0A8Tu+AwGz12RFR65JvyhWXSPg7RUIwXzbg6YLcmA=="
# valueFrom:
# secretKeyRef:
# name: server
# key: token
- name: ATTIC_SERVER_DATABASE_URL
valueFrom:
secretKeyRef:
name: database
key: url
volumeMounts:
- name: data
mountPath: /attic
- name: attic-config
mountPath: /config.toml
subPath: config.toml
volumes:
- name: server
secret:
secretName: server
- name: attic-config
configMap:
defaultMode: 420
name: attic-config
- name: data
persistentVolumeClaim:
claimName: attic
@@ -9,23 +9,23 @@ metadata:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
oceanbox.io/expose: internal
labels:
app.kubernetes.io/component: nix-cache
name: nix-cache
namespace: ncps
app.kubernetes.io/component: attic
name: attic
namespace: attic
spec:
ingressClassName: nginx
rules:
- host: cache.srv.oceanbox.io
- host: attic.srv.oceanbox.io
http:
paths:
- backend:
service:
name: nix-cache
name: attic
port:
name: http-web
name: http
path: /
pathType: ImplementationSpecific
pathType: Prefix
tls:
- hosts:
- cache.srv.oceanbox.io
secretName: cache.srv.oceanbox.io-tls
- attic.srv.oceanbox.io
secretName: attic.srv.oceanbox.io-tls
@@ -1,10 +1,9 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nix-cache
name: attic
labels:
app: nix-cache
tier: proxy
app: attic
spec:
accessModes:
- ReadWriteOnce
+6
View File
@@ -0,0 +1,6 @@
apiVersion: v1
kind: Secret
metadata:
name: server
stringData:
token: "ref+sops://secrets.yml#attic/jwtToken"
+15
View File
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: attic
labels:
app: attic
spec:
type: ClusterIP
selector:
app: attic
component: website
ports:
- name: http
port: 8080
targetPort: http
-62
View File
@@ -1,62 +0,0 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nix-cache
labels:
app: nix-cache
tier: proxy
spec:
replicas: 1
selector:
matchLabels:
app: nix-cache
tier: proxy
template:
metadata:
labels:
app: nix-cache
tier: proxy
spec:
initContainers:
- image: alpine:latest
name: create-directories
args:
- /bin/sh
- -c
- "mkdir -m 0755 -p /storage/var && mkdir -m 0700 -p /storage/var/ncps && mkdir -m 0700 -p /storage/var/ncps/db"
volumeMounts:
- name: nix-cache-persistent-storage
mountPath: /storage
- image: kalbasit/ncps:latest # NOTE: It's recommended to use a tag here, but we live dangerously
name: migrate-database
args:
- /bin/dbmate
- --url=sqlite:/storage/var/ncps/db/db.sqlite
- migrate
- up
volumeMounts:
- name: nix-cache-persistent-storage
mountPath: /storage
containers:
- image: kalbasit/ncps:latest # NOTE: It's recommended to use a tag here!
name: nix-cache
args:
- /bin/ncps
- serve
- --cache-hostname=cache.srv.oceanbox.io
- --cache-data-path=/storage
- --cache-database-url=sqlite:/storage/var/ncps/db/db.sqlite
- --upstream-cache=https://cache.nixos.org
- --upstream-cache=https://nix-community.cachix.org
- --upstream-public-key=cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
- --upstream-public-key=nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=
ports:
- containerPort: 8501
name: http-web
volumeMounts:
- name: nix-cache-persistent-storage
mountPath: /storage
volumes:
- name: nix-cache-persistent-storage
persistentVolumeClaim:
claimName: nix-cache
-15
View File
@@ -1,15 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: nix-cache
labels:
app: nix-cache
tier: proxy
spec:
type: ClusterIP
ports:
- name: http-web
port: 8501
selector:
app: nix-cache
tier: proxy