Skip to content

Commit 25f2137

Browse files
committed
switch to generating the INTERNAL_COMMAND_TOKEN
1 parent b31a457 commit 25f2137

File tree

5 files changed

+66
-14
lines changed

5 files changed

+66
-14
lines changed

.env.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ DATABASE_URL="file:./data.db?connection_limit=1"
44
CACHE_DATABASE_PATH="./other/cache.db"
55
SESSION_SECRET="super-duper-s3cret"
66
HONEYPOT_SECRET="super-duper-s3cret"
7-
INTERNAL_COMMAND_TOKEN="some-made-up-token"
87
RESEND_API_KEY="re_blAh_blaHBlaHblahBLAhBlAh"
98
SENTRY_DSN="your-dsn"
109

10+
# this is set to a random value in the Dockerfile
11+
INTERNAL_COMMAND_TOKEN="some-made-up-token"
12+
1113
# the mocks and some code rely on these two being prefixed with "MOCK_"
1214
# if they aren't then the real github api will be attempted
1315
GITHUB_CLIENT_ID="MOCK_GITHUB_CLIENT_ID"
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Generated Internal Command Env Var
2+
3+
Date: 2024-06-19
4+
5+
Status: accepted
6+
7+
## Context
8+
9+
There are use cases where your application needs to talk to itself over HTTP.
10+
One example of this is when a read-replica instance needs to trigger an update
11+
to the cache in the primary instance. This can be done by making an HTTP request
12+
to the primary instance.
13+
14+
To secure this communication, we can use a secret token that is shared between
15+
the instances. This token can be stored in the environment variables of the
16+
instances.
17+
18+
Originally, this token was manually generated once and set as a secret in the
19+
Fly app. This token was then used in the application code to authenticate the
20+
requests.
21+
22+
However, this manual process is error-prone and can lead to security issues if
23+
the token is leaked.
24+
25+
An alternative is to generate the token in the Dockerfile and set it as an
26+
environment variable in the Fly app. This way, the token is generated
27+
automatically and is unique for each deployment.
28+
29+
One drawback to this is during the deployment process, an old replica might
30+
still be running with the old token. This can cause issues if the new replica is
31+
expecting the new token. However, this should be short-lived and it's also
32+
possible the read replica is running out-of-date code anyway so it may be to our
33+
benefit anyway.
34+
35+
## Decision
36+
37+
We will generate the internal command token in the Dockerfile and set it as an
38+
environment variable in the Fly app.
39+
40+
## Consequences
41+
42+
We'll need to remove the steps during initial setup and the documentation
43+
instructions. This will simplify the setup process and reduce the risk of
44+
security issues due to leaked tokens.

docs/deployment.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ Prior to your first deployment, you'll need to do a few things:
5555
[your repo secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets)
5656
with the name `FLY_API_TOKEN`.
5757

58-
- Add a `SESSION_SECRET`, `INTERNAL_COMMAND_TOKEN`, and `HONEYPOT_SECRET` to
59-
your fly app secrets, to do this you can run the following commands:
58+
- Add a `SESSION_SECRET` and `HONEYPOT_SECRET` to your fly app secrets, to do
59+
this you can run the following commands:
6060

6161
```sh
62-
fly secrets set SESSION_SECRET=$(openssl rand -hex 32) INTERNAL_COMMAND_TOKEN=$(openssl rand -hex 32) HONEYPOT_SECRET=$(openssl rand -hex 32) --app [YOUR_APP_NAME]
63-
fly secrets set SESSION_SECRET=$(openssl rand -hex 32) INTERNAL_COMMAND_TOKEN=$(openssl rand -hex 32) HONEYPOT_SECRET=$(openssl rand -hex 32) --app [YOUR_APP_NAME]-staging
62+
fly secrets set SESSION_SECRET=$(openssl rand -hex 32) HONEYPOT_SECRET=$(openssl rand -hex 32) --app [YOUR_APP_NAME]
63+
fly secrets set SESSION_SECRET=$(openssl rand -hex 32) HONEYPOT_SECRET=$(openssl rand -hex 32) --app [YOUR_APP_NAME]-staging
6464
```
6565

6666
> **Note**: If you don't have openssl installed, you can also use
@@ -190,7 +190,14 @@ node application (on port 8081).
190190
Helpful commands:
191191

192192
```
193-
docker build -t epic-stack . -f other/Dockerfile --build-arg COMMIT_SHA=`git rev-parse --short HEAD` # builds the docker container
194-
mkdir ~/litefs # mountpoint for your sqlite databases
195-
docker run -d -p 8081:8081 -e SESSION_SECRET='somesecret' -e INTERNAL_COMMAND_TOKEN='somesecret' -e HONEYPOT_SECRET='somesecret' -e FLY='false' -v ~/litefs:/litefs epic-stack # Runs the docker container. http://localhost:8081 should now point to your docker instance. ~/litefs directory has the sqlite databases
193+
# builds the docker container
194+
docker build -t epic-stack . -f other/Dockerfile --build-arg COMMIT_SHA=`git rev-parse --short HEAD`
195+
196+
# mountpoint for your sqlite databases
197+
mkdir ~/litefs
198+
199+
# Runs the docker container.
200+
docker run -d -p 8081:8081 -e SESSION_SECRET='somesecret' -e HONEYPOT_SECRET='somesecret' -e FLY='false' -v ~/litefs:/litefs epic-stack
201+
202+
# http://localhost:8081 should now point to your docker instance. ~/litefs directory has the sqlite databases
196203
```

other/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ ENV DATABASE_PATH="$LITEFS_DIR/$DATABASE_FILENAME"
6161
ENV DATABASE_URL="file:$DATABASE_PATH"
6262
ENV CACHE_DATABASE_FILENAME="cache.db"
6363
ENV CACHE_DATABASE_PATH="$LITEFS_DIR/$CACHE_DATABASE_FILENAME"
64+
ENV INTERNAL_COMMAND_TOKEN=$(openssl rand -hex 32)
6465
ENV INTERNAL_PORT="8080"
6566
ENV PORT="8081"
6667
ENV NODE_ENV="production"

remix.init/index.mjs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,10 @@ export default async function main({ rootDirectory }) {
3737
fs.readFile(PKG_PATH, 'utf-8'),
3838
])
3939

40-
const newEnv = env
41-
.replace(/^SESSION_SECRET=.*$/m, `SESSION_SECRET="${getRandomString(16)}"`)
42-
.replace(
43-
/^INTERNAL_COMMAND_TOKEN=.*$/m,
44-
`INTERNAL_COMMAND_TOKEN="${getRandomString(16)}"`,
45-
)
40+
const newEnv = env.replace(
41+
/^SESSION_SECRET=.*$/m,
42+
`SESSION_SECRET="${getRandomString(16)}"`,
43+
)
4644

4745
const newFlyTomlContent = flyTomlContent.replace(
4846
new RegExp(appNameRegex, 'g'),

0 commit comments

Comments
 (0)