Skip to content

Commit 668f3c2

Browse files
Deploy: Configure Railway deployment with Docker and fix dependencies
- Add Dockerfile for production deployment - Add @whop/sdk and drizzle-zod to server dependencies - Configure proper environment variables and startup - Remove deprecated railway.json configs - Server ready for production on Railway
1 parent 7d84f66 commit 668f3c2

13 files changed

Lines changed: 247 additions & 108 deletions

.dockerignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
node_modules
2+
dist
3+
.git
4+
.env
5+
*.log
6+
client
7+
docs
8+
tests
9+
scripts

.nixpacksdir

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
server

Dockerfile

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,18 @@
1-
FROM node:20-alpine AS build
2-
WORKDIR /app
3-
4-
# Install dependencies
5-
COPY package*.json ./
6-
RUN npm ci
7-
8-
# Copy source code
9-
COPY . .
10-
11-
# Build client (outputs to dist/public) and server (outputs to dist/)
12-
RUN npm run build
1+
FROM node:20-alpine
132

14-
# Production stage
15-
FROM node:20-alpine AS runtime
163
WORKDIR /app
174

18-
# Install only production dependencies
19-
COPY package*.json ./
20-
RUN npm ci --omit=dev
5+
# Copy server package files and install dependencies
6+
COPY server/package*.json ./
7+
RUN npm install --production
218

22-
# Copy built output
23-
COPY --from=build /app/dist ./dist
24-
COPY --from=build /app/shared ./shared
9+
# Copy source code
10+
COPY server/ ./
11+
COPY shared/ ./shared/
2512

2613
# Environment
2714
ENV NODE_ENV=production
2815
EXPOSE 5000
2916

30-
# Start server
31-
CMD ["node", "dist/prod.js"]
17+
# Run tsx directly - bypass npm
18+
CMD ["node_modules/.bin/tsx", "index.ts"]

RAILWAY_ENV_SETUP.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Railway Environment Variables Setup
2+
3+
## ⚠️ CRITICAL: Set These Variables in Railway Dashboard
4+
5+
Go to your Railway project → **Variables** tab → Click **+ New Variable** for each:
6+
7+
### Required Variables (Copy these EXACTLY)
8+
9+
```
10+
FORCE_IN_MEMORY_DB=true
11+
```
12+
13+
```
14+
NODE_ENV=production
15+
```
16+
17+
```
18+
SESSION_SECRET=railway-production-secret-change-this-to-random-string
19+
```
20+
21+
```
22+
PHANTOM_WALLET_ADDRESS=Demo
23+
```
24+
25+
```
26+
DATABASE_URL=postgresql://placeholder:placeholder@localhost:5432/placeholder
27+
```
28+
29+
### Optional Variables (Add if you have these services)
30+
31+
```
32+
HELIUS_API_KEY=your-helius-key-here
33+
```
34+
35+
```
36+
QUICKNODE_RPC_URL=your-quicknode-url-here
37+
```
38+
39+
## How to Add Variables in Railway
40+
41+
1. Open your Railway project
42+
2. Click on your service (the one running the server)
43+
3. Go to the **Variables** tab
44+
4. Click **+ New Variable**
45+
5. Enter the variable name and value
46+
6. Click **Add**
47+
7. Repeat for all variables above
48+
8. Railway will automatically redeploy when you save
49+
50+
## Verification
51+
52+
After deployment, check the logs. You should see:
53+
54+
```
55+
🌍 Environment: production
56+
💾 Database Mode: IN-MEMORY
57+
🔧 DB Config - FORCE_IN_MEMORY_DB: true
58+
🔑 Using session secret: railway-fa...
59+
```
60+
61+
If you DON'T see these lines, the environment variables aren't being loaded!
62+
63+
## Troubleshooting
64+
65+
**If variables aren't showing up:**
66+
67+
1. Make sure you're adding them to the SERVICE, not the project
68+
2. Variables should be in the **Variables** tab, not **Settings**
69+
3. Each variable should be on its own line
70+
4. No quotes needed around values in Railway UI
71+
5. After adding all variables, click **Deploy** if it doesn't auto-deploy
72+
73+
**Still not working?**
74+
75+
The deploy logs will show: `📋 All ENV vars: NODE_ENV, PORT, RAILWAY_...`
76+
77+
If you don't see `FORCE_IN_MEMORY_DB` in that list, Railway isn't seeing the variables.

railway.json

Lines changed: 0 additions & 30 deletions
This file was deleted.

railway.toml

Lines changed: 0 additions & 14 deletions
This file was deleted.

