Self-Hosting Guide
Deploy LinkForty on your own infrastructure with complete control over your data.
Why Self-Host?
Control & Flexibility:
- ✅ No per-install fees (unlimited scaling)
- ✅ No vendor lock-in
- ✅ Deploy anywhere (AWS, GCP, Azure, on-premise)
Data Privacy:
- ✅ Complete data ownership
- ✅ GDPR/CCPA compliance on your terms
- ✅ No third-party data sharing
Customization:
- ✅ Full source code access (MIT license)
- ✅ Custom features and integrations
- ✅ White-label deployment
System Requirements
Minimum Specifications
Server:
- CPU: 2 cores
- RAM: 4 GB
- Storage: 20 GB SSD
- OS: Ubuntu 20.04+ / Debian 11+ / RHEL 8+
Software:
- Docker 20.10+ and Docker Compose 2.0+
- OR Node.js 18+ with PostgreSQL 14+ and Redis 7+
Expected Load Capacity:
- ~1,000 requests/minute
- ~100,000 links
- ~1M clicks/month
Recommended Specifications (Production)
Server:
- CPU: 4 cores
- RAM: 8 GB
- Storage: 100 GB SSD
- OS: Ubuntu 22.04 LTS
Expected Load Capacity:
- ~10,000 requests/minute
- ~1M links
- ~10M clicks/month
Cloud Provider Options
Recommended instance types for minimum specifications:
| Provider | Instance Type | Specs |
|---|---|---|
| DigitalOcean | Droplet (Basic) | 2 CPU, 4GB RAM |
| AWS | t3.medium | 2 CPU, 4GB RAM |
| Google Cloud | e2-medium | 2 CPU, 4GB RAM |
| Hetzner | CX21 | 2 CPU, 4GB RAM |
| Vultr | Regular Performance | 2 CPU, 4GB RAM |
Installation Methods
Choose your deployment method:
Method 1: Docker Compose (Recommended)
Fastest and easiest deployment. Everything configured out of the box.
Method 2: Manual Installation
For custom setups or when Docker isn't available.
Method 3: Kubernetes
For enterprise deployments with high availability.
Method 1: Docker Compose (Recommended)
Step 1: Clone Repository
git clone https://github.com/linkforty/linkforty-cloud.git
cd linkforty-cloud
Step 2: Configure Environment
Create .env file:
cp .env.example .env
nano .env
Required environment variables:
# Database
DATABASE_URL=postgresql://linkforty:your-strong-password@postgres:5432/linkforty
POSTGRES_USER=linkforty
POSTGRES_PASSWORD=your-strong-password
POSTGRES_DB=linkforty
# Redis
REDIS_URL=redis://redis:6379
# Application
NODE_ENV=production
PORT=3000
FRONTEND_URL=https://yourdomain.com
# Security (CHANGE THESE!)
JWT_SECRET=your-super-secret-jwt-key-at-least-32-characters-long
ENCRYPTION_KEY=your-encryption-key-32-characters-minimum
# Optional: Email (for user invitations)
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASSWORD=your-sendgrid-api-key
SMTP_FROM=noreply@yourdomain.com
# Optional: S3 (for QR code storage)
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_REGION=us-east-1
AWS_S3_BUCKET=linkforty-qrcodes
Security Note: Generate strong secrets with:
# Generate JWT secret
openssl rand -base64 48
# Generate encryption key
openssl rand -base64 32
Step 3: Build and Start Services
# Build Docker images
docker-compose build
# Start all services
docker-compose up -d
This starts:
- Frontend: React app (Nginx)
- Backend: Fastify API server
- PostgreSQL: Database
- Redis: Cache and session storage
Step 4: Run Database Migrations
docker-compose exec backend npm run migrate
Step 5: Create Admin User
docker-compose exec backend npm run create-admin
# You'll be prompted for:
# - Email: admin@yourdomain.com
# - Password: (your secure password)
# - Organization Name: Your Company
Step 6: Verify Installation
# Check all services are running
docker-compose ps
# Should show:
# linkforty-frontend Up 80, 443
# linkforty-backend Up 3000
# linkforty-postgres Up 5432
# linkforty-redis Up 6379
Visit http://your-server-ip and log in with your admin credentials.
Step 7: Set Up SSL (Required for Production)
Option A: Using Let's Encrypt (Free)
Install Certbot:
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx
Generate certificate:
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Update docker-compose.yml to use SSL:
services:
frontend:
ports:
- "80:80"
- "443:443"
volumes:
- /etc/letsencrypt:/etc/letsencrypt:ro
Option B: Using Cloudflare (Free SSL + CDN)
- Point your domain to Cloudflare nameservers
- Enable Full (strict) SSL mode in Cloudflare dashboard
- Create origin certificate in Cloudflare
- Install origin certificate on your server
- Enable Always Use HTTPS in Cloudflare
Step 8: Configure Nginx (Optional)
For better performance, configure Nginx reverse proxy:
# /etc/nginx/sites-available/linkforty
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# Frontend
location / {
proxy_pass http://localhost:3001;
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;
}
# Backend API
location /api {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Short link redirects
location ~ ^/[a-zA-Z0-9]+$ {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Enable site:
sudo ln -s /etc/nginx/sites-available/linkforty /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Method 2: Manual Installation
Step 1: Install Dependencies
# Update system
sudo apt-get update && sudo apt-get upgrade -y
# Install Node.js 18
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# Install PostgreSQL 14
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update
sudo apt-get install -y postgresql-14
# Install Redis 7
sudo apt-get install -y redis-server
Step 2: Configure PostgreSQL
# Create database and user
sudo -u postgres psql << EOF
CREATE DATABASE linkforty;
CREATE USER linkforty WITH PASSWORD 'your-strong-password';
GRANT ALL PRIVILEGES ON DATABASE linkforty TO linkforty;
\q
EOF
Step 3: Clone and Build
# Clone repository
git clone https://github.com/linkforty/linkforty-cloud.git
cd linkforty-cloud
# Install dependencies
npm install
cd backend && npm install && cd ..
# Build frontend
npm run build
# Build backend
cd backend && npm run build && cd ..
Step 4: Configure Environment
cp .env.example .env
nano .env
Set production values (same as Docker Compose method).
Step 5: Run Migrations
cd backend
npm run migrate
cd ..
Step 6: Set Up systemd Services
Create backend service:
sudo nano /etc/systemd/system/linkforty-backend.service
[Unit]
Description=LinkForty Backend
After=network.target postgresql.service redis.service
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/linkforty-cloud/backend
Environment="NODE_ENV=production"
EnvironmentFile=/opt/linkforty-cloud/.env
ExecStart=/usr/bin/node dist/index.js
Restart=on-failure
[Install]
WantedBy=multi-user.target
Create frontend service:
sudo nano /etc/systemd/system/linkforty-frontend.service
[Unit]
Description=LinkForty Frontend
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/linkforty-cloud
ExecStart=/usr/bin/npx serve -s dist -l 3001
Restart=on-failure
[Install]
WantedBy=multi-user.target
Enable and start services:
sudo systemctl daemon-reload
sudo systemctl enable linkforty-backend linkforty-frontend
sudo systemctl start linkforty-backend linkforty-frontend
# Check status
sudo systemctl status linkforty-backend
sudo systemctl status linkforty-frontend
Method 3: Kubernetes
Prerequisites
- Kubernetes cluster (EKS, GKE, AKS, or self-hosted)
- kubectl configured
- Helm 3+
Step 1: Add Helm Repository
helm repo add linkforty https://charts.linkforty.com
helm repo update
Step 2: Create Values File
# values.yaml
replicaCount: 3
image:
repository: linkforty/linkforty-cloud
tag: "latest"
pullPolicy: IfNotPresent
service:
type: LoadBalancer
port: 80
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: linkforty.yourdomain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: linkforty-tls
hosts:
- linkforty.yourdomain.com
postgresql:
enabled: true
auth:
username: linkforty
password: your-strong-password
database: linkforty
primary:
persistence:
size: 20Gi
redis:
enabled: true
auth:
enabled: false
master:
persistence:
size: 8Gi
env:
JWT_SECRET: your-super-secret-jwt-key
ENCRYPTION_KEY: your-encryption-key
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 80
Step 3: Install with Helm
helm install linkforty linkforty/linkforty-cloud -f values.yaml
Step 4: Verify Deployment
kubectl get pods
kubectl get services
kubectl logs -l app=linkforty
Post-Installation Setup
1. Configure Custom Domain
Update DNS records:
A linkforty.yourdomain.com → your-server-ip
A *.linkforty.yourdomain.com → your-server-ip (for custom domains)
2. Set Up Backups
PostgreSQL Backup Script
#!/bin/bash
# /opt/linkforty-cloud/backup.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/linkforty"
mkdir -p $BACKUP_DIR
# Backup database
docker-compose exec -T postgres pg_dump -U linkforty linkforty | gzip > "$BACKUP_DIR/linkforty_$DATE.sql.gz"
# Keep only last 30 days
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete
# Upload to S3 (optional)
aws s3 cp "$BACKUP_DIR/linkforty_$DATE.sql.gz" s3://your-backup-bucket/
Add to crontab:
crontab -e
# Daily backup at 2 AM
0 2 * * * /opt/linkforty-cloud/backup.sh
3. Set Up Monitoring
Using Docker Stats
docker stats linkforty-backend linkforty-frontend
Using Prometheus + Grafana
# docker-compose.yml additions
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3002:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
4. Configure Firewall
# Allow HTTP/HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Allow SSH (change port if needed)
sudo ufw allow 22/tcp
# Enable firewall
sudo ufw enable
5. Set Up Log Rotation
sudo nano /etc/logrotate.d/linkforty
/opt/linkforty-cloud/logs/*.log {
daily
rotate 14
compress
delaycompress
notifempty
missingok
sharedscripts
postrotate
docker-compose restart backend frontend
endscript
}
Updating LinkForty
Docker Compose
cd /opt/linkforty-cloud
# Pull latest code
git pull origin main
# Rebuild images
docker-compose build
# Run migrations (if needed)
docker-compose exec backend npm run migrate
# Restart services
docker-compose up -d
Manual Installation
cd /opt/linkforty-cloud
# Pull latest code
git pull origin main
# Update dependencies
npm install
cd backend && npm install && cd ..
# Rebuild
npm run build
cd backend && npm run build && cd ..
# Run migrations
cd backend && npm run migrate && cd ..
# Restart services
sudo systemctl restart linkforty-backend linkforty-frontend
Troubleshooting
Backend Won't Start
# Check logs
docker-compose logs backend
# Common issues:
# 1. Database not ready - wait 10 seconds and retry
# 2. Redis not accessible - check REDIS_URL
# 3. Port 3000 in use - change PORT in .env
Frontend Shows "API Connection Error"
# Check VITE_API_URL in .env
# Should be: https://yourdomain.com/api
# Verify backend is running
curl http://localhost:3000/api/health
Database Connection Errors
# Test PostgreSQL connection
docker-compose exec postgres psql -U linkforty -d linkforty -c "SELECT 1;"
# Check DATABASE_URL format:
# postgresql://username:password@host:port/database
High Memory Usage
# Increase PostgreSQL shared_buffers
docker-compose exec postgres psql -U linkforty -d linkforty -c "ALTER SYSTEM SET shared_buffers = '256MB';"
docker-compose restart postgres
# Increase Node.js memory limit
# In docker-compose.yml:
environment:
- NODE_OPTIONS=--max-old-space-size=2048
Production Checklist
Before going live:
- ✅ SSL certificate installed and working
- ✅ Strong JWT_SECRET and ENCRYPTION_KEY generated
- ✅ Database backups configured (daily minimum)
- ✅ Firewall rules configured
- ✅ Monitoring set up (Prometheus/Grafana or cloud provider)
- ✅ Log rotation configured
- ✅ DNS records pointing to server
- ✅ SMTP configured for user invitations
- ✅ Rate limiting enabled (default: 100 req/min per IP)
- ✅ Admin user created
- ✅ Test link created and working
- ✅ Health check endpoint responding (
/api/health)
Getting Help
Platform Guides - Usage documentation
- Report Issues - Bug reports
- API Reference - API documentation