Skip to content

ArchiveBox

Self-hosted web archiving platform. ArchiveBox captures websites in multiple formats simultaneously — HTML, PDF, screenshot, WARC, media extraction, git clone — using a built-in Chromium headless browser. All archived content is stored on a persistent volume, with SQLite by default or optional external PostgreSQL for metadata.

Single instance only — no horizontal scaling

ArchiveBox uses one collection writer even with PostgreSQL. The chart enforces a single Recreate Deployment; do not scale it horizontally.

Key Features

  • Multi-format archiving — HTML, PDF, screenshot, WARC, media, git clone in one pass
  • Chromium headless — full JavaScript rendering with /dev/shm tmpfs for stability
  • SQLite or PostgreSQL — embedded SQLite or an existing PostgreSQL service
  • Access control — public index/add controls and upstream UI snapshot permissions
  • Upstream privilege drop — starts as root, detects collection ownership, then drops privileges
  • S3 backup — /data archives with Secret credentials or workload identity
  • Persistent storage — one PVC for archived content and SQLite when selected

Architecture and boundaries

One Recreate Deployment owns the complete /data dataset: SQLite, indexes, configuration, and captured artifacts. The optional backup CronJob reads that same claim and uploads a volume archive to S3-compatible storage. Never run two writers against the claim, even when the StorageClass supports ReadWriteMany.

The chart owns Kubernetes workload, storage, routing, credentials, and optional backup resources. TLS policy, capture-egress controls, malicious-content isolation, storage lifecycle, off-cluster retention, and monitoring remain platform responsibilities. Review the complete design for the Mermaid topology, security and observability boundaries, gaps, and explicit non-goals.

Installation

HTTPS repository:

helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install archivebox helmforge/archivebox -f values.yaml

OCI registry:

helm install archivebox oci://ghcr.io/helmforgedev/helm/archivebox -f values.yaml

Deployment Examples

# values.yaml — Basic ArchiveBox with Traefik ingress
archivebox:
  adminUsername: admin
  adminPassword: 'my-secure-password'

persistence:
  enabled: true
  size: 100Gi

ingress:
  enabled: true
  ingressClassName: traefik
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: archive.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: archivebox-tls
      hosts:
        - archive.example.com
# values.yaml — Private instance (no public access)
# Recommended for internet-facing deployments
archivebox:
  adminUsername: admin
  adminPassword: 'my-secure-password'
  allowedHosts: 'archive.example.com'
  publicIndex: 'False'
  publicAddLinks: 'False'
  serverSecurityMode: safe-onedomain-nojsreplay

persistence:
  enabled: true
  size: 100Gi

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: archive.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Production setup with explicit resource limits
# Chromium requires at least 2Gi RAM to archive pages reliably
archivebox:
  adminUsername: admin
  adminPassword: 'my-secure-password'
  timeout: '120'
  mediaMaxSize: '1g'

resources:
  requests:
    cpu: 500m
    memory: 2Gi
  limits:
    cpu: 2000m
    memory: 4Gi

persistence:
  enabled: true
  size: 200Gi

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: archive.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Daily S3 backup of the full /data directory
# Backup includes both the SQLite database and all archived files.
archivebox:
  adminUsername: admin
  adminPassword: 'my-secure-password'

persistence:
  enabled: true
  size: 100Gi

backup:
  enabled: true
  schedule: '0 3 * * *'
  s3:
    endpoint: https://s3.amazonaws.com
    bucket: my-archivebox-backups
    prefix: daily
    existingSecret: archivebox-s3

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: archive.example.com
      paths:
        - path: /
          pathType: Prefix

Configuration Reference

Security Scan

Kubescape scan for the chart standards backfill:

Framework Score
MITRE 100%
NSA 65%
SOC2 80%

Production hardening should include explicit CPU and memory limits, restricted namespace network policy where required, and existing Secrets for admin and S3 credentials.

Core

Parameter Type Default Description
nameOverride string "" Override the chart name.
fullnameOverride string "" Override the full release name.
commonLabels object {} Extra labels added to all resources.
commonAnnotations object {} Annotations added to chart-owned resources.

Image

Parameter Type Default Description
image.repository string docker.io/archivebox/archivebox ArchiveBox container image.
image.tag string "0.9.77" Image tag.
image.pullPolicy string IfNotPresent Image pull policy.
imagePullSecrets array [] Pull secrets for private registries.

ArchiveBox Configuration

