1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-21 18:55:36 +02:00

fix: address code review issues with Docker setup

- .gitignore: whitelist Dockerfile, docker-compose.yml, docker/ so they
  are actually tracked (the * catch-all was silently dropping them)
- Dockerfile: build and ship the archivr CLI alongside archivr-server so
  users can run `archivr init` inside the container on first setup
- docker/config.example.toml: fix archive_path to point at the .archivr
  subdirectory that archivr init creates (not the parent directory), which
  is what read_archive_paths expects
- docs/README.md: replace the bare mkdir quickstart step with
  `archivr init`, explain why mkdir is insufficient; add a callout that
  auth_db_path must be set explicitly to a writable path when the config
  mount is read-only
This commit is contained in:
TheGeneralist 2026-06-30 11:20:55 +02:00
parent 2ba832ad59
commit 38d3066ee4
Signed by: thegeneralist01
SSH key fingerprint: SHA256:pp9qddbCNmVNoSjevdvQvM5z0DHN7LTa8qBMbcMq/R4
5 changed files with 170 additions and 3 deletions

5
.gitignore vendored
View file

@ -19,6 +19,11 @@
!ARCHIVR-MENTAL-MODEL.md !ARCHIVR-MENTAL-MODEL.md
!NEXT.md !NEXT.md
!Dockerfile
!docker-compose.yml
!docker/
!docker/**
!modules/ !modules/
!modules/** !modules/**

97
Dockerfile Normal file
View file

@ -0,0 +1,97 @@
# syntax=docker/dockerfile:1
###############################################################################
# Stage 1 Build the Rust server and CLI binaries
###############################################################################
FROM rust:1.87-slim-bookworm AS builder
RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
# Layer the dependency build separately for better cache reuse.
# Stub out every crate so Cargo can resolve and compile all dependencies
# before we copy the real source.
COPY Cargo.toml Cargo.lock ./
COPY crates/archivr-core/Cargo.toml crates/archivr-core/Cargo.toml
COPY crates/archivr-server/Cargo.toml crates/archivr-server/Cargo.toml
COPY crates/archivr-cli/Cargo.toml crates/archivr-cli/Cargo.toml
RUN mkdir -p \
crates/archivr-core/src \
crates/archivr-server/src \
crates/archivr-cli/src \
&& touch crates/archivr-core/src/lib.rs \
&& echo 'fn main() {}' > crates/archivr-server/src/main.rs \
&& echo 'fn main() {}' > crates/archivr-cli/src/main.rs \
&& cargo build --release -p archivr-server -p archivr-cli || true
# Build the real binaries; touch source files to force Cargo to relink.
COPY crates/ crates/
RUN touch \
crates/archivr-core/src/lib.rs \
crates/archivr-server/src/main.rs \
crates/archivr-cli/src/main.rs \
&& cargo build --release -p archivr-server -p archivr-cli
###############################################################################
# Stage 2 Runtime image
###############################################################################
FROM debian:bookworm-slim
# Runtime dependencies:
# chromium used by single-file-cli for full-page archiving
# nodejs + npm runtime for single-file-cli
# python3 + pip + venv twitter scraper
# ca-certificates outbound HTTPS from the server
# libssl3 OpenSSL linked by the Rust binary
RUN apt-get update && apt-get install -y --no-install-recommends \
chromium \
nodejs \
npm \
python3 \
python3-pip \
python3-venv \
ca-certificates \
libssl3 \
&& rm -rf /var/lib/apt/lists/*
# Install single-file-cli globally so `single-file` is on PATH.
RUN npm install -g single-file-cli
# Install yt-dlp and twitter-api-client into an isolated venv to avoid
# conflicts with Debian's system Python packages.
RUN python3 -m venv /opt/archivr-venv \
&& /opt/archivr-venv/bin/pip install --no-cache-dir \
yt-dlp \
twitter-api-client
# Server and CLI binaries (CLI is needed to run `archivr init` on first setup)
COPY --from=builder /build/target/release/archivr-server /usr/local/bin/archivr-server
COPY --from=builder /build/target/release/archivr /usr/local/bin/archivr
# Pre-built frontend assets (already compiled; no Vite build step needed)
COPY crates/archivr-server/static/ /usr/share/archivr-server/static/
# Twitter scraper script
COPY vendor/twitter/scrape_user_tweet_contents.py \
/usr/local/lib/archivr/scrape_user_tweet_contents.py
# Wire up env vars that the server (and archivr-core) read at runtime.
# ARCHIVR_BIND and ARCHIVR_TWITTER_CREDENTIALS_FILE are intentionally left
# unset here — set them in docker-compose.yml or at `docker run` time.
ENV ARCHIVR_STATIC_DIR=/usr/share/archivr-server/static \
ARCHIVR_CHROME=/usr/bin/chromium \
ARCHIVR_SINGLE_FILE=/usr/local/bin/single-file \
ARCHIVR_TWEET_PYTHON=/opt/archivr-venv/bin/python3 \
ARCHIVR_TWEET_SCRAPER=/usr/local/lib/archivr/scrape_user_tweet_contents.py \
ARCHIVR_YT_DLP=/opt/archivr-venv/bin/yt-dlp
EXPOSE 8080
# Expects the TOML config at /config/archivr-server.toml (mount a volume).
# Copy docker/config.example.toml as a starting point.
ENTRYPOINT ["archivr-server", "/config/archivr-server.toml"]

23
docker-compose.yml Normal file
View file

@ -0,0 +1,23 @@
services:
archivr:
build: .
image: archivr-server:latest
restart: unless-stopped
ports:
- "8080:8080"
environment:
# Listen on all interfaces inside the container so the port mapping works.
ARCHIVR_BIND: "0.0.0.0:8080"
# Uncomment and set this to enable Twitter/X archiving.
# The file must be accessible inside the container (e.g. in the config volume).
# ARCHIVR_TWITTER_CREDENTIALS_FILE: /config/twitter-cookies.txt
volumes:
# Mount a directory containing archivr-server.toml as read-only config.
# Copy docker/config.example.toml to ./config/archivr-server.toml to start.
- ./config:/config:ro
# Persistent volume for the auth database and archive directories.
# The paths inside must match archive_path values in your TOML config.
- archivr-data:/data
volumes:
archivr-data:

View file

@ -0,0 +1,32 @@
# archivr-server.toml — example configuration for Docker deployment.
#
# Copy this file to ./config/archivr-server.toml (next to docker-compose.yml),
# edit it to suit your setup, then run:
#
# docker compose up -d
#
# The bind address defaults to 127.0.0.1:8080. When running under Docker,
# set ARCHIVR_BIND=0.0.0.0:8080 in the environment (docker-compose.yml does
# this already) — the env var takes precedence over the value below.
# bind = "0.0.0.0:8080"
# Path to the server-level authentication database.
# Must be on a persistent volume so it survives container restarts.
auth_db_path = "/data/archivr-auth.sqlite"
# Define one or more archives.
# archive_path must point to the .archivr directory created by `archivr init`,
# on the persistent data volume (/data by default).
# Initialize each archive before starting the server (see Docker quickstart step 2).
[[archives]]
id = "main"
label = "Main Archive"
archive_path = "/data/archives/main/.archivr"
# Add more archives as needed:
# [[archives]]
# id = "videos"
# label = "Videos"
# archive_path = "/data/archives/videos/.archivr"

View file

@ -205,12 +205,17 @@ A `Dockerfile` and `docker-compose.yml` are provided for self-hosting without Ni
# edit config/archivr-server.toml — set archive id, label, and archive_path # edit config/archivr-server.toml — set archive id, label, and archive_path
``` ```
2. Create the archive directory on the persistent data volume before the first start: 2. Initialize each archive on the persistent data volume before the first start.
The image includes the `archivr` CLI for this purpose:
```sh ```sh
docker compose run --rm archivr mkdir -p /data/archives/main docker compose run --rm archivr archivr init /data/archives/main --name "Main Archive"
``` ```
This creates `/data/archives/main/.archivr/` with the metadata the server requires.
A bare `mkdir` is not enough — the server reads `name` and `store_path` files that
only `archivr init` writes.
3. Start the server: 3. Start the server:
```sh ```sh
@ -224,7 +229,12 @@ A `Dockerfile` and `docker-compose.yml` are provided for self-hosting without Ni
| Mount | Purpose | | Mount | Purpose |
|-------|---------| |-------|---------|
| `./config` (read-only) | Directory containing `archivr-server.toml` | | `./config` (read-only) | Directory containing `archivr-server.toml` |
| `archivr-data` named volume | Auth database and archive directories | | `archivr-data` named volume | Auth database (`/data/archivr-auth.sqlite`) and archive directories |
> **Important:** `auth_db_path` must be set explicitly in `archivr-server.toml` to a
> path on the writable data volume (e.g. `/data/archivr-auth.sqlite`). If left unset,
> the server defaults to writing the auth database next to the config file — which is
> on the read-only `/config` mount and will fail. The example config sets this correctly.
**Twitter/X archiving** **Twitter/X archiving**