Skip to content

Commit

Permalink
fly wip
Browse files Browse the repository at this point in the history
  • Loading branch information
elliotBraem committed Jan 15, 2025
1 parent e57b612 commit 5a2a0df
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 41 deletions.
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,8 @@ frontend/**/*.sw?
# flyctl launch added from node_modules/tailwindcss/stubs/.gitignore
!node_modules/tailwindcss/stubs/**/*
fly.toml

# workspace
landing-page
docs
.github
18 changes: 18 additions & 0 deletions .github/workflows/fly-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# See https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/

name: Fly Deploy
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy app
runs-on: ubuntu-latest
concurrency: deploy-group # optional: ensure only one action runs at a time
steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: flyctl deploy --remote-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
20 changes: 13 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,15 @@ RUN bun run build
FROM oven/bun as production
WORKDIR /app

# Create directory for mount with correct permissions
RUN mkdir -p /.data/db /.data/cache && \
chown -R bun:bun /.data
# Install LiteFS dependencies
RUN apt-get update -y && apt-get install -y ca-certificates fuse3 sqlite3

# Copy LiteFS binary
COPY --from=flyio/litefs:0.5 /usr/local/bin/litefs /usr/local/bin/litefs

# Create directories for mounts with correct permissions
RUN mkdir -p /litefs /var/lib/litefs /public && \
chown -R bun:bun /litefs /var/lib/litefs /public

# Copy only necessary files from builder
COPY --from=builder --chown=bun:bun /app/package.json /app/bun.lockb /app/turbo.json ./
Expand All @@ -41,12 +47,12 @@ COPY --from=builder --chown=bun:bun /app/frontend/dist ./frontend/dist
COPY --from=builder --chown=bun:bun /app/backend/dist ./backend/dist

# Set environment variables
ENV DATABASE_URL="file:/.data/db/sqlite.db"
ENV CACHE_DIR="/.data/cache"
ENV DATABASE_URL="file:/litefs/db"
ENV CACHE_DIR="/litefs/cache"
ENV NODE_ENV="production"

# Expose the port
EXPOSE 3000

# Start the application using the production start script
CMD ["bun", "run", "start"]
# Start LiteFS (runs app with distributed file system for SQLite)
ENTRYPOINT ["litefs", "mount"]
Binary file modified bun.lockb
Binary file not shown.
63 changes: 44 additions & 19 deletions docs/docs/developers/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,22 @@ fly auth login
1. Initialize your Fly.io application:

```bash
cd backend/
bun run deploy:init
```

