chartered ✈️

Chartered is an alternative registry implementation that goes a little bit futher than your bog-standard registry, providing AAA (authentication, authorisation & accounting) guarentees for each of your crates.

Sections

Getting Started

To get started with Chartered, running the servers & uploading your first crate.

Chartered Guide

The guide will give you the run down on all things chartered.

Appendices:

Other documentation:

Getting Started

To get started with Chartered, run the server and upload your first crate.

Server Installation

Chartered's server comes in 3 parts:

  • chartered-git: hosts the git server which clients grab the crate index from, along with their credentials to grab the crates from the next service,
  • chartered-web: hosts the API portion of chartered, which serves the crates themselves (or a redirect to them, depending on which storage backend you're using) and hosts the "web API" which is consumed by our final service,
  • chartered-frontend: a React-based crates.io-like web UI for viewing crates, managing organisations and viewing AAA data.

Each of these services are hosted separately from one another, and could technically be swapped out for other implementations - the only shared layer between the three of them is database storage for crate lookups and authentication credential vending. All of the services have the ability to be clustered with no extra configuration.

Backend Services

chartered-git and chartered-web's setups are similar, first they need a database set up - either SQLite or PostgreSQL, PostgreSQL is recommended anywhere outside of development/local use for obvious reasons.

Both the aformentioned services have sane defaults for development and can be ran simply by running the binary, the services will bind to 127.0.0.1:8899 and 127.0.0.1:8080 respectively and store crate files in /tmp/chartered, configuration away from these defaults is simple.

Using the recommended setup, S3 & PostgreSQL:

chartered-web config

bind_address = "127.0.0.1:8080"
database_uri = "postgres://user:password@localhost/chartered"
storage_uri  = "s3://s3-eu-west-1.amazonaws.com/my-cool-crate-store/"
frontend_base_uri = "http://localhost:5173/"

[auth.password]
enabled = true

# openid connect provider
[auth.gitlab]
enabled = true
discovery_uri = "https://gitlab.com/"
client_id = "[client-id]"
client_secret = "[client-secret]"

chartered-git config

bind_address = "127.0.0.1:2233"
database_uri = "postgres://user:password@localhost/chartered" # can also be `sqlite://`
web_base_uri = "http://localhost:8888/"

[committer]
name = "Chartered"
email = "noreply@chart.rs"
message = "Updated crates!"

These configuration files can be passed into each binary using the -c CLI argument.

Alternative crate stores will be considered, please consider contributing or create an issue on GitHub. MySQL support, however, is a no-go.

chartered-web & chartered-git can be built from source easily or ran using the Dockerfile:

$ docker build https://github.com/w4/chartered.git#main \
    --target chartered-web \
    -t chartered-web:master
$ docker build https://github.com/w4/chartered.git#main \
    --target chartered-git \
    -t chartered-git:master
$ docker -v $PWD/web-config.toml:/config.toml run -d chartered-web --config /config.toml
$ docker -v $PWD/git-config.toml:/config.toml run -d chartered-git --config /config.toml

Frontend

The frontend only needs to be configured to point to the chartered-web service. This can be done by changing the bundled config.json. This can then be hosted in S3/minio/your preferred static hosting platform, a Dockerfile can also be built which uses static-web-server to run on your own server without another way of hosting static content:

# buildkit doesn't yet support subdirectories for git repositories
$ DOCKER_BUILDKIT=0 docker build \
    https://github.com/w4/chartered.git#main:chartered-frontend \
    --build-arg BASE_URL=https://api.my.instance.chart.rs \
    -t chartered-frontend:master
$ docker run -d -p 8080:80 chartered-frontend:master
$ curl http://127.0.0.1:8080
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8">...

Where BASE_URL points to the chartered-web instance.

User Guide

Using chartered as a user is actually pretty simple, it's very much like your standard Cargo registry except with two extra concepts: organisations and permissions.

Organisations are very much like the organisations you'll likely have used on your preferred SCM host, a group of users that have group-level permissions, in Chartered case the permissions these users may have are:

Permissions

  • VISIBLE
    • Essentially the base-level permission meaning the user belongs to the group, if the user doesn't have this permission they're not in the group, this permission at the crate-level means the user can download the crate and see it in the WebUI.
  • PUBLISH_VERSION
    • Gives the ability to publish a new version for crates belonging to the group.
  • YANK_VERSION
    • Gives the ability to yank (and unyank) published versions for crates belonging to the group.
  • MANAGE_USERS
    • Gives the ability to add (and remove) users from the group, and crates belonging to the organisation.
  • CREATE_CRATE
    • Gives the ability to create a new crate under the organisation.

All these permissions, with the exception of CREATE_CRATE, can also be used at the crate-level for giving extra permissions to org members for a particular crate - or even users outside of the org. Bare in mind, however, these permissions are additive - it is not possible for permissions to be subtracted from a user at the crate-level if they have been granted them by the organisation.

Publishing your first crate

With all this in mind, it's about time you started publishing your first crate!

Chartered has excellent integration with Cargo's alternative registry implementation and is used very much like a standard alternative registry. The only prerequisites for publishing your crate are:

  1. Have an SSH key added to your Chartered account, which you can do via the WebUI
  2. Belong to an organisation you have the PUBLISH_VERSION permission for, anyone can create a new organisation if you don't already belong to one.

And once you're ready, you can add the organisation's registry to your .cargo/config.toml like so:

[registries]
my-organisation = { index = "ssh://ssh.chart.rs/my-organisation" }

(You should create this file if it doesn't already exist)

You can now publish the crate using cargo as you normally would, except with the registry specified:

$ cargo publish --registry my-organisation --token ""

Note: the token is purposefully empty, as the token will be vended by the index based on your SSH key.

Pulling in dependencies

Again, not too dissimilar from using crates.io, you can declare your dependencies as normal with the exception that you need to specify the organisation the crate should be pulled from provided you've declared the organisation in .cargo/config.toml as shown in the previous section of this guide.

[dependencies]
my-other-crate = { version = "0.1", registry = "my-organisation" }

Your other Cargo dependencies from crates.io can be declared as normal alongside organisation dependencies.

Chartered Guide

Configuration Reference

An exhaustive list of all configuration values in chartered.

Configuration files are written in the TOML format, with simple key-value pairs inside of sections (tables). The following is a quick overview of all settings, with detailed descriptions found below

chartered-git

Configuration format

bind_address = "127.0.0.1:2233"
database_uri = "postgres://user:password@localhost/chartered" # can also be `sqlite://`
web_base_uri = "http://localhost:8888/"

[committer]
name = "Chartered"
email = "noreply@chart.rs"
message = "Updated crates!"

Configuration keys

bind_address

  • Type: string

The IP address and port the web server should be bound to.

database_uri

  • Type: string

A connection string for the backing database, either postgres or sqlite, either in the format of postgres://user:password@localhost/chartered (a postgres connection URI), sqlite:///path/to/chartered.db or sqlite://:memory:.

web_base_uri

  • Type: string

The path at which the Chartered API (chartered-web) is running. This should always be HTTPS when running in production.

committer

The committer table defines the author of the commit that's sent to the user.

name
  • Type: string
  • Default: chartered

The name of the committer for any commits being created by chartered-git.

email
  • Type: string
  • Default: noreply@chart.rs

The email address to list for the author of the commit pushed to the user

message
  • Type: string
  • Default: Update crates

The commit message to use for any commits sent out.


chartered-web

Configuration format

bind_address = "127.0.0.1:8080"
database_uri = "postgres://user:password@localhost/chartered" # can also be `sqlite://`

storage_uri  = "s3://s3-eu-west-1.amazonaws.com/my-cool-crate-store/" # or file:///var/lib/chartered

frontend_base_uri = "http://localhost:5173/"
trusted_ip_header = "x-forwarded-for"

[auth.password]
enabled = true # enables password auth 

[auth.<provider>] # openid connect provider
enabled = true
discovery_uri = "https://gitlab.com/"
client_id = "[client-id]"
client_secret = "[client-secret]"

Configuration keys

bind_address

  • Type: string

The IP address and port the web server should be bound to.

database_uri

  • Type: string

A connection string for the backing database, either postgres or sqlite, either in the format of postgres://user:password@localhost/chartered (a postgres connection URI), sqlite:///path/to/chartered.db or sqlite://:memory:.

storage_uri

  • Type: string

A URI in which crates should be stored, this can either be an s3:// connection URI, or a local file path using file://.

frontend_base_uri

  • Type: string

The base URL at which the frontend is being hosted.

trusted_ip_header

  • Type: string
  • Default: null

Allows a header to override the socket address as the end user's IP address

[auth.password]

The [auth.password] table controls the username/password-based authentication method.

enable
  • Type: bool
  • Default: false

Enables username/password-based authentication and registration.

[auth.<provider>]

[auth.<provider>] tables represent an OpenID Connect provider that can be used to login and register to the chartered instance. <provider> should not be changed once set as the value is stored in the database along with users.

enabled
  • Type: bool

Enables the authentication provider, if this is disabled users will not be able to login nor register using the provider.

discovery_uri
  • Type: bool

The OIDC Discovery URI that can be used to grab configuration for the provider, not including /.well-known/openid-configuration.

client_id
  • Type: string

The Client ID given by the provider to identify the service.

client_secret
  • Type: string

The client secret given by the provider to authenticate the service.