\documentclass[10pt,a4paper]{article} % Packages \usepackage{fancyhdr} % For header and footer \usepackage{multicol} % Allows multicols in tables \usepackage{tabularx} % Intelligent column widths \usepackage{tabulary} % Used in header and footer \usepackage{hhline} % Border under tables \usepackage{graphicx} % For images \usepackage{xcolor} % For hex colours %\usepackage[utf8x]{inputenc} % For unicode character support \usepackage[T1]{fontenc} % Without this we get weird character replacements \usepackage{colortbl} % For coloured tables \usepackage{setspace} % For line height \usepackage{lastpage} % Needed for total page number \usepackage{seqsplit} % Splits long words. %\usepackage{opensans} % Can't make this work so far. Shame. Would be lovely. \usepackage[normalem]{ulem} % For underlining links % Most of the following are not required for the majority % of cheat sheets but are needed for some symbol support. \usepackage{amsmath} % Symbols \usepackage{MnSymbol} % Symbols \usepackage{wasysym} % Symbols %\usepackage[english,german,french,spanish,italian]{babel} % Languages % Document Info \author{sigrid (sigrid-hal9)} \pdfinfo{ /Title (deploy-from-ci-tokens-and-commands-for-7-hosts.pdf) /Creator (Cheatography) /Author (sigrid (sigrid-hal9)) /Subject (Deploy from CI: tokens \& commands for 7 hosts Cheat Sheet) } % Lengths and widths \addtolength{\textwidth}{6cm} \addtolength{\textheight}{-1cm} \addtolength{\hoffset}{-3cm} \addtolength{\voffset}{-2cm} \setlength{\tabcolsep}{0.2cm} % Space between columns \setlength{\headsep}{-12pt} % Reduce space between header and content \setlength{\headheight}{85pt} % If less, LaTeX automatically increases it \renewcommand{\footrulewidth}{0pt} % Remove footer line \renewcommand{\headrulewidth}{0pt} % Remove header line \renewcommand{\seqinsert}{\ifmmode\allowbreak\else\-\fi} % Hyphens in seqsplit % This two commands together give roughly % the right line height in the tables \renewcommand{\arraystretch}{1.3} \onehalfspacing % Commands \newcommand{\SetRowColor}[1]{\noalign{\gdef\RowColorName{#1}}\rowcolor{\RowColorName}} % Shortcut for row colour \newcommand{\mymulticolumn}[3]{\multicolumn{#1}{>{\columncolor{\RowColorName}}#2}{#3}} % For coloured multi-cols \newcolumntype{x}[1]{>{\raggedright}p{#1}} % New column types for ragged-right paragraph columns \newcommand{\tn}{\tabularnewline} % Required as custom column type in use % Font and Colours \definecolor{HeadBackground}{HTML}{333333} \definecolor{FootBackground}{HTML}{666666} \definecolor{TextColor}{HTML}{333333} \definecolor{DarkBackground}{HTML}{7878F0} \definecolor{LightBackground}{HTML}{EEEEFD} \renewcommand{\familydefault}{\sfdefault} \color{TextColor} % Header and Footer \pagestyle{fancy} \fancyhead{} % Set header to blank \fancyfoot{} % Set footer to blank \fancyhead[L]{ \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{C} \SetRowColor{DarkBackground} \vspace{-7pt} {\parbox{\dimexpr\textwidth-2\fboxsep\relax}{\noindent \hspace*{-6pt}\includegraphics[width=5.8cm]{/web/www.cheatography.com/public/images/cheatography_logo.pdf}} } \end{tabulary} \columnbreak \begin{tabulary}{11cm}{L} \vspace{-2pt}\large{\bf{\textcolor{DarkBackground}{\textrm{Deploy from CI: tokens \& commands for 7 hosts Cheat Sheet}}}} \\ \normalsize{by \textcolor{DarkBackground}{sigrid (sigrid-hal9)} via \textcolor{DarkBackground}{\uline{cheatography.com/219283/cs/48542/}}} \end{tabulary} \end{multicols}} \fancyfoot[L]{ \footnotesize \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{LL} \SetRowColor{FootBackground} \mymulticolumn{2}{p{5.377cm}}{\bf\textcolor{white}{Cheatographer}} \\ \vspace{-2pt}sigrid (sigrid-hal9) \\ \uline{cheatography.com/sigrid-hal9} \\ \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Cheat Sheet}} \\ \vspace{-2pt}Published 28th October, 2026.\\ Updated 28th October, 2026.\\ Page {\thepage} of \pageref{LastPage}. \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Sponsor}} \\ \SetRowColor{white} \vspace{-5pt} %\includegraphics[width=48px,height=48px]{dave.jpeg} Measure your website readability!\\ www.readability-score.com \end{tabulary} \end{multicols}} \begin{document} \raggedright \raggedcolumns % Set font size to small. Switch to any value % from this page to resize cheat sheet text: % www.emerson.emory.edu/services/latex/latex_169.html \footnotesize % Small font. \begin{tabularx}{17.67cm}{x{5.5264 cm} x{11.7436 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Create a token}} \tn % Row 0 \SetRowColor{LightBackground} \{\{width=14\}\}Railway & Project settings → Tokens. Account tokens: \seqsplit{railway.com/account/tokens} \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} Render & Dashboard → Account Settings → API key. Shown in full only once \tn % Row Count 6 (+ 3) % Row 2 \SetRowColor{LightBackground} Fly.io & \{\{noshy\}\}`fly tokens create deploy -a \textless{}app\textgreater{} -{}-name ci -{}-expiry 48h` (copy all of it, `FlyV1 ` prefix included) \tn % Row Count 11 (+ 5) % Row 3 \SetRowColor{white} Vercel & \seqsplit{vercel.com/account/tokens.} \{\{noshy\}\}`vercel tokens add "CI deploy"` works only if you already use a classic account token; a `vercel login` session can't make one \tn % Row Count 17 (+ 6) % Row 4 \SetRowColor{LightBackground} Heroku & \{\{noshy\}\}`heroku authorizations:create -d "ci" -e 86400 -S` (`-e` in seconds; no expiry if left out) \tn % Row Count 21 (+ 4) % Row 5 \SetRowColor{white} \seqsplit{DigitalOcean} & \seqsplit{cloud.digitalocean.com/account/api/tokens} \tn % Row Count 23 (+ 2) % Row 6 \SetRowColor{LightBackground} Cloudish & \{\{noshy\}\}`POST /api/v1/keys` (cloudish.ai), no credential needed (see the Cloudish block) \tn % Row Count 27 (+ 4) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{3.374 cm} x{6.4106 cm} x{7.0854 cm} } \SetRowColor{DarkBackground} \mymulticolumn{3}{x{17.67cm}}{\bf\textcolor{white}{Give the token to your script}} \tn % Row 0 \SetRowColor{LightBackground} \{\{width=14\}\}Railway & \{\{noshy\}\}`RAILWAY\_TOKEN` & Project token: one environment in one project \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} Railway & \{\{noshy\}\}`RAILWAY\_API\_TOKEN` & Account token (broadest) or workspace token (one workspace) \tn % Row Count 7 (+ 4) % Row 2 \SetRowColor{LightBackground} Render & \{\{noshy\}\}`RENDER\_API\_KEY` & API key. Unlike `render login` tokens, it doesn't expire on its own \tn % Row Count 12 (+ 5) % Row 3 \SetRowColor{white} Fly.io & \{\{noshy\}\}`FLY\_API\_TOKEN` & A deploy token covers one app \tn % Row Count 14 (+ 2) % Row 4 \SetRowColor{LightBackground} Vercel & \{\{noshy\}\}`VERCEL\_TOKEN` & A personal token from your account \tn % Row Count 17 (+ 3) % Row 5 \SetRowColor{white} Heroku & \{\{noshy\}\}`HEROKU\_API\_KEY` & Overrides the token saved by `heroku login` \tn % Row Count 20 (+ 3) % Row 6 \SetRowColor{LightBackground} \seqsplit{DigitalOcean} & \{\{noshy\}\}`DIGITALOCEAN\_ACCESS\_TOKEN` & An API token; or pass \{\{noshy\}\}`-{}-access-token` per command \tn % Row Count 24 (+ 4) % Row 7 \SetRowColor{white} \seqsplit{Cloudish} & \{\{noshy\}\}`CLOUDISH\_API\_KEY` & One key; it can't spend past its prepaid balance \tn % Row Count 27 (+ 3) \hhline{>{\arrayrulecolor{DarkBackground}}---} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{5.5264 cm} x{11.7436 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{No browser on the machine?}} \tn % Row 0 \SetRowColor{LightBackground} \{\{width=14\}\}Railway & `railway login -{}-browserless` (for SSH sessions) \tn % Row Count 2 (+ 2) % Row 1 \SetRowColor{white} Render & Skip `login`; the token variable above is enough \tn % Row Count 4 (+ 2) % Row 2 \SetRowColor{LightBackground} Fly.io & Skip `login`; the token variable above is enough \tn % Row Count 6 (+ 2) % Row 3 \SetRowColor{white} Vercel & Skip `login`; the token variable above is enough \tn % Row Count 8 (+ 2) % Row 4 \SetRowColor{LightBackground} Heroku & Skip `login`; the token variable above is enough \tn % Row Count 10 (+ 2) % Row 5 \SetRowColor{white} \seqsplit{DigitalOcean} & With \{\{noshy\}\}`DIGITALOCEAN\_ACCESS\_TOKEN` set, `doctl auth init` saves it with no prompt \tn % Row Count 14 (+ 4) % Row 6 \SetRowColor{LightBackground} Cloudish & Nothing to log in to: the first call returns the key \tn % Row Count 16 (+ 2) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{5.5264 cm} x{11.7436 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Deploy}} \tn % Row 0 \SetRowColor{LightBackground} \{\{width=14\}\}Railway & \{\{noshy\}\}`RAILWAY\_TOKEN=xxx railway up` (add \{\{noshy\}\}`-{}-ci` to stream only build logs and exit when the build completes) \tn % Row Count 5 (+ 5) % Row 1 \SetRowColor{white} Render & \{\{noshy\}\}`render deploys create \textless{}service-id\textgreater{} -{}-output json -{}-confirm -{}-wait` \tn % Row Count 8 (+ 3) % Row 2 \SetRowColor{LightBackground} Fly.io & `fly deploy` (uses the settings in `fly.toml`; builds remotely by default) \tn % Row Count 11 (+ 3) % Row 3 \SetRowColor{white} Vercel & \{\{noshy\}\}`vercel deploy -{}-prod -{}-yes \textgreater{} url.txt` (stdout is the deploy URL) \tn % Row Count 14 (+ 3) % Row 4 \SetRowColor{LightBackground} Heroku & \{\{noshy\}\}`heroku container:login`, then `heroku container:push web -a \textless{}app\textgreater{}`, then `heroku container:release web -a \textless{}app\textgreater{}` \tn % Row Count 19 (+ 5) % Row 5 \SetRowColor{white} \seqsplit{DigitalOcean} & First time: \{\{noshy\}\}`doctl apps create -{}-spec app.yaml -{}-wait`. Later: `doctl apps create-deployment \textless{}app-id\textgreater{} -{}-wait` \tn % Row Count 24 (+ 5) % Row 6 \SetRowColor{LightBackground} Cloudish & \{\{noshy\}\}`POST /api/v1/projects` (cloudish.ai) with a tar.gz of the folder (see the Cloudish block) \tn % Row Count 28 (+ 4) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{5.5264 cm} x{11.7436 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Did it work?}} \tn % Row 0 \SetRowColor{LightBackground} \{\{width=14\}\}Railway & `railway up` exits `0` when the deploy reaches `SUCCESS`, `1` if it fails. `-{}-ci` exits once the build completes. With `-{}-detach`: poll `railway deployment list -{}-json` \tn % Row Count 7 (+ 7) % Row 1 \SetRowColor{white} Render & `-{}-wait` blocks; a failed deploy exits non-zero \tn % Row Count 9 (+ 2) % Row 2 \SetRowColor{LightBackground} Fly.io & Watches the deploy until the machines are healthy (-{}-wait-timeout, default 5 min); -{}-detach returns at once. Then: \{\{noshy\}\}`fly status -a \textless{}app\textgreater{}` \tn % Row Count 15 (+ 6) % Row 3 \SetRowColor{white} Vercel & Exit code not `0` = error; read stderr \tn % Row Count 17 (+ 2) % Row 4 \SetRowColor{LightBackground} Heroku & No wait flag. Check \{\{noshy\}\}`heroku releases -a \textless{}app\textgreater{}` and `heroku ps -a \textless{}app\textgreater{}` \tn % Row Count 20 (+ 3) % Row 5 \SetRowColor{white} \seqsplit{DigitalOcean} & `-{}-wait` gives up after 30 min by default (`-{}-wait-timeout 1h` for longer); the deploy itself keeps running \tn % Row Count 24 (+ 4) % Row 6 \SetRowColor{LightBackground} Cloudish & Poll \{\{noshy\}\}`GET /api/v1/images/builds/\textless{}id\textgreater{}` until `status` is `succeeded` or `failed` \tn % Row Count 28 (+ 4) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{5.5264 cm} x{11.7436 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Read logs}} \tn % Row 0 \SetRowColor{LightBackground} \{\{width=14\}\}Railway & `railway logs` · build: \{\{noshy\}\}`railway logs -{}-build` · last 100: `railway logs -n 100` \tn % Row Count 4 (+ 4) % Row 1 \SetRowColor{white} Render & \{\{noshy\}\}`render logs -{}-resources \textless{}service-id\textgreater{} -{}-tail` (`-{}-resources` is required in scripts) \tn % Row Count 8 (+ 4) % Row 2 \SetRowColor{LightBackground} Fly.io & \{\{noshy\}\}`fly logs -a \textless{}app\textgreater{}` streams; `-{}-no-tail` prints the buffer and exits \tn % Row Count 11 (+ 3) % Row 3 \SetRowColor{white} Vercel & \{\{noshy\}\}`vercel logs -{}-deployment \textless{}url-or-id\textgreater{} -{}-json` (default: last 30 min, 100 records) \tn % Row Count 15 (+ 4) % Row 4 \SetRowColor{LightBackground} Heroku & \{\{noshy\}\}`heroku logs -{}-tail -a \textless{}app\textgreater{}` · `heroku logs -n 200 -a \textless{}app\textgreater{}` (Cedar apps, the generation before Fir: up to 1,500 lines) \tn % Row Count 20 (+ 5) % Row 5 \SetRowColor{white} \seqsplit{DigitalOcean} & \{\{noshy\}\}`doctl apps logs \textless{}app-id\textgreater{} web -{}-type build` (`build`, `deploy` or `run`; add `-{}-follow` to stream) \tn % Row Count 24 (+ 4) % Row 6 \SetRowColor{LightBackground} Cloudish & \{\{noshy\}\}`GET /api/v1/docker/\textless{}alias\textgreater{}/\textless{}app\textgreater{}/logs` \tn % Row Count 26 (+ 2) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Cloudish: the whole flow in curl}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{17.67cm}}{\# 1. Get a key. No account, card or browser. \newline curl -X POST \$API/keys \textbackslash{} \newline -H "content-type: application/json" \textbackslash{} \newline -d '\{"alias": "my-app"\}' \newline \# -\textgreater{} "key": "cld\_...", "apiKey": \{"alias": ...\} \newline export \seqsplit{CLOUDISH\_API\_KEY=cld\_...} \newline \# Keep the key out of chat and logs. \newline ALIAS=my-app \# the apiKey.alias in the answer \newline AUTH="Authorization: Bearer \$CLOUDISH\_API\_KEY" \newline \newline \# 2. Pack the folder (Dockerfile at its root), \newline \# minus secrets. \newline tar -{}-exclude='.env*' -{}-exclude='.git' \textbackslash{} \newline -czf context.tar.gz . \newline \newline \# 3. Build on Cloudish's servers and deploy. \newline \# No local Docker. \newline curl -X POST \$API/projects -H "\$AUTH" \textbackslash{} \newline -F name=my-app -F port=8080 \textbackslash{} \newline -F context=@context.tar.gz \newline \# -\textgreater{} "build": \{"id": 123, "status": "pending"\} \newline \newline \# 4. Wait for the build, then URL and logs. \newline curl \$API/images/builds/123 -H "\$AUTH" \newline curl \seqsplit{\$API/projects/\$ALIAS/my-app} -H "\$AUTH" \newline \# The URL is in subdomain.url. \newline curl \seqsplit{\$API/docker/\$ALIAS/my-app/logs} -H "\$AUTH"} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Cloudish errors you'll meet}} \tn % Row 0 \SetRowColor{LightBackground} `503` "nothing accepts connections on port …" & `port` doesn't match the port your server listens on (default `8080`) \tn % Row Count 4 (+ 4) % Row 1 \SetRowColor{white} "Job has reached the specified backoff limit" & The build most likely ran out of CPU or memory; retry with `buildCpuCores` / `buildMemoryGb` \tn % Row Count 9 (+ 5) % Row 2 \SetRowColor{LightBackground} `402` & The key's balance is zero. Builds and deploys answer `402`; running apps stop within a minute, volumes kept \tn % Row Count 15 (+ 6) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{5.5264 cm} x{11.7436 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Gotchas by host}} \tn % Row 0 \SetRowColor{LightBackground} \{\{width=14\}\}Railway & A script never creates a project on its own. Link one first (`railway up -{}-new` creates one), or the run fails with `NOT\_AUTHENTICATED` or a no-project error \tn % Row Count 6 (+ 6) % Row 1 \SetRowColor{white} Railway & Set only one of \{\{noshy\}\}`RAILWAY\_TOKEN` and \{\{noshy\}\}`RAILWAY\_API\_TOKEN`; both at once is an error \tn % Row Count 10 (+ 4) % Row 2 \SetRowColor{LightBackground} Railway & Raw API calls with a project token use the `Project-Access-Token` header, not `Authorization: Bearer` \tn % Row Count 14 (+ 4) % Row 3 \SetRowColor{white} Fly.io & Deploy tokens last 20 years unless you set `-{}-expiry` \tn % Row Count 16 (+ 2) % Row 4 \SetRowColor{LightBackground} Vercel & If `-{}-token` and \{\{noshy\}\}`VERCEL\_TOKEN` are both set, the flag wins \tn % Row Count 19 (+ 3) % Row 5 \SetRowColor{white} Heroku & \{\{noshy\}\}`container:push` needs Docker on your machine. Heroku documents this flow for Cedar-generation apps only \tn % Row Count 24 (+ 5) % Row 6 \SetRowColor{LightBackground} Heroku & \{\{noshy\}\}`heroku auth:token` gives a token valid for 1 year; use `authorizations:create` for CI \tn % Row Count 28 (+ 4) % Row 7 \SetRowColor{white} \seqsplit{DigitalOcean} & \{\{noshy\}\}`doctl apps create` needs App Platform to have access to your repo \tn % Row Count 31 (+ 3) \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{5.5264 cm} x{11.7436 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Gotchas by host (cont)}} \tn % Row 8 \SetRowColor{LightBackground} Cloudish & The \{\{noshy\}\}`claimUrl` (which lets a person take over the key) works once and expires in 30 minutes \tn % Row Count 4 (+ 4) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Keep tokens safe}} \tn \SetRowColor{white} \mymulticolumn{1}{x{17.67cm}}{- Put the token in an environment variable, not a flag. Vercel's docs warn that command-line arguments "can be visible in process lists and logs". \newline % Row Count 3 (+ 3) - Pick the narrowest token: a Railway project token over an account token, a Fly deploy token over an org token. \newline % Row Count 6 (+ 3) - Give it an end date: Fly `-{}-expiry 48h`, Heroku `-e 86400`. Render API keys don't expire on their own, so revoke them in the dashboard when done. \newline % Row Count 9 (+ 3) - Revoke: `fly tokens list`, then `fly tokens revoke \textless{}id\textgreater{}`. Vercel: `vercel tokens rm \textless{}id\textgreater{}`. \newline % Row Count 11 (+ 2) - Never paste a key into chat, code or logs, and keep `.env` files out of anything you upload.% Row Count 13 (+ 2) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{x{8.635 cm} x{8.635 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{17.67cm}}{\bf\textcolor{white}{Which host fits}} \tn % Row 0 \SetRowColor{LightBackground} \{\{width=25\}\}You need a fully automated workflow & Cloudish: the only one of the seven where the script creates its own key. On the others, a person signs up and makes the token first. (Without an account, a person can still try two others: vercel deploy -{}-temporary puts a folder online, not in CI, until someone claims it; ssh railway.new gives a Linux VM to claim within 24 hours.) \tn % Row Count 17 (+ 17) % Row 1 \SetRowColor{white} You need a managed Postgres database & Railway (`railway add -{}-database postgres`) or Render (Render Postgres). Cloudish has none; you run the database inside your container on a volume \tn % Row Count 25 (+ 8) % Row 2 \SetRowColor{LightBackground} A person iterates on a frontend app & Vercel \tn % Row Count 27 (+ 2) \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Sources (as of 2026-10-26)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{17.67cm}}{\{\{noshy\}\}- Railway: \{\{link="https://docs.railway.com/cli"\}\}CLI\{\{/link\}\} · \{\{link="https://docs.railway.com/cli/up"\}\}up\{\{/link\}\} · \{\{link="https://docs.railway.com/cli/login"\}\}login\{\{/link\}\} · \{\{link="https://docs.railway.com/integrations/api"\}\}API\{\{/link\}\} · \{\{link="https://docs.railway.com/pricing/free-trial"\}\}free trial\{\{/link\}\} \newline % Row Count 7 (+ 7) - Render: \{\{link="https://render.com/docs/cli"\}\}CLI\{\{/link\}\} · \{\{link="https://render.com/docs/cli-reference"\}\}CLI reference\{\{/link\}\} · \{\{link="https://render.com/docs/api"\}\}API\{\{/link\}\} \newline % Row Count 11 (+ 4) - Fly.io: \{\{link="https://docs.fly.io/security/tokens"\}\}tokens\{\{/link\}\} · \{\{link="https://docs.fly.io/launch/continuous-deployment-with-github-actions"\}\}GitHub Actions\{\{/link\}\} · \{\{link="https://docs.fly.io/flyctl/deploy"\}\}fly deploy\{\{/link\}\} · \{\{link="https://docs.fly.io/flyctl/logs"\}\}fly logs\{\{/link\}\} \newline % Row Count 18 (+ 7) - Vercel: \{\{link="https://vercel.com/docs/cli"\}\}CLI\{\{/link\}\} · \{\{link="https://vercel.com/docs/cli/deploy"\}\}deploy\{\{/link\}\} · \{\{link="https://vercel.com/docs/cli/logs"\}\}logs\{\{/link\}\} · \{\{link="https://vercel.com/docs/cli/global-options"\}\}global options\{\{/link\}\} \newline % Row Count 24 (+ 6) - Heroku: \{\{link="https://devcenter.heroku.com/articles/authentication"\}\}authentication\{\{/link\}\} · \{\{link="https://devcenter.heroku.com/articles/heroku-cli-commands"\}\}CLI commands\{\{/link\}\} · \{\{link="https://devcenter.heroku.com/articles/container-registry-and-runtime"\}\}container registry\{\{/link\}\} · \{\{link="https://devcenter.heroku.com/articles/logging"\}\}logging\{\{/link\}\} · \{\{link="https://devcenter.heroku.com/articles/generations"\}\}generations\{\{/link\}\} \newline % Row Count 34 (+ 10) } \tn \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Sources (as of 2026-10-26) (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{17.67cm}}{- DigitalOcean: \{\{link="https://docs.digitalocean.com/reference/doctl/reference/auth/init/"\}\}auth init\{\{/link\}\} · \{\{link="https://docs.digitalocean.com/reference/doctl/reference/apps/create/"\}\}apps create\{\{/link\}\} · \{\{link="https://docs.digitalocean.com/reference/doctl/reference/apps/create-deployment/"\}\}create-deployment\{\{/link\}\} · \{\{link="https://docs.digitalocean.com/reference/doctl/reference/apps/logs/"\}\}apps logs\{\{/link\}\} \newline % Row Count 9 (+ 9) - Cloudish: \{\{link="https://cloudish.ai/skill.md?ref=cc-s101a1"\}\}skill.md\{\{/link\}\} · \{\{link="https://cloudish.ai/llms.txt?ref=cc-s101a1"\}\}llms.txt\{\{/link\}\} \newline % Row Count 13 (+ 4) Made by Cloudish (\{\{link="https://cloudish.ai/?ref=cc-s101a1"\}\}cloudish.ai/\{\{/link\}\}), by Hal9 (\{\{link="https://hal9.com/"\}\}hal9.com/\{\{/link\}\}). Cloudish is one of the seven hosts on this sheet. Spotted something out of date? Leave a comment.% Row Count 18 (+ 5) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \end{document}