Skip to main content

git_cache_proxy/
config.rs

1// SPDX-License-Identifier: Apache-2.0
2//! Command-line / environment configuration.
3
4use std::path::PathBuf;
5
6use clap::{Parser, ValueEnum};
7
8/// Log output format.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
10pub enum LogFormat {
11    /// Human-readable single-line text.
12    Text,
13    /// One JSON object per line (for log shippers).
14    Json,
15}
16
17#[derive(Parser, Debug, Clone)]
18#[command(
19    name = "git-cache-proxy",
20    version,
21    about = "Read-only caching proxy for Git repositories"
22)]
23pub struct Config {
24    /// Address to bind the HTTP server to.
25    #[arg(long, env = "GITCACHEPROXY_BIND", default_value = "0.0.0.0:8080")]
26    pub bind: String,
27
28    /// Directory holding the bare mirror caches.
29    #[arg(
30        long,
31        env = "GITCACHEPROXY_CACHE_ROOT",
32        default_value = "/var/cache/git-cache-proxy"
33    )]
34    pub cache_root: PathBuf,
35
36    /// Upstream git base URL, e.g. `https://git.example.com`. Requested repo
37    /// paths are appended to this to locate the origin.
38    #[arg(long, env = "GITCACHEPROXY_UPSTREAM")]
39    pub upstream: String,
40
41    /// Optional header injected on upstream clone/fetch for auth, e.g.
42    /// `Authorization: Bearer <token>`. Read from the environment so the token
43    /// never appears in argv (and it is passed to git via env, not `-c`, so it
44    /// stays out of the child's argv too).
45    #[arg(
46        long,
47        env = "GITCACHEPROXY_UPSTREAM_AUTH_HEADER",
48        hide_env_values = true
49    )]
50    pub upstream_auth_header: Option<String>,
51
52    /// Optional bearer token clients must present (`Authorization: Bearer ...`).
53    /// Unset = serve anonymously (intended for a network-restricted deployment).
54    #[arg(long, env = "GITCACHEPROXY_SERVE_TOKEN", hide_env_values = true)]
55    pub serve_token: Option<String>,
56
57    /// Skip the upstream fetch on `info/refs` if the mirror was refreshed within
58    /// this many seconds. Coalesces bursts of clones for the same repo. `0` =
59    /// always fetch (freshest, more upstream load).
60    #[arg(long, env = "GITCACHEPROXY_FETCH_TTL_SECONDS", default_value_t = 10)]
61    pub fetch_ttl_seconds: u64,
62
63    /// Maximum number of requests handled concurrently, shared across all
64    /// connections. Excess requests queue until a slot frees. This bounds the
65    /// concurrent upstream clone/fetch work a burst can trigger (the slot is held
66    /// for the handler, then released before the packfile streams, so it caps
67    /// setup rather than in-flight streaming). `0` = unlimited. Complementary to
68    /// any ingress-level rate limiting.
69    #[arg(
70        long,
71        env = "GITCACHEPROXY_MAX_CONCURRENT_REQUESTS",
72        default_value_t = 64
73    )]
74    pub max_concurrent_requests: usize,
75
76    /// Maximum size, in MiB, of a decoded `git-upload-pack` request body (the
77    /// client's want/have negotiation). Bounds in-memory buffering and defuses a
78    /// gzip decompression bomb - a small compressed body can expand ~1000x. This
79    /// caps only the negotiation request, never the streamed packfile response,
80    /// so raising it is rarely needed even for very large repositories.
81    #[arg(long, env = "GITCACHEPROXY_MAX_DECODED_BODY_MB", default_value_t = 512)]
82    pub max_decoded_body_mb: u64,
83
84    /// Maximum total size, in MiB, of the on-disk mirror cache. When a clone or
85    /// fetch pushes the total over this, least-recently-used idle mirrors are
86    /// evicted in the background until it is back under; an evicted mirror is
87    /// transparently re-cloned on its next request. `0` = unlimited: no eviction
88    /// and no accounting, so the cache grows without bound (the default).
89    #[arg(long, env = "GITCACHEPROXY_CACHE_MAX_MB", default_value_t = 0)]
90    pub cache_max_mb: u64,
91
92    /// Path to the git binary.
93    #[arg(long, env = "GITCACHEPROXY_GIT_BINARY", default_value = "git")]
94    pub git_binary: String,
95
96    /// Log filter directive (e.g. `info`, `git_cache_proxy=debug,tower=warn`).
97    /// Overridden by the `RUST_LOG` environment variable when set.
98    #[arg(long, env = "GITCACHEPROXY_LOG", default_value = "info")]
99    pub log: String,
100
101    /// Log output format.
102    #[arg(
103        long,
104        value_enum,
105        env = "GITCACHEPROXY_LOG_FORMAT",
106        default_value = "text"
107    )]
108    pub log_format: LogFormat,
109}