> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tinykit.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# VPS / Self-Hosted

> Deploy tinykit on your own server

Run tinykit on any Linux VPS—DigitalOcean, Linode, Hetzner, AWS, or your own hardware.

## Requirements

* **OS**: Ubuntu 22.04+ / Debian 12+ (or any Linux with Node.js support)
* **RAM**: 1GB minimum, 2GB recommended
* **Disk**: 5GB minimum
* **Node.js**: 20.x or later
* **Ports**: 80, 443 (with reverse proxy) or custom port

***

## Quick Setup

<Steps>
  <Step title="Install Node.js">
    ```bash theme={null}
    # Ubuntu/Debian
    curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
    sudo apt-get install -y nodejs

    # Verify
    node --version  # Should be v20.x.x
    npm --version
    ```
  </Step>

  <Step title="Clone and Install">
    ```bash theme={null}
    # Clone repository
    git clone https://github.com/tinykit-studio/tinykit.git
    cd tinykit

    # Install dependencies
    npm install

    # Build for production
    npm run build
    ```
  </Step>

  <Step title="Configure Environment">
    ```bash theme={null}
    # Copy example config
    cp .env.example .env

    # Edit with your settings
    nano .env
    ```

    Set these variables:

    ```bash theme={null}
    LLM_PROVIDER=anthropic
    LLM_API_KEY=sk-ant-...
    LLM_MODEL=claude-sonnet-4-20250514
    PORT=3000
    HOST=0.0.0.0
    ```
  </Step>

  <Step title="Download Pocketbase">
    ```bash theme={null}
    npm run pocketbase:download
    ```
  </Step>

  <Step title="Start the Server">
    ```bash theme={null}
    # Make start script executable
    chmod +x deploy/railway/start.sh

    # Start (for testing)
    ./deploy/railway/start.sh
    ```
  </Step>
</Steps>

***

## Production Setup with PM2

Use PM2 to keep tinykit running and restart on crashes:

```bash theme={null}
# Install PM2 globally
npm install -g pm2

# Create PM2 ecosystem file
cat > ecosystem.config.js << 'EOF'
module.exports = {
  apps: [{
    name: 'tinykit',
    script: './deploy/railway/start.sh',
    cwd: '/path/to/tinykit',
    env: {
      NODE_ENV: 'production',
      PORT: 3000,
      HOST: '0.0.0.0'
    },
    // Restart on failure
    restart_delay: 5000,
    max_restarts: 10,
    // Logging
    error_file: './logs/error.log',
    out_file: './logs/out.log',
    merge_logs: true,
    time: true
  }]
}
EOF

# Start with PM2
pm2 start ecosystem.config.js

# Save PM2 config (survives reboot)
pm2 save

# Enable PM2 startup on boot
pm2 startup
```

### PM2 Commands

```bash theme={null}
pm2 status           # View status
pm2 logs tinykit     # View logs
pm2 restart tinykit  # Restart
pm2 stop tinykit     # Stop
pm2 delete tinykit   # Remove from PM2
```

***

## Reverse Proxy Setup

### Caddy (Recommended)

Caddy automatically handles SSL certificates:

```bash theme={null}
# Install Caddy
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
```

Create Caddyfile:

```bash theme={null}
sudo nano /etc/caddy/Caddyfile
```

```
app.yourdomain.com {
    reverse_proxy localhost:3000
}

# Multiple domains for different apps
recipes.yourdomain.com {
    reverse_proxy localhost:3000
}

blog.yourdomain.com {
    reverse_proxy localhost:3000
}
```

```bash theme={null}
# Reload Caddy
sudo systemctl reload caddy
```

### nginx

```bash theme={null}
# Install nginx
sudo apt install nginx

# Create config
sudo nano /etc/nginx/sites-available/tinykit
```

```nginx theme={null}
server {
    listen 80;
    server_name app.yourdomain.com;

    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_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;
        proxy_cache_bypass $http_upgrade;
    }
}
```

