Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simpler install process for new users #305

Merged
merged 16 commits into from
Mar 14, 2023
Merged

Simpler install process for new users #305

merged 16 commits into from
Mar 14, 2023

Conversation

ianroberts
Copy link
Member

Now we are publishing release Docker images to ghcr.io it is no longer strictly necessary to clone the whole gate-teamware repository in order to run a release version (or in fact a dev version) under docker-compose. All you actually need is:

  • the compose file itself
  • generate-docker-env.sh to generate your initial .env file
  • create-django-db.sh which is bind-mounted into the postgresql container to create the initial DB
  • the nginx folder which is bind-mounted into the frontend container to reverse proxy to the back end.

Everything else comes in the images that are pulled from ghcr.io.

This PR provides a "quick start" mechanism to enable this compose deployment from the public images. I've simplified the .env generator so that once a suitable .env file is in place the "production" deployment can be run purely using docker compose up without needing the separate deploy.sh script. I've then created a "get Teamware" script that runs the user through a set of interactive prompts for the critical configuration data (admin email address, public host name, SMTP server details, etc.) and then downloads and configures a minimal compose stack with just those four items listed above, ready to be launched using docker compose. This was inspired by https://acme.sh, which has a bootstrapping shell script at a short URL which you download and run to download and install the rest of the tool.

Initially I've hand-created the installation bundle but going forward the idea is that when we make a vN.M.P tag on GitHub the "get Teamware" script and associated install files bundle will be generated by an action and uploaded as GitHub release artifacts. The short URL https://gate.ac.uk/get-teamware.sh will then become a simple redirect to the file in the latest GitHub release, so anyone can install the latest version by making an empty dir and running

curl -LO https://gate.ac.uk/get-teamware.sh
bash ./get-teamware.sh

I've also moved the instructions for how to install releases out of the "developer" guide and into the main README since they're no longer specific to developers of Teamware as such.

@github-actions
Copy link

github-actions bot commented Mar 5, 2023

Jest Coverage

File % Stmts % Branch % Funcs % Lines Uncovered Line #s
All files 80 77.37 74.19 79.92
File % Stmts % Branch % Funcs % Lines Uncovered Line #s
All files 80 77.37 74.19 79.92
_src/components 77.14 77.35 85.71 77.14
_ AnnotationRenderer.vue 76.23 77.35 84 76.23 126,141-142,196,219,240,247-261,269,275-285,319
_ MarkdownEditor.vue 100 100 100 100
_ MarkdownRenderer.vue 100 100 100 100
_src/components/annotation 80.95 86.66 82.35 80.95
_ CheckboxInput.vue 85.71 100 100 85.71 19
_ HtmlDisplay.vue 80 100 100 80 26-30
_ InputErrorDisplay.vue 100 0 100 100 19-25
_ RadioInput.vue 85.71 100 100 85.71 19
_ SelectorInput.vue 71.42 100 66.66 71.42 20,27
_ TextInput.vue 75 100 66.66 75 26
_ TextareaInput.vue 66.66 100 50 66.66 20
_src/enum 100 100 100 100
_ DocumentTypes.js 100 100 100 100
_src/jrpc 90.32 83.33 75 90.32
_ index.js 90.32 83.33 75 90.32 29,38-39
_src/utils 77.77 74.6 38.46 77.46
_ annotations.js 96.55 81.25 100 96.42 35
_ dict.js 100 100 100 100
_ index.js 55.88 54.54 11.11 55.88 9-14,28-93
_tests/unit 100 100 100 100
_ globalVue.js 100 100 100 100

