Aller au contenu
s3nd.sh

@s3nd/cli

Un fichier entre deux machines, avec un code.

Déplacez un fichier avec put et get, vérifiez qu’un bucket est réellement prêt à recevoir des transferts avec doctor, et gardez les réglages dans un fichier que vous pouvez versionner. Directement vers S3 sans rien déployer, ou via votre propre serveur avec un jeton.

$ s3nd put ./report.pdf
report.pdf · 284 kB · expires in 1 day
K7QP2M4X

$ CODE=$(s3nd put ./report.pdf)          # the code is stdout, the rest is stderr
$ tar cz ./project | s3nd put - --name project.tar.gz

# on the other machine
$ s3nd get K7QP2M4X
Wrote /home/you/report.pdf · 284 kB

$ s3nd get K7QP2M4X -o -  | less        # or to stdout
$ s3nd rm K7QP2M4X
Burned K7QP2M4X

init et doctor

La commande à lancer en premier.

Une mauvaise configuration S3 échoue tard et vaguement. doctor effectue les opérations dont s3nd a réellement besoin et rapporte ce qui s’est passé, plutôt que de lire votre policy et de raisonner dessus. L’objet sonde est supprimé avant de rendre la main.

un point de départ par fournisseur
$ s3nd init --provider r2 --bucket transfers
Wrote /home/you/transfers/s3nd.config.json

Put the three values in .env, and keep it out of git:
  R2_ACCOUNT_ID=
  R2_ACCESS_KEY_ID=
  R2_SECRET_ACCESS_KEY=
The R2 API token needs Object Read & Write on this bucket, and nothing else.
Give the bucket a lifecycle rule that deletes objects under "transfers/" after a day or two.
Run `s3nd doctor` it performs the operations s3nd needs and reports what happened.
et la vérification qui justifie la commande
$ s3nd doctor
Using /home/you/transfers/s3nd.config.json
 Configuration: bucket "transfers", region "auto"
 Credentials: resolved, key ends in 1a2b
 Bucket reachable: HeadBucket succeeded
 Write, read, delete: round-tripped a probe object
! Expiry cleanup: no enabled expiration rule
 Add an S3 lifecycle rule that expires objects under this bucket after a day or
    two. Without it, expired transfers stay stored and billed.

1 check(s) failed.

Cette dernière vérification est celle que personne ne découvre avant l’arrivée d’une facture. expiresIn empêche un transfert d’être remis ; seule une règle de cycle de vie supprime l’objet. Pointé sur un serveur, doctor vérifie la seule chose qui compte là-bas, un vrai aller-retour, et sort avec un code non nul en cas d’échec, donc il sert de smoke test de déploiement.

Configuration

Des réglages versionnables, des clés qui ne le sont pas.

${VAR} est lu depuis l’environnement, et envFile nomme un fichier à charger d’abord sans écraser ce que le shell a déjà défini. Les profils tiennent plusieurs configurations dans un seul fichier. Un flag bat une variable, qui bat le fichier.

s3nd.config.json
{
  "envFile": ".env",
  "profiles": {
    "r2": {
      "bucket": "transfers",
      "region": "auto",
      "endpoint": "https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com",
      "expiresIn": "24h",
      "credentials": { "accessKeyId": "${R2_ACCESS_KEY_ID}", "secretAccessKey": "${R2_SECRET_ACCESS_KEY}" }
    },
    "local": { "bucket": "transfers", "endpoint": "http://localhost:9000" },
    "prod":  { "remote": "https://drop.example.com/api/transfers", "token": "${S3ND_TOKEN}" }
  }
}
$ s3nd -p local doctor          # against a MinIO container, offline
$ s3nd -p r2 put ./report.pdf
$ s3nd -p prod put ./report.pdf # through your server, with a token

$ s3nd config                   # which value won, and where it came from
file         /home/you/transfers/s3nd.config.json (profile "r2")
mode         straight to S3
bucket       transfers                                 $S3ND_BUCKET
endpoint     https://8c4….r2.cloudflarestorage.com     s3nd.config.json (r2)
credentials  …1a2b                                     s3nd.config.json (r2)
expires in   1 day                                     s3nd.config.json (r2)

Le fichier est cherché depuis le répertoire courant vers le haut, puis dans ~/.config/s3nd/config.json. s3nd config masque l’identifiant de clé et n’affiche jamais le secret ni le jeton. L’environnement seul fonctionne aussi, ce qui est la forme que veut la CI.

Contre votre propre serveur

Une implémentation, deux câblages.

Chaque commande accepte --remote, qui la pointe sur un déploiement du protocole de transfert au lieu de S3. La CLI a exactement une implémentation, le client du protocole, branchée soit sur fetch, soit directement sur le handler dans le même processus. Les deux modes ne peuvent pas diverger.

$ s3nd --remote https://drop.example.com/api/transfers --token "$TOKEN" put ./report.pdf
K7QP2M4X

$ s3nd doctor --remote https://drop.example.com/api/transfers --token "$TOKEN"
 Server: https://drop.example.com/api/transfers answered
 Create, read, delete: round-tripped code 8WTXQC8R

Conséquence pratique : la machine d’où vous lancez ça a besoin d’un jeton pour votre propre déploiement plutôt que d’identifiants S3. C’est la forme qui convient à une équipe, où donner les clés du bucket à chaque laptop ne convient pas.

s3nd init --provider remote écrit le point de départ correspondant, et doctor --remote prouve que le serveur répond avant que quiconque n’en dépende.

Mettre en place un serveur

Référence

Six commandes, une douzaine d’options.

Commandes

put <file>
Stocke un fichier et affiche le code à transmettre. "-" lit stdin
get <code>
Récupère ce qu’un code désigne, vers le nom de fichier stocké, -o, ou stdout
rm <code>
Brûle un code
doctor
Vérifie que cette configuration peut réellement stocker des transferts. Code de sortie non nul quand une vérification échoue
init
Écrit un s3nd.config.json de départ pour aws, r2, minio, scaleway, wasabi ou remote
config
Affiche la configuration résolue, et d’où vient chaque valeur

Options

-c, --config
Fichier de configuration à lire
-p, --profile
Profil à utiliser dedans
--env-file
Lit d’abord des paires KEY=value depuis ce fichier
--bucket, --prefix, --region, --endpoint
Réglages du bucket, prioritaires sur le fichier et l’environnement
--expires-in
3600, 30m, 24h, 7d, ou never
--remote, --token
Parle à un serveur s3nd plutôt qu’à S3 directement
--name
Nom de fichier sous lequel stocker le transfert
--json
Sortie lisible par une machine, pour les scripts et pour doctor en CI

Sinon, la configuration vient des mêmes variables d’environnement que la bibliothèque : S3ND_BUCKET, S3ND_ENDPOINT, S3ND_REMOTE, S3ND_TOKEN et les identifiants AWS habituels. Node 20 ou plus ; l’analyse des arguments est le parseArgs de node:util, donc il n’y a rien d’autre à installer.

Déposez un fichier. Donnez le code.

Pointez-le sur le bucket que vous payez déjà. Rien à déployer, aucune inscription, personne au milieu.