```bash theme={null}
# Enable site
sudo ln -s /etc/nginx/sites-available/tinykit /etc/nginx/sites-enabled/

# Test config
sudo nginx -t

# Reload nginx
sudo systemctl reload nginx

# Add SSL with Certbot
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d app.yourdomain.com
```

***

## Systemd Service (Alternative to PM2)

Create a systemd service for automatic startup:

```bash theme={null}
sudo nano /etc/systemd/system/tinykit.service
```

```ini theme={null}
[Unit]
Description=tinykit
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/path/to/tinykit
ExecStart=/path/to/tinykit/deploy/railway/start.sh
Restart=on-failure
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=tinykit
Environment=NODE_ENV=production
Environment=PORT=3000
Environment=HOST=0.0.0.0
Environment=LLM_PROVIDER=anthropic
Environment=LLM_API_KEY=sk-ant-...

[Install]
WantedBy=multi-user.target
```

```bash theme={null}
# Reload systemd
sudo systemctl daemon-reload

# Enable on boot
sudo systemctl enable tinykit

# Start
sudo systemctl start tinykit

# Check status
sudo systemctl status tinykit

# View logs
sudo journalctl -u tinykit -f
```

***

## Firewall Setup

```bash theme={null}
# Allow HTTP/HTTPS
sudo ufw allow 80
sudo ufw allow 443

# Or allow custom port
sudo ufw allow 3000

# Enable firewall
sudo ufw enable
```

***

## Updating

```bash theme={null}
cd /path/to/tinykit

# Pull latest
git pull

# Install new dependencies
npm install

# Rebuild
npm run build

# Restart
pm2 restart tinykit
# or
sudo systemctl restart tinykit
```

***

## Backup

### Database Backup

```bash theme={null}
# Stop the app (optional, for consistent backup)
pm2 stop tinykit

# Copy database
cp -r pocketbase/pb_data /backup/tinykit-$(date +%Y%m%d)

# Restart
pm2 start tinykit
```

### Automated Backups

```bash theme={null}
# Add to crontab
crontab -e
```

```
# Daily backup at 2 AM
0 2 * * * cp -r /path/to/tinykit/pocketbase/pb_data /backup/tinykit-$(date +\%Y\%m\%d)

# Keep only last 7 days
0 3 * * * find /backup -name "tinykit-*" -mtime +7 -delete
```

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Pocketbase won't start">
    Check permissions:

    ```bash theme={null}
    chmod +x pocketbase/pocketbase
    ls -la pocketbase/
    ```

    Ensure the binary matches your architecture (amd64 vs arm64).
  </Accordion>

  <Accordion title="Permission denied errors">
    Ensure the user running tinykit owns the directory:

    ```bash theme={null}
    sudo chown -R $USER:$USER /path/to/tinykit
    ```
  </Accordion>

  <Accordion title="Port already in use">
    Check what's using the port:

    ```bash theme={null}
    sudo lsof -i :3000
    ```

    Kill the process or change the PORT in your config.
  </Accordion>

  <Accordion title="SSL certificate errors">
    With Caddy, certificates are automatic. With nginx + Certbot:

    ```bash theme={null}
    sudo certbot renew --dry-run
    ```
  </Accordion>

  <Accordion title="Out of memory">
    Check memory usage:

    ```bash theme={null}
    free -h
    htop
    ```

    Consider adding swap or upgrading your VPS.
  </Accordion>
</AccordionGroup>

***

## Security Checklist

* [ ] Keep the system updated: `sudo apt update && sudo apt upgrade`
* [ ] Use strong passwords for Pocketbase admin
* [ ] Enable firewall (ufw)
* [ ] Use HTTPS (Caddy or Certbot)
* [ ] Don't expose port 3000 directly—use a reverse proxy
* [ ] Regular backups
* [ ] Consider fail2ban for brute-force protection