```
mkdir gate-teamware
cd gate-teamware
curl -LO https://gate.ac.uk/get-teamware.sh
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now this is a file hosted directly on gate.ac.uk, but once we have a published release it will become a redirect to the latest GitHub release version.

case $DEPLOY_ENV in

production|prod)
DJANGO_ALLOWED_HOSTS=$TEAMWARE_HOST_URL_PRODUCTION
export DJANGO_ALLOWED_HOSTS
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inherited process environment overrides .env for docker-compose, so we can declare DJANGO_ALLOWED_HOSTS directly in the .env but still override it if we want to for staging/test. This then means that ./deploy.sh prod is directly equivalent to a simple docker compose up -d

@@ -15,7 +15,7 @@ if [ -f .env ]; then
fi

# get current branch
BRANCH=$(git rev-parse --abbrev-ref HEAD)
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo main)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Asume main (which ultimately means the published ghcr.io images) if generate-docker-env.sh is run from outside of a git clone.

@@ -78,7 +90,7 @@ SUPERUSER_PASSWORD=${SUPERUSER_PASSWORD:-password}
# *including* the trailing slash
#
# leave blank for local images
IMAGE_REGISTRY=${IMAGE_REGISTRY:-ghcr.io/gatenlp/}
IMAGE_REGISTRY=${IMAGE_REGISTRY-ghcr.io/gatenlp/}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and a number of other settings can legitimately be set to the empty string, so I've switched from :- (default if unset or if set to the empty string) to just - (default if unset, but if set to empty then leave empty)

#

# GATE Teamware version that this script will install
DEFAULT_IMAGE_TAG=latest
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gets replaced by the release tag by the create-release workflow, so the script published as an artifact in a given release will install the version of Teamware corresponding to that specific release.

Copy link
Contributor

@davidwilby davidwilby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really great, I like the quickstart approach and this greatly simplifies the docker deployment.

recommend that public access be via secure HTTPS, for which you will need
to deploy a separate front end proxy forwarding to the GATE Teamware
application; configuration of such a proxy is beyond the scope of this quick
start script.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include some text similar to this regarding proxy forwarding alongside the install instructions to forewarn users? Just so someone doesn't run this script and find this out right at the end?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've gone one better in my latest revision - I've added an optional add-on to the docker-compose stack that brings up an https reverse proxy on port 443. I don't want to make that a standard part of the stack because it only works if the machine is open to the internet on 80/443 (because it uses ACME to obtain certificates) but it's a way to mark the path of least resistance.

@ianroberts ianroberts force-pushed the quick-start-script branch from 80784e3 to 0c186b6 Compare March 6, 2023 18:24
@ianroberts
Copy link
Member Author

This PR is becoming bigger and more complex.

I noticed that we weren't passing any of the email configuration environment variables through to the backend from the compose file, so I added those; then saw we weren't even setting the "require email activation" parameter in .env, so added that; then realised that check_create_superuser would be broken if email activation is turned on, so fixed that too... I guess since our primary deployment moved to Kubernetes the docker-compose side hasn't been maintained so much.

Anyway, I think this should be more or less ready now, and I've tested it end-to-end on an AWS EC2 machine with the Caddy HTTPS reverse proxy in the mix as well.

@ianroberts ianroberts requested a review from davidwilby March 7, 2023 15:31
Copy link
Contributor

@davidwilby davidwilby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Would you mind briefly explaining Caddy to me in simple terms and it's role here?

@ianroberts
Copy link
Member Author

Caddy is a web server written in Go that is designed to be HTTPS-by-default with zero configuration. If you tell it that it is serving a publicly-resolvable DNS hostname then it will go out and obtain trusted certificates using ACME and keep them renewed and up to date automatically. If you tell it to serve localhost it can't get ACME certificates but it still generates its own certificate authority and issues server certificates from that. The extra compose file configures Caddy in the compose stack to do essentially the same job as the ingress controller does in a Kubernetes deployment - terminate TLS and reverse proxy /static to the nginx container and everything else to the backend.

@ianroberts
Copy link
Member Author

I'm happy if you're happy, at least to make this version 1, but since I've trodden on many of the same files as #298 I'll let you merge that first and then rebase this.

@davidwilby
Copy link
Contributor

I'm happy if you're happy, at least to make this version 1, but since I've trodden on many of the same files as #298 I'll let you merge that first and then rebase this.

If you don't mind? I was waiting for this one to be merged, happy to do it either way round.

@ianroberts
Copy link
Member Author

ianroberts commented Mar 9, 2023

You go ahead and finish the privacy policy first, I’ll add questions about the contact details settings to the quick start script as part of my rebase and then merge mine.

@ianroberts ianroberts force-pushed the quick-start-script branch from 13c3f6b to 33dcd5c Compare March 9, 2023 20:38
@ianroberts
Copy link
Member Author

ianroberts commented Mar 9, 2023

Rebased on latest dev including privacy policy changes. Could I ask for a final sanity check before merging as I've made a number of changes compared to the previous push - in particular I've tried to sort out proper quoting of values in the .env file with ee67d74 but it turned out a lot more complex than I expected it to be.

@ianroberts ianroberts force-pushed the quick-start-script branch 2 times, most recently from fb2b521 to 88b2e86 Compare March 10, 2023 15:41
Copy link
Contributor

@davidwilby davidwilby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Sorry to keep you waiting.

This allows the production deployment to be run directly using "docker compose up" rather than requiring the use of deploy.sh (though deploy.sh still works and is still necessary if you want to override variables for staging or test deployments)
We should now properly preserve spaces etc. in multi-word env vars when re-writing the env file.  I've gone with double quoting strings but backslash-escaping double quotes, dollar signs and backslashes within them.  At first glance it would have been easier just to use single quotes, but there are differences between the way docker-compose parses an .env file and the way it behaves when "source"d by bash, which are easier to paper over if we use double quoted strings.

Under docker-compose rules you can escape single quotes inside single quoted strings as \', but bash has no way to put a single quote inside a single quoted string full stop.  So we have to use double quotes if we want to allow for both " and ' inside the same variable value.  But different parsers have different rules about other escapes inside double quoted strings:

- bash, "docker compose" (v2) and "docker-compose" (v1) all require you to escape \ as \\ and " as \"
- bash and compose v2 require escaping of $ as \$, but docker-compose v1 does not and reads a \$ "escape" as the literal backslash-dollar sequence
- bash requires escaping of ` as \` but neither version of compose requires this, reading \` as \`

However, all three parsers support ${VAR} substitution so what we actually do is:

1. declare special variables __BT__='`' and __DOLLAR__='$' at the top of the .env file
2. when we want to quote a value, we replace
  - " with \"
  - \ with \\
  - $ with ${__DOLLAR__}
  - ` with ${__BT__}

The resulting .env file reliably reads the same values under all three parsers, provided you don't try and include line breaks within a value.
…inimal additional config, rather than requiring a whole clone
…ot so much for developers as for people who want to host their own instance of a released version of Teamware
@ianroberts ianroberts merged commit a7b0eb5 into dev Mar 14, 2023
@ianroberts
Copy link
Member Author

Thanks, I've done a final rebase and merged into dev

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants