| 1 | # Object storage |
| 2 | |
| 3 | Uploads, generated files, anything your app wants to still have next week — |
| 4 | none of it belongs on the box's local disk, because the process that wrote |
| 5 | it there is not guaranteed to be the one serving your next request. Each app |
| 6 | can have a bucket of its own instead, and the credentials for it arrive in |
| 7 | your process as environment variables. |
| 8 | |
| 9 | ```sh |
| 10 | carlos store create -app hello |
| 11 | ``` |
| 12 | |
| 13 | That records the request and nothing more. No bucket exists yet: creating |
| 14 | declares that the app wants one, and provisioning is a step on the Carloku |
| 15 | side. `carlos store status` is where you watch for it landing. |
| 16 | |
| 17 | ## What your app ends up with |
| 18 | |
| 19 | Five variables under a prefix, `CARLOS_STORE` unless you name another: |
| 20 | `CARLOS_STORE_BUCKET`, `_REGION`, `_ACCESS_KEY` and `_SECRET_KEY`, plus |
| 21 | `_ENDPOINT` where the backend has one. Your app reads them like any other |
| 22 | config and talks to the bucket directly, with whichever S3 client its |
| 23 | language already has. Nothing proxies that traffic. |
| 24 | |
| 25 | The bucket, region and endpoint are ordinary values — `carlos env list` will |
| 26 | show them to you. The two keys are delivered through the sealed store, so |
| 27 | they reach your process and stop being readable to anyone, including you. |
| 28 | [Env and secrets](/docs/config/) explains why that is one-way. |
| 29 | |
| 30 | If your app already expects a particular set of names, say so at create |
| 31 | time and skip the adapter code: |
| 32 | |
| 33 | ```sh |
| 34 | carlos store create -app hello -env-prefix BLOBS |
| 35 | ``` |
| 36 | |
| 37 | ## Watching it arrive |
| 38 | |
| 39 | ```sh |
| 40 | carlos store status -app hello |
| 41 | ``` |
| 42 | |
| 43 | You get what you declared, what was granted, and what was provisioned — |
| 44 | bucket, region, the user the credential belongs to, and the key id currently |
| 45 | in use. Two of its lines are worth knowing before you meet them. One says a |
| 46 | delivered variable has not reached your app's config yet. That is the |
| 47 | ordinary state for a few seconds after any change, and a problem only if it |
| 48 | persists. The other says a rotation was started and never finished. |
| 49 | |
| 50 | ## Rotating the key |
| 51 | |
| 52 | ```sh |
| 53 | carlos store rotate -app hello |
| 54 | ``` |
| 55 | |
| 56 | A fresh credential is minted and delivered, and the previous one keeps |
| 57 | working. Your app picks the new values up the way it picks up any config |
| 58 | change: the box rewrites the environment for the app's routes and cycles the |
| 59 | process, within seconds. Leaving the old key alive is the point of doing it |
| 60 | in two halves — an upload that started under it gets to finish, and a second |
| 61 | instance that has not converged yet keeps serving. |
| 62 | |
| 63 | Close the window when you are satisfied nothing is still using it: |
| 64 | |
| 65 | ```sh |
| 66 | carlos store rotate -finish -app hello |
| 67 | ``` |
| 68 | |
| 69 | Until you do, `status` keeps telling you a rotation is pending. |
| 70 | |
| 71 | One habit worth forming. The secret never appears at your terminal — rotate |
| 72 | prints the new key's id and that is the whole of what you see — so if the |
| 73 | value ever turns up somewhere it shouldn't, it came out of the app. Whatever |
| 74 | your app dumps at startup is the first place to look. |
| 75 | |
| 76 | [carlos store](https://carlosframework.com/docs/cli/#carlos-store) has the |
| 77 | sub-verbs and the rest of their flags. |
| 78 | |