Parameter Type Default Description
archivebox.port integer 5797 Internal HTTP port.
archivebox.adminUsername string admin Admin account username, created on first run.
archivebox.adminPassword string "" Admin account password. Auto-generated if empty.
archivebox.existingSecret string "" Existing Kubernetes Secret containing admin credentials.
archivebox.existingSecretUsernameKey string admin-username Key in the existing secret for the admin username.
archivebox.existingSecretPasswordKey string admin-password Key in the existing secret for the admin password.
archivebox.baseUrl string "" Canonical public URL; empty uses first-use UI configuration.
archivebox.serverSecurityMode string auto ArchiveBox replay security mode.
archivebox.puid / archivebox.pgid string "" Optional UID/GID overrides; empty detects the collection owner.
archivebox.allowedHosts string "*" Comma-separated allowed hostnames. Set to your domain in production.
archivebox.publicIndex string "True" Allow unauthenticated access to the archive index page.
archivebox.publicAddLinks string "False" Allow unauthenticated access to the add URL view (PUBLIC_ADD_VIEW).
archivebox.mediaMaxSize string "750m" Maximum size for media downloads (e.g. 750m, 1g).
archivebox.timeout string "60" Timeout per URL archiving job, in seconds.
archivebox.timezone string UTC Timezone for scheduled tasks and timestamps.
archivebox.extraEnv array [] Extra environment variables for advanced configuration.

When the chart manages the admin Secret, it retains that Secret on Helm uninstall and reuses its generated password on upgrade. Set archivebox.existingSecret when credential lifecycle must remain entirely outside Helm.

Restrict public access before exposing to the internet

By default, publicIndex is "True". Restrict it and allowedHosts before exposing the service. Manage individual snapshot permissions in the ArchiveBox UI.

External PostgreSQL

Parameter Type Default Description
externalDatabase.enabled boolean false Use an existing PostgreSQL database.
externalDatabase.host string "" PostgreSQL hostname.
externalDatabase.port integer 5432 PostgreSQL port.
externalDatabase.name string archivebox Database name.
externalDatabase.user string archivebox Database user.
externalDatabase.existingSecret string "" Secret containing the password.
externalDatabase.existingSecretPasswordKey string database-password Password key in the Secret.

The chart waits for an authenticated PostgreSQL SELECT 1 before starting ArchiveBox. /data still stores captures and configuration. Migrate existing SQLite data before enabling this option.

Persistence

The PVC stores the entire /data directory: SQLite database, all archived files (HTML, PDFs, screenshots, WARCs, media), and ArchiveBox configuration. Size it generously — archived pages with media can consume gigabytes quickly. Chart-created claims carry helm.sh/resource-policy: keep, so helm uninstall retains the dataset. Namespace deletion and storage-provider retention policy can still remove it; use an existing claim when lifecycle must remain fully outside Helm.

Parameter Type Default Description
persistence.enabled boolean true Enable a PVC for /data (database + all archived content).
persistence.size string 50Gi PVC size. Plan for 100GB+ for active archiving.
persistence.storageClass string "" StorageClass for the PVC.
persistence.accessModes array ["ReadWriteOnce"] PVC access modes.
persistence.existingClaim string "" Use an existing PVC instead of creating one.
Storage must allow ownership changes

A narrowly scoped init container changes only a root-owned /data mount root to the selected UID/GID; it never recursively rewrites existing collections. Some NFS provisioners block chown, so configure the provisioner accordingly.

Backup

The S3 backup archives /data. With SQLite, that includes the database and archived files. With external PostgreSQL, the CronJob does not dump the database; retain a matching pg_dump and quiesced /data archive.

backup.enabled requires persistence.enabled: true; the chart rejects an ephemeral backup configuration because the CronJob must mount the durable data claim.

Parameter Type Default Description
backup.enabled boolean false Enable scheduled S3 backup CronJob.
backup.schedule string "0 3 * * *" Cron schedule for backups.
backup.suspend boolean false Suspend the CronJob without deleting it.
backup.concurrencyPolicy string Forbid CronJob concurrency policy.
backup.successfulJobsHistoryLimit integer 3 Number of successful Job records to keep.
backup.failedJobsHistoryLimit integer 3 Number of failed Job records to keep.
backup.backoffLimit integer 1 Job retry limit.
backup.archivePrefix string archivebox Prefix for backup archive filenames.
backup.images.tar string docker.io/library/alpine:3.22 Image used for tar archive.
backup.images.uploader string docker.io/helmforge/mc:1.0.0 Image used for S3 upload.
backup.resources object {} Resources for backup containers.
backup.podSecurityContext object hardened defaults Pod-level security for the backup job.
backup.securityContext object hardened defaults Container-level security for backup containers.
backup.serviceAccount.create boolean true Create a dedicated backup ServiceAccount.
backup.serviceAccount.name string "" Existing backup ServiceAccount when creation is disabled.
backup.serviceAccount.annotations object {} Workload identity annotations.
backup.serviceAccount.automountServiceAccountToken boolean false Mount the Kubernetes API token.
backup.s3.endpoint string "" S3-compatible endpoint URL.
backup.s3.bucket string "" Target bucket name.
backup.s3.prefix string archivebox Key prefix within the bucket.
backup.s3.createBucketIfNotExists boolean true Create the bucket automatically if it does not exist.
backup.s3.existingSecret string "" Existing secret containing S3 access and secret keys.
backup.s3.existingSecretAccessKeyKey string access-key Key in the existing secret for the S3 access key.
backup.s3.existingSecretSecretKeyKey string secret-key Key in the existing secret for the S3 secret key.
backup.s3.accessKey string "" Inline S3 access key (ignored when existingSecret is set).
backup.s3.secretKey string "" Inline S3 secret key (ignored when existingSecret is set).
backup.s3.region string "" AWS region for Pod Identity or IRSA.
backup.s3.credentialsFromPodIdentity boolean false Use workload identity instead of static keys.

