Skip to content
GitHub

Deployment and configuration

Run Depsilo v0.11.0 with persistent state, readiness checks, diagnostics, and tested backup and restore.

The following command keeps configuration, SQLite, and the local object cache in one named volume:

Terminal
docker volume create depsilo-state
docker run -d --name depsilo \
-p 23333:23333 \
-v depsilo-state:/root/.depsilo \
--restart unless-stopped \
ghcr.io/depsilo/depsilo:0.11.0

v0.11.0 setup writes absolute database and local-cache paths into its generated configuration, so a new installation only needs to persist /root/.depsilo. The official image runs as UID/GID 10001:10001; new named volumes inherit that ownership. For an older root-running container or v0.9.0 Compose layout, follow the versioned upgrade guide before reopening its state.

State Path in the container Purpose
Configuration /root/.depsilo/config.toml Generated by setup; may contain sensitive values
SQLite /root/.depsilo/data/depsilo.db Authoritative users, policy, audit, and cache metadata
Local object cache /root/.depsilo/data/cache Package artifacts; excluded from depsilo backup

When storage.type is s3, only cache objects move to the remote backend. Configuration and SQLite remain local state and still require persistence and backup. An S3 backend does not make v0.11.0 multi-instance or highly available.

Use a host directory instead of a named volume when host-side tools must read or back up the state root directly. Keep the mount target at /root/.depsilo and prepare ownership for the image’s fixed 10001:10001 identity first:

终端窗口
state_dir="$HOME/.local/share/depsilo/state"
mkdir -p "$state_dir"
docker run --rm --user 0:0 \
--entrypoint /bin/chown \
--mount "type=bind,src=$state_dir,dst=/root/.depsilo" \
ghcr.io/depsilo/depsilo:0.11.0 \
-R 10001:10001 /root/.depsilo
docker run -d --name depsilo \
-p 23333:23333 \
--mount "type=bind,src=$state_dir,dst=/root/.depsilo" \
ghcr.io/depsilo/depsilo:0.11.0

Keep one state source per instance: switching between a named volume and a bind mount starts from a different state unless you migrate it explicitly. The repository ships compose.yaml (named volume) and compose.bind.yaml (host directory); both accept DEPSILO_IMAGE, DEPSILO_BIND_ADDRESS, and PORT.

终端窗口
docker logs depsilo

Open http://localhost:23333, enter the one-time bootstrap token from the startup log, and create the first administrator. Depsilo has no default admin/admin account. Do not expose startup logs; protect or retire retained bootstrap log data according to your log policy after setup.

For a new installation, use the Linux or macOS amd64 / arm64 archive. This POSIX shell script selects the stable asset for your system, checks its SHA-256, and installs it at ~/.local/bin/depsilo. It requires curl, tar, and either sha256sum or macOS’s built-in shasum. For an existing instance, back up its state and follow the matching upgrade procedure first.

终端窗口
(
set -eu
case "$(uname -s)" in
Linux) depsilo_os=linux ;;
Darwin) depsilo_os=darwin ;;
*) printf 'Use the Windows archive from the release page.\n' >&2; exit 1 ;;
esac
case "$(uname -m)" in
x86_64|amd64) depsilo_arch=amd64 ;;
aarch64|arm64) depsilo_arch=arm64 ;;
*) printf 'Unsupported CPU architecture.\n' >&2; exit 1 ;;
esac
depsilo_archive="depsilo_0.11.0_${depsilo_os}_${depsilo_arch}.tar.gz"
depsilo_release='https://github.com/depsilo/depsilo/releases/download/v0.11.0'
depsilo_download_dir=$(mktemp -d "${TMPDIR:-/tmp}/depsilo-install.XXXXXX")
trap 'rm -rf "$depsilo_download_dir"' EXIT
cd "$depsilo_download_dir"
curl -fSL "$depsilo_release/$depsilo_archive" -o "$depsilo_archive"
curl -fSL "$depsilo_release/checksums.txt" -o checksums.txt
awk -v archive="$depsilo_archive" '$2 == archive' checksums.txt > selected.sha256
test -s selected.sha256
if command -v sha256sum >/dev/null 2>&1; then
sha256sum -c selected.sha256
else
shasum -a 256 -c selected.sha256
fi
tar -xzf "$depsilo_archive" depsilo
mkdir -p "$HOME/.local/bin"
install -m 0755 depsilo "$HOME/.local/bin/depsilo"
)

