Skip to main content

How to install Docker

Docker is the easiest way to get started with self-hosted Sparrow. This guide assumes you are running the command from the machine you intend to host from.

System Requirements​

  • Linux VM (Ubuntu 20.04+ recommended)
  • Docker Engine 20.10+
  • Docker Compose 2.0+
  • Minimum 4GB RAM
  • At least 20GB free disk space
  • Internet connectivity
  • Custom domain names with DNS configured

Architecture Overview​

The Sparrow stack consists of the following components:

  • MongoDB: Database server
  • Sparrow API: Main API service
  • Sparrow Auth: Authentication service
  • Sparrow Proxy: Proxy service
  • Sparrow Web: Web application frontend
  • Nginx: Reverse proxy for SSL termination and routing

Pre-requisites​

1. Install Docker and Docker Compose​

# Update the package index
sudo apt-get update

# Install required packages
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common

# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# Set up the Docker repository
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# Install Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io

# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.17.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Add your user to the docker group to run Docker without sudo
sudo usermod -aG docker ${USER}

Log out and log back in for the group changes to take effect.

2. Configure DNS​

Ensure you have configured DNS records for your custom domains pointing to your server's IP address:

  • api.yourdomain.com → Your VM's public IP
  • auth.yourdomain.com → Your VM's public IP
  • app.yourdomain.com → Your VM's public IP

Deployment Steps​

First clone the SparrowAPI repository:

git clone https://github.com/sparrowapp-dev/sparrow-api.git
cd sparrowapp-dev

Create env

cp .env.example .env
cd ~/sparrow-app

# Create necessary directories for Nginx
mkdir -p ./nginx/conf.d
mkdir -p ./nginx/ssl
mkdir -p ./nginx/html
mkdir -p ./nginx/logs

3. Create Environment Variables File​

Update the .env.docker-setup with the environment variables:

Environment variables

4. Create Nginx Configuration​

Create a file named nginx/conf.d/sparrow.conf:

# Redirect HTTP to HTTPS
server {
listen 80;
server_name api.yourdomain.com auth.yourdomain.com app.yourdomain.com;
location /.well-known/acme-challenge/ {
root /usr/share/nginx/html;
}

location / {
return 301 https://$host$request_uri;
}
}

# Sparrow API configuration
server {
listen 443 ssl;
server_name api.yourdomain.com;

ssl_certificate /etc/nginx/ssl/api.yourdomain.com.crt;
ssl_certificate_key /etc/nginx/ssl/api.yourdomain.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

location / {
proxy_pass http://sparrow-api:9000;
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_read_timeout 90;
}
# WebSocket support for socket.io
location /socket.io/ {
proxy_pass http://sparrow-api:9001;
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;
}

# WebSocket support for AI assistant
location /ai-assistant {
proxy_pass http://sparrow-api:9000;
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;
}
}

# Sparrow Auth configuration
server {
listen 443 ssl;
server_name auth.yourdomain.com;

ssl_certificate /etc/nginx/ssl/auth.yourdomain.com.crt;
ssl_certificate_key /etc/nginx/ssl/auth.yourdomain.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

location / {
proxy_pass http://sparrow-auth:80;
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_read_timeout 90;
}
}

# Sparrow Web configuration
server {
listen 443 ssl;
server_name app.yourdomain.com;

ssl_certificate /etc/nginx/ssl/app.yourdomain.com.crt;
ssl_certificate_key /etc/nginx/ssl/app.yourdomain.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

location / {
proxy_pass http://sparrow-web:80;
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_read_timeout 90;
}
}

Note: Replace all instances of yourdomain.com with your actual domain name.

5. Create Dockerfile for Auth Service​

Create a file named Dockerfile for the Sparrow Auth service:

FROM node:18-alpine AS builder

WORKDIR /app

# Copy package files and install dependencies
COPY package.json package-lock.json ./
RUN npm ci

# Copy source files
COPY . .

# Build the application
RUN npm run build

# Production stage
FROM nginx:alpine

# Copy built files
COPY --from=builder /app/dist /usr/share/nginx/html

# Copy nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

6. Configure SSL Certificates​

Option 1: Self-signed certificates (for development only)​

Create a script named generate-ssl.sh:

#!/bin/bash

# Create directories if they don't exist
mkdir -p ./nginx/ssl

# Generate self-signed certificates for each domain
generate_self_signed_cert() {
domain=$1
echo "Generating self-signed certificate for $domain"
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ./nginx/ssl/$domain.key \
-out ./nginx/ssl/$domain.crt \
-subj "/CN=$domain/O=Sparrow/C=US"
}

# Generate certificates for each domain
generate_self_signed_cert "api.yourdomain.com"
generate_self_signed_cert "auth.yourdomain.com"
generate_self_signed_cert "app.yourdomain.com"

echo "Self-signed certificates generated successfully!"

Make the script executable and run it:

chmod +x generate-ssl.sh
./generate-ssl.sh

Note: Replace all instances of yourdomain.com with your actual domain name.

Install Certbot:

sudo apt-get update
sudo apt-get install -y certbot

Stop any services running on ports 80 and 443:

sudo systemctl stop nginx # If you have nginx installed

Obtain certificates:

sudo certbot certonly --standalone -d api.yourdomain.com --agree-tos --email your@email.com
sudo certbot certonly --standalone -d auth.yourdomain.com --agree-tos --email your@email.com
sudo certbot certonly --standalone -d app.yourdomain.com --agree-tos --email your@email.com

