Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## What this repo is

This repo holds configuration templates for running the Dockstore webservice and UI on AWS ECS/Fargate. There is no application code here. The repo contains Mustache templates, static config, Dockerfiles for the ELK logging stack, and shell scripts. Local Dockstore development belongs in the main `dockstore/dockstore` repo, not here.

Related repos:
- `dockstore/dockstore-deploy` checks this repo out as a **git submodule**. Its `cdk-templates/dockstore` Fargate stack fills in these templates from a Secrets Manager secret (`/DeploymentConfig/<env>/BootstrapConfigFile`) that holds the same key/value pairs as `compose.config`. A new key added here therefore also has to be added to that secret in each environment.
- `dockstore/dockstore` is the webservice itself. It owns the Liquibase changelogs whose version contexts `init_migration.sh.template` lists, and the Dropwizard config schema that `web.yml.template` fills in.

## Commands

```bash
# Render all templates into config/ (and a few into scripts/). Requires `mustache` (Ruby gem) and `jq`.
bash install_bootstrap --script

# Validate the rendered nginx config (this is what CI does)
docker run -v $PWD/config/nginx-conf/default.nginx_http.conf:/etc/nginx/conf.d/default.conf:ro \
-v $PWD/config/nginx-conf/default.nginx_http.shared.conf:/etc/nginx/conf.d/default.nginx_http.shared.conf:ro \
-v $PWD/config/nginx-conf/default.nginx_http.security.conf:/etc/nginx/conf.d/default.nginx_http.security.conf:ro \
nginx:1.13.1 nginx -t -c /etc/nginx/nginx.conf

# Secret scanning (also installs git-secrets hooks via husky)
npm ci
npm run install-git-secrets

# Dev ELK logging stack (elasticsearch-logstash, logstash, kibana, elastalert)
docker compose -f docker-compose.dev.yml build
docker compose -f docker-compose.dev.yml up --force-recreate --remove-orphans
```

There is no test suite. CI (`.github/workflows/docker-image.yml`) runs the git-secrets scan, renders the templates with `install_bootstrap --script`, and runs `nginx -t` on the result. Run both locally to check a change.

## How templating works

- `dockstore_launcher_config/compose.config` is a flat JSON file of every template variable. The committed copy holds only placeholder values (`replaceme`, `foobar`). Real values are supplied at deploy time and must never be committed.
- `install_bootstrap` loads that JSON as shell variables through `jq`. It uses `UI2_HASH` to download the UI's `index.html`/`manifest.json` from `gui.dockstore.org`. It then runs `mustache compose.config <template> > <output>` for each template. Outputs go to `config/nginx-conf/`, `config/nginx-html2/`, `config/webservice/`, `config/rules/` and `config/*`. `scripts/essnapshot_backup.sh` and `scripts/postgres_backup.sh` are generated too. All of these are gitignored.
- **Adding a new config value:** add the key to `compose.config`, keeping the keys alphabetical, and reference it in the relevant template (usually `templates/web.yml.template`, the Dropwizard config). In Mustache, `{{ X }}` HTML-escapes the value and `{{{ X }}}` does not. Use triple braces for passwords and other values that may contain special characters. Boolean keys drive sections (`{{#X}}...{{/X}}` / `{{^X}}...{{/X}}`).
- Any new template must also get its own `mustache` line in the `template()` function of `install_bootstrap`, or it won't be rendered.
- `staticConfig/` holds config that is mounted as-is without templating (ELK and elastalert). `templates/rules/` holds the elastalert rules. They are templated because they need `SLACK_URL`.

## Database migrations (recurring release task)

`templates/init_migration.sh.template` runs the webservice JAR's `db migrate` with Liquibase `--include` contexts. Each Dockstore release appends its version (e.g. `1.21.0`) to the comma-separated list on the **last** line, which runs as the `dockstore` user. Leave the earlier lines alone. They handle the `DATABASE_GENERATED` fresh-DB versus existing-DB paths and the `1.7.0.relinquish` step, which must run as `postgres`.

