[{"data":1,"prerenderedAt":1370},["ShallowReactive",2],{"navigation_docs":3,"-systems-serverless-registry-worker":296,"-systems-serverless-registry-worker-surround":1365},[4,65,110],{"title":5,"path":6,"stem":7,"children":8,"icon":64},"Systems & Solutions","\u002Fsystems","1.systems\u002F0.index",[9,11,29,46],{"title":10,"path":6,"stem":7},"Overview",{"title":12,"path":13,"stem":14,"children":15},"Serverless Registry","\u002Fsystems\u002Fserverless-registry","1.systems\u002Fserverless-registry\u002F0.index",[16,17,21,25],{"title":10,"path":13,"stem":14},{"title":18,"path":19,"stem":20},"CloudFlare Worker","\u002Fsystems\u002Fserverless-registry\u002Fworker","1.systems\u002Fserverless-registry\u002F1.worker",{"title":22,"path":23,"stem":24},"sreg CLI","\u002Fsystems\u002Fserverless-registry\u002Fsreg-cli","1.systems\u002Fserverless-registry\u002F2.sreg-cli",{"title":26,"path":27,"stem":28},"GitHub Actions","\u002Fsystems\u002Fserverless-registry\u002Fgithub-actions","1.systems\u002Fserverless-registry\u002F3.github-actions",{"title":30,"path":31,"stem":32,"children":33},"Serverless Satis","\u002Fsystems\u002Fserverless-satis","1.systems\u002Fserverless-satis\u002F0.index",[34,35,39,43],{"title":10,"path":31,"stem":32},{"title":36,"path":37,"stem":38},"CLI generator","\u002Fsystems\u002Fserverless-satis\u002Fs3-satis","1.systems\u002Fserverless-satis\u002F1.s3-satis",{"title":40,"path":41,"stem":42},"GitHub Action","\u002Fsystems\u002Fserverless-satis\u002Fs3-satis-github-action","1.systems\u002Fserverless-satis\u002F2.s3-satis-github-action",{"title":18,"path":44,"stem":45},"\u002Fsystems\u002Fserverless-satis\u002Fcloudflare-worker","1.systems\u002Fserverless-satis\u002F3.cloudflare-worker",{"title":47,"path":48,"stem":49,"children":50},"WebPrint","\u002Fsystems\u002Fwebprint","1.systems\u002Fwebprint\u002F0.index",[51,52,56,60],{"title":10,"path":48,"stem":49},{"title":53,"path":54,"stem":55},"Server","\u002Fsystems\u002Fwebprint\u002Fserver","1.systems\u002Fwebprint\u002F1.server",{"title":57,"path":58,"stem":59},"Host Service","\u002Fsystems\u002Fwebprint\u002Fservice","1.systems\u002Fwebprint\u002F2.service",{"title":61,"path":62,"stem":63},"API","\u002Fsystems\u002Fwebprint\u002Fapi","1.systems\u002Fwebprint\u002F3.api","mdi:monitor",{"title":66,"path":67,"stem":68,"children":69,"icon":109},"Apps & Tools","\u002Fapps","2.apps\u002F0.index",[70,71,75,79,83,87,91],{"title":10,"path":67,"stem":68},{"title":72,"path":73,"stem":74},"File Hasher.NET","\u002Fapps\u002Ffile-hasher","2.apps\u002F1.file-hasher",{"title":76,"path":77,"stem":78},"GitFlow Tool","\u002Fapps\u002Fgit-flow","2.apps\u002F1.git-flow",{"title":80,"path":81,"stem":82},"NFC to RFID","\u002Fapps\u002Fnfc-to-rfid","2.apps\u002F1.nfc-to-rfid",{"title":84,"path":85,"stem":86},"PDF Scan Splitter","\u002Fapps\u002Fpdf-scan-splitter","2.apps\u002F1.pdf-scan-splitter",{"title":88,"path":89,"stem":90},"USB Scale Counter","\u002Fapps\u002Fusb-scale-counter","2.apps\u002F1.usb-scale-counter",{"title":92,"path":93,"stem":94,"children":95,"page":108},"Deprecated","\u002Fapps\u002Fdeprecated","2.apps\u002F9.deprecated",[96,100,104],{"title":97,"path":98,"stem":99},"Batch Comparator","\u002Fapps\u002Fdeprecated\u002Fcomparator","2.apps\u002F9.deprecated\u002Fcomparator",{"title":101,"path":102,"stem":103},"ContactBridge","\u002Fapps\u002Fdeprecated\u002Fcontact-bridge","2.apps\u002F9.deprecated\u002Fcontact-bridge",{"title":105,"path":106,"stem":107},"File Hasher.PY","\u002Fapps\u002Fdeprecated\u002Ffile-hasher-python","2.apps\u002F9.deprecated\u002Ffile-hasher-python",false,"teenyicons:terminal-outline",{"title":111,"path":112,"stem":113,"children":114,"icon":295},"Libraries & Packages","\u002Flibraries","3.libraries\u002F0.index",[115,116,173,214,227,239],{"title":10,"path":112,"stem":113},{"title":117,"path":118,"stem":119,"children":120,"page":108},"PHP & Laravel","\u002Flibraries\u002Fphp","3.libraries\u002F100.php",[121,125,129,133,137,141,145,149,153,157,161,165,169],{"title":122,"path":123,"stem":124},"Binary Tools","\u002Flibraries\u002Fphp\u002Fbinary-tools","3.libraries\u002F100.php\u002Fbinary-tools",{"title":126,"path":127,"stem":128},"Certificate Chain","\u002Flibraries\u002Fphp\u002Fcert-chain","3.libraries\u002F100.php\u002Fcert-chain",{"title":130,"path":131,"stem":132},"Eloquent Sluggable","\u002Flibraries\u002Fphp\u002Feloquent-sluggable","3.libraries\u002F100.php\u002Feloquent-sluggable",{"title":134,"path":135,"stem":136},"Eloquent Tokenable","\u002Flibraries\u002Fphp\u002Feloquent-tokenable","3.libraries\u002F100.php\u002Feloquent-tokenable",{"title":138,"path":139,"stem":140},"Eloquent ULID-able","\u002Flibraries\u002Fphp\u002Feloquent-ulidable","3.libraries\u002F100.php\u002Feloquent-ulidable",{"title":142,"path":143,"stem":144},"Eloquent UUID-able","\u002Flibraries\u002Fphp\u002Feloquent-uuidable","3.libraries\u002F100.php\u002Feloquent-uuidable",{"title":146,"path":147,"stem":148},"emSzmal Banking API wrapper","\u002Flibraries\u002Fphp\u002Femszmal","3.libraries\u002F100.php\u002Femszmal",{"title":150,"path":151,"stem":152},"EPC Tag Data Standard","\u002Flibraries\u002Fphp\u002Fepc-tds","3.libraries\u002F100.php\u002Fepc-tds",{"title":154,"path":155,"stem":156},"File Hasher.PHP","\u002Flibraries\u002Fphp\u002Ffile-hasher","3.libraries\u002F100.php\u002Ffile-hasher",{"title":158,"path":159,"stem":160},"Content Negotiable Responses for Laravel","\u002Flibraries\u002Fphp\u002Flaravel-content-negotiable-responses","3.libraries\u002F100.php\u002Flaravel-content-negotiable-responses",{"title":162,"path":163,"stem":164},"LPD Client and Server","\u002Flibraries\u002Fphp\u002Flpd","3.libraries\u002F100.php\u002Flpd",{"title":166,"path":167,"stem":168},"Partial Key Verification Library for PHP","\u002Flibraries\u002Fphp\u002Fpartial-key-verification","3.libraries\u002F100.php\u002Fpartial-key-verification",{"title":170,"path":171,"stem":172},"WebPrint.PHP","\u002Flibraries\u002Fphp\u002Fwebprint","3.libraries\u002F100.php\u002Fwebprint",{"title":174,"path":175,"stem":176,"children":177,"page":108},"Capacitor.JS","\u002Flibraries\u002Fcapacitor","3.libraries\u002F200.capacitor",[178,182,186,190,194,198,202,206,210],{"title":179,"path":180,"stem":181},"SPP Bluetooth Printer for Capacitor.js","\u002Flibraries\u002Fcapacitor\u002Fbluetooth-printer","3.libraries\u002F200.capacitor\u002Fbluetooth-printer",{"title":183,"path":184,"stem":185},"Sunmi Camera Scanner for Capacitor.js","\u002Flibraries\u002Fcapacitor\u002Fsunmi-camera-scanner","3.libraries\u002F200.capacitor\u002Fsunmi-camera-scanner",{"title":187,"path":188,"stem":189},"Sunmi Keyboard Handler for Capacitor.js","\u002Flibraries\u002Fcapacitor\u002Fsunmi-keyboard-handler","3.libraries\u002F200.capacitor\u002Fsunmi-keyboard-handler",{"title":191,"path":192,"stem":193},"Sunmi Inner Printer SDK for Capacitor.js","\u002Flibraries\u002Fcapacitor\u002Fsunmi-printer","3.libraries\u002F200.capacitor\u002Fsunmi-printer",{"title":195,"path":196,"stem":197},"Sunmi Scan Head  SDK for Capacitor.js","\u002Flibraries\u002Fcapacitor\u002Fsunmi-scanhead","3.libraries\u002F200.capacitor\u002Fsunmi-scanhead",{"title":199,"path":200,"stem":201},"Sunmi Scan Head (lite) SDK for Capacitor.js","\u002Flibraries\u002Fcapacitor\u002Fsunmi-scanhead-lite","3.libraries\u002F200.capacitor\u002Fsunmi-scanhead-lite",{"title":203,"path":204,"stem":205},"Sunmi UHF RFID SDK for Capacitor.js","\u002Flibraries\u002Fcapacitor\u002Fsunmi-uhf","3.libraries\u002F200.capacitor\u002Fsunmi-uhf",{"title":207,"path":208,"stem":209},"Dymo M10 USB Scale driver for Capacitor.js","\u002Flibraries\u002Fcapacitor\u002Fusb-scale","3.libraries\u002F200.capacitor\u002Fusb-scale",{"title":211,"path":212,"stem":213},"WebView WatchDog for Capacitor.js","\u002Flibraries\u002Fcapacitor\u002Fwebview-watchdog","3.libraries\u002F200.capacitor\u002Fwebview-watchdog",{"title":215,"path":216,"stem":217,"children":218,"page":108},"JavaScript & TypeScript","\u002Flibraries\u002Fjs","3.libraries\u002F300.js",[219,223],{"title":220,"path":221,"stem":222},"Partial Key Verification Library for TS\u002FJS","\u002Flibraries\u002Fjs\u002Fpartial-key-verification","3.libraries\u002F300.js\u002Fpartial-key-verification",{"title":224,"path":225,"stem":226},"WebPrint.JS","\u002Flibraries\u002Fjs\u002Fwebprint","3.libraries\u002F300.js\u002Fwebprint",{"title":228,"path":229,"stem":230,"children":231,"page":108},".NET & C#","\u002Flibraries\u002Fnet","3.libraries\u002F400.net",[232,235],{"title":72,"path":233,"stem":234},"\u002Flibraries\u002Fnet\u002Ffile-hasher","3.libraries\u002F400.net\u002Ffile-hasher",{"title":236,"path":237,"stem":238},"Partial Key Verification Library for Compact Framework","\u002Flibraries\u002Fnet\u002Fpartial-key-verification","3.libraries\u002F400.net\u002Fpartial-key-verification",{"title":92,"path":240,"stem":241,"children":242,"page":108},"\u002Flibraries\u002Fdeprecated","3.libraries\u002F999.deprecated",[243,247,251,255,259,263,267,271,275,279,283,287,291],{"title":244,"path":245,"stem":246},"CoinHive API and Captcha","\u002Flibraries\u002Fdeprecated\u002Fcoinhive-api","3.libraries\u002F999.deprecated\u002Fcoinhive-api",{"title":248,"path":249,"stem":250},"Eloquent Encryptable","\u002Flibraries\u002Fdeprecated\u002Feloquent-encryptable","3.libraries\u002F999.deprecated\u002Feloquent-encryptable",{"title":252,"path":253,"stem":254},"Eloquent GUID-able","\u002Flibraries\u002Fdeprecated\u002Feloquent-guidable","3.libraries\u002F999.deprecated\u002Feloquent-guidable",{"title":256,"path":257,"stem":258},"Laravel Web Cron","\u002Flibraries\u002Fdeprecated\u002Flaravel-cron","3.libraries\u002F999.deprecated\u002Flaravel-cron",{"title":260,"path":261,"stem":262},"Laravel .env filler","\u002Flibraries\u002Fdeprecated\u002Flaravel-dotenv-filler","3.libraries\u002F999.deprecated\u002Flaravel-dotenv-filler",{"title":264,"path":265,"stem":266},"Laravel Permissions","\u002Flibraries\u002Fdeprecated\u002Flaravel-permissions","3.libraries\u002F999.deprecated\u002Flaravel-permissions",{"title":268,"path":269,"stem":270},"Polish Validator Rules for Laravel","\u002Flibraries\u002Fdeprecated\u002Flaravel-polish-validator","3.libraries\u002F999.deprecated\u002Flaravel-polish-validator",{"title":272,"path":273,"stem":274},"Laravel SMS Notification Channel","\u002Flibraries\u002Fdeprecated\u002Flaravel-sms","3.libraries\u002F999.deprecated\u002Flaravel-sms",{"title":276,"path":277,"stem":278},"Laravel SMS Notification Channel - JustSend.pl Driver","\u002Flibraries\u002Fdeprecated\u002Flaravel-sms-justsend","3.libraries\u002F999.deprecated\u002Flaravel-sms-justsend",{"title":280,"path":281,"stem":282},"Laravel SMS Notification Channel - SerwerSMS.pl Driver","\u002Flibraries\u002Fdeprecated\u002Flaravel-sms-serwersms","3.libraries\u002F999.deprecated\u002Flaravel-sms-serwersms",{"title":284,"path":285,"stem":286},"Diceware Generator","\u002Flibraries\u002Fdeprecated\u002Fpassphrase-generator","3.libraries\u002F999.deprecated\u002Fpassphrase-generator",{"title":288,"path":289,"stem":290},"Raw Printer tools for C#","\u002Flibraries\u002Fdeprecated\u002Fraw-printer","3.libraries\u002F999.deprecated\u002Fraw-printer",{"title":292,"path":293,"stem":294},"Signed Document","\u002Flibraries\u002Fdeprecated\u002Fsigned-document","3.libraries\u002F999.deprecated\u002Fsigned-document","charm:package",{"id":297,"title":298,"active":299,"body":300,"description":1357,"extension":1358,"featured":1359,"featured_description":1359,"featured_icon":1359,"github":333,"layout":1359,"links":1359,"list_title":298,"meta":1360,"navigation":1361,"path":19,"platform":18,"seo":1362,"stem":20,"system":12,"system_url":13,"type":1363,"__hash__":1364},"docs\u002F1.systems\u002Fserverless-registry\u002F1.worker.md","Serverless Registry Worker",true,{"type":301,"value":302,"toc":1332},"minimark",[303,327,346,351,354,421,440,456,460,471,547,550,675,679,682,715,732,738,793,807,812,838,856,862,866,869,873,880,886,893,899,902,912,917,923,927,939,945,951,958,963,969,976,982,985,991,997,1000,1013,1019,1029,1034,1056,1062,1074,1080,1105,1110,1113,1126,1193,1210,1233,1248,1252,1268,1272,1282,1286,1307,1311],[304,305,306,307,311,312,320,321,326],"p",{},"The Worker is the registry itself. It serves the native read protocols of the package managers, the\npublishing and administration API (",[308,309,310],"code",{},"\u002Fapi\u002Fv1",") and a landing page with an admin panel. Files are kept in\n",[313,314,319],"a",{"href":315,":target":316,"rel":317},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fr2\u002F","_blank",[318],"nofollow","CloudFlare R2",", credentials in\n",[313,322,325],{"href":323,":target":316,"rel":324},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fkv\u002F",[318],"CloudFlare KV",".",[328,329,330,336,341],"u-button-group",{},[331,332,335],"u-button",{"href":333,"icon":334,"target":316},"https:\u002F\u002Fgithub.com\u002Fkduma-OSS\u002Fserverless-registry-worker","bxl:github","GitHub Repository",[331,337,340],{"href":338,"icon":339,"target":316},"https:\u002F\u002Fgithub.com\u002Fkduma-OSS\u002Fserverless-registry-worker\u002Fblob\u002Fmain\u002Fdocs\u002Fdeployment.md","material-symbols:menu-book","Deployment guide",[331,342,345],{"href":343,"icon":344,"target":316},"https:\u002F\u002Fdeploy.workers.cloudflare.com\u002F?url=https:\u002F\u002Fgithub.com\u002Fkduma-OSS\u002Fserverless-registry-worker","simple-icons:cloudflare","Deploy to CloudFlare",[347,348,350],"h2",{"id":349},"deployment","Deployment",[304,352,353],{},"Pick one of three ways, all using the same repository:",[355,356,357,373],"table",{},[358,359,360],"thead",{},[361,362,363,367,370],"tr",{},[364,365,366],"th",{},"Path",[364,368,369],{},"For whom",[364,371,372],{},"Deploys on",[374,375,376,394,407],"tbody",{},[361,377,378,385,388],{},[379,380,381,384],"td",{},[382,383,345],"em",{}," button",[379,386,387],{},"most installations",[379,389,390,391],{},"every push to your ",[308,392,393],{},"main",[361,395,396,399,402],{},[379,397,398],{},"Fork + GitHub Actions",[379,400,401],{},"those who prefer GitHub Actions",[379,403,404,405],{},"every push to your fork's ",[308,406,393],{},[361,408,409,415,418],{},[379,410,411,412],{},"Local ",[308,413,414],{},"npm run deploy",[379,416,417],{},"developers and one-off installs",[379,419,420],{},"every time you run it",[304,422,423,424,427,428,431,432,435,436,439],{},"Everything is provisioned from ",[308,425,426],{},"wrangler.jsonc"," on the first deploy: the Worker ",[308,429,430],{},"serverless-registry",",\na KV namespace (",[308,433,434],{},"AUTH","), an R2 bucket (",[308,437,438],{},"R2_BUCKET","), static assets and an hourly cron cleanup.\nNothing installation-specific is committed - settings live in the CloudFlare dashboard, so updates are conflict-free.",[304,441,442,443,447,448,452,453,326],{},"The repository also brings two GitHub workflows for your own copy (see ",[313,444,446],{"href":445},"#updating","Updating","):\n",[449,450,451],"strong",{},"Update from upstream"," and ",[449,454,455],{},"Configure bindings",[347,457,459],{"id":458},"configuration","Configuration",[304,461,462,463,466,467,470],{},"Set in the Worker's ",[382,464,465],{},"Settings"," → ",[382,468,469],{},"Variables and Secrets",":",[355,472,473,486],{},[358,474,475],{},[361,476,477,480,483],{},[364,478,479],{},"Variable",[364,481,482],{},"Type",[364,484,485],{},"Description",[374,487,488,501,513,530],{},[361,489,490,495,498],{},[379,491,492],{},[308,493,494],{},"PUBLIC_URL",[379,496,497],{},"variable",[379,499,500],{},"Public address of the registry (also the audience of OIDC tokens).",[361,502,503,508,510],{},[379,504,505],{},[308,506,507],{},"S3_ENDPOINT",[379,509,497],{},[379,511,512],{},"R2 S3 endpoint used for presigned URLs.",[361,514,515,524,527],{},[379,516,517,520,521],{},[308,518,519],{},"S3_ACCESS_KEY_ID",", ",[308,522,523],{},"S3_SECRET_ACCESS_KEY",[379,525,526],{},"secrets",[379,528,529],{},"R2 API token scoped to the bucket.",[361,531,532,537,540],{},[379,533,534],{},[308,535,536],{},"SESSION_SECRET",[379,538,539],{},"secret",[379,541,542,543,546],{},"Signs panel sessions (",[308,544,545],{},"openssl rand -base64 48",").",[304,548,549],{},"Optional variables (defaults apply while unset):",[355,551,552,564],{},[358,553,554],{},[361,555,556,558,561],{},[364,557,479],{},[364,559,560],{},"Default",[364,562,563],{},"Effect",[374,565,566,584,600,615,632,646,661],{},[361,567,568,573,578],{},[379,569,570],{},[308,571,572],{},"ECOSYSTEMS",[379,574,575],{},[308,576,577],{},"composer,npm,cargo,generic,nuget,swift,maven",[379,579,580,581,326],{},"Enabled ecosystems; a disabled one answers ",[308,582,583],{},"404",[361,585,586,591,597],{},[379,587,588],{},[308,589,590],{},"MAX_UPLOAD_BYTES",[379,592,593,596],{},[308,594,595],{},"536870912"," (512 MiB)",[379,598,599],{},"Largest accepted file of a version.",[361,601,602,607,612],{},[379,603,604],{},[308,605,606],{},"APPEND_WINDOW_HOURS",[379,608,609],{},[308,610,611],{},"24",[379,613,614],{},"How long files may be appended to a generic version.",[361,616,617,622,625],{},[379,618,619],{},[308,620,621],{},"TOKEN_PREFIX",[379,623,624],{},"empty",[379,626,627,628,631],{},"Fixed prefix (e.g. ",[308,629,630],{},"srg_",") for issued tokens, so leaked ones can be found with grep.",[361,633,634,639,643],{},[379,635,636],{},[308,637,638],{},"LOGIN_TOKEN_EXTENDED_TTL_HOURS",[379,640,641],{},[308,642,611],{},[379,644,645],{},"How long a pull token lasts when it is approved with \"extended validity\" (1 to 720); otherwise one hour.",[361,647,648,653,658],{},[379,649,650],{},[308,651,652],{},"CHECK_UPDATES",[379,654,655],{},[308,656,657],{},"true",[379,659,660],{},"Settings page checks GitHub for a newer release once a day.",[361,662,663,668,672],{},[379,664,665],{},[308,666,667],{},"R2_BUCKET_NAME",[379,669,670],{},[308,671,430],{},[379,673,674],{},"Bucket name in presigned URLs.",[347,676,678],{"id":677},"authentication","Authentication",[304,680,681],{},"Every credential is a project name with exactly one kind, a list of grants and one or more secrets:",[683,684,685,699,709],"ul",{},[686,687,688,691,692,520,695,698],"li",{},[308,689,690],{},"read"," - installs packages; its key token is safe to commit into the consumer's repository (",[308,693,694],{},"auth.json",[308,696,697],{},".npmrc",", ...),",[686,700,701,704,705,708],{},[308,702,703],{},"publish"," - publishes versions with ",[308,706,707],{},"sreg",", usually from GitHub Actions; never reads,",[686,710,711,714],{},[308,712,713],{},"admin"," - the panel and the administrative API; no grants.",[304,716,717,718,721,722,725,726,728,729,326],{},"A grant is an ecosystem, a package name or ",[308,719,720],{},"vendor\u002F*"," pattern and a version constraint in that ecosystem's syntax\n(",[308,723,724],{},"*"," for all). ",[308,727,690],{}," grants are transitive by default. Grants can be edited as rows or as text, one per line in the\nshorthand ",[308,730,731],{},"eco:package[:versions[:transitive]]",[304,733,734,735,737],{},"A credential holds one or more ",[449,736,526],{},", each with an optional description:",[355,739,740,750],{},[358,741,742],{},[361,743,744,747],{},[364,745,746],{},"Secret",[364,748,749],{},"What it is",[374,751,752,773,783],{},[361,753,754,759],{},[379,755,756],{},[308,757,758],{},"key",[379,760,761,762,765,766,769,770,772],{},"A generated token ",[308,763,764],{},"\u003Cproject>:\u003Csecret>",", used as Bearer, Basic or raw ",[308,767,768],{},"Authorization"," header. A ",[308,771,758],{}," is always generated, never a chosen password.",[361,774,775,780],{},[379,776,777],{},[308,778,779],{},"login",[379,781,782],{},"A password and, optionally, a one-time code (TOTP) for an authenticator app. Used to sign in to the panel and to approve CLI operations in the browser (below).",[361,784,785,790],{},[379,786,787],{},[308,788,789],{},"gh",[379,791,792],{},"Trusts a GitHub repository (optionally a ref, workflow and environment) so its Actions jobs authenticate with OIDC, with no stored secret.",[304,794,795,796,798,799,801,802,326],{},"A ",[308,797,703],{}," credential with a ",[308,800,789],{}," secret is the recommended setup for CI. See the\n",[313,803,806],{"href":804,":target":316,"rel":805},"https:\u002F\u002Fgithub.com\u002Fkduma-OSS\u002Fserverless-registry-worker\u002Fblob\u002Fmain\u002Fdocs\u002Fdeployment.md#a-publish-credential-for-github-actions-oidc-no-secret",[318],"deployment guide",[808,809,811],"h3",{"id":810},"logins-for-people","Logins for people",[304,813,795,814,816,817,819,820,822,823,829,830,833,834,837],{},[308,815,690],{}," or ",[308,818,703],{}," credential can also hold a ",[308,821,779],{}," secret, so that people use the CLI instead of copying tokens around:\n",[313,824,826],{"href":825},"\u002Fsystems\u002Fserverless-registry\u002Fsreg-cli#sreg-login",[308,827,828],{},"sreg login"," and the ",[308,831,832],{},"--login"," option open a page of the registry\n(",[308,835,836],{},"\u002Fauthorize\u002F...","), where you sign in (or, when the browser is already signed in, only approve) and the CLI receives a\nshort-lived signed token:",[683,839,840,850],{},[686,841,842,843,846,847,849],{},"a ",[449,844,845],{},"pull token"," lasts one hour, or ",[308,848,638],{}," hours when you tick \"extended validity\",",[686,851,842,852,855],{},[449,853,854],{},"publish token"," lasts 15 minutes and works only for the package versions you approved; it is issued only when the\ncredential's grants allow every one of them, and with a one-time code a recent one is required.",[304,857,858,859,326],{},"Expiring the login secret ends its tokens and browser sessions. The Worker does not limit sign-in attempts - add a\nCloudFlare rate limiting rule for the path starting with ",[308,860,861],{},"\u002Fauthorize\u002F",[347,863,865],{"id":864},"admin-panel","Admin panel",[304,867,868],{},"Opening the registry in a browser shows a small panel, rendered by the Worker without any framework or external resources.",[808,870,872],{"id":871},"first-run","First run",[304,874,875,876,879],{},"While the registry has no credential at all, the page first checks the installation settings and lists any missing ones\n(with how to add them), then offers to create the first admin. Enter a project name, optionally choose a password\n(otherwise one is generated) and tick ",[449,877,878],{},"Require a one-time code"," to protect the login with an authenticator app.",[304,881,882],{},[883,884],"img",{"alt":872,"src":885},"\u002Fsystems\u002Fserverless-registry\u002Fpanel-first-run.png",[304,887,888,889,892],{},"The password is shown ",[449,890,891],{},"only once",", together with a QR code (and a link and a key) for the authenticator app when you\nasked for the code. Store it in a password manager. The form never appears again, and there is no password reset - consider\ncreating a second admin credential for a colleague.",[304,894,895],{},[883,896],{"alt":897,"src":898},"Admin created","\u002Fsystems\u002Fserverless-registry\u002Fpanel-admin-created.png",[808,900,901],{"id":779},"Login",[304,903,904,905,908,909,911],{},"The login page defaults to a login (the project name) and a password; ",[449,906,907],{},"Token"," is the other tab, for a ",[308,910,758],{}," secret.\nWith a one-time code the sign-in has two steps: the password, then the code from the authenticator app.\nA signed session cookie keeps you signed in for 12 hours.",[304,913,914],{},[883,915],{"alt":901,"src":916},"\u002Fsystems\u002Fserverless-registry\u002Fpanel-login.png",[304,918,919],{},[883,920],{"alt":921,"src":922},"One-time code","\u002Fsystems\u002Fserverless-registry\u002Fpanel-login-code.png",[808,924,926],{"id":925},"approving-cli-operations","Approving CLI operations",[304,928,929,930,932,933,935,936,938],{},"When a CLI command runs with ",[308,931,832],{}," (or ",[308,934,828],{},"), the page it prints shows exactly what is requested -\na pull token, or a publish token for named package versions. Sign in with a ",[308,937,779],{}," secret, or just approve when you are\nalready signed in:",[304,940,941],{},[883,942],{"alt":943,"src":944},"Sign in to approve a CLI operation","\u002Fsystems\u002Fserverless-registry\u002Fpanel-authorize-signin.png",[304,946,947],{},[883,948],{"alt":949,"src":950},"Approve a publish token for one version","\u002Fsystems\u002Fserverless-registry\u002Fpanel-authorize-approve.png",[808,952,954,955,957],{"id":953},"browsing-packages-read-credentials","Browsing packages (",[308,956,690],{}," credentials)",[304,959,795,960,962],{},[308,961,690],{}," credential sees every package its grants cover, with an ecosystem badge, the number of versions and the latest version.\nA filter bar narrows the list by name and ecosystem.",[304,964,965],{},[883,966],{"alt":967,"src":968},"Packages visible to a read credential","\u002Fsystems\u002Fserverless-registry\u002Fpanel-packages-read.png",[304,970,971,972,975],{},"A package page lists its versions and has ready-to-paste client configuration with copy buttons\n(a command, files or environment variables - pick one with the chooser). Replace ",[308,973,974],{},"\u003Ctoken>"," with your token.",[304,977,978],{},[883,979],{"alt":980,"src":981},"Package page with client configuration","\u002Fsystems\u002Fserverless-registry\u002Fpanel-package.png",[304,983,984],{},"A version page lists its files with sizes and checksums, downloads them through a short-lived presigned link\nand shows how to install exactly that version.",[304,986,987],{},[883,988],{"alt":989,"src":990},"Version page","\u002Fsystems\u002Fserverless-registry\u002Fpanel-version.png",[808,992,994,995,957],{"id":993},"administration-admin-credentials","Administration (",[308,996,713],{},[304,998,999],{},"An admin gets three pages in the header.",[304,1001,1002,1005,1006,452,1009,1012],{},[449,1003,1004],{},"Packages"," - the same list with ",[382,1007,1008],{},"Reindex",[382,1010,1011],{},"Delete"," on each row; a package's page also lets you yank or delete its versions.",[304,1014,1015],{},[883,1016],{"alt":1017,"src":1018},"Packages (admin)","\u002Fsystems\u002Fserverless-registry\u002Fpanel-admin-packages.png",[304,1020,1021,1024,1025,1028],{},[449,1022,1023],{},"Credentials"," - every project in a table, plus a ",[382,1026,1027],{},"New credential"," form that shows the new token once.",[304,1030,1031],{},[883,1032],{"alt":1023,"src":1033},"\u002Fsystems\u002Fserverless-registry\u002Fpanel-admin-credentials.png",[304,1035,1036,1037,520,1039,520,1042,452,1045,1048,1049,1051,1052,1055],{},"A credential has the tabs ",[382,1038,10],{},[382,1040,1041],{},"Grants",[382,1043,1044],{},"Secrets",[382,1046,1047],{},"Danger zone",". Grants are an ecosystem, a package name or\n",[308,1050,720],{}," pattern and a version constraint in that ecosystem's syntax; ",[382,1053,1054],{},"Edit as text"," shows them one per line to copy and paste in bulk:",[304,1057,1058],{},[883,1059],{"alt":1060,"src":1061},"Credential grants","\u002Fsystems\u002Fserverless-registry\u002Fpanel-credential-grants.png",[304,1063,1064,1065,1067,1068,1070,1071,1073],{},"Secrets are ",[308,1066,758],{}," tokens, ",[308,1069,779],{}," passwords (with an optional one-time code) or GitHub Actions ",[308,1072,789],{}," entries (OIDC) that trust a repository, optionally restricted to a ref, workflow or environment. Each can have a description, be edited and be expired individually. A new secret's token or password is shown once:",[304,1075,1076],{},[883,1077],{"alt":1078,"src":1079},"Credential secrets","\u002Fsystems\u002Fserverless-registry\u002Fpanel-credential-secrets.png",[304,1081,1082,1084,1085,520,1088,816,1091,1093,1094,1096,1097,1100,1101,1104],{},[449,1083,465],{}," - the running version, a setup checklist with every installation setting as ",[382,1086,1087],{},"Set",[382,1089,1090],{},"Missing",[382,1092,560],{}," (secret values are never shown) and, unless ",[308,1095,652],{}," is ",[308,1098,1099],{},"false",", whether a newer release exists. While one exists, admins also see an ",[449,1102,1103],{},"Update available"," flag in the header of every page.",[304,1106,1107],{},[883,1108],{"alt":465,"src":1109},"\u002Fsystems\u002Fserverless-registry\u002Fpanel-settings.png",[347,1111,446],{"id":1112},"updating",[304,1114,1115,1116,1118,1119,1121,1122,1125],{},"The Settings page and the ",[449,1117,1103],{}," flag tell you when a newer release exists. The easiest way to update is the\n",[449,1120,451],{}," workflow of your own repository (",[382,1123,1124],{},"Actions"," tab):",[355,1127,1128,1138],{},[358,1129,1130],{},[361,1131,1132,1135],{},[364,1133,1134],{},"Input",[364,1136,1137],{},"Meaning",[374,1139,1140,1167,1183],{},[361,1141,1142,1147],{},[379,1143,1144],{},[308,1145,1146],{},"channel",[379,1148,1149,1152,1153,1156,1157,1160,1161,1164,1165,546],{},[308,1150,1151],{},"stable"," (newest release), ",[308,1154,1155],{},"prerelease"," (betas included), ",[308,1158,1159],{},"custom"," (a tag) or ",[308,1162,1163],{},"develop"," (upstream's ",[308,1166,393],{},[361,1168,1169,1174],{},[379,1170,1171],{},[308,1172,1173],{},"tag",[379,1175,1176,1177,1179,1180,326],{},"Only for ",[308,1178,1159],{},": a release tag such as ",[308,1181,1182],{},"v0.2.0",[361,1184,1185,1190],{},[379,1186,1187],{},[308,1188,1189],{},"dry_run",[379,1191,1192],{},"Show the change in the run's summary without pushing.",[304,1194,1195,1196,1198,1199,1202,1203,1206,1207,326],{},"It never goes to an older version than your repository has, keeps your own bindings, name, routes and variables when\n",[308,1197,426],{}," conflicts, checks the result with ",[308,1200,1201],{},"wrangler deploy --dry-run"," and pushes to the default branch, which deploys.\nFiles of ",[308,1204,1205],{},".github\u002Fworkflows"," are updated only when you save a token as the repository secret ",[308,1208,1209],{},"UPDATE_TOKEN",[304,1211,1212,1213,1215,1216,1219,1220,520,1223,816,1226,1229,1230,1232],{},"The ",[449,1214,455],{}," workflow writes the R2 bucket (including its ",[308,1217,1218],{},"jurisdiction",": ",[308,1221,1222],{},"eu",[308,1224,1225],{},"fedramp",[308,1227,1228],{},"none","),\nKV namespace, Worker name and custom domain into ",[308,1231,426],{}," from a form, so that deploys and updates keep them.\nA bucket created in a jurisdiction needs it in the binding, otherwise a deploy binds the Worker to another, empty bucket.",[304,1234,1235,1236,1239,1240,1243,1244,326],{},"Read the changelog before updating: entries marked ",[449,1237,1238],{},"Breaking"," need something from you and ",[449,1241,1242],{},"Requires migration"," entries run\nautomatically on the first request after the deploy. Details, manual update paths and rollback are in the\n",[313,1245,806],{"href":1246,":target":316,"rel":1247},"https:\u002F\u002Fgithub.com\u002Fkduma-OSS\u002Fserverless-registry-worker\u002Fblob\u002Fmain\u002Fdocs\u002Fdeployment.md#7-updating",[318],[808,1249,1251],{"id":1250},"protection-against-a-wrong-r2-bucket","Protection against a wrong R2 bucket",[304,1253,1254,1255,1258,1259,1262,1263,326],{},"The Worker remembers an installation id in KV and in the bucket. When a deploy binds it to another or a new bucket, the\npackage and publish endpoints answer ",[308,1256,1257],{},"503 bucket_mismatch"," instead of working on the wrong bucket (nothing is published into\nit, nothing looks deleted), and the panel shows a banner. Fix the binding and deploy again; only if the bucket really is the\nnew one, an admin confirms it with ",[449,1260,1261],{},"Use this bucket",". See\n",[313,1264,1267],{"href":1265,":target":316,"rel":1266},"https:\u002F\u002Fgithub.com\u002Fkduma-OSS\u002Fserverless-registry-worker\u002Fblob\u002Fmain\u002Fdocs\u002Fdeployment.md#10-troubleshooting",[318],"troubleshooting",[347,1269,1271],{"id":1270},"operations","Operations",[304,1273,1274,1275,520,1278,1281],{},"The deployment guide also covers the free plan limits, backups and troubleshooting (",[308,1276,1277],{},"401",[308,1279,1280],{},"426 client_too_old",", presigning errors).",[347,1283,1285],{"id":1284},"compatibility","Compatibility",[304,1287,1288,1289,1291,1292,1295,1296,1299,1300,1302,1303,1306],{},"The Worker and ",[308,1290,707],{}," are released independently. The Worker answers with the oldest accepted client in\n",[308,1293,1294],{},"X-Min-Client-Version"," and rejects older ones with ",[308,1297,1298],{},"426"," (",[308,1301,707],{}," exit code ",[308,1304,1305],{},"3","). The previous API version is kept\nfor at least one minor release after an incompatible change.",[347,1308,1310],{"id":1309},"documentation","Documentation",[683,1312,1313,1320,1327],{},[686,1314,1315],{},[313,1316,1319],{"href":1317,":target":316,"rel":1318},"https:\u002F\u002Fgithub.com\u002Fkduma-OSS\u002Fserverless-registry-worker\u002Fblob\u002Fmain\u002Fdocs\u002Fspec.md",[318],"Specification",[686,1321,1322],{},[313,1323,1326],{"href":1324,":target":316,"rel":1325},"https:\u002F\u002Fgithub.com\u002Fkduma-OSS\u002Fserverless-registry-worker\u002Fblob\u002Fmain\u002Fdocs\u002Fapi.md",[318],"HTTP API contract",[686,1328,1329],{},[313,1330,340],{"href":338,":target":316,"rel":1331},[318],{"title":1333,"searchDepth":1334,"depth":1334,"links":1335},"",2,[1336,1337,1338,1342,1351,1354,1355,1356],{"id":349,"depth":1334,"text":350},{"id":458,"depth":1334,"text":459},{"id":677,"depth":1334,"text":678,"children":1339},[1340],{"id":810,"depth":1341,"text":811},3,{"id":864,"depth":1334,"text":865,"children":1343},[1344,1345,1346,1347,1349],{"id":871,"depth":1341,"text":872},{"id":779,"depth":1341,"text":901},{"id":925,"depth":1341,"text":926},{"id":953,"depth":1341,"text":1348},"Browsing packages (read credentials)",{"id":993,"depth":1341,"text":1350},"Administration (admin credentials)",{"id":1112,"depth":1334,"text":446,"children":1352},[1353],{"id":1250,"depth":1341,"text":1251},{"id":1270,"depth":1334,"text":1271},{"id":1284,"depth":1334,"text":1285},{"id":1309,"depth":1334,"text":1310},"CloudFlare Worker serving a private package registry for Composer, npm, cargo, NuGet, Swift, Maven and generic files.","md",null,{},{"title":18},{"title":298,"description":1357},"app","idQSRmr1DilJRXvcK7opV5wJcyqkThRiFBjtXgloKg8",[1366,1368],{"title":10,"path":13,"stem":14,"description":1367,"children":-1},"Solution for hosting a private package registry for Composer, npm, cargo, NuGet, Swift, Maven and generic files without running any servers.",{"title":22,"path":23,"stem":24,"description":1369,"children":-1},"Command line tool for publishing packages to Serverless Registry and writing package manager credentials.",1793220976332]