Asset names include depsilo_0.11.0_linux_amd64.tar.gz. Windows ZIP archives and all checksum files are on the v0.11.0 release page. For signature checks, follow the release verification guide.

Start the service in the foreground and keep this terminal open to read the bootstrap token:

终端窗口
cd "$HOME"
"$HOME/.local/bin/depsilo" version
"$HOME/.local/bin/depsilo" serve --host 127.0.0.1 --port 23333

Open http://localhost:23333 to complete setup, then run the readiness check and first request from the quick start in another terminal. HTTPS is not required for this local check. With no explicit configuration file, a new installation saves configuration, the database, and local cache under the running user’s ~/.depsilo/. Run only one process against that state. Stop with Ctrl+C and resume with the same serve command. For continuous operation, configure a service manager with the same user and configuration path.

Use http://127.0.0.1:23333 for the local check. For HTTPS access from other devices, run Caddy on the same Linux host and proxy to Depsilo’s loopback HTTP port. This example assumes clients connect directly to Caddy; a CDN or another proxy requires its own trust configuration.

  1. Keep the backend port local. For a binary installation, use --host 127.0.0.1 as above. For the quick-start Docker container, the following commands briefly stop service and recreate its port mapping while retaining the original depsilo-state named volume. They apply only to that volume name and mount layout; adapt other installations to their existing mounts first.
终端窗口
docker stop depsilo
docker rm depsilo
docker run -d --name depsilo --restart unless-stopped \
-p 127.0.0.1:23333:23333 \
-v depsilo-state:/root/.depsilo \
ghcr.io/depsilo/depsilo:0.11.0
  1. Prepare a domain and Caddy. Follow the official installation instructions for a Linux package with the systemd service. Point your domain’s A/AAAA records at this host, allow the certificate checks on ports 80/443, and persist Caddy’s certificate data. Replace depsilo.example.com below with your domain and add this site to /etc/caddy/Caddyfile, keeping any existing sites:
Caddyfile
depsilo.example.com {
reverse_proxy 127.0.0.1:23333 {
header_up Host {hostport}
}
}

The proxy retains the public Host and sets X-Forwarded-Proto so Depsilo generates HTTPS artifact URLs. Caddy manages certificates for qualifying public domains. Internal names require an internal CA trusted by every client. See automatic HTTPS and proxy headers.

  1. Validate and load the configuration. These commands assume the official caddy systemd service is already running; for its initial start, follow the service guide.
终端窗口
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
sudo systemctl reload caddy
  1. Check the HTTPS endpoint from a client. Replace the domain and run without disabling certificate verification:
终端窗口
DEPSILO_URL='https://depsilo.example.com'
curl -fsS "$DEPSILO_URL/ready"
curl -fsS "$DEPSILO_URL/npm/is-number" -o /dev/null -w 'HTTP %{http_code}\n'

After HTTP 200, find this is-number request in Admin → Access logs at the same HTTPS address. Follow Verify caching to check returned artifact URLs and downloads, then use this HTTPS endpoint in client configuration.

server.trusted_proxies controls trust in forwarded client IPs and trusts no proxies by default. To record original client IPs, add only the proxy addresses Depsilo actually sees; a host proxy reaching a Docker container may not appear as 127.0.0.1. This setting does not replace Host / X-Forwarded-Proto forwarding. Do not trust every address just to recover client IPs.

v0.11.0 resolves the same setting in this order, highest precedence first:

  1. CLI flag
  2. DEPSILO_* environment variable
  3. config.toml
  4. Built-in default

For example, server.port maps to DEPSILO_SERVER_PORT and cache.ttl_index maps to DEPSILO_CACHE_TTL_INDEX. Set DEPSILO_CONFIG to select a file. Without it, Depsilo searches ./config.toml, /app/config.toml, and ~/.depsilo/config.toml.

The most deployment-sensitive differences are:

Setting v0.11.0 built-in default v0.11.0 example Production guidance
server.host 127.0.0.1 0.0.0.0 The official container sets DEPSILO_SERVER_HOST=0.0.0.0; binary installs widen it deliberately or sit behind a TLS proxy
server.port 23333 23333 Keep probes and client URLs in sync when changing it
database.dsn ./data/depsilo.db ./data/depsilo.db Use an absolute path in the container volume
storage.path ./data/cache ./data/cache Use an absolute path in the container volume
cache.max_size_gb 20 20 Size for artifact volume and disk budget
cache.ttl_index 5m 1h Choose for your metadata freshness requirement
cache.ttl_blob 72h 72h Evaluate with capacity and offline tolerance
auth.enabled true true Keep authentication enabled for the admin plane
auth.token_ttl 168h 168h Shorten to match your session policy

When no configuration file exists, v0.11.0 relocates the effective database and cache defaults under ~/.depsilo/data/ and generates a temporary secure JWT secret for setup. This is special missing-file behavior; it does not make the placeholder in an explicit example configuration safe.

With an explicit configuration, a non-loopback listener refuses to start when auth.jwt_secret = "change-me-in-production". Inject a random value through your secret manager, for example:

终端窗口
export DEPSILO_AUTH_JWT_SECRET="$(openssl rand -hex 32)"

Do not commit the secret or send it through public logs.

On first upgrade or activation, Depsilo seeds ordinary ecosystem upstreams into the database. After that import, Admin and the database are authoritative: restarts do not recreate an upstream that an operator changed or deleted. Adding configuration for a previously inactive supported ecosystem can activate that ecosystem on the next restart.

Docker registries and extra indexes remain configuration-owned and are not managed by ordinary Admin Upstream CRUD. Deployment automation should distinguish these sources rather than treating the file as a continuous source of truth for all runtime state.

/ready checks SQLite and object storage and returns a non-2xx response when either is unavailable. It intentionally excludes upstream health because Depsilo may still serve cached packages during an upstream outage.

终端窗口
curl -fsS http://127.0.0.1:23333/ready
docker exec depsilo /app/depsilo doctor
docker exec depsilo /app/depsilo doctor --json

The container image health check also uses /ready. Use it to decide whether an orchestrator should send traffic to the instance; use /health only as a process liveness signal. doctor additionally checks version alignment, storage, upstreams, and cache hit rate. Without DEPSILO_TOKEN it reports fewer protected admin details, but its basic diagnostics still run.

depsilo backup can create a consistent SQLite snapshot while the service is running. Write the archive to the state volume and copy it to a controlled backup location outside the container:

终端窗口
docker exec depsilo mkdir -p /root/.depsilo/backups
docker exec depsilo /app/depsilo backup \
--out /root/.depsilo/backups/depsilo-backup.tar.gz
docker cp depsilo:/root/.depsilo/backups/depsilo-backup.tar.gz .

The archive contains only the config.toml file and a consistent SQLite snapshot. It does not contain local or S3 cache objects. Treat it as sensitive because it contains users, policies, audit data, and potentially secret configuration. Encrypt it, restrict access, and copy it outside the deployment failure domain. Protect cache data separately or accept that it will be fetched again.

On ordinary Linux Docker, docker cp usually makes the exported archive owned by the host user running the command, while depsilo backup creates it with mode 0600. If that host owner is not 10001:10001 inside the container, a read-only bind mount may be unreadable by the default non-root restore process. This does not occur in every Docker environment.

Run the following in the directory holding the archive. It expects this page’s depsilo container and depsilo-state named volume. The script checks the archive, running container, and image version, then creates a separate temporary input volume. Only a preparation container runs as root to copy the archive and set ownership; the input directory stays 0700 and the archive 0600. It checks access from a read-only mount as the image’s default non-root user before stopping the service. The actual restore also runs as that user, which owns the resulting state files. On preparation failure, the script does not stop the service and attempts to remove only this temporary volume. Ensure the source archive is trusted before copying it into the volume.