## Branching

The repo follows Hubflow (gitflow) conventions. `develop` is the main integration branch and the default target for PRs. Work is done on `feature/*` branches cut from `develop` and merged back into it. `hotfix/*` branches are for urgent fixes, and `release/*` branches are cut for releases and tagged.

## Pull requests

Always create PRs in draft mode (e.g. `gh pr create --draft`). Only a human may take a PR out of draft and mark it ready for review. Never do that yourself.

Always check with the user before pushing to GitHub, even to a branch or PR already being worked on in the conversation. A push can start a CI build or interrupt one that is already running.

Fill out PRs using `.github/PULL_REQUEST_TEMPLATE.md` (Description, Review Instructions, Issue as a GitHub issue or `SEAB-` ticket) instead of a generic Summary/Test plan format. Keep Description and Review Instructions to one paragraph each, or two for a genuinely complicated change. Copy the template's checkboxes verbatim. Never reword, reformat or condense them, and never add text to an item. Change `[ ]` to `[x]` only after actually confirming that item for this PR.

Diff the work against `develop` (or whatever branch the PR targets). Avoid stylistic or other minor changes that inflate the diff, unless they fix something a code-quality check (e.g. CodeQL) actually flagged.

### Using CI and review feedback

- Use GitHub Actions results (check runs, job logs) through `gh` or the GitHub MCP server to diagnose failures instead of guessing.
- Review comments from human developers are high-priority direction. Investigate each one and propose a concrete fix, even without being asked. Bot-authored comments are useful but come second to human reviewers.

## JIRA

When adding comments to JIRA tickets, clearly indicate that Claude wrote the comment. For example, start with a line like "This comment was generated by Claude (Claude Code)."

## Other conventions

