Skip to content

Commit ab0f0b4

Browse files
committed
Update deploy docs
1 parent 48a6ef4 commit ab0f0b4

File tree

3 files changed

+179
-60
lines changed

3 files changed

+179
-60
lines changed

MyApp/_pages/kamal-deploy.md

Lines changed: 170 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,36 @@
22
title: Deploying with Kamal
33
---
44

5-
ServiceStack templates now support deployment using Kamal, a CLI tool from the BaseCamp team that simplifies containerized application deployments. Kamal wraps SSH and Docker to streamline self-hosting while maintaining GitHub Actions as the CI runner.
5+
All project templates includes the necessary GitHub Actions for CI/CD with automatic Docker image builds and
6+
production deployment with Kamal to any Linux server with SSH. Kamal is a CLI tool from the BaseCamp team that simplifies containerized application deployments, wrapping SSH and Docker to streamline self-hosting while maintaining GitHub Actions as the CI runner.
67

78
<lite-youtube class="w-full mx-4 my-4" width="560" height="315" videoid="-mDJfRG8mLQ" style="background-image: url('https://img.youtube.com/vi/-mDJfRG8mLQ/maxresdefault.jpg')"></lite-youtube>
89

910
## Overview
1011

1112
Kamal enables simple commands to deploy containerized applications to Linux hosts, handling:
12-
- Bootstrap configuration
13-
- Reverse proxy setup
14-
- SSL certificate provisioning
15-
- Zero-downtime deployments
16-
- Health checks on deploy
17-
- Rolling back changes
13+
- **Docker containerization** with optimized .NET images
14+
- **Bootstrap configuration**
15+
- **Reverse proxy setup**
16+
- **SSL auto-certification** via Let's Encrypt
17+
- **Zero-downtime deployments**
18+
- **Health checks on deploy**
19+
- **Rolling back changes**
20+
- **Volume persistence** for App_Data including any SQLite database
21+
- **GitHub Container Registry** integration
1822

