-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
134 changed files
with
13,261 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
version: "3.9" | ||
|
||
services: | ||
nginx-proxy: | ||
image: nginxproxy/nginx-proxy | ||
container_name: nginx-proxy | ||
restart: always | ||
ports: | ||
- "80:80" | ||
- "443:443" | ||
volumes: | ||
- conf:/etc/nginx/conf.d | ||
- vhost:/etc/nginx/vhost.d | ||
- html:/usr/share/nginx/html | ||
- dhparam:/etc/nginx/dhparam | ||
- certs:/etc/nginx/certs:ro | ||
- /var/run/docker.sock:/tmp/docker.sock:ro | ||
labels: | ||
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy" | ||
|
||
letsencrypt: | ||
image: nginxproxy/acme-companion:2.2 | ||
container_name: nginx-proxy-le | ||
restart: always | ||
depends_on: | ||
- "nginx-proxy" | ||
environment: | ||
- [email protected] | ||
volumes: | ||
- certs:/etc/nginx/certs:rw | ||
- acme:/etc/acme.sh | ||
- vhost:/etc/nginx/vhost.d | ||
- html:/usr/share/nginx/html | ||
- /var/run/docker.sock:/var/run/docker.sock:ro | ||
|
||
networks: | ||
default: | ||
name: nginx | ||
|
||
volumes: | ||
conf: | ||
vhost: | ||
html: | ||
dhparam: | ||
certs: | ||
acme: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# ServiceStack mix GitHub Actions | ||
`release.yml` generated from `x mix release-ghr-vanilla`, this template in designed to help with CI deployment to a dedicated server with SSH access. | ||
|
||
## Overview | ||
`release.yml` is designed to work with a ServiceStack app deploying directly to a single server via SSH. A docker image is built and stored on GitHub's `ghcr.io` docker registry when a GitHub Release is created. | ||
|
||
GitHub Actions specified in `release.yml` then copy files remotely via scp and use `docker-compose` to run the app remotely via SSH. | ||
|
||
## Deployment server setup | ||
To get this working, a server needs to be setup with the following: | ||
|
||
- SSH access | ||
- docker | ||
- docker-compose | ||
- ports 443 and 80 for web access of your hosted application | ||
|
||
This can be your own server or any cloud hosted server like Digital Ocean, AWS, Azure etc. | ||
|
||
When setting up your server, you'll want to use a dedicated SSH key for access to be used by GitHub Actions. GitHub Actions will need the *private* SSH key within a GitHub Secret to authenticate. This can be done via ssh-keygen and copying the public key to the authorized clients on the server. | ||
|
||
To let your server handle multiple ServiceStack applications and automate the generation and management of TLS certificates, an additional docker-compose file is provided via the `x mix` template, `nginx-proxy-compose.yml`. This docker-compose file is ready to run and can be copied to the deployment server. | ||
|
||
For example, once copied to remote `~/nginx-proxy-compose.yml`, the following command can be run on the remote server. | ||
|
||
``` | ||
docker-compose -f ~/nginx-proxy-compose.yml up -d | ||
``` | ||
|
||
This will run an nginx reverse proxy along with a companion container that will watch for additional containers in the same docker network and attempt to initialize them with valid TLS certificates. | ||
|
||
## GitHub Repository setup | ||
The `release.yml` uses the following secrets. | ||
|
||
- DEPLOY_HOST - hostname used to SSH to, this can either be an IP address or subdomain with A record pointing to the server. | ||
- DEPLOY_USERNAME - the username being logged into via SSH. Eg, `ubuntu`, `ec2-user`, `root` etc. | ||
- DEPLOY_KEY - SSH private key used to remotely access deploy server/app host. | ||
- LETSENCRYPT_EMAIL - Email address, required for Let's Encrypt automated TLS certificates. | ||
|
||
These secrets can use the [GitHub CLI](https://cli.github.com/manual/gh_secret_set) for ease of creation. Eg, using the GitHub CLI the following can be set. | ||
|
||
```bash | ||
gh secret set DEPLOY_HOST -b"<DEPLOY_HOST, domain or subdomain for your application and server host.>" | ||
gh secret set DEPLOY_USERNAME -b"<DEPLOY_USERNAME, the username being logged into via SSH. Eg, `ubuntu`, `ec2-user`, `root` etc.>" | ||
gh secret set DEPLOY_KEY -b"<DEPLOY_KEY, SSH private key used to remotely access deploy server/app host.>" | ||
gh secret set LETSENCRYPT_EMAIL -b"<LETSENCRYPT_EMAIL, Email address for your TLS certificate generation, eg [email protected]>" | ||
``` | ||
|
||
These secrets are used to populate variables within GitHub Actions and other configuration files. | ||
|
||
## What's the process of `release.yml`? | ||
|
||
![](https://raw.githubusercontent.com/ServiceStack/docs/master/docs/images/mix/release-ghr-vanilla-diagram.png) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
name: Build | ||
|
||
on: | ||
pull_request: {} | ||
push: | ||
branches: | ||
- '**' # matches every branch | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-20.04 | ||
steps: | ||
- name: checkout | ||
uses: actions/[email protected] | ||
|
||
- name: setup .net core | ||
uses: actions/setup-dotnet@v3 | ||
with: | ||
dotnet-version: '6.0' | ||
|
||
- name: build | ||
run: dotnet build | ||
working-directory: . | ||
|
||
- name: test | ||
run: | | ||
dotnet test | ||
if [ $? -eq 0 ]; then | ||
echo TESTS PASSED | ||
else | ||
echo TESTS FAILED | ||
exit 1 | ||
fi | ||
working-directory: ./MyApp.Tests | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
name: Release | ||
permissions: | ||
packages: write | ||
contents: write | ||
on: | ||
# Triggered on new GitHub Release | ||
release: | ||
types: [published] | ||
# Triggered on every successful Build action | ||
workflow_run: | ||
workflows: ["Build"] | ||
branches: [main,master] | ||
types: | ||
- completed | ||
# Manual trigger for rollback to specific release or redeploy latest | ||
workflow_dispatch: | ||
inputs: | ||
version: | ||
default: latest | ||
description: Tag you want to release. | ||
required: true | ||
|
||
jobs: | ||
push_to_registry: | ||
runs-on: ubuntu-22.04 | ||
if: ${{ github.event.workflow_run.conclusion != 'failure' }} | ||
steps: | ||
# Checkout latest or specific tag | ||
- name: checkout | ||
if: ${{ github.event.inputs.version == '' || github.event.inputs.version == 'latest' }} | ||
uses: actions/checkout@v3 | ||
- name: checkout tag | ||
if: ${{ github.event.inputs.version != '' && github.event.inputs.version != 'latest' }} | ||
uses: actions/checkout@v3 | ||
with: | ||
ref: refs/tags/${{ github.event.inputs.version }} | ||
|
||
# Assign environment variables used in subsequent steps | ||
- name: Env variable assignment | ||
run: echo "image_repository_name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV | ||
# TAG_NAME defaults to 'latest' if not a release or manual deployment | ||
- name: Assign version | ||
run: | | ||
echo "TAG_NAME=latest" >> $GITHUB_ENV | ||
if [ "${{ github.event.release.tag_name }}" != "" ]; then | ||
echo "TAG_NAME=${{ github.event.release.tag_name }}" >> $GITHUB_ENV | ||
fi; | ||
if [ "${{ github.event.inputs.version }}" != "" ]; then | ||
echo "TAG_NAME=${{ github.event.inputs.version }}" >> $GITHUB_ENV | ||
fi; | ||
- name: Login to GitHub Container Registry | ||
uses: docker/login-action@v2 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
# Build and push new docker image, skip for manual redeploy other than 'latest' | ||
- name: Build and push Docker images | ||
uses: docker/build-push-action@v3 | ||
if: ${{ github.event.inputs.version == '' || github.event.inputs.version == 'latest' }} | ||
with: | ||
file: Dockerfile | ||
context: . | ||
push: true | ||
tags: ghcr.io/${{ env.image_repository_name }}:${{ env.TAG_NAME }} | ||
|
||
deploy_via_ssh: | ||
needs: push_to_registry | ||
runs-on: ubuntu-22.04 | ||
if: ${{ github.event.workflow_run.conclusion != 'failure' }} | ||
steps: | ||
# Checkout latest or specific tag | ||
- name: checkout | ||
if: ${{ github.event.inputs.version == '' || github.event.inputs.version == 'latest' }} | ||
uses: actions/checkout@v3 | ||
- name: checkout tag | ||
if: ${{ github.event.inputs.version != '' && github.event.inputs.version != 'latest' }} | ||
uses: actions/checkout@v3 | ||
with: | ||
ref: refs/tags/${{ github.event.inputs.version }} | ||
|
||
- name: repository name fix and env | ||
run: | | ||
echo "image_repository_name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV | ||
echo "domain=${{ secrets.DEPLOY_HOST }}" >> $GITHUB_ENV | ||
echo "letsencrypt_email=${{ secrets.LETSENCRYPT_EMAIL }}" >> $GITHUB_ENV | ||
echo "TAG_NAME=latest" >> $GITHUB_ENV | ||
if [ "${{ github.event.release.tag_name }}" != "" ]; then | ||
echo "TAG_NAME=${{ github.event.release.tag_name }}" >> $GITHUB_ENV | ||
fi; | ||
if [ "${{ github.event.inputs.version }}" != "" ]; then | ||
echo "TAG_NAME=${{ github.event.inputs.version }}" >> $GITHUB_ENV | ||
fi; | ||
- name: Create .env file | ||
run: | | ||
echo "Generating .env file" | ||
echo "# Autogenerated .env file" > .env | ||
echo "HOST_DOMAIN=${{ secrets.DEPLOY_HOST }}" >> .env | ||
echo "LETSENCRYPT_EMAIL=${{ secrets.LETSENCRYPT_EMAIL }}" >> .env | ||
echo "APP_NAME=${{ github.event.repository.name }}" >> .env | ||
echo "IMAGE_REPO=${{ env.image_repository_name }}" >> .env | ||
echo "RELEASE_VERSION=${{ env.TAG_NAME }}" >> .env | ||
# Copy only the docker-compose.yml to remote server home folder | ||
- name: copy files to target server via scp | ||
uses: appleboy/[email protected] | ||
with: | ||
host: ${{ secrets.DEPLOY_HOST }} | ||
username: ${{ secrets.DEPLOY_USERNAME }} | ||
port: 22 | ||
key: ${{ secrets.DEPLOY_KEY }} | ||
source: "./docker-compose.yml,./docker-compose.prod.yml,./.env" | ||
target: "~/.deploy/${{ github.event.repository.name }}/" | ||
|
||
- name: Run remote db migrations | ||
uses: appleboy/[email protected] | ||
env: | ||
APPTOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
USERNAME: ${{ secrets.DEPLOY_USERNAME }} | ||
with: | ||
host: ${{ secrets.DEPLOY_HOST }} | ||
username: ${{ secrets.DEPLOY_USERNAME }} | ||
key: ${{ secrets.DEPLOY_KEY }} | ||
port: 22 | ||
envs: APPTOKEN,USERNAME | ||
script: | | ||
echo $APPTOKEN | docker login ghcr.io -u $USERNAME --password-stdin | ||
cd ~/.deploy/${{ github.event.repository.name }} | ||
docker compose -f ./docker-compose.yml -f ./docker-compose.prod.yml pull | ||
docker compose -f ./docker-compose.yml -f ./docker-compose.prod.yml up app-migration | ||
# Deploy Docker image with your application using `docker compose up` remotely | ||
- name: remote docker-compose up via ssh | ||
uses: appleboy/[email protected] | ||
env: | ||
APPTOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
USERNAME: ${{ secrets.DEPLOY_USERNAME }} | ||
with: | ||
host: ${{ secrets.DEPLOY_HOST }} | ||
username: ${{ secrets.DEPLOY_USERNAME }} | ||
key: ${{ secrets.DEPLOY_KEY }} | ||
port: 22 | ||
envs: APPTOKEN,USERNAME | ||
script: | | ||
echo $APPTOKEN | docker login ghcr.io -u $USERNAME --password-stdin | ||
cd ~/.deploy/${{ github.event.repository.name }} | ||
docker compose -f ./docker-compose.yml -f ./docker-compose.prod.yml pull | ||
docker compose -f ./docker-compose.yml -f ./docker-compose.prod.yml up app -d |
Oops, something went wrong.