Linkwarden Deployment and Usage Guide
1. Prerequisites
Software Requirements
- Node.js 18.x or later
- npm or yarn package manager
- PostgreSQL database (version 12 or higher)
- Redis (for session storage and caching)
- Docker and Docker Compose (optional, for containerized deployment)
- Git (for cloning the repository)
Optional Dependencies (for full functionality)
- Playwright (for webpage archiving - installed automatically via npm)
- Ollama, OpenAI API, Azure API, or Anthropic API key (for AI tagging features)
- SMTP server or email service (for email authentication and notifications)
- Wayback Machine (archive.org) integration (for link preservation)
Accounts Needed (Optional)
- OAuth provider accounts (for SSO integration):
- Apple, Auth0, Azure AD, Discord, Google, etc.
- See the full list in
apps/web/pages/api/v1/auth/[...nextauth].ts
2. Installation
Clone the Repository
git clone https://github.com/linkwarden/linkwarden.git
cd linkwarden
Install Dependencies
# Install root dependencies
npm install
# Install Playwright browsers (required for archiving)
npx playwright install
Database Setup
# Create PostgreSQL database (example)
createdb linkwarden
# Or using Docker
docker run --name linkwarden-db -e POSTGRES_PASSWORD=yourpassword -d postgres:15
3. Configuration
Environment Variables
Create a .env file in the root directory with the following variables:
Required Variables
# Database
DATABASE_URL="postgresql://username:password@localhost:5432/linkwarden"
# Redis
REDIS_URL="redis://localhost:6379"
# Next.js
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="your-secret-key-here"
# File Storage (local by default)
FILE_STORAGE_PATH="./data"
Email Configuration (Optional but recommended)
EMAIL_FROM="noreply@yourdomain.com"
EMAIL_SERVER="smtp://username:password@smtp.example.com:587"
Authentication Providers (Optional)
Enable any OAuth provider by setting its environment variables:
# Example for Google OAuth
NEXT_PUBLIC_GOOGLE_ENABLED="true"
GOOGLE_CLIENT_ID="your-client-id"
GOOGLE_CLIENT_SECRET="your-client-secret"
GOOGLE_CUSTOM_NAME="Google" # Optional custom name
# Example for GitHub
NEXT_PUBLIC_GITHUB_ENABLED="true"
GITHUB_CLIENT_ID="your-client-id"
GITHUB_CLIENT_SECRET="your-client-secret"
AI Tagging (Optional)
# Choose one AI provider
NEXT_PUBLIC_OLLAMA_ENDPOINT_URL="http://localhost:11434" # For local Ollama
OPENAI_API_KEY="your-openai-api-key" # For OpenAI
AZURE_API_KEY="your-azure-api-key" # For Azure OpenAI
ANTHROPIC_API_KEY="your-anthropic-api-key" # For Anthropic
Archiving Configuration
# Browser timeout for archiving (in minutes)
BROWSER_TIMEOUT=5
# Disable preservation if needed
DISABLE_PRESERVATION="false"
# Wayback Machine integration
WAYBACK_MACHINE_ENABLED="true"
Application Limits
# Maximum links per user
MAX_LINKS_PER_USER=30000
Database Schema
Run database migrations:
# Generate Prisma client
npx prisma generate
# Apply migrations
npx prisma db push
# Or for production:
npx prisma migrate deploy
4. Build & Run
Development Mode
# Start the development server
npm run dev
# The application will be available at http://localhost:3000
Production Build
# Build the application
npm run build
# Start the production server
npm start
Worker Process (for archiving)
Linkwarden uses a worker process for background tasks like webpage archiving. In production, you need to run:
# Start the worker
npm run worker
Using Docker Compose (Simplified)
Create a docker-compose.yml file:
version: '3.8'
services:
postgres:
image: postgres:15
environment:
POSTGRES_PASSWORD: linkwarden_password
POSTGRES_DB: linkwarden
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
app:
build: .
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://postgres:linkwarden_password@postgres:5432/linkwarden
REDIS_URL: redis://redis:6379
NEXTAUTH_URL: http://localhost:3000
NEXTAUTH_SECRET: your-secret-key-here
depends_on:
- postgres
- redis
volumes:
postgres_data:
Build and run:
docker-compose up -d
5. Deployment
Platform Recommendations
VPS/Cloud Server (Recommended for full control)
- DigitalOcean, Linode, AWS EC2, Google Cloud Compute
- Requires manual setup of PostgreSQL, Redis, and Node.js
- Use PM2 or systemd for process management
PM2 configuration example:
npm install -g pm2
pm2 start npm --name "linkwarden-web" -- start
pm2 start npm --name "linkwarden-worker" -- run worker
pm2 save
pm2 startup
Container Platforms
- Docker with Docker Compose (simplest)
- Kubernetes (for scalable deployments)
- Railway, Render, Fly.io (platforms with good Node.js support)
Managed Database Options
- Supabase (PostgreSQL with built-in authentication)
- Neon, Aiven, AWS RDS (managed PostgreSQL)
Deployment Checklist
-
Set up infrastructure:
- PostgreSQL database
- Redis instance
- File storage (local disk or S3-compatible storage)
-
Configure environment:
- Set all required environment variables
- Configure SSL/TLS certificates
- Set up firewall rules (open ports 3000, 5432, 6379)
-
Build and deploy:
git pull origin main npm install npm run build npx prisma migrate deploy npm start -
Set up reverse proxy (recommended):
- Use Nginx or Caddy as reverse proxy
- Configure SSL with Let's Encrypt
Example Nginx configuration:
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
6. Troubleshooting
Common Issues and Solutions
Database Connection Issues
Error: P1001: Can't reach database server
# Solution:
1. Verify DATABASE_URL is correct
2. Check if PostgreSQL is running: `sudo systemctl status postgresql`
3. Verify firewall allows port 5432
4. Test connection: `psql DATABASE_URL`
Authentication Problems
# If email login doesn't work:
1. Verify EMAIL_FROM and EMAIL_SERVER are set
2. Check SMTP server credentials
3. Test email sending manually
# If OAuth providers don't appear:
1. Check if NEXT_PUBLIC_[PROVIDER]_ENABLED="true"
2. Verify client ID and secret are correct
3. Ensure callback URLs are configured in OAuth provider dashboard
Archiving Not Working
# If screenshots/PDFs aren't generated:
1. Check Playwright installation: `npx playwright install --with-deps`
2. Verify DISABLE_PRESERVATION="false"
3. Check browser timeout: BROWSER_TIMEOUT should be > 0
4. Look for errors in worker logs
File Upload Issues
# If file uploads fail:
1. Check FILE_STORAGE_PATH exists and is writable
2. Verify file size limits (default 50MB)
3. Check available disk space
Performance Issues
# Slow page loads:
1. Enable Redis caching
2. Check database indexes: `npx prisma studio`
3. Monitor worker process CPU/memory usage
4. Consider increasing BROWSER_TIMEOUT for complex pages
Mobile App Connection
# If mobile app can't connect to self-hosted instance:
1. Ensure your instance is publicly accessible
2. Configure CORS if needed
3. Use HTTPS for production (required by mobile apps)
4. Verify API endpoints are accessible
Logs and Debugging
# View application logs
npm run dev # Development logs
pm2 logs linkwarden-web # Production logs (if using PM2)
docker-compose logs -f # Docker logs
# Check worker process logs
npm run worker # Development
pm2 logs linkwarden-worker # Production
# Database debugging
npx prisma studio # GUI for database inspection
Getting Help
- Check the official documentation: https://docs.linkwarden.app
- Join Discord community: https://discord.com/invite/CtuYV47nuJ
- Create GitHub issues: https://github.com/linkwarden/linkwarden/issues
- Review source code for configuration examples in the provided key files