2. Create persistent volumes for SQLite and cache:
2. Create the LiteFS volume (see [LiteFS Spreedrun](https://fly.io/docs/litefs/speedrun/) for more information):

```bash
bun run deploy:volumes
```

3. Deploy the application:
3. Attach Consul for LiteFS cluster management (this sets the FLY_CONSUL_URL secret for the app, which is required for LitefS leases):

```bash
bun run deploy:consul
```

4. Deploy the application:

```bash
bun run deploy
Expand All @@ -60,11 +65,26 @@ bun run deploy

The deployment includes:

- Persistent storage for SQLite database
- Cache directory support
- Auto-scaling configuration
- Distributed SQLite using LiteFS
- Automatic file replication across instances
- High availability with minimum 2 machines
- Primary/replica configuration using Consul
- HTTPS enabled by default

#### Architecture

- Primary instance (LAX region) handles write operations
- Replicas automatically sync data from primary
- Consul manages primary/replica coordination
- Files in /public directory are replicated across instances
- Automatic failover if primary becomes unavailable

#### Key Files

- `fly.toml`: Main Fly.io configuration
- `litefs.yml`: LiteFS configuration
- `Dockerfile`: Container and LiteFS setup

### Environment Variables

Make sure to configure your environment variables in Fly.io:
Expand Down Expand Up @@ -103,18 +123,23 @@ fly dashboard
Common issues and solutions:

1. **Database Connection Issues**
- Verify volume mount paths
- Check SQLite file permissions
- Ensure volumes are properly created

2. **Memory/CPU Issues**
- Monitor resource usage with `fly status`
- Adjust VM size if needed
- Consider enabling auto-scaling

3. **Network Issues**
- Check Fly.io region configuration
- Verify firewall settings
- Test network connectivity
- Check LiteFS mount status: `fly ssh console -C "ls -la /litefs"`
- Verify Consul connection: `fly consul status`
- Check primary/replica status: `fly logs`

2. **File Replication Issues**
- Verify LiteFS FUSE mount: `fly ssh console -C "mount | grep litefs"`
- Check file permissions: `fly ssh console -C "ls -la /public"`
- Monitor LiteFS logs: `fly logs --level debug`

3. **Memory/CPU Issues**
- Monitor resource usage: `fly status`
- Check machine distribution: `fly scale show`
- Adjust VM configuration in fly.toml if needed

4. **Primary/Replica Issues**
- Verify Consul health: `fly consul status`
- Check region configuration: `fly regions list`
- Monitor primary elections: `fly logs --level info`

For more help, consult the [Fly.io documentation](https://fly.io/docs/) or join their [community Discord](https://fly.io/discord).
11 changes: 5 additions & 6 deletions fly.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# fly.toml app configuration file generated for public-goods-news-quiet-wildflower-8563 on 2024-12-18T14:47:13-06:00
# fly.toml app configuration file generated for curatedotfun on 2025-01-15T13:48:42-07:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = 'public-goods-news-quiet-wildflower-8563'
primary_region = 'lax'
app = 'curatedotfun'
primary_region = 'den'

[build]
dockerfile = 'Dockerfile'
Expand All @@ -13,10 +13,9 @@ primary_region = 'lax'
PORT = '3000'

[[mounts]]
source = 'data'
destination = '/.data'
source = "litefs"
destination = "/var/lib/litefs"
initial_size = '1GB'

[http_service]
internal_port = 3000
force_https = true
Expand Down
5 changes: 3 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
"tailwindcss": "^3.4.16"
},
"devDependencies": {
"@rsbuild/core": "1.1.9",
"@eslint/js": "^9.15.0",
"@rsbuild/core": "1.1.13",
"@rsbuild/plugin-react": "1.1.0",
"@tanstack/router-plugin": "^1.97.0",
"@eslint/js": "^9.15.0",
"@types/bun": "^1.1.16",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.4",
Expand Down
6 changes: 3 additions & 3 deletions frontend/rsbuild.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { defineConfig } from '@rsbuild/core'
import { pluginReact } from '@rsbuild/plugin-react'
import { TanStackRouterRspack } from '@tanstack/router-plugin/rspack'
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import { TanStackRouterRspack } from '@tanstack/router-plugin/rspack';

export default defineConfig({
plugins: [pluginReact()],
Expand Down
54 changes: 54 additions & 0 deletions litefs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# The fuse section describes settings for the FUSE file system. This file system
# is used as a thin layer between the SQLite client in your application and the
# storage on disk. It intercepts disk writes to determine transaction boundaries
# so that those transactions can be saved and shipped to replicas.
fuse:
dir: "/litefs"
mount-timeout: "5s"
allow-other: true
directories:
- path: "/public"
read-only: false

# The data section describes settings for the internal LiteFS storage. We'll
# mount a volume to the data directory so it can be persisted across restarts.
# However, this data should not be accessed directly by the user application.
data:
dir: "/var/lib/litefs"

# This flag ensure that LiteFS continues to run if there is an issue on starup.
# It makes it easy to ssh in and debug any issues you might be having rather
# than continually restarting on initialization failure.
exit-on-error: false

# This section defines settings for the option HTTP proxy.
# This proxy can handle primary forwarding & replica consistency
# for applications that use a single SQLite database.
proxy:
addr: ":8080"
target: "localhost:3000"
db: "db"
passthrough:
- "*.ico"
- "*.png"

# This section defines a list of commands to run after LiteFS has connected
# and sync'd with the cluster. You can run multiple commands but LiteFS expects
# the last command to be long-running (e.g. an application server). When the
# last command exits, LiteFS is shut down.
exec:
- cmd: "bun run start"

# The lease section specifies how the cluster will be managed. We're using the
# "consul" lease type so that our application can dynamically change the primary.
#
# These environment variables will be available in your Fly.io application.
lease:
type: "consul"
advertise-url: "http://${HOSTNAME}.vm.${FLY_APP_NAME}.internal:20202"
candidate: ${FLY_REGION == PRIMARY_REGION}
promote: true

consul:
url: "${FLY_CONSUL_URL}"
key: "litefs/${FLY_APP_NAME}"
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "public-goods-news",
"name": "curate-dot-fun",
"private": true,
"type": "module",
"packageManager": "[email protected]",
Expand All @@ -9,15 +9,14 @@
"start": "NODE_ENV=production bun run backend/dist/index.js",
"lint": "bunx turbo run lint",
"deploy:init": "fly launch",
"deploy:volumes": "fly volumes create sqlite --size 1 --region lax && fly volumes create cache --size 1 --region lax",
"deploy:consul": "fly consul attach",
"deploy": "fly deploy",
"fmt": "prettier --write '**/*.{js,jsx,ts,tsx,json}'",
"fmt:check": "prettier --check '**/*.{js,jsx,ts,tsx,json}'"
},
"workspaces": [
"frontend",
"backend",
"docs"
"backend"
],
"devDependencies": {
"turbo": "latest",
Expand Down

0 comments on commit 5a2a0df

Please sign in to comment.