Terminal
sh -eu <<'RESTORE'
image='ghcr.io/depsilo/depsilo:0.11.0'
archive="$PWD/depsilo-backup.tar.gz"
if ! test -f "$archive" || ! test -r "$archive"; then
echo 'Backup archive is missing or unreadable; aborting.' >&2
exit 1
fi
test "$(docker inspect --format '{{.State.Running}}' depsilo)" = true
test "$(docker inspect --format '{{.Image}}' depsilo)" = \
"$(docker image inspect --format '{{.Id}}' "$image")"
test "$(docker inspect --format '{{range .Mounts}}{{if and (eq .Type "volume") (eq .Destination "/root/.depsilo")}}{{.Name}}{{end}}{{end}}' depsilo)" = depsilo-state
input_volume="depsilo-restore-input-$(date +%s)-$$"
if docker volume inspect "$input_volume" >/dev/null 2>&1; then
echo 'Input volume already exists; aborting.' >&2
exit 1
fi
docker volume create "$input_volume" >/dev/null
trap 'docker volume rm "$input_volume" >/dev/null || true' 0
docker run --rm --user 0:0 --entrypoint /bin/sh \
-v "$archive:/source/depsilo-backup.tar.gz:ro" \
--mount "type=volume,src=$input_volume,dst=/backup" \
"$image" -ec '
cp /source/depsilo-backup.tar.gz /backup/depsilo-backup.tar.gz
chown 10001:10001 /backup /backup/depsilo-backup.tar.gz
chmod 0700 /backup
chmod 0600 /backup/depsilo-backup.tar.gz
'
docker run --rm --entrypoint /bin/sh \
--mount "type=volume,src=$input_volume,dst=/backup,readonly" \
"$image" -ec '
test "$(id -u):$(id -g)" = 10001:10001
test "$(stat -c "%u:%g:%a" /backup)" = 10001:10001:700
test "$(stat -c "%u:%g:%a" /backup/depsilo-backup.tar.gz)" = 10001:10001:600
test -r /backup/depsilo-backup.tar.gz
test -s /backup/depsilo-backup.tar.gz
'
trap - 0
docker stop depsilo
docker run --rm \
-v depsilo-state:/root/.depsilo \
--mount "type=volume,src=$input_volume,dst=/backup,readonly" \
-e DEPSILO_CONFIG=/root/.depsilo/config.toml \
-e DEPSILO_DATABASE_DSN=/root/.depsilo/data/depsilo.db \
-e DEPSILO_STORAGE_PATH=/root/.depsilo/data/cache \
"$image" restore /backup/depsilo-backup.tar.gz
docker start depsilo
curl -fsS http://127.0.0.1:23333/ready
printf '\nAfter checking Admin, policies and a client fetch, remove only this input volume:\ndocker volume rm %s\n' "$input_volume"
RESTORE

/ready only checks readiness. Verify admin login, policies, upstreams, and a real client package fetch. Only after manual verification succeeds, run the printed docker volume rm command to remove this run’s temporary input volume. If restore, startup, or verification fails, keep the original backup and depsilo-state intact; retain the input volume while investigating and deciding how to roll back. Rehearse the whole procedure in isolation first: creating an archive does not verify a restore.

Docker Desktop, rootless Docker, user namespace mappings, and unusual volume drivers may map file ownership differently. If the preparation container cannot read the host archive or change volume ownership, it stops before downtime; check your environment’s mappings and volume permissions instead of widening the archive to 0644 or running the actual restore as root.

[audit] checkpoint_file appends audit chain-head checkpoints as NDJSON with fsync, and depsilo audit verify, the integrity API, and the audit page cross-check every line. The checkpoint must live outside the database’s failure domain: mount it on a controlled host directory, or push it to a WORM gateway or log platform with [audit] checkpoint_url. Keeping both next to each other leaves a full-database rewrite undetectable. Checkpoints are written every 15 minutes by default; checkpoint_interval changes that.

  • Pin the 0.11.0 tag, or an image digest when stronger reproducibility is required.
  • Expose the service through a TLS reverse proxy or controlled network, and restrict the Admin and setup surfaces.
  • Persist configuration, SQLite, and the local cache; apply least privilege to the state volume and backups.
  • Put JWT and other secrets in a secret manager, not an image or repository.
  • Route traffic with /ready, diagnose the whole path with doctor, and rehearse restores regularly.