fix: standalone Dockerfile + clear Railway deploy instructions

- Rewrite Dockerfile to be fully standalone (no workspace deps)
- Use npm install instead of pnpm workspace
- Update README with step-by-step Railway deployment
- Critical: Root Directory must be set to 'secure' in Railway
- Add instructions for getting Telegram user ID

https://claude.ai/code/session_015VqJ7gN4vaxtYfYc92UjLs
This commit is contained in:
Claude 2026-01-30 07:28:25 +00:00
parent 6a0c49e5c7
commit b4f8a457a8
No known key found for this signature in database
4 changed files with 52 additions and 54 deletions

View File

@ -2,34 +2,30 @@
"$schema": "https://railway.app/railway.schema.json",
"name": "AssureBot",
"description": "Lean, secure, self-hosted AI assistant with Telegram, document analysis, and scheduled tasks",
"icon": "https://raw.githubusercontent.com/TNovs1/moltbot/main/secure/icon.png",
"services": [
{
"name": "assurebot",
"build": {
"builder": "DOCKERFILE",
"dockerfilePath": "secure/Dockerfile"
"dockerfilePath": "secure/Dockerfile",
"watchPatterns": ["secure/**"]
},
"deploy": {
"startCommand": "node dist/index.js",
"healthcheckPath": "/health",
"healthcheckTimeout": 30,
"healthcheckTimeout": 60,
"restartPolicyType": "ON_FAILURE",
"restartPolicyMaxRetries": 3
},
"variables": {
"DATABASE_URL": {
"reference": "postgres.DATABASE_URL"
},
"REDIS_URL": {
"reference": "redis.REDIS_URL"
},
"DATABASE_URL": "${{Postgres.DATABASE_URL}}",
"REDIS_URL": "${{Redis.REDIS_URL}}",
"TELEGRAM_BOT_TOKEN": {
"description": "Telegram bot token from @BotFather",
"required": true
},
"ALLOWED_USERS": {
"description": "Comma-separated Telegram user IDs (e.g., 123456789,987654321)",
"description": "Comma-separated Telegram user IDs",
"required": true
},
"ANTHROPIC_API_KEY": {
@ -37,33 +33,25 @@
"required": false
},
"OPENAI_API_KEY": {
"description": "OpenAI API key (or use ANTHROPIC_API_KEY or OPENROUTER_API_KEY)",
"description": "OpenAI API key",
"required": false
},
"OPENROUTER_API_KEY": {
"description": "OpenRouter API key (or use ANTHROPIC_API_KEY or OPENAI_API_KEY)",
"description": "OpenRouter API key (100+ models)",
"required": false
},
"AI_MODEL": {
"description": "Model to use (e.g., claude-3-5-sonnet-20241022, gpt-4o, anthropic/claude-3.5-sonnet)",
"description": "Model override (e.g., claude-3-5-sonnet-20241022)",
"required": false
},
"WEBHOOK_SECRET": {
"description": "Secret for authenticating webhooks (auto-generated if empty)",
"required": false
},
"SANDBOX_ENABLED": {
"description": "Enable Docker sandbox for code execution",
"default": "false"
}
}
},
{
"name": "postgres",
"name": "Postgres",
"plugin": "postgresql"
},
{
"name": "redis",
"name": "Redis",
"plugin": "redis"
}
]

View File

@ -1,43 +1,42 @@
# AssureBot - Minimal Docker Image
# AssureBot - Standalone Docker Image
# Lean, secure, self-hosted AI assistant for Railway
#
# Build from repo root: docker build -f secure/Dockerfile .
# Or set Railway root directory to: secure/
FROM node:22-slim AS builder
WORKDIR /app
# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
# Copy workspace config and package files
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json ./
COPY secure/package.json ./secure/
# Copy package files (handles both root and secure/ as context)
COPY package*.json ./
COPY tsconfig.json* ./
COPY *.ts ./
COPY *.d.ts ./
# Install dependencies
RUN pnpm install --frozen-lockfile --prod=false
# Copy source
COPY secure/ ./secure/
RUN npm install --omit=dev=false
# Build TypeScript
RUN cd secure && pnpm exec tsc
RUN npm run build
# Production image
FROM node:22-slim AS runner
# Security: Run as non-root user
RUN useradd -m -u 1000 -s /bin/bash assurebot
USER assurebot
WORKDIR /app
# Copy built files and production deps
COPY --from=builder --chown=assurebot:assurebot /app/node_modules ./node_modules
COPY --from=builder --chown=assurebot:assurebot /app/secure/node_modules ./secure/node_modules
COPY --from=builder --chown=assurebot:assurebot /app/secure/dist ./dist
COPY --from=builder --chown=assurebot:assurebot /app/secure/package.json ./
COPY --from=builder --chown=assurebot:assurebot /app/dist ./dist
COPY --from=builder --chown=assurebot:assurebot /app/package.json ./
# Create data directory for audit logs
RUN mkdir -p /app/data
# Create data directory for audit logs (before switching user)
RUN mkdir -p /app/data && chown assurebot:assurebot /app/data
USER assurebot
ENV NODE_ENV=production
ENV PORT=8080
@ -45,7 +44,7 @@ ENV PORT=8080
EXPOSE 8080
# Health check
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
CMD node -e "fetch('http://localhost:8080/health').then(r => process.exit(r.ok ? 0 : 1))" || exit 1
CMD ["node", "dist/index.js"]

View File

@ -49,17 +49,27 @@ Your AI agent that runs on your infrastructure, answers only to you, and you can
## Deploy to Railway
### One-Click
[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/assurebot)
### Manual
### Quick Start
1. Fork this repo
2. Create Railway project from GitHub
3. Set environment variables (see below)
4. Add volume at `/data`
5. Deploy
2. Create new Railway project → "Deploy from GitHub repo"
3. Select your fork
4. **Critical**: Click "Settings" → Set **Root Directory** to `secure`
5. Add services:
- Click "New" → "Database" → "PostgreSQL"
- Click "New" → "Database" → "Redis"
6. In main service, add Variables:
- `TELEGRAM_BOT_TOKEN` (from @BotFather)
- `ALLOWED_USERS` (your Telegram user ID, get it from @userinfobot)
- `OPENROUTER_API_KEY` or `ANTHROPIC_API_KEY` or `OPENAI_API_KEY`
7. Railway auto-wires `DATABASE_URL` and `REDIS_URL` from the database services
8. Deploy!
### Getting Your Telegram User ID
1. Message @userinfobot on Telegram
2. It replies with your user ID (a number like `123456789`)
3. Use this as `ALLOWED_USERS`
## Configuration

View File

@ -2,12 +2,13 @@
"$schema": "https://railway.app/railway.schema.json",
"build": {
"builder": "DOCKERFILE",
"dockerfilePath": "secure/Dockerfile"
"dockerfilePath": "Dockerfile"
},
"deploy": {
"startCommand": "node dist/index.js",
"healthcheckPath": "/health",
"healthcheckTimeout": 30,
"healthcheckTimeout": 60,
"restartPolicyType": "ON_FAILURE",
"restartPolicyMaxRetries": 5
"restartPolicyMaxRetries": 3
}
}