Skip Navigation

Scott Spence

SvelteKit Environment Variables with Fly.io Deployment

• 3 min read
Hey! Thanks for stopping by! Looks like this post was updated 3 years ago. Just bear in mind it was originally posted 3 years ago. If there's anything in here which doesn't make sense, please get in touch.

Real quick! I’m going to go through what I did to get a SvelteKit project deployed to Fly.io and how to set up environment variables. The back story is that I wasn’t getting the best response times from the project I deployed to Vercel for Building Session Analytics with SvelteKit and Turso DB. It was an experiment but still, waiting 6 seconds for a response from the server is not good.

I decide to try out Fly.io and see if I could get better result. There’s a speed run over on the Fly.io docs that get’s you started: https://fly.io/docs/js/frameworks/svelte

This doesn’t cover what you need to do to get environment variables working though.

I followed the steps in the speed run and kept getting errors like this:

1#0 5.057 "TURSO_DB_URL" is not exported by "virtual:$env/static/private", imported by "src/lib/turso/client.ts".
2#0 5.057 file: /app/src/lib/turso/client.ts:3:1
3#0 5.057 1: import {
4#0 5.057 2:   TURSO_DB_AUTH_TOKEN,
5#0 5.057 3:   TURSO_DB_URL,
6#0 5.057      ^
7#0 5.057 4: } from '$env/static/private';

I couldn’t get the static private environment variables to work so I decided to try out the dynamic private environment variables.

So, anywhere I was importing the static private environment variables I changed to dynamic private:

1-import {
2-  TURSO_DB_AUTH_TOKEN,
3-  TURSO_DB_URL,
4-} from '$env/static/private';
5+import { env } from '$env/dynamic/private';
6+const { TURSO_DB_AUTH_TOKEN, TURSO_DB_URL } = env;

Then made sure my secrets were available to the fly CLI:

1fly secrets set TURSO_DB_URL=secret_token
2fly secrets set TURSO_DB_AUTH_TOKEN=secret_token
3fly secrets set IPINFO_TOKEN=secret_token

Then I needed to add the secrets to the Docker file created by fly launch:

1# ...
2
3# Copy application code
4COPY --link . .
5
6# Mount secrets and build application
7RUN --mount=type=secret,id=TURSO_DB_AUTH_TOKEN \
8    --mount=type=secret,id=TURSO_DB_URL \
9    --mount=type=secret,id=IPINFO_TOKEN \
10    TURSO_DB_AUTH_TOKEN="$(cat /run/secrets/TURSO_DB_AUTH_TOKEN)" \
11    TURSO_DB_URL="$(cat /run/secrets/TURSO_DB_URL)" \
12    IPINFO_TOKEN="$(cat /run/secrets/IPINFO_TOKEN)" \
13    && pnpm run build
14
15# Remove development dependencies
16RUN pnpm prune --prod
17
18# ...

Then deploying again (with fly deploy) worked!

One other thing to note is that the Fly CLI doesn’t seem to pick up the environment variables so I had to add them manually to the fly deploy command each time I want to deploy:

1fly deploy --build-secret TURSO_DB_URL="secret_token" --build-secret TURSO_DB_URL="secret_token" --build-secret IPINFO_TOKEN="secret_token"

Update

Another update to this, it seems that the Fly CLI changes a fair bit!

I was getting countless issues with building and not having the secrets available to the Docker build. I found something that worked for me.

So, I had to add the secrets to the Dockerfile ARG TURSO_DB_URL and ARG TURSO_DB_AUTH_TOKEN, then build the app with the tokens RUN TURSO_DB_URL=$TURSO_DB_URL TURSO_DB_AUTH_TOKEN=$TURSO_DB_AUTH_TOKEN pnpm run build:

1# syntax = docker/dockerfile:1
2
3# Adjust NODE_VERSION as desired
4ARG NODE_VERSION=18.19.0
5FROM node:${NODE_VERSION}-slim as base
6
7# Declare build arguments for secrets
8ARG TURSO_DB_URL
9ARG TURSO_DB_AUTH_TOKEN
10
11LABEL fly_launch_runtime="Node.js"
12
13# Node.js app lives here
14WORKDIR /app
15
16# Set production environment
17ENV NODE_ENV="production"
18
19# Install pnpm
20ARG PNPM_VERSION=8.15.4
21RUN npm install -g pnpm@$PNPM_VERSION
22
23# Throw-away build stage to reduce size of final image
24FROM base as build
25
26# Install packages needed to build node modules
27RUN apt-get update -qq && \
28    apt-get install --no-install-recommends -y build-essential node-gyp pkg-config python-is-python3
29
30# Install node modules
31COPY --link .npmrc package.json pnpm-lock.yaml ./
32RUN pnpm install --frozen-lockfile --prod=false
33
34# Copy application code
35COPY --link . .
36
37# Build application using build arguments
38RUN TURSO_DB_URL=$TURSO_DB_URL TURSO_DB_AUTH_TOKEN=$TURSO_DB_AUTH_TOKEN pnpm run build
39
40# Remove development dependencies
41RUN pnpm prune --prod
42
43# Final stage for app image
44FROM base
45
46# Copy built application
47COPY --from=build /app /app
48
49# Start the server by default, this can be overwritten at runtime
50EXPOSE 3000
51CMD [ "pnpm", "run", "start" ]

Then also had to pass them into the fly deploy command:

1fly deploy --build-arg TURSO_DB_URL=$TURSO_DB_URL --build-arg TURSO_DB_AUTH_TOKEN=$TURSO_DB_AUTH_TOKEN

😅

There's a reactions leaderboard you can check out too.

Sign up for the newsletter

Want to keep up to date with what I'm working on?

Join other developers and sign up for the newsletter.

I care about the protection of your data. Read the Privacy Policy for more info.

Copyright © 2017 - 2026 - All rights reserved Scott Spence