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

Add docker-staging.yml for deployment to staging #334

Merged
merged 1 commit into from
Mar 17, 2023
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
5 changes: 2 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ NOTIFICATIONS_EMAIL_USER="[email protected]"
SMTP_PORT=1025

# SSO Config
HOSTNAME=http://localhost:8080
# NOTE: we don't use localhost here due to DNS issues between Docker and host
HOSTNAME=http://host.docker.internal:8080
# The SimpleSAML IDP's XML metadata
SAML_IDP_METADATA_PATH=config/idp-metadata-dev.xml
# Our apps's SP Entity ID, which is also the URL to our metadata.
SAML_ENTITY_ID=http://host.docker.internal:8080/sp
26 changes: 14 additions & 12 deletions DEPLOY.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@ A number of environment variables and Docker secrets are required at runtime.

The following configuration values must be set via environment variables.

| Variable Name | Description |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PORT` | The server runs on port `8080` by default |
| `LOG_LEVEL` | The log level to use for log messages. One of `error`, `debug`, `info`, etc. See [Winston docs](https:/winstonjs/winston#logging-levels). Defaults to `info` |
| `ROOT_DOMAIN` | The DNS root domain for the hosted zone (e.g., `starchart.com`) |
| `AWS_ROUTE53_HOSTED_ZONE_ID` | The existing Amazon Route53 Hosted Zone ID to use (e.g., `Z23ABC4XYZL05B`) |
| `NOTIFICATIONS_EMAIL_USER` | The email address from which notifications are sent |
| `SMTP_PORT` | The port to use for the SMTP server. Defaults to `587` in production (using `smtp.office365.com`) and `1025` in development (using ([MailHog](https:/mailhog/MailHog)) |
| `LETS_ENCRYPT_ACCOUNT_EMAIL` | The email address to use for the app's [single Let's Encrypt account](https://letsencrypt.org/docs/integration-guide/#one-account-or-many) |
| `REDIS_URL` | The Redis server to use for the worker queues. Defaults to `redis://redis:6379` in production and `localhost:6379` in development. |
| `SAML_IDP_METADATA_PATH` | The file path of the SAML Identify Provider (IdP)'s metadata XML. We store various XML files in `config/` and use `config/idp-metadata-dev.xml` by default. |
| `SECRETS_OVERRIDE` | In development, to override the Docker secrets |
| Variable Name | Description |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `HOSTNAME` | The hostname of the server (e.g., `https://mycustomdomain.senecacollege.ca`). NOTE: when running in development, use `http://host.docker.internal:8080` vs. `http://localhost`, so that Docker DNS resolution works between the login container and host. |
| `PORT` | The server runs on port `8080` by default |
| `LOG_LEVEL` | The log level to use for log messages. One of `error`, `debug`, `info`, etc. See [Winston docs](https:/winstonjs/winston#logging-levels). Defaults to `info` |
| `ROOT_DOMAIN` | The DNS root domain for the hosted zone (e.g., `starchart.com`) |
| `AWS_ROUTE53_HOSTED_ZONE_ID` | The existing Amazon Route53 Hosted Zone ID to use (e.g., `Z23ABC4XYZL05B`) |
| `NOTIFICATIONS_EMAIL_USER` | The email address from which notifications are sent |
| `SMTP_PORT` | The port to use for the SMTP server. Defaults to `587` in production (using `smtp.office365.com`) and `1025` in development (using ([MailHog](https:/mailhog/MailHog)) |
| `LETS_ENCRYPT_ACCOUNT_EMAIL` | The email address to use for the app's [single Let's Encrypt account](https://letsencrypt.org/docs/integration-guide/#one-account-or-many) |
| `REDIS_URL` | The Redis server to use for the worker queues. Defaults to `redis://redis:6379` in production and `localhost:6379` in development. |
| `SAML_IDP_METADATA_PATH` | The file path of the SAML Identify Provider (IdP)'s metadata XML. We store various XML files in `config/` and use `config/idp-metadata-dev.xml` by default in development. |
| `SECRETS_OVERRIDE` | In development, to override the Docker secrets |
| `DATABASE_SETUP` | In order to sync the Prisma schema with MySQL, set `DATABASE_SETUP=1` when running the app |

### Secrets

Expand Down
15 changes: 12 additions & 3 deletions app/lib/saml.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,30 @@ const idp = samlify.IdentityProvider({
metadata: xml,
});

const { HOSTNAME } = process.env;

/**
* We require the hostname or can't configure SAML.
*/
if (!HOSTNAME) {
throw new Error('HOSTNAME environment variable is missing');
}

// Here we configure the service provider: https://samlify.js.org/#/sp-configuration
const sp = samlify.ServiceProvider({
entityID: process.env.SAML_ENTITY_ID,
entityID: new URL('/sp', HOSTNAME).href,
nameIDFormat: ['urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'],
wantAssertionsSigned: true,
assertionConsumerService: [
{
Binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
Location: process.env.HOSTNAME + '/login/callback',
Location: new URL('/login/callback', HOSTNAME).href,
},
],
singleLogoutService: [
{
Binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
Location: process.env.HOSTNAME + '/logout/callback',
Location: new URL('/logout/callback', HOSTNAME).href,
},
],
});
Expand Down
67 changes: 67 additions & 0 deletions docker-staging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Stack Definition for Staging
services:
# Redis is used to back our worker queues. It is not exposed.
redis:
image: redis:7.0.9-alpine3.17@sha256:8201775852e31262823ac8da9d76d0c8f36583f1a028b4800c35fc319c75289f
restart: unless-stopped
volumes:
- redis-data:/data
deploy:
placement:
# We run the redis instance on the manager node only
constraints: [node.role == manager]

mycustomdomain:
# Staging runs the most recent commit on the main branch
image: ghcr.io/developingspace/starchart:main
restart: unless-stopped
depends_on:
- redis
ports:
- 8080:8080
environment:
- HOSTNAME=https://mycustomdomain-dev.senecacollege.ca
- AWS_ROUTE53_HOSTED_ZONE_ID=Z0228625ICAL609E0BBT
- [email protected]
- LETS_ENCRYPT_DIRECTORY_URL=https://acme-staging-v02.api.letsencrypt.org/directory
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need to confirm this with @dadolhay.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm going to land, but if this is needing to get changed, let me know if a follow up.

- LOG_LEVEL=info
- NODE_ENV=production
- [email protected]
- PORT=8080
- REDIS_URL=redis://redis:6379
- ROOT_DOMAIN=_stage_.mystudentproject.ca
secrets:
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- DATABASE_URL
- LETS_ENCRYPT_ACCOUNT_PRIVATE_KEY_PEM
- NOTIFICATIONS_USERNAME
- NOTIFICATIONS_PASSWORD
- SESSION_SECRET
deploy:
mode: replicated
replicas: 2
update_config:
# Only update 1 instance at a time, not all at once (rolling-update)
parallelism: 1
# If the update fails, rollback to last-known-good
failure_action: rollback

secrets:
AWS_ACCESS_KEY_ID:
external: true
AWS_SECRET_ACCESS_KEY:
external: true
DATABASE_URL:
external: true
LETS_ENCRYPT_ACCOUNT_PRIVATE_KEY_PEM:
external: true
NOTIFICATIONS_USERNAME:
external: true
NOTIFICATIONS_PASSWORD:
external: true
SESSION_SECRET:
external: true

volumes:
redis-data: