Deploying Astro to Fly: Part 2
4 min readA quick how-to guide on deploying your server-side rendered Astro projects to Fly.io.

Introduction
In part one of the series we covered how to deploy static Astro projects to fly.io. Here in part two we will cover how to deploy server-side rendered Astro projects, and it’s just as easy if not easier!
Updating our Astro Project for SSR
pnpm astro add node
import { defineConfig } from 'astro/config';
+ import node from '@astrojs/node';
export default defineConfig({
+ adapter: node({
+ mode: 'standalone',
+ }),
+ output: 'server',
+ server: {
+ port: 3000,
+ },
site: "https://astro-project.fly.dev",
});
Updating Docker & Fly Configurations
We are basically going to revert what we did to both files. Like I mentioned before this is actually easier than the static deployment.
# syntax = docker/dockerfile:1
# Adjust NODE_VERSION as desired
ARG NODE_VERSION=20.9.0
FROM node:${NODE_VERSION}-slim as base
LABEL fly_launch_runtime="Node.js"
# Node.js app lives here
WORKDIR /app
# Set production environment
ENV NODE_ENV="production"
# Install pnpm
ARG PNPM_VERSION=8.10.5
RUN npm install -g pnpm@$PNPM_VERSION
# Throw-away build stage to reduce size of final image
FROM base as build
# Install packages needed to build node modules
- RUN apt-get update -qq && \
- apt-get install -y build-essential pkg-config python-is-python3
+ RUN apt-get update -qq && \
+ apt-get install --no-install-recommends -y build-essential node-gyp pkg-config python-is-python3
# Install node modules
COPY --link package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod=false
# Copy application code
COPY --link . .
# Build application
RUN pnpm run build
# Remove development dependencies
RUN pnpm prune --prod
# Final stage for app image
- FROM pierrezemb/gostatic
+ FROM base
# Copy built application
- COPY --from=build /app/dist /srv/http
+ COPY --from=build /app /app
# Start the server by default, this can be overwritten at runtime
+ EXPOSE 3000
+ CMD [ "pnpm", "run", "start" ]
# fly.toml app configuration file generated for astro-project on 2024-01-07T13:23:32-05:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#
app = "astro-project"
primary_region = "bog"
[build]
- [[services]]
- http_checks = []
- internal_port = 8043
- processes = ["app"]
- protocol = "tcp"
- script_checks = []
-
- [[services.concurrency]]
- hard_limit = 25
- soft_limit = 20
- type = "connections"
-
- [[services.ports]]
- handlers = ["http"]
- port = 80
- force_https = true
-
- [[services.ports]]
- handlers = ["tls", "http"]
- port = 443
-
- [[services.tcp_checks]]
- grace_period = "1s"
- interval = "15s"
- restart_limit = 0
- timeout = "2s"
+ [http_service]
+ internal_port = 3000
+ force_https = true
+ auto_stop_machines = true
+ auto_start_machines = true
+ min_machines_running = 0
+ processes = ["app"]
[[vm]]
cpu_kind = "shared"
cpus = 1
memory_mb = 1024
One last thing we will need to do before we can deploy is update our start
script in the package.json
. When we run pnpm build
their will be a dist/
that is output by Astro. In this directory you should find another directory called server/
with an entry.mjs
file inside of it. This is the file that we will need to tell Docker to execute on Fly’s servers.
{
"name": "astro-project",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
- "start": "astro dev",
+ "start": "HOST=0.0.0.0 node ./dist/server/entry.mjs",
"build": "astro check && astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/check": "~0.3.4",
"@astrojs/node": "7.0.4",
"astro": "^4.1.1",
"typescript": "~5.3.3"
},
"devDependencies": {
"@flydotio/dockerfile": "~0.5.0"
}
}
NOTE: Please note the addition of
HOST=0.0.0.0
to the command. This is necessary as when we start the server Astro believes it is running locally so we end up with 127.0.0.1:3000. This is fine on your and my machine but on Fly this will not…fly…hahaha!
And with that we can run fly deploy
and wait to visit our updated Astro project that is not server-side rendered.
fly deploy
==> Verifying app config
Validating /Users/cody/Developer/Personal/astro-project/fly.toml
Platform: machines
✓ Configuration is valid
--> Verified app config
==> Building image
Remote builder fly-builder-throbbing-bush-1757 ready
Remote builder fly-builder-throbbing-bush-1757 ready
==> Building image with Docker
--> docker host: 20.10.12 linux x86_64
# #########################
# ... Lots of Docker output
# #########################
Watch your deployment at https://fly.io/apps/astro-project/monitoring
-------
Updating existing machines in 'astro-project' with rolling strategy
-------
✔ [1/2] Machine 9080ee2df06258 [app] update succeeded
✔ [2/2] Machine e7842741b99483 [app] update succeeded
-------
Visit your newly deployed app at https://astro-project.fly.dev/
Related Articles
From NextJS to Astro
In 2023 I began making the move from NextJS to Astro for my personal website and blog. This is my experience with the transition.
Deploying Astro to Fly: Part 1
A quick how-to guide on deploying your static Astro projects to Fly.io.
Certificate Issues Between Fly & Turso
That time I ran into issues with my certificates being invalid leading to problems communicating between Fly.io and my Turso database.
Adding Related Articles with Astro Content Collections
Astro's content collection feature is a game changer for easily managing content in a type safe manner. It also can help to easily add related collections or data types through referencing. In this article I show how I implemented a related articles feature.
Cody is a Christian, USN Veteran, Jayhawk, and an American expat living outside of Bogotá, Colombia. He is currently looking for new opportunities in the tech industry.