You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Quickstart, monorepo-layout, deployment, 404, landing hero, root README,
AGENTS, and the bootstrap compose.env.tftpl comment now point users at
GitHub's "Use this template" button instead of fork-style clone language.
This is a template repository; forks create lineage we don't want.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
{ value: "0", label: "local Node or Bun installs" },
24
24
]}
25
25
>
26
-
Clone the [BoringStack monorepo](https://github.com/boringstack-xyz/boringstack),
27
-
run `./setup.sh --up`, and Compose starts Postgres, Valkey, api-dev (migrations +
26
+
Click **Use this template** on the [BoringStack monorepo](https://github.com/boringstack-xyz/boringstack),
27
+
clone your new repo, run `./setup.sh --up`, and Compose starts Postgres, Valkey, api-dev (migrations +
28
28
OpenAPI), and ui-dev (Vite on :3001 with generated client). Optional overlays:
29
29
Mailpit, Bull Board, observability, GlitchTip.
30
30
</PageIntro>
@@ -46,8 +46,8 @@ import FaqItem from "../../components/FaqItem.tsx";
46
46
items={[
47
47
{
48
48
label: "01",
49
-
title: "Clone the monorepo",
50
-
body: "One repo contains apps/api, apps/ui, infra/compose, and apps/docs.",
49
+
title: "Use this template",
50
+
body: "Click \"Use this template\" on GitHub, then clone the new repo created under your org.",
51
51
},
52
52
{
53
53
label: "02",
@@ -75,14 +75,18 @@ You now have Postgres, Valkey, the API, and the UI running locally with hot relo
75
75
- About 4 GB of free RAM.
76
76
- No local Node or Bun needed for the default path; everything runs in containers.
77
77
78
-
## Step 1. Clone the monorepo
78
+
## Step 1. Use this template
79
+
80
+
The BoringStack monorepo is a [GitHub template repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template). On the [`boringstack-xyz/boringstack`](https://github.com/boringstack-xyz/boringstack) page, click **Use this template → Create a new repository** to make a fresh copy under your org with full ownership and no fork relationship.
Fork the monorepo on GitHub if you want your own copy under your org. API, UI, docs, Compose, and bootstrap infrastructure all live in this one tree.
89
+
API, UI, docs, Compose, and bootstrap infrastructure all live in this one tree. Run `bun run rename:project` from the root any time to rebrand the BoringStack identifiers across the codebase.
Copy file name to clipboardExpand all lines: apps/docs/src/content/docs/topics/deployment.mdx
+10-9Lines changed: 10 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
title: Deployment
3
-
description: Boring deployment. Single-host VPS, Docker, one monorepo fork, GHCR images, one prod profile. HTTPS via ACME, perimeter locked by Cloudflare.
3
+
description: Boring deployment. Single-host VPS, Docker, one repo created from the GitHub template, GHCR images, one prod profile. HTTPS via ACME, perimeter locked by Cloudflare.
@@ -23,8 +23,9 @@ import FaqItem from "../../../components/FaqItem.tsx";
23
23
]}
24
24
>
25
25
BoringStack runs on a VPS you control: Docker Compose, GHCR images, Traefik
26
-
TLS, and Cloudflare at the edge. Fork the monorepo, fill compose/.env, then
27
-
boot the production profile manually or let OpenTofu do first provisioning.
26
+
TLS, and Cloudflare at the edge. Use the GitHub template to create your repo,
27
+
fill compose/.env, then boot the production profile manually or let OpenTofu
28
+
do first provisioning.
28
29
</PageIntro>
29
30
30
31
## The mental model
@@ -81,15 +82,15 @@ Push to `main` with changes under `apps/api` or `apps/ui`. Path-filtered release
81
82
82
83
## First-time wiring
83
84
84
-
Three things need configuring before the first deploy. The release workflows handle everything else from your monorepo fork URL.
85
+
Three things need configuring before the first deploy. The release workflows handle everything else from your repo URL.
85
86
86
87
### 1. Publish images to GHCR
87
88
88
-
The API and UI release workflows run on push to `main` when their app paths change. They use `${{ github.event.repository.name }}` plus an app suffix, so a fork named `acme-stack` publishes `ghcr.io/<your-owner>/acme-stack-api:latest` and `ghcr.io/<your-owner>/acme-stack-ui:latest` automatically. The default `GITHUB_TOKEN` has `packages: write` via the workflow grant, so the first push from a freshly-forked repo works without secret setup.
89
+
The API and UI release workflows run on push to `main` when their app paths change. They use `${{ github.event.repository.name }}` plus an app suffix, so a repo named `acme-stack` publishes `ghcr.io/<your-owner>/acme-stack-api:latest` and `ghcr.io/<your-owner>/acme-stack-ui:latest` automatically. The default `GITHUB_TOKEN` has `packages: write` via the workflow grant, so the first push from a fresh template clone works without secret setup.
89
90
90
91
After the first publish, **make the GHCR package public** so the VPS can pull without credentials:
91
92
92
-
1. Go to the fork's Packages tab and open both containers: `<repo>-api` and `<repo>-ui`.
93
+
1. Go to your repo's Packages tab and open both containers: `<repo>-api` and `<repo>-ui`.
93
94
2. Package settings → Change visibility → Public.
94
95
95
96
Without this, downstream consumers (your VPS) need a pull credential.
@@ -122,7 +123,7 @@ The module derives `IMAGE_OWNER`, `API_IMAGE_NAME=<repo>-api`, and `UI_IMAGE_NAM
122
123
123
124
Use this once, after Quickstart and before the first production boot:
124
125
125
-
-[ ] BoringStack monorepo forked under your org/user.
126
+
-[ ]Repo created from the BoringStack template (**Use this template** on [`boringstack-xyz/boringstack`](https://github.com/boringstack-xyz/boringstack)) under your org/user.
126
127
-[ ] First API and UI images published to GHCR (push to `main`, then watch each Actions tab).
127
128
-[ ] GHCR packages set to **Public**, or the VPS has a pull credential.
128
129
-[ ]`compose/.env` has `IMAGE_OWNER` and any renamed `API_IMAGE_NAME` / `UI_IMAGE_NAME`.
@@ -132,7 +133,7 @@ Use this once, after Quickstart and before the first production boot:
132
133
-[ ][Firewall & TLS](/runbooks/firewall-and-tls/) verified: Cloudflare can reach the origin, direct requests cannot.
133
134
-[ ][Backups](/runbooks/backups/) configured and at least one restore drill run.
134
135
-[ ][Cloudflare Email setup](/runbooks/cloudflare-email-setup/) completed if Cloudflare is your outbound mail provider.
135
-
-[ ] Optional OpenTofu path: `terraform.tfvars` has fork URLs, real `domain`, and production secrets.
136
+
-[ ] Optional OpenTofu path: `terraform.tfvars` has your repo URL, real `domain`, and production secrets.
136
137
137
138
## First-time deploy
138
139
@@ -141,7 +142,7 @@ The preferred path is [Provisioning with OpenTofu](/topics/provisioning-with-tof
141
142
Manual path if you'd rather:
142
143
143
144
1. Provision a Ubuntu VPS with Docker installed.
144
-
2. Clone your monorepo fork onto the VPS.
145
+
2. Clone the repo you created from the template onto the VPS.
145
146
3. Write `compose/.env` with `PUBLIC_UI_HOST`, `ACME_EMAIL`, `IMAGE_OWNER`, and the rest from `.env.example`.
146
147
4.`STACK=prod ./scripts/compose-up.sh pull && STACK=prod ./scripts/compose-up.sh up -d`.
147
148
5. Run the [Firewall & TLS runbook](/runbooks/firewall-and-tls/) to verify Cloudflare-only ingress.
0 commit comments