The scheduled CronJob reads live /data and does not stop ArchiveBox. Use a quiesced maintenance window for application-consistent recovery points. With workload identity enabled, the chart does not render static S3 credentials.

Service

Parameter Type Default Description
service.type string ClusterIP Kubernetes service type.
service.port integer 80 Service port exposed to the cluster.
service.annotations object {} Annotations for the Service.

Ingress

Parameter Type Default Description
ingress.enabled boolean false Enable an Ingress resource.
ingress.ingressClassName string traefik Ingress class name.
ingress.annotations object {} Annotations for the Ingress (e.g. cert-manager).
ingress.hosts array [] Ingress host and path rules.
ingress.tls array [] TLS configuration (secret name and hosts).

Probes

Probes use the /health/ endpoint.

Parameter Type Default Description
probes.startup.enabled boolean true Enable startup probe.
probes.startup.initialDelaySeconds integer 15 Startup probe initial delay.
probes.startup.periodSeconds integer 5 Startup probe period.
probes.startup.timeoutSeconds integer 3 Startup probe timeout.
probes.startup.failureThreshold integer 120 Startup probe failure threshold.
probes.liveness.enabled boolean true Enable liveness probe.
probes.liveness.initialDelaySeconds integer 0 Liveness probe initial delay.
probes.liveness.periodSeconds integer 15 Liveness probe period.
probes.liveness.timeoutSeconds integer 5 Liveness probe timeout.
probes.liveness.failureThreshold integer 3 Liveness probe failure threshold.
probes.readiness.enabled boolean true Enable readiness probe.
probes.readiness.initialDelaySeconds integer 0 Readiness probe initial delay.
probes.readiness.periodSeconds integer 10 Readiness probe period.
probes.readiness.timeoutSeconds integer 5 Readiness probe timeout.
probes.readiness.failureThreshold integer 3 Readiness probe failure threshold.

Resources and Security

ArchiveBox uses Chromium internally to render pages. The Chromium process requires at least 2 GB RAM to function reliably. Without memory limits, the container may be OOMKilled during archiving of JavaScript-heavy pages.

Parameter Type Default Description
resources object {} CPU and memory requests and limits. Recommended: 2–4 Gi RAM.
podSecurityContext object { seccompProfile: { type: RuntimeDefault } } Pod-level security context.
securityContext object Root startup with bounded capabilities Upstream entrypoint privilege-drop contract.

The application container starts as root so the upstream entrypoint can detect the collection owner and drop privileges. The default workload therefore needs an explicit exception in namespaces enforcing Pod Security restricted.

Service Account

Parameter Type Default Description
serviceAccount.create boolean false Create a dedicated ServiceAccount.
serviceAccount.name string "" Override the ServiceAccount name.
serviceAccount.annotations object {} Annotations for the ServiceAccount.

The chart creates no RBAC permissions. Kubernetes ServiceAccount token automount policy still applies to the selected ServiceAccount and namespace.

Scheduling

Parameter Type Default Description
nodeSelector object {} Node selector for scheduling.
tolerations array [] Tolerations for scheduling.
affinity object {} Affinity rules.
topologySpreadConstraints array [] Topology spread constraints.
priorityClassName string "" PriorityClass for the pod.
terminationGracePeriodSeconds integer 30 Termination grace period.
podLabels object {} Extra labels for the pod.
podAnnotations object {} Extra annotations for the pod.

Extra

Parameter Type Default Description
extraVolumes array [] Extra volumes to attach to the pod.
extraVolumeMounts array [] Extra volume mounts for the container.
extraManifests array [] Extra Kubernetes manifests deployed alongside the chart.

Common Issues

Pod OOMKilled during archiving

Archiving JavaScript-heavy or media-rich pages triggers full Chromium rendering. Without explicit resources limits, the container may be OOMKilled. Set at least memory: 2Gi in resources.requests and memory: 4Gi in resources.limits. Monitor memory usage during peak archiving.

Archiving times out on slow or complex pages

The default archivebox.timeout is 60 seconds. Pages with slow external resources or heavy JavaScript may time out before the snapshot is complete. Increase timeout to 120 or 180 for more reliable archiving of complex pages.

More Information