server/RAILWAY_DEPLOY.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Railway Deployment Instructions
2+
3+
## Required Environment Variables
4+
5+
Set these in your Railway dashboard under **Variables**:
6+
7+
```
8+
FORCE_IN_MEMORY_DB=true
9+
DATABASE_URL=postgresql://placeholder:placeholder@localhost:5432/placeholder
10+
SESSION_SECRET=your-random-secret-here-change-me
11+
PHANTOM_WALLET_ADDRESS=Demo
12+
NODE_ENV=production
13+
```
14+
15+
## How to Deploy
16+
17+
1. Push code to GitHub
18+
2. Railway will auto-deploy
19+
3. Check the build logs
20+
4. Health check at `/api/health` should return `{"status":"ok"}`
21+
22+
## Troubleshooting
23+
24+
If deployment fails:
25+
- Check Railway build logs for errors
26+
- Verify all environment variables are set
27+
- Ensure `nixpacks.toml` exists in server directory
28+
- Check that `package.json` has `tsx` dependency
29+
30+
## Current Configuration
31+
32+
- **Runtime**: Node.js 20
33+
- **Build**: `npm install`
34+
- **Start**: `npm start` (runs `tsx index.ts`)
35+
- **Database**: In-memory mode (no PostgreSQL needed)
36+
- **Port**: Auto-assigned by Railway

server/app.ts

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ import fs from "fs";
1111
export const app = express();
1212

1313
// Session middleware for wallet authentication
14+
const SESSION_SECRET = process.env.SESSION_SECRET || 'railway-fallback-secret-' + Date.now();
15+
console.log('🔑 Using session secret:', SESSION_SECRET.substring(0, 10) + '...');
16+
1417
app.use(session({
15-
secret: process.env.SESSION_SECRET || 'default-secret-change-in-production',
18+
secret: SESSION_SECRET,
1619
resave: false,
1720
saveUninitialized: false,
1821
cookie: {
@@ -65,25 +68,36 @@ export async function startServer() {
6568
// Register API routes
6669
const server = await registerRoutes(app);
6770

68-
// Serve static files in production
71+
// Serve static files in production (if available)
6972
if (process.env.NODE_ENV === 'production') {
7073
const distPath = path.join(process.cwd(), 'dist', 'public');
7174

72-
if (!fs.existsSync(distPath)) {
73-
console.error(`❌ Build directory not found: ${distPath}`);
74-
console.error('Run "npm run build" first!');
75-
process.exit(1);
75+
if (fs.existsSync(distPath)) {
76+
// Serve static assets
77+
app.use(express.static(distPath));
78+
79+
// SPA fallback - serve index.html for all non-API routes
80+
app.use('*', (_req, res) => {
81+
res.sendFile(path.join(distPath, 'index.html'));
82+
});
83+
84+
console.log('✅ Serving static files from dist/public');
85+
} else {
86+
console.log('ℹ️ No frontend build found - running API-only mode');
87+
console.log('ℹ️ This is normal for Railway backend deployment');
88+
89+
// Simple root endpoint for API-only mode
90+
app.get('/', (_req, res) => {
91+
res.json({
92+
message: 'Rug Killer API Server',
93+
status: 'online',
94+
endpoints: {
95+
health: '/api/health',
96+
docs: 'https://github.com/drixindustries/Rug-Killer-On-Solana'
97+
}
98+
});
99+
});
76100
}
77-
78-
// Serve static assets
79-
app.use(express.static(distPath));
80-
81-
// SPA fallback - serve index.html for all non-API routes
82-
app.use('*', (_req, res) => {
83-
res.sendFile(path.join(distPath, 'index.html'));
84-
});
85-
86-
console.log('✅ Serving static files from dist/public');
87101
} else {
88102
// Development mode - use Vite dev server
89103
try {
@@ -92,8 +106,21 @@ export async function startServer() {
92106
const { setupVite } = await import(viteDevPath);
93107
await setupVite(app, server);
94108
} catch (error: any) {
95-
console.error('❌ Failed to load Vite dev server (this is normal in production):', error.message);
96-
console.log('ℹ️ Running in production mode without Vite');
109+
console.warn('⚠️ Failed to load Vite dev server:', error.message);
110+
console.log('ℹ️ Running in API-only mode');
111+
112+
// Simple root endpoint for API-only mode
113+
app.get('/', (_req, res) => {
114+
res.json({
115+
message: 'Rug Killer API Server',
116+
status: 'online',
117+
mode: 'development',
118+
endpoints: {
119+
health: '/api/health',
120+
docs: 'https://github.com/drixindustries/Rug-Killer-On-Solana'
121+
}
122+
});
123+
});
97124
}
98125
}
99126

server/db.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import 'dotenv/config';
1+
// Try to load .env if it exists (local dev), but don't fail if it doesn't (Railway)
2+
try {
3+
await import('dotenv/config');
4+
} catch {
5+
// Railway injects env vars directly - no dotenv needed
6+
}
7+
28
import { Pool } from 'pg';
39
import { drizzle } from 'drizzle-orm/node-postgres';
410
import * as schema from "../shared/schema.ts";
@@ -7,6 +13,9 @@ import * as schema from "../shared/schema.ts";
713
const DATABASE_URL = process.env.DATABASE_URL;
814
const FORCE_IN_MEMORY = process.env.FORCE_IN_MEMORY_DB === 'true';
915

16+
console.log('🔧 DB Config - DATABASE_URL present:', !!DATABASE_URL);
17+
console.log('🔧 DB Config - FORCE_IN_MEMORY_DB:', process.env.FORCE_IN_MEMORY_DB);
18+
1019
let db: any;
1120
let pool: any = null;
1221

0 commit comments

Comments
 (0)