1923
::: info
20-
Kamal is built by the BaseCamp team, developers of Hey email service and BaseCamp project management tool. For comprehensive documentation on all Kamal features, visit [https://kamal-deploy.org/](https://kamal-deploy.org/)
24+
Kamal is built by the BaseCamp team, developers of Hey.com and BaseCamp.com. For comprehensive documentation on all Kamal features, visit [https://kamal-deploy.org](https://kamal-deploy.org)
2125
:::
2226

27+
### Hosting Recommendation
28+
29+
If you don't have a Linux Server, we recommend Hetzner
30+
[who we've found](https://docs.servicestack.net/ormlite/litestream#savings-at-scale)
31+
offers the best value [US Cloud VMs](https://cloud.hetzner.com) offering **$15/mo** for a dedicated VM with
32+
**2vCPU / 8GB** RAM which is being used to host **30 Docker Apps**, including all project template live demos -
33+
using the GitHub Actions included in each template.
34+
2335
## Getting Started
2436

2537
### Prerequisites
@@ -30,30 +42,104 @@ Kamal is built by the BaseCamp team, developers of Hey email service and BaseCam
3042
### Initial Setup
3143

3244
1. Create a new ServiceStack application:
33-
```bash
45+
:::sh
3446
npx create-net blazor-vue MyApp
35-
```
47+
:::
3648

37-
2. Generate deployment SSH key:
38-
```bash
49+
2. Create the SSH Private and Public Keys:
50+
:::sh
3951
ssh-keygen -t ed25519 -C "deploy@myapp" -f ./deploy-key
40-
```
52+
:::
4153

42-
3. Copy public key to enable server access:
43-
```bash
54+
3. Copy Public Key to deployment server to enable SSH access:
55+
:::sh
4456
cat ~/deploy-key.pub | ssh <user>@<your-ip> "cat >> ~/.ssh/authorized_keys"
45-
```
57+
:::
4658

47-
### GitHub Actions
59+
4. Configure GitHub Secrets for Kamal to access your deployment server:
4860

49-
The template includes a GitHub Actions workflow that is broken up into 3 steps that trigger on push to the `main` branch, and then on successful build and test, it will deploy the application to your server.
61+
- SSH private key to access the server: ssh-rsa ...
62+
:::sh
63+
gh secret set SSH_PRIVATE_KEY < ~/deploy-key
64+
:::
5065

51-
Once you create your GitHub repository, add the `SSH_PRIVATE_KEY` secret to your repository settings with the contents of your private key file.
66+
- IP address of the server to deploy to: 100.100.100.100
67+
:::sh
68+
gh secret set KAMAL_DEPLOY_IP [your.ip]
69+
:::
5270

53-
```bash
54-
gh secret set SSH_PRIVATE_KEY < ~/deploy-key
71+
- Email for Let's Encrypt SSL certificate: [email protected]
72+
:::sh
73+
gh secret set LETSENCRYPT_EMAIL [your@email]
74+
:::
75+
76+
These Required variables can be globally configured in your GitHub Organization or User secrets which will
77+
enable deploying all your Repositories to the same server.
78+
79+
Optionally configure any other global secrets to be shared by all Apps here:
80+
81+
:::sh
82+
gh secret set SERVICESTACK_LICENSE [license-key]
83+
:::
84+
85+
5. Configure GitHub Secrets for your App
86+
87+
The only secret that needs to be configured per App is:
88+
89+
Hostname used for SSL certificate and Kamal proxy: www.example.org
90+
91+
:::sh
92+
gh secret set KAMAL_DEPLOY_HOST [www.example.org]
93+
:::
94+
95+
You could register any App-specific secrets here, although our preference is instead of polluting each
96+
GitHub Repository with multiple App-specific GitHub Action Secrets, you can save all your secrets in a single
97+
`APPSETTINGS_PATCH` GitHub Action Secret to patch `appsettings.json` with environment-specific configuration
98+
using [JSON Patch](https://jsonpatch.com). E.g:
99+
100+
JSON Patch to apply to appsettings.json:
101+
:::sh
102+
gh secret set APPSETTINGS_PATCH [json-patch]
103+
:::
104+
105+
JSON Patch example:
106+
107+
```json
108+
[
109+
{
110+
"op":"replace",
111+
"path":"/ConnectionStrings/DefaultConnection",
112+
"value":"Server=service-postgres;Port=5432;User Id=dbuser;Password=dbpass;Database=dbname"
113+
},
114+
{ "op":"add", "path":"/SmtpConfig", "value":{
115+
"UserName": "SmptUser",
116+
"Password": "SmptPass",
117+
"Host": "email-smtp.us-east-1.amazonaws.com",
118+
"Port": 587,
119+
"From": "[email protected]",
120+
"FromName": "MyApp",
121+
122+
}
123+
},
124+
{ "op":"add", "path":"/Admins", "value": ["[email protected]","[email protected]"] },
125+
{ "op":"add", "path":"/CorsFeature/allowOriginWhitelist/-", "value":"https://example.org" }
126+
]
55127
```
56128

129+
### Inferred Variables
130+
131+
These variables are inferred from the GitHub Action context and don't need to be configured.
132+
133+
| Variable | Source | Description |
134+
|----------|--------|-------------|
135+
| `GITHUB_REPOSITORY` | `${{github.repository}}` | `acme/example.org` - used for service name and image |
136+
| `KAMAL_REGISTRY_USERNAME` | `${{github.actor}}` | GitHub username for container registry |
137+
| `KAMAL_REGISTRY_PASSWORD` | `${{secrets.GITHUB_TOKEN}}` | GitHub token for container registry auth |
138+
139+
### GitHub Actions
140+
141+
The template includes a GitHub Actions workflow that is broken up into 3 steps that trigger on push to the `main` branch, and then on successful build and test, it will deploy the application to your server.
142+
57143
### Structure
58144

59145
The deployment scripts are embedded in the templates [/.github/workflows](https://github.com/NetCoreTemplates/blazor-vue/tree/main/.github/workflows):
@@ -64,6 +150,8 @@ The deployment scripts are embedded in the templates [/.github/workflows](https:
64150
build-container.yml
65151
release.yml
66152
/.kamal
153+
/hooks
154+
secrets
67155
/config
68156
deploy.yml
69157
```
@@ -80,59 +168,91 @@ Your App's Kamal deployment is configured in [config/deploy.yml](https://github.
80168

81169
### Configuration
82170

83-
Update `config/deploy.yml` with your deployment settings:
171+
The [/config/deploy.yml](https://github.com/NetCoreTemplates/next-static/blob/main/config/deploy.yml) configuration
172+
is designed to be reusable across projects as it dynamically derives service names, image paths, and volume mounts
173+
from environment variables, so you only need to configure your server's IP and hostname using GitHub Action secrets.
174+
175+
Once you make these changes, commit and push to your repository to trigger the GitHub Actions workflow.
176+
177+
Kamal will deploy the required services including Docker and Kamal Proxy if your server doesn't already have them installed.
178+
179+
:::info
180+
When using ASP.NET Core applications with Kamal-Proxy, ensure your application is running with the environment variable `ASPNETCORE_FORWARDEDHEADERS_ENABLED` set to `true`.
181+
The template has this by default, but if you are getting errors with 302 redirects, ensure this is set.
182+
:::
183+
184+
The authentication between GitHub Container Registry (ghcr.io) and your server is handled by the GitHub Actions workflow, the `deploy.yml` and [Kamal Secrets](https://kamal-deploy.org/docs/configuration/environment-variables/#secrets).
185+
186+
### Using Kamal Locally
187+
188+
To also be able to use kamal locally to inspect logs or deploy from your own server you can add the GitHub Action
189+
Secrets into a local `.env` file, e.g:
190+
191+
```bash
192+
# Required for Kamal deploy.yml template processing
193+
194+
GITHUB_REPOSITORY=acme/example.org
84195

85-
```yaml
86-
service: myapp
87-
image: your-github-username/myapp
196+
# Server deployment details
197+
KAMAL_DEPLOY_IP=100.100.100.100
198+
KAMAL_DEPLOY_HOST=example.org
88199

89-
servers:
90-
web:
91-
- <your-server-ip-address>
200+
# Container registry credentials (for ghcr.io)
201+
KAMAL_REGISTRY_USERNAME=my-user
202+
GITHUB_TOKEN=ghp_xxx
92203

93-
proxy:
94-
ssl: true
95-
host: myapp.example.com
204+
# Login to GitHub Container Registry
205+
#echo $KAMAL_REGISTRY_PASSWORD | docker login ghcr.io -u my-user --password-stdin
96206
```
97207

98-
::: info
99-
The `image` value should match your GitHub repository path on ghcr.io. For example: `ghcr.io/username/repository`
208+
You can then load the environment variables into your shell with:
209+
210+
:::sh
211+
source ./load-env.sh
100212
:::
101213

102-
Once you make these changes, commit and push to your repository to trigger the GitHub Actions workflow.
103214

104-
Kamal will deploy the required services including Docker and Kamal Proxy if you server doesn't already have them installed.
215+
Which will allow you to use kamal locally to access your deployment server, e.g:
105216

106-
:::info
107-
When using ASP.NET Core applications with Kamal-Proxy, ensure your application is running with the environment variable `ASPNETCORE_FORWARDEDHEADERS_ENABLED` set to `true`.
108-
The template has this by default, but if you are getting errors with 302 redirects, ensure this is set.
217+
:::sh
218+
kamal app logs -f
109219
:::
110220

111-
The authentication between GitHub Container Registry (ghcr.io) and your server is handled by the GitHub Actions workflow, the `deploy.yml` and [Kamal Secrets](https://kamal-deploy.org/docs/configuration/environment-variables/#secrets).
112-
113221
:::info
114222
You can still use the Kamal CLI locally, but if you want to directly push deployments with `kamal deploy`, you will need to locally populate `KAMAL_REGISTRY_USER` and `KAMAL_REGISTRY_PASSWORD` with your GitHub username and a GitHub Personal Access Token with `read:packages` scope.
115223
:::
116224

225+
### Hard code App specific variables
226+
227+
Alternatively if you don't want to maintain a `.env` with GitHub Action Secrets you can hard-code all
228+
App-specific variables in your `deploy.yml` file so it doesn't need to perform any template processing
229+
for its Environment Variable substitutions.
230+
117231
## Common Kamal Commands
118232

119233
Kamal provides several useful commands for managing your deployment:
120234

121-
```bash
122-
# View deployment details
235+
- View deployment details
236+
:::sh
123237
kamal details
238+
:::
124239

125-
# Check application logs
126-
kamal app logs
240+
- Check application logs
241+
:::sh
242+
kamal app logs -f
243+
:::
127244

128-
# Deploy new version
245+
- Deploy new version
246+
:::sh
129247
kamal deploy
248+
:::
130249

131-
# Restart application
250+
- Restart application
251+
:::sh
132252
kamal app boot
133-
```
253+
:::
134254

135-
::: info
255+
:::info
136256
Kamal commands are context-aware and will use the configuration from your current application directory. This makes managing multiple applications across different servers a lot easier as more applications are added.
137257
:::
138258

@@ -151,6 +271,6 @@ Delete the `.<app-name>` file in your deployment user's home directory and re-ru
151271

152272
If you are getting:
153273

154-
Image ghcr.io/netcoreapps/northwindauto:latest is missing the 'service' label
274+
Image ghcr.io/netcoreapps/northwindauto:latest is missing the 'service' label
155275

156-
Ensure that your AppHost csproj file has `ContainerLabel` with the value matching the `service` in your `deploy.yml` file.
276+
Ensure your AppHost **csproj** has `ContainerLabel` with the value matching the `service` in your `deploy.yml`.

MyApp/_pages/templates/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ slug: templates-overview
55

66
ServiceStack accelerates .NET development with battle-tested templates for building modern applications - from high-performance Web APIs and backend services to full-stack web apps, microservices, and cloud-native solutions. Whether you're building a Jamstack site, a Blazor application, or a serverless API, ServiceStack provides the foundation to ship faster.
77

8-
:::copy
8+
:::sh
99
npx create-net ls
1010
:::
1111

@@ -23,10 +23,10 @@ Where it will display all repositories in [.NET 10](https://github.com/NetCoreTe
2323
$ npx create-net `<template>` `<name>`
2424
```
2525

26-
For example to create a new **Vue Single Page App**, run:
26+
For example to create a new **Next.js statically generated React App**, run:
2727

2828
:::sh
29-
npx create-net vue-spa ProjectName
29+
npx create-net next-static ProjectName
3030
:::
3131

3232
Or download a customized project template from our Getting Started Page:

MyApp/_pages/templates/react-spa.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,12 @@ built-in ASP.NET Core React SPA template with many new value-added and high-prod
2525
</div>
2626
</div>
2727

28-
:::{.text-center}
29-
## Live Demo
30-
:::
31-
32-
:::{.shadow .pb-1}
33-
[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/csharp-templates/react-spa.png)](https://react-spa.react-templates.net)
34-
:::
28+
<vibe-template
29+
template="react-spa"
30+
title="React SPA"
31+
description="A feature-rich React Single Page Application powered by Vite. Includes Blog functionality, Todos, shadcn/ui components, API Keys management, AI Chat capabilities, and Swagger UI - all integrated with a robust .NET backend."
32+
href="https://react-templates.net/docs/templates/react-spa"
33+
screenshot="https://github.com/ServiceStack/docs.servicestack.net/blob/main/MyApp/wwwroot/img/pages/react/react-spa.webp?raw=true"></vibe-template>
3534

3635
## ASP.NET Core React SPA Template
3736

0 commit comments

Comments
 (0)