Copy certificates to Nginx directory:

sudo cp /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem ./nginx/ssl/api.yourdomain.com.crt
sudo cp /etc/letsencrypt/live/api.yourdomain.com/privkey.pem ./nginx/ssl/api.yourdomain.com.key
sudo cp /etc/letsencrypt/live/auth.yourdomain.com/fullchain.pem ./nginx/ssl/auth.yourdomain.com.crt
sudo cp /etc/letsencrypt/live/auth.yourdomain.com/privkey.pem ./nginx/ssl/auth.yourdomain.com.key
sudo cp /etc/letsencrypt/live/app.yourdomain.com/fullchain.pem ./nginx/ssl/app.yourdomain.com.crt
sudo cp /etc/letsencrypt/live/app.yourdomain.com/privkey.pem ./nginx/ssl/app.yourdomain.com.key

Set appropriate permissions:

sudo chmod 644 ./nginx/ssl/*.crt
sudo chmod 600 ./nginx/ssl/*.key

7. Deploy the Sparrow Stack​

Build and start the Docker containers:

# Build images and start containers
docker-compose up -d

# Check if all containers are running
docker-compose ps

8. Configure Automatic SSL Renewal (Let's Encrypt only)​

Create a script named renew-ssl.sh:

#!/bin/bash

# Stop nginx container
docker-compose stop nginx-proxy

# Renew certificates
sudo certbot renew

# Copy renewed certificates
sudo cp /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem ./nginx/ssl/api.yourdomain.com.crt
sudo cp /etc/letsencrypt/live/api.yourdomain.com/privkey.pem ./nginx/ssl/api.yourdomain.com.key
sudo cp /etc/letsencrypt/live/auth.yourdomain.com/fullchain.pem ./nginx/ssl/auth.yourdomain.com.crt
sudo cp /etc/letsencrypt/live/auth.yourdomain.com/privkey.pem ./nginx/ssl/auth.yourdomain.com.key
sudo cp /etc/letsencrypt/live/app.yourdomain.com/fullchain.pem ./nginx/ssl/app.yourdomain.com.crt
sudo cp /etc/letsencrypt/live/app.yourdomain.com/privkey.pem ./nginx/ssl/app.yourdomain.com.key

# Start nginx container
docker-compose start nginx-proxy

echo "SSL certificates renewed successfully!"

Make the script executable:

chmod +x renew-ssl.sh

Add a cron job to run the renewal script monthly:

crontab -e

Add the following line:

0 0 1 * * /home/username/sparrow-deployment/renew-ssl.sh >> /home/username/sparrow-deployment/ssl-renewal.log 2>&1

Replace username with your actual username.

Verification and Troubleshooting​

Verify Deployment​

Once the setup is complete, verify that your services are accessible:

  1. Web app: https://app.yourdomain.com
  2. Auth service: https://auth.yourdomain.com
  3. API service: https://api.yourdomain.com

Troubleshooting​

Check Container Logs​

# Check logs for a specific service
docker-compose logs sparrow-api
docker-compose logs sparrow-auth
docker-compose logs sparrow-web
docker-compose logs nginx-proxy

# Follow logs in real-time
docker-compose logs -f nginx-proxy

Check Nginx Configuration​

# Enter the Nginx container
docker-compose exec nginx-proxy sh

# Test Nginx configuration
nginx -t

# Check Nginx logs
cat /var/log/nginx/error.log

SSL Issues​

# Check SSL certificate validity
openssl x509 -in ./nginx/ssl/api.yourdomain.com.crt -text -noout

Network Issues​

# Check if ports are open
sudo netstat -tulpn | grep -E '80|443'

# Test connectivity between containers
docker-compose exec sparrow-web ping sparrow-api

Maintenance​

Updating Services​

To update a service with a new image or configuration:

# Pull the latest images
docker-compose pull

# Rebuild and restart services
docker-compose up -d --build

Backup and Restore​

Backup MongoDB Data​

# Create a backup directory
mkdir -p ~/sparrow-backups

# Backup MongoDB data
docker-compose exec mongo mongodump --out /data/db/backup
docker cp $(docker-compose ps -q mongo):/data/db/backup ~/sparrow-backups/mongo-$(date +%Y%m%d)

Restore MongoDB Data​

# Copy backup to container
docker cp ~/sparrow-backups/mongo-20230101 $(docker-compose ps -q mongo):/data/db/restore

# Restore data
docker-compose exec mongo mongorestore /data/db/restore

Monitoring​

Consider adding a monitoring solution like Prometheus and Grafana:

# Add to docker-compose.yml
services:
prometheus:
image: prom/prometheus
volumes:
- ./prometheus:/etc/prometheus
- prometheus_data:/prometheus
ports:
- "9090:9090"
networks:
- localnet
restart: unless-stopped

grafana:
image: grafana/grafana
volumes:
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
networks:
- localnet
restart: unless-stopped

volumes:
prometheus_data:
grafana_data:

Security Considerations​

  1. Firewall Configuration: Configure your server's firewall to allow only necessary ports:

    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw enable
  2. Strong passwords: Ensure all services use strong passwords.

  3. Regular updates: Keep all containers updated:

    docker-compose pull
    docker-compose up -d
  4. SSL certificate renewal: Regularly renew SSL certificates.

  5. Access logs monitoring: Regularly check Nginx access logs for suspicious activity.

Support and Resources​

Contributing​

Contributions to improve this guide are welcome. Please submit pull requests or open issues to discuss proposed changes.