- git-secrets runs through the husky hooks on commit. Add real false positives to `.gitallowed`.
- `docker-compose.yml` and the EC2-based setup were removed in `ff22ced`, and `install_bootstrap` no longer prompts interactively. Old docs or comments that mention them are stale.
14 changes: 4 additions & 10 deletions DEV-README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Make sure elasticsearch-logstash has essnapshot write permissions.
sudo chown -R ubuntu:ubuntu essnapshot
sudo chmod -R 775 essnapshot
```
Run this commands from within the docker-compose.dev.yml server.
Run these commands on the host running the `docker-compose.dev.yml` stack.
```
curl -X PUT "localhost:9200/_snapshot/my_backup" -H 'Content-Type: application/json' -d'
{
Expand All @@ -71,7 +71,7 @@ curator_cli show_snapshots --repository my_backup

### Creating daily snapshots

Take a look at `scripts/essnapshot_backup.sh` for the appropriate cron tasks to setup the daily backup. Note that this relies upon an IAM user setup with write permissions to the appropriate S3 bucket.
Take a look at `scripts/essnapshot_backup.sh` (generated by `install_bootstrap` from `templates/essnapshot_backup.sh`) for the appropriate cron tasks to setup the daily backup. Note that this relies upon an IAM user setup with write permissions to the appropriate S3 bucket.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Interesting that it offered to update the readme's
I never use this repo locally so we have a ticket out to merge this with dockstore-deploy anyway

Any objections @svonworl ?


### Delete snapshot
`curl -X DELETE "localhost:9200/_snapshot/my_backup/snapshot-2018.09.26"`
Expand All @@ -80,7 +80,7 @@ Alternatively, you can delete old snapshots automatically using curator. Delete


### Restoring snapshots procedure
Before bringing up elasticsearch-logstash, download the newest zip file from s3 and extract its contents into the essnapshot directory. Then follow the [Snapshot repository creation](#snapshot-repository-creation) section and ensure the snapshots are readable. Restart elasticsearch-logstash if not snapshots are found. Perform the snapshot restore:
Before bringing up elasticsearch-logstash, download the newest zip file from s3 and extract its contents into the essnapshot directory. Then follow the [Snapshot repository creation](#snapshot-repository-creation) section and ensure the snapshots are readable. Restart elasticsearch-logstash if no snapshots are found. Perform the snapshot restore:
- `curl -X POST "localhost:9200/_all/_close"`
Replace "snapshot-2019.01.04" with the actual snapshot name
- `curl -X POST "localhost:9200/_snapshot/my_backup/snapshot-2019.01.04/_restore?wait_for_completion=true"`
Expand All @@ -97,13 +97,7 @@ See the correct elastic version of the [elastic guide](https://www.elastic.co/gu
# Additional Notes
- If metricbeats is brought up before logstash's elasticsearch, metricbeats will keep restarting until logstash's elasticsearch is operational.
- Default index pattern must be selected before any dashboards can be viewed. Set the default index pattern using the star.
- Generally, every command used by docker-compose.yml should have `docker-compose` replaced with `docker-compose -f docker-compose.dev.yml`. `docker-compose up` becomes `docker-compose -f docker-compose.dev.yml up`

## Self-signed certificate
To use self-signed certificate to run https locally:
- go to compose\_setup
- `bash scripts/self-signed-certificate.sh`
- swap the comments in the [templates/default.nginx_https.shared.conf.template](templates/default.nginx_https.shared.conf.template) and [docker-compose.yml](docker-compose.yml)
- All `docker compose` commands for this stack need `-f docker-compose.dev.yml`, e.g. `docker compose -f docker-compose.dev.yml up`

## Elasticsearch Production Setup Differences
Set vm.max_map_count as described in https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#docker-cli-run-prod-mode
49 changes: 22 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,49 @@ Log issues and see general documentation at [dockstore](https://github.com/ga4gh

If you are looking for how to run Dockstore locally as a developer, you are probably in the wrong place and should take a look at https://github.com/dockstore/dockstore/blob/develop/docker-compose.yml

## Prerequisities
## Prerequisites

1. Tested on Ubuntu 20.04
1. At least 20GB of disk space, 16GB of RAM, and 4 CPUs
1. Docker setup following [https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/](https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/) including the post-installation steps for running without sudo
1. The running Dockstore website will require ports 80 and 443 by default
1. `mustache` (the Ruby gem, `gem install mustache`), `jq`, and `wget` to render the templates
1. Docker with Compose v2 (`docker compose`) if you want to run the development logging stack
1. A client id and client secret for each of the integrations you wish to setup, github and quay.io as a minimum probably. You will need client ids and secrets for each integration as documented on the internal [wiki](https://wiki.oicr.on.ca/display/DOC/OAuth+Apps+and+Other+3rd+Party+Registration).

## Usage

1. Call the install\_bootstrap script. This templates the contents of `templates` using mustache to the `config` directory while recording your answers for future use.
1. Fill in `dockstore_launcher_config/compose.config`, a flat JSON file of every templated value. The committed copy only contains placeholder values; do not check in real client ids, secrets, or passwords.
1. Each integration requires a client id and a secret
2. The discourse URL is needed to link Dockstore to a discussion forum
3. The tag manager ID is used if you want to properly track visitors to Dockstore and what pages they browse to
4. `UI2_HASH` selects the version of the UI whose `index.html` and `manifest.json` are downloaded from `gui.dockstore.org`

2. Some additional information on the answers requested in the script
1. Each integration requires a client id and a secret, it is worth saying that you should not check these in
2. The discourse URL is needed to link Dockstore to a discussion forum
3. the Google verification code and tag manager ID are used if you want to properly track visitors to Dockstore and what pages they browse to
2. Run `bash install_bootstrap`. It reads `compose.config` and templates the contents of `templates` into the `config` directory (plus `scripts/essnapshot_backup.sh` and `scripts/postgres_backup.sh`) using mustache. It does not prompt for answers.

3. After following the instructions in the bootstrap script and starting up the site with AWS Fargate, you can browse to the Dockstore site hosted at port 443 by default using `https://<domain-name>`.
3. In staging and production, [dockstore-deploy](https://github.com/dockstore/dockstore-deploy) includes this repo as a submodule and supplies the `compose.config` values from AWS Secrets Manager. When you add a new key to `compose.config`, it also needs to be added there. After the site is started with AWS Fargate, you can browse to it at `https://<domain-name>`.

The current setup relies upon an externally hosted container orchestration service (currently AWS ECS with Fargate), externally hosted database (currently AWS RDS) and externally hosted search (currently AWS Elasticsearch).

The current setup relies upon an externally hosted container orchestration service (current AWS ECS with Fargate), externally hosted database (currently AWS RDS) and externally hosted search (currently AWS Elasticsearch).

### Loading Up a Database ###

Loading up a database is usually not necessary since AWS RDS is persistent. Refer to https://github.com/dockstore/dockstore-deploy#database-setup
Loading up a database is usually not necessary since AWS RDS is persistent. Refer to https://github.com/dockstore/dockstore-deploy#database-setup

Note that database migration is run once during the startup process and is controlled via the `DATABASE_GENERATED` variable. Answer `yes` if you are working as a developer and want to start work from scratch from an empty database. Answer `no` if you are working as an administrator and/or wish to start Dockstore from a production or staging copy of the database.
Note that database migration is run once during the startup process (`templates/init_migration.sh.template`) and is controlled via the `DATABASE_GENERATED` value in `compose.config`. Set it to `true` if you are working as a developer and want to start work from scratch from an empty database. Set it to `false` if you are working as an administrator and/or wish to start Dockstore from a production or staging copy of the database.

When a new Dockstore release adds database migrations, add its version to the `--include` list on the last line of `templates/init_migration.sh.template`.

## Logging Usage

If using with logstash in a container (for development), use `-f docker-compose.yml -f docker-compose.dev.yml` flags after each `docker compose` command to merge docker-compose files (e.g. `docker compose -f docker-compse.yml -f docker-compose.dev.yml build`)
## Logging Usage

For example to deploy just logging
The development logging stack (Elasticsearch, Logstash, Kibana, ElastAlert) is defined in `docker-compose.dev.yml`. Its containers use the `awslogs` logging driver, so `LOG_GROUP_NAME` must be set in the environment (or in a `.env` file). Run `bash install_bootstrap` first so that the files it mounts from `config/` exist.

```
docker compose -f docker-compose.dev.yml build
docker compose -f docker-compose.dev.yml build
nohup docker compose -f docker-compose.dev.yml up --force-recreate --remove-orphans >/dev/null 2>&1 &
docker compose -f docker-compose.dev.yml logs --follow
docker compose -f docker-compose.dev.yml down
docker compose -f docker-compose.dev.yml kill
```

`--force-recreate --remove-orphans` re-creates all containers known to compose and removes containers for services that no longer exist. `docker system prune` cleans out old containers and images. See [DEV-README.md](DEV-README.md) for more details on the logging stack.

### Kibana Dashboard Setup ###
Import the [export.json](export.json) Dashboard from compose\_setup/export.json by going to Kibana's management => saved objects => import. See https://www.elastic.co/guide/en/kibana/current/managing-saved-objects.html for more info, especially the 2nd warning.

Expand All @@ -56,16 +58,9 @@ To install and check for git secrets:

```
npm ci
npm run install-git secrets
npm run install-git-secrets
```

This should install git secrets into your local repository and perform a scan.
If secrets are found, the run will error and output the potential secret to stdout.
If you believe the scan is a false-positive, add the line glob to .gitallowed.

## Handy docker-compose commands:
1. `install_bootstrap --script` will template and build everything using your previous answers (useful for quick iteration)
2. `docker compose down` will bring all containers down safely
3. `nohup docker compose up --force-recreate --remove-orphans >/dev/null 2>&1 &` will re-create all containers known to docker-compose and delete those volumes that no longer are associated with running containers
4. `docker system prune` for cleaning out old containers and images
5. To watch the logs `docker compose logs --follow` while debugging
Loading