Skip to content

Commit 4b79fb6

Browse files
authored
Use a .env file for local dev instance config (#728)
+ Install dotenv Gradle plugin to source instance configs as env vars, reading a `.env` file for local development launches via `bootRun`. + This replaces the prior use of a YAML file in `/etc/hoist/conf` for Toolbox. + Include `.env.template` to enumerate required vars. + Update README to document. + NOTE - requires new `build.gradle` file to be created at root directory of wrapper projects (Toolbox + hoist-core checked out together). Documented w/required file contents in the README.
1 parent 1be5f2d commit 4b79fb6

File tree

5 files changed

+128
-86
lines changed

5 files changed

+128
-86
lines changed

Diff for: .env.template

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Duplicate this file in your local repo with filename `.env`. It will be ignored by git, but loaded
2+
# by Gradle via a dotenv Gradle plugin and passed to Toolbox to use as instance configs.
3+
4+
# Note that any values provided in this template will never be read - they are there to provide
5+
# example values only. Any uncommented vars in this file *must* be set in a local .env file.
6+
# See the README for more information.
7+
8+
# Required variables - must be set in .env, build will throw if missing.
9+
APP_TOOLBOX_ENVIRONMENT=Development
10+
APP_TOOLBOX_DB_HOST=localhost
11+
APP_TOOLBOX_DB_SCHEMA=toolbox
12+
APP_TOOLBOX_DB_USER=toolbox
13+
APP_TOOLBOX_DB_PASSWORD=toolbox
14+
15+
# Additional DB options
16+
#APP_TOOLBOX_USE_H2=true
17+
#APP_TOOLBOX_DB_CREATE=update
18+
19+
# Bootstrap admin
20+
# The _USER var can be set on its own to grant an OAuth (Auth0) sourced user admin rights in local
21+
# development. This is supported by Toolbox's use of Hoist Core DefaultRoleService.
22+
#APP_TOOLBOX_BOOTSTRAP_ADMIN_USER=
23+
24+
# If the _PASSWORD var is also set, Toolbox will create a password-enabled user in its user
25+
# database that can be used when Auth0 is not available. Pair this with the env below to disable
26+
# the OAuth flow entirely and present a form-based login.
27+
#APP_TOOLBOX_BOOTSTRAP_ADMIN_PASSWORD=
28+
#APP_TOOLBOX_USE_OAUTH=false
29+
30+
# Email support
31+
#APP_TOOLBOX_SMTP_HOST=
32+
#APP_TOOLBOX_SMTP_USER=
33+
#APP_TOOLBOX_SMTP_PASSWORD=

Diff for: .gitignore

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# IDE Files (mostly)
2-
###################
32
.idea/*
43
!/.idea/scopes/
54
!/.idea/copyright/
@@ -8,8 +7,11 @@
87
.project
98
.classpath
109

11-
# Compiled source #
12-
###################
10+
# Local instance configs w/secrets
11+
toolbox.yml
12+
.env
13+
14+
# Compiled source
1315
.gradle/
1416
build/
1517
bin/
@@ -18,14 +20,11 @@ out/
1820
/client-app/node_modules/
1921
/client-app/tsconfig.tsbuildinfo
2022

21-
# Logs #
22-
########
23+
# Logs
2324
toolbox-logs/
2425
*.log
25-
toolbox.yml
2626

27-
# OS generated files #
28-
######################
27+
# OS generated files
2928
.DS_Store
3029
.DS_Store?
3130
ehthumbs.db

Diff for: README.md

+68-76
Original file line numberDiff line numberDiff line change
@@ -23,60 +23,36 @@ applications, which typically use whatever enterprise database is already in pla
2323
infrastructure, but it provides a common and easy-to-run DB for local development and our AWS-based
2424
deployments.
2525

26-
* For initial/test usage, Toolbox is configured to use an in-memory H2 database that will be
27-
rebuilt at startup of the app. This is governed by the `useH2` instance configuration (see below).
28-
* For persistent deployments, Toolbox is designed to work with MySQL 5.x.*. If you don't already
29-
have it installed and are on a Mac, we recommend installing via [Homebrew](https://brew.sh/) with
30-
`brew install [email protected]`.
31-
* Create a new empty database named `toolbox`, being sure to use a UTF8 charset. Alternatively, use
32-
an export of the deployed toolbox DB with `CREATE DATABASE` included (Anselm can provide).
33-
* For local development, use of the `root` account is fine, or you can create a local user and
34-
password dedicated to Toolbox. If using a non-root account, ensure that the user has DBO rights on
35-
the new database.
26+
* For initial/test usage, Toolbox is can run with a transient in-memory database (H2) that will be
27+
rebuilt at startup of the app. This is enabled via the `useH2` instance configuration (see below).
28+
* For persistent deployments, Toolbox is designed to work with MySQL. If you don't already have it
29+
installed and are on a Mac, we recommend installing via [Homebrew](https://brew.sh/) with
30+
`brew install mysql`.
31+
* Create a new empty database named `toolbox`, being sure to use a UTF8 charset (fortunately this is
32+
the default for newer versions of MySQL). Alternatively, use an export of the deployed toolbox DB
33+
with `CREATE DATABASE` included (Anselm can provide).
34+
* For local development, use of the `root` account is fine, or (better) you can create a local user
35+
and password dedicated to Toolbox. If using a non-root account, ensure that the user has DBO
36+
rights on the new database. Database credentials are provided to the app via instance
37+
configuration (see below).
3638
* If the server is started against an empty database, Grails will auto-create the required schemas
3739
on first run as long as a suitable value is provided for the `dbCreate` data source parameter. See
38-
`grails-app/conf/runtime.groovy` for where this is set - we leave toolbox on `update` to allow for
39-
automatic schema changes as needed.
40+
the `DBConfig` class for where this is set - we leave toolbox on `update` to allow for automatic
41+
schema changes as needed.
4042

4143
## Instance Configuration
4244

43-
Hoist applications can read low-level, instance-specific information from a YML configuration file
44-
on the local machine where they run. This is used primarily to set database credentials, which we
45-
don't wish to check in to source control but which are required to connect to the DB and read all
46-
_other_ data-driven app configurations.
47-
48-
* Create a new instance config file - the default location is `/etc/hoist/conf/toolbox.yml`.
49-
* If you don't wish to create that directory structure under `/etc/`, you can place the same file
50-
elsewhere and point the server there with a JavaOpt - see the hoist-core provided
51-
[`InstanceConfigUtils.groovy`](https://github.com/xh/hoist-core/blob/develop/src/main/groovy/io/xh/hoist/util/InstanceConfigUtils.groovy)
52-
for details.
53-
* The contents of this file (for Toolbox) will typically be as follows:
54-
55-
```
56-
environment: Development
57-
serverURL: http://localhost
58-
59-
# The following are for use in early runs of the project before you have granted roles to any users,
60-
# or in cases where Auth0 isn't acting as expected, or you're hosting the app on a device.
61-
# The bootstrapAdminUser will be available for forms based login and will be granted the role
62-
# needed (HOIST_ROLE_MANAGER) to grant access to other users.
63-
useOAuth: false
64-
bootstrapAdminUser: [email protected]
65-
bootstrapAdminPassword: "your password"
66-
67-
# Enable in memory h2 database option. When ready, configure proper DB below and set to false
68-
useH2: true
69-
70-
# MySql DB config - provide either root or a dedicated local account, if using.
71-
dbHost: localhost:3306
72-
dbSchema: toolbox
73-
dbUser: root
74-
dbPassword: "your database user password"
75-
```
76-
77-
* When running the Toolbox server, look for a message along the lines of "Loaded 10 instanceConfigs
78-
from /etc/hoist/conf/toolbox.yml" to be logged to the console early on in the startup process.
79-
This will indicate that Hoist has successfully read your config.
45+
Hoist applications require low-level "instance configuration" properties to provide settings such
46+
as database credentials and other environment-specific settings that should not be checked into
47+
source control. These properties can be set in one of two primary ways: a YAML file on the local
48+
filesystem, or environment variables.
49+
50+
Toolbox is configured to source these properties from *environment variables*, and uses a Gradle
51+
plugin to read them from a `.env` file in the project root. That file should never be pushed to git
52+
(it's listed in .gitignore accordingly), but an `.env.template` file *is* checked-in to enumerate
53+
required and optional properties.
54+
55+
Copy `.env.template` to `.env` and fill in the required values for your local database connection.
8056

8157
## Authentication
8258

@@ -88,27 +64,6 @@ When adding a new top-level entry-point for Toolbox (such as a new example appli
8864
URL must be registered with Auth0 as a valid OAuth callback URL. Either Lee or Anselm can update our
8965
Auth0 config accordingly.
9066

91-
## Developing with HTTPS on `xh.io` domain
92-
93-
It can be useful to run Toolbox locally with HTTPS enabled and on a sub-domain of `xh.io`,
94-
especially when testing OAuth, CORS, or cookie dependent features.
95-
Follow these steps to run with HTTPS on the `toolbox-local.xh.io:3000` domain:
96-
1. add this entry to your dev machine's `hosts` file: `127.0.0.1 toolbox-local.xh.io`
97-
2. start the Grails server with the following additional VM Options:
98-
```
99-
-Dserver.ssl.enabled=true
100-
-Dserver.ssl.certificate=classpath:local-dev/toolbox-local.xh.io-self-signed.crt
101-
-Dserver.ssl.certificate-private-key=classpath:local-dev/toolbox-local.xh.io-self-signed.key
102-
-Dserver.ssl.trust-certificate=classpath:local-dev/toolbox-local.xh.io-self-signed.ca.crt
103-
```
104-
The referenced files are self-signed certs commited to the repo for local dev purposes.
105-
They expire on Sunday, May 21, 2034 at 6:11:28AM.
106-
3. Visit `https://toolbox-local.xh.io:8080/ping` in your browser to proceed past the SSL warning
107-
for API calls.
108-
4. Start the GUI with the `startWithHoistSecure` npm script. Go to `https://toolbox-local.xh.io:3000/app/home`
109-
in your browser and proceed past the SSL warning.
110-
111-
11267
## Wrapper project for Toolbox + Hoist development
11368

11469
A special project / directory structure can be useful for developing Toolbox alongside the Hoist
@@ -123,17 +78,34 @@ use when setting up Toolbox.
12378
* Create a new `settings.gradle` file within the top-level directory. The contents of this file will
12479
be a single line: `include "toolbox", "hoist-core"`. This tells Gradle to reference and combine
12580
the `build.gradle` targets of those two sub-projects into a single umbrella project.
81+
* Create a new `build.gradle` file within the top-level directory. This is required to support the
82+
`co.uzzu.dotenv` plugin used by Toolbox to read environment variables - the plugin must be applied
83+
to the root project, which is the top-level wrapper directory in this mode. The Toolbox
84+
`build.gradle` file is where the plugin is actually applied, but for that to work in wrapper mode
85+
the plugin must be defined within the root (wrapper) project also, requiring a build file. Its
86+
contents should be:
87+
```groovy
88+
buildscript {
89+
repositories {
90+
gradlePluginPortal()
91+
}
92+
dependencies {
93+
classpath "co.uzzu.dotenv:gradle:4.0.0" // keep in sync with version in Toolbox build.gradle
94+
}
95+
}
96+
```
12697
* From the checked-out `toolbox` sub-directory, copy the `gradle` directory and the `gradlew` (or
12798
`gradlew.bat` if on Windows) wrapper script and paste the copies into the top-level wrapper
12899
directory.
129-
* Your top-level directory should now contain four sub-directories, `settings.gradle`, and the
130-
`gradlew` script.
100+
* Your top-level directory should now contain four sub-directories, `settings.gradle`,
101+
`build.gradle`, and the `gradlew` script.
131102
* From the top-level directory, run `./gradlew` to ensure that Gradle can properly configure the
132103
unified build.
133-
* If using IntelliJ, create a newJ project by running through the "New project from existing
104+
* If using IntelliJ, create a new project by running through the "New project from existing
134105
sources..." workflow and pointing the IDE at the top-level `settings.gradle` file.
135-
* IntelliJ should detect that this is a Gradle/Grails project, download and index the server-side
136-
dependencies, and set up an appropriate "Run Configuration" to start the Toolbox server.
106+
* IntelliJ should detect that this is a Gradle/Grails project, download and index the
107+
server-side dependencies, and set up an appropriate "Run Configuration" to start the Toolbox
108+
server.
137109
138110
Having all three repos checked out in a single IntelliJ project can be useful to have the code
139111
on-hand, but to actually run Toolbox using the local Hoist libraries some additional steps are
@@ -146,8 +118,28 @@ required.
146118
* To run the client using the local `hoist-react`, start your local webpack-dev-server from the
147119
`toolbox/client-app` directory by running `yarn startWithHoist`.
148120
121+
## Developing with HTTPS on `xh.io` domain
122+
123+
It can be useful to run Toolbox locally with HTTPS enabled and on a sub-domain of `xh.io`,
124+
especially when testing OAuth, CORS, or cookie dependent features. Follow these steps to run with
125+
HTTPS on the `toolbox-local.xh.io:3000` domain:
126+
127+
1. Add this entry to your dev machine's `hosts` file: `127.0.0.1 toolbox-local.xh.io`
128+
2. Start the Grails server with the additional VM options below. The referenced files are
129+
self-signed certs commited to the repo for local dev purposes.
130+
```
131+
-Dserver.ssl.enabled=true
132+
-Dserver.ssl.certificate=classpath:local-dev/toolbox-local.xh.io-self-signed.crt
133+
-Dserver.ssl.certificate-private-key=classpath:local-dev/toolbox-local.xh.io-self-signed.key
134+
-Dserver.ssl.trust-certificate=classpath:local-dev/toolbox-local.xh.io-self-signed.ca.crt
135+
```
136+
3. Visit `https://toolbox-local.xh.io:8080/ping` in your browser to proceed past the SSL warning
137+
for API calls.
138+
4. Start the GUI with the `startWithHoistSecure` npm script. Go to
139+
`https://toolbox-local.xh.io:3000/app/` in your browser and proceed past the SSL warning.
140+
149141
------------------------------------------
150142
151143
📫☎️🌎 [email protected] | <https://xh.io/contact>
152144
153-
Copyright © 2022 Extremely Heavy Industries Inc.
145+
Copyright © 2024 Extremely Heavy Industries Inc.

Diff for: build.gradle

100755100644
+18-1
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import static java.lang.Boolean.parseBoolean
33
buildscript {
44
repositories {
55
mavenCentral()
6-
maven {url 'https://plugins.gradle.org/m2/'}
6+
gradlePluginPortal()
77
maven {url 'https://repo.grails.org/grails/core'}
88
}
99
dependencies {
1010
classpath "org.grails:grails-gradle-plugin:$grailsGradlePluginVersion"
1111
classpath "org.grails.plugins:hibernate5:$grailsHibernatePluginVersion"
12+
classpath "co.uzzu.dotenv:gradle:$dotEnvGradlePluginVersion"
1213
}
1314
}
1415

@@ -19,6 +20,12 @@ apply plugin:'idea'
1920
apply plugin:'war'
2021
apply plugin:'org.grails.grails-web'
2122

23+
// Must be applied to root project - matters when running Toolbox in a wrapper project mode w/hoist-core.
24+
// See README.md for more details on this configuration, including contents of top-level build.gradle file.
25+
gradle.rootProject {
26+
apply plugin:'co.uzzu.dotenv.gradle'
27+
}
28+
2229
repositories {
2330
mavenCentral()
2431
maven {url 'https://repo.grails.org/grails/core'}
@@ -106,6 +113,8 @@ bootRun {
106113
jvmArgs(allJvmArgs)
107114
sourceResources sourceSets.main
108115
systemProperties hoistMetaData
116+
// Bring .env sourced environment variables into bootRun JVM process.
117+
environment env.allVariables()
109118
}
110119

111120
tasks.withType(GroovyCompile) {
@@ -133,3 +142,11 @@ tasks.war.doFirst {
133142
properties.putAll(hoistMetaData)
134143
infoFile.withOutputStream {properties.store(it, null)}
135144
}
145+
146+
// Ensure that all variables defined in .env.template are set in local .env
147+
tasks.bootRun.doFirst {
148+
def missingEnvVars = env.allVariablesOrNull().findAll {it.value == null}.collect {it.key}
149+
if (missingEnvVars) {
150+
throw new GradleException("Environment variables listed in .env.template not set in local .env file as required: ${missingEnvVars}")
151+
}
152+
}

Diff for: gradle.properties

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ hoistCoreVersion=21.0-SNAPSHOT
88
groovyVersion=3.0.21
99
grailsVersion=6.2.0
1010
grailsGradlePluginVersion=6.2.0
11-
gormVersion=8.1.0
11+
dotEnvGradlePluginVersion=4.0.0
1212
grailsHibernatePluginVersion=8.1.0
13+
gormVersion=8.1.0
1314
hazelcast.version=5.3.7
1415
logback.version=1.2.7
1516

0 commit comments

Comments
 (0)