Skip to content

Commit

Permalink
Remove put in server
Browse files Browse the repository at this point in the history
  • Loading branch information
linyinfeng committed Mar 23, 2023
1 parent 0b7c993 commit bf6e35f
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 210 deletions.
58 changes: 25 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,63 @@

OCI Registry As Nix Cache.

## Host

Simply run,

```bash
oranc --listen "{LISTEN_ADDRESS}:{LISTEN_PORT}" --upstream "https://cache.nixos.org"
```

Run `oranc --help` for more options.

## Usage

Try [oranc.li7g.com](https://oranc.li7g.com) and [oranc-upload.li7g.com](https://oranc-upload.li7g.com) (for upload).

It's better to self-host an instance. If you do so, please replace all `oranc.li7g.com` below with your instance.
Try [oranc.li7g.com](https://oranc.li7g.com). It's better to self-host an instance. If you do so, please replace all `oranc.li7g.com` below with your instance.

1. Set your credentials.

```bash
export AWS_ACCESS_KEY_ID=(echo -n "{USERNAME}:{PASSWORD}" | base64)
export AWS_SECRET_ACCESS_KEY="_" # can be anything
export ORANC_USERNAME={YOUR_OCI_REGISTRY_USERNAME}
export ORANC_PASSWORD={YOUR_OCI_REGISTRY_PASSWORD}
```

2. Initialize your OCI registry.

```bash
oranc push --registry {OCI_REGISTRY} --repository {OCI_REPOSITORY} initialize
```

2. Prepare your signing keys.
*Make the repository public*, otherwise, caching will not work.

3. Prepare your signing keys.

```console
$ nix key generate-secret --key-name {KEY_NAME} > {PRIVATE_KEY_FILE}
$ cat {PRIVATE_KEY_FILE} | nix key convert-secret-to-public
{PUBLIC_KEY}
```

3. Build and sign something.
4. Build and sign something. oranc *only* pushes signed store paths.

```bash
nix build
nix store sign ./result --recursive --key-file {PRIVATE_KEY_FILE}
```

4. Push to your OCI registry.
5. Push to your OCI registry.

```bash
nix copy ./result \
--to "s3://{REPOSITORY_NAME_PART_2}?endpoint=https://oranc.li7g.com/{OCI_REGISTRY}/{REPOSITORY_NAME_PART_1}"
echo ./result | oranc push --registry {OCI_REGISTRY} --repository {OCI_REPOSITORY}
```

Currently, only support repository names consist of two parts separated by `'/'`.

For example, `s3://cache?endpoint=https://oranc.li7g.com/ghcr.io/linyinfeng` uploads to `ghcr.io/linyinfeng/cache`.
Run `oranc push --help` for more options.

Use <https://oranc-upload.li7g.com> if the size of `nar` files exceeded Cloudflare's limit.

5. Use your OCI registry as a cache.
6. Use your OCI registry as a cache.

In `nix.conf`:

```text
substituters = https://oranc.li7g.com/{OCI_REGISTRY}/{REPOSITORY_NAME_PART_1}/{REPOSITORY_NAME_PART_2}
substituters = https://oranc.li7g.com/{OCI_REGISTRY}/{OCI_REPOSITORY}
trusted-public-keys = {PUBLIC_KEY}
```

Make sure your OCI repository allows anonymous pull.
## Host oranc server

Otherwise, you need to use the following authorization header to access it through oranc.
Simply run,

```text
AWS4-HMAC-SHA256 Credential={AWS_ACCESS_KEY_ID}/
```
```bash
oranc server --listen "{LISTEN_ADDRESS}:{LISTEN_PORT}"
```

Run `oranc server --help` for more options.
20 changes: 1 addition & 19 deletions nixos/module.nix
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,6 @@ in {
Socket address to listen on.
'';
};
upstreams = lib.mkOption {
type = with lib.types; listOf str;
default = ["https://cache.nixos.org"];
description = ''
Upstream caches.
'';
};
ignoreUpstream = lib.mkOption {
type = lib.types.str;
default = "nix-cache-info";
description = ''
Ignore upstream check for keys matching this pattern.
'';
};
log = lib.mkOption {
type = lib.types.str;
default = "oranc=info";
Expand All @@ -57,11 +43,7 @@ in {
config = lib.mkIf cfg.enable {
systemd.services.oranc = {
script = ''
${cfg.package}/bin/oranc server --listen "${cfg.listen}" \
${
lib.concatMapStringsSep "\n" (u: "--upstream \"${u}\" \\") cfg.upstreams
}
--ignore-upstream "${cfg.ignoreUpstream}" ${lib.escapeShellArgs cfg.extraArgs}
${cfg.package}/bin/oranc server --listen "${cfg.listen}" ${lib.escapeShellArgs cfg.extraArgs}
'';
serviceConfig = {
DynamicUser = true;
Expand Down
8 changes: 1 addition & 7 deletions src/options.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clap::{Parser, Subcommand};
use regex::Regex;
use reqwest::Url;

use std::net::SocketAddr;

#[derive(Clone, Debug, Parser)]
Expand All @@ -23,12 +23,6 @@ pub enum Commands {
pub struct ServerOptions {
#[arg(short, long, default_value = "[::]:8080")]
pub listen: SocketAddr,
#[arg(short, long, value_name = "URL")]
pub upstream: Vec<Url>,
#[arg(short, long, value_name = "PATTERN", default_value = "nix-cache-info")]
pub ignore_upstream: Regex,
#[arg(long)]
pub upstream_anonymous: bool,
#[arg(short, long, value_name = "NUM", default_value = "3")]
pub max_retry: usize,
}
Expand Down
11 changes: 4 additions & 7 deletions src/push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,26 +189,24 @@ async fn push_one(
let nar_info_data = nar_info_content.into_bytes();

registry::put(
options,
&mut client,
&nar_oci_reference,
auth,
&nar_file_url,
Some(NAR_CONTENT_TYPE.to_owned()),
nar_file_data,
options.max_retry,
options.dry_run,
)
.await?;

registry::put(
options,
&mut client,
&nar_info_oci_reference,
auth,
&nar_info_filename,
Some(NARINFO_CONTENT_TYPE.to_owned()),
nar_info_data,
options.max_retry,
options.dry_run,
)
.await?;

Expand Down Expand Up @@ -298,17 +296,16 @@ pub async fn push_initialize_main(
log::debug!("nix-cache-info:\n{nix_cache_info}");
let key = "nix-cache-info";
let content_type = "text/x-nix-cache-info";
let reference = build_reference(options.registry, options.repository, key);
let reference = build_reference(options.registry.clone(), options.repository.clone(), key);
let mut client = Default::default();
registry::put(
&options,
&mut client,
&reference,
&auth,
key,
Some(content_type.to_string()),
nix_cache_info.into_bytes(),
options.max_retry,
options.dry_run,
)
.await?;
Ok(())
Expand Down
10 changes: 4 additions & 6 deletions src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use oci_distribution::{
Client, Reference,
};

use crate::{convert::key_to_tag, error::Error};
use crate::{convert::key_to_tag, error::Error, options::PushOptions};

pub const LAYER_MEDIA_TYPE: &str = "application/octet-stream";
pub const CONTENT_TYPE_ANNOTATION: &str = "com.linyinfeng.oranc.content.type";
Expand Down Expand Up @@ -91,17 +91,14 @@ pub async fn get_layer_info(
Ok(Some(info))
}

// TODO refactor server and simplify put function
#[allow(clippy::too_many_arguments)]
pub async fn put(
options: &PushOptions,
client: &mut Client,
reference: &Reference,
auth: &RegistryAuth,
key: &str,
optional_content_type: Option<String>,
data: Vec<u8>,
max_retry: usize,
dry_run: bool,
) -> Result<(), Error> {
let content_type = match optional_content_type {
None => "application/octet-stream".to_string(),
Expand Down Expand Up @@ -140,13 +137,14 @@ pub async fn put(
};
let image_manifest = OciImageManifest::build(&layers, &config, Some(image_annotations));

let max_retry = options.max_retry;
if max_retry < 1 {
return Err(Error::InvalidMaxRetry(max_retry));
}
let mut errors = vec![];
for attempt in 1..max_retry {
log::debug!("push {reference:?}, attempt {attempt}/{max_retry}");
if dry_run {
if options.dry_run {
log::debug!("dry run, skipped");
return Ok(());
}
Expand Down
Loading

0 comments on commit bf6e35f